59 lines
2.7 KiB
JavaScript
59 lines
2.7 KiB
JavaScript
const { execFileSync } = require('node:child_process');
|
|
const { readdir, readFile, stat, writeFile } = require('node:fs/promises');
|
|
const { join, relative, sep } = require('node:path');
|
|
const terser = require('terser');
|
|
|
|
const root = join(__dirname, '..');
|
|
const publicDirs = ['frameworks', 'utilities', 'components'];
|
|
|
|
const version = () => {
|
|
const tags = execFileSync('git', ['tag', '--sort=-v:refname'], { cwd: root, encoding: 'utf8' })
|
|
.trim().split(/\s+/).filter(tag => /^v\d+\.\d+\.\d+$/.test(tag));
|
|
if (!tags.length) return '1.0.0';
|
|
const [major, minor, patch] = tags[0].slice(1).split('.').map(Number);
|
|
return `${major}.${minor}.${patch + 1}`;
|
|
};
|
|
|
|
const filesBelow = async directory => {
|
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
const results = await Promise.all(entries.map(entry => {
|
|
const file = join(directory, entry.name);
|
|
return entry.isDirectory() ? filesBelow(file) : Promise.resolve(entry.name.endsWith('.js') && !entry.name.endsWith('.min.js') ? [file] : []);
|
|
}));
|
|
return results.flat();
|
|
};
|
|
|
|
const setVersion = (text, nextVersion) => text
|
|
.replace(/"version": "\d+\.\d+\.\d+"/, `"version": "${nextVersion}"`)
|
|
.replace(/@apigo\.cc\/ui@\d+\.\d+\.\d+/g, `@apigo.cc/ui@${nextVersion}`);
|
|
|
|
(async () => {
|
|
const nextVersion = version();
|
|
const sources = (await Promise.all(publicDirs.map(dir => filesBelow(join(root, dir))))).flat();
|
|
const sourceVersions = Object.fromEntries(await Promise.all(sources.map(async file => {
|
|
const path = relative(root, file).split(sep).join('/');
|
|
return [path, Math.floor((await stat(file)).mtimeMs).toString(36)];
|
|
})));
|
|
const uiFile = join(root, 'ui.js');
|
|
const uiSource = await readFile(uiFile, 'utf8');
|
|
const builtUi = uiSource.replace(
|
|
/const build = \{ version: '[^']*', files: \{[^\n]*\} \};/,
|
|
`const build = { version: '${nextVersion}', files: ${JSON.stringify(sourceVersions)} };`
|
|
);
|
|
if (builtUi === uiSource && !uiSource.includes('const build =')) throw new Error('ui.js build manifest is missing');
|
|
await writeFile(uiFile, builtUi);
|
|
|
|
const minify = async file => {
|
|
const output = await terser.minify(await readFile(file, 'utf8'), { compress: true, mangle: true, format: { comments: false } });
|
|
if (output.error) throw output.error;
|
|
await writeFile(file.replace(/\.js$/, '.min.js'), output.code + '\n');
|
|
};
|
|
await Promise.all([...sources, uiFile].map(minify));
|
|
|
|
for (const name of ['package.json', 'README.md', 'README.zh-CN.md', 'AI.yaml']) {
|
|
const file = join(root, name);
|
|
await writeFile(file, setVersion(await readFile(file, 'utf8'), nextVersion));
|
|
}
|
|
console.log(`Built @apigo.cc/ui@${nextVersion} (${sources.length} module files)`);
|
|
})();
|