mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-14 20:34:19 +08:00
132 lines
3.7 KiB
JavaScript
132 lines
3.7 KiB
JavaScript
// build.mjs
|
||
import {build} from 'esbuild';
|
||
import fs from 'fs';
|
||
import path from 'path';
|
||
import {fileURLToPath} from 'url';
|
||
|
||
const __filename = fileURLToPath(import.meta.url);
|
||
const __dirname = path.dirname(__filename);
|
||
|
||
// 源码目录(你问的“入口目录”)
|
||
const VIEWS_DIR = path.join(__dirname, 'views');
|
||
// 输出目录
|
||
const DIST_DIR = path.join(__dirname, '../htdocs/luci-static/resources/view/hijpass');
|
||
|
||
// 限定哪些 from 模块名当作 luci 模块(name = require name)
|
||
const luciModuleNames = new Set(
|
||
['view', 'fs', 'form', 'uci', 'ui', 'network', 'baseclass', 'rpc', 'poll']);
|
||
|
||
/**
|
||
* 扫描 views 目录下的所有 .ts 文件,返回绝对路径列表
|
||
*/
|
||
function scanEntryFiles(dir) {
|
||
const files = fs.readdirSync(dir, {withFileTypes: true});
|
||
const entries = [];
|
||
|
||
for (const file of files) {
|
||
if (file.isDirectory()) {
|
||
// 若你需要递归子目录,这里可以继续深入
|
||
const subDir = path.join(dir, file.name);
|
||
entries.push(...scanEntryFiles(subDir));
|
||
} else if (file.isFile() && file.name.endsWith('.ts')) {
|
||
entries.push(path.join(dir, file.name));
|
||
}
|
||
}
|
||
|
||
return entries;
|
||
}
|
||
|
||
/**
|
||
* 为单个入口文件构建(entryPath 为绝对路径)
|
||
*/
|
||
async function buildOne(entryPath) {
|
||
// 本次构建中用到的 luci 模块名
|
||
const usedModules = new Set();
|
||
|
||
const luciPlugin = {
|
||
name: 'luci-from-plugin',
|
||
setup(pluginBuild) {
|
||
pluginBuild.onResolve({filter: /.*/}, args => {
|
||
if (luciModuleNames.has(args.path)) {
|
||
usedModules.add(args.path);
|
||
return {
|
||
path: args.path,
|
||
namespace: 'luci-virtual'
|
||
};
|
||
}
|
||
});
|
||
|
||
pluginBuild.onLoad({filter: /.*/, namespace: 'luci-virtual'}, args => {
|
||
const moduleName = args.path;
|
||
const code = `
|
||
// Virtual luci module: ${moduleName}
|
||
export default ${moduleName};
|
||
`;
|
||
return {
|
||
contents: code,
|
||
loader: 'ts'
|
||
};
|
||
});
|
||
}
|
||
};
|
||
|
||
// 计算输出文件名:views/demo.ts → dist/demo.js
|
||
const rel = path.relative(VIEWS_DIR, entryPath); // demo.ts
|
||
const baseName = rel.replace(/\.ts$/, ''); // demo
|
||
const outFile = path.join(DIST_DIR, `${baseName}.js`);
|
||
|
||
await build({
|
||
entryPoints: [entryPath],
|
||
bundle: true,
|
||
platform: 'browser',
|
||
format: 'iife',
|
||
target: ['es2022'],
|
||
outfile: outFile,
|
||
sourcemap: false,
|
||
minify: true,
|
||
globalName: 'LuciView',
|
||
plugins: [luciPlugin]
|
||
});
|
||
|
||
const bundled = fs.readFileSync(outFile, 'utf-8');
|
||
const requireLines = Array.from(usedModules)
|
||
.sort()
|
||
.map(name => `'require ${name}';`)
|
||
.join('\n');
|
||
|
||
const snippet = `
|
||
'use strict';
|
||
${requireLines}
|
||
|
||
${bundled}
|
||
|
||
return LuciView.default;
|
||
`;
|
||
|
||
fs.mkdirSync(path.dirname(outFile), {recursive: true});
|
||
fs.writeFileSync(outFile, snippet, 'utf-8');
|
||
console.log(`Build luci snippet: ${path.relative(__dirname, outFile)}`);
|
||
}
|
||
|
||
/**
|
||
* 主流程:扫描 views 目录并构建所有 .ts
|
||
*/
|
||
async function bundleAll() {
|
||
const entries = scanEntryFiles(VIEWS_DIR);
|
||
if (entries.length === 0) {
|
||
console.warn('No .ts files found in views/ directory');
|
||
return;
|
||
}
|
||
|
||
for (const entry of entries) {
|
||
// 按顺序构建每个入口;如需并行可用 Promise.all
|
||
// 但串行 log 更清晰,出错也好排查
|
||
await buildOne(entry);
|
||
}
|
||
}
|
||
|
||
bundleAll().catch(err => {
|
||
console.error(err);
|
||
process.exit(1);
|
||
});
|