mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-28 09:02:12 +08:00
* feat(cli): add unified Commander CLI for QingLong 2.x * fix(cli): publish via npm and address security review feedback * ci(cli): package npm artifacts and remove evaluation collateral * test(cli): use a fixed shell fixture for log retention * refactor(cli): separate remote npm client from panel tools * feat(cli): cover active panel OpenAPI resources * docs(cli): unify authentication and skill guidance * refactor(cli): isolate internal commands and generate Commander help * refactor(cli): organize remote and internal modules by responsibility * ci(cli): publish verified npm archives from master * fix(cli): publish under the whyour npm scope * ci: use npm trusted publishing for both packages * docs: introduce the published CLI on the project homepage * fix(cli): preserve server log truncation and correct login hints * fix(cli): accept dashboard record request bodies * fix(cli): preserve stdin for local task execution * fix(cli): resolve task executables after changing directory * fix(cli): preserve shell function tasks and sanitize test failures * fix(cli): preserve shell hook state and resolve workdir after hooks * fix(cli): preserve cleanup across shared shell task timeouts * fix(cli): isolate shell control descriptors and reap timed-out descendants
78 lines
2.5 KiB
JavaScript
78 lines
2.5 KiB
JavaScript
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const { execFileSync } = require('node:child_process');
|
|
const root = path.resolve(__dirname, '..');
|
|
// Deleted commands must not survive incremental builds or npm prepack.
|
|
fs.rmSync(path.join(root, 'dist'), { recursive: true, force: true });
|
|
execFileSync(
|
|
process.execPath,
|
|
[
|
|
require.resolve('typescript/bin/tsc'),
|
|
'-p',
|
|
path.join(root, 'tsconfig.json'),
|
|
],
|
|
{ stdio: 'inherit' },
|
|
);
|
|
require('esbuild').buildSync({
|
|
entryPoints: [path.join(root, 'src/shared/cli/commander.ts')],
|
|
outfile: path.join(root, 'dist/shared/cli/commander.js'),
|
|
bundle: true,
|
|
platform: 'node',
|
|
format: 'cjs',
|
|
target: 'node22',
|
|
minify: true,
|
|
sourcemap: true,
|
|
legalComments: 'inline',
|
|
});
|
|
const license = path.join(
|
|
path.dirname(require.resolve('commander')),
|
|
'LICENSE',
|
|
);
|
|
fs.mkdirSync(path.join(root, 'dist/licenses'), { recursive: true });
|
|
fs.copyFileSync(license, path.join(root, 'dist/licenses/commander-LICENSE'));
|
|
|
|
// The public npm artifact must not contain or import local operational code.
|
|
const remote = require('esbuild').buildSync({
|
|
entryPoints: [path.join(root, 'src/entrypoints/remote.ts')],
|
|
outfile: path.join(root, 'dist/npm/ql.js'),
|
|
bundle: true,
|
|
platform: 'node',
|
|
format: 'cjs',
|
|
target: 'node22',
|
|
minify: true,
|
|
sourcemap: true,
|
|
legalComments: 'inline',
|
|
metafile: true,
|
|
});
|
|
for (const input of Object.keys(remote.metafile.inputs)) {
|
|
if (/(?:^|[\\/])src[\\/](?:internal|compatibility|developer)[\\/]/.test(input))
|
|
throw new Error(
|
|
'Local implementation leaked into remote npm bundle: ' + input,
|
|
);
|
|
}
|
|
fs.copyFileSync(license, path.join(root, 'dist/npm/commander-LICENSE'));
|
|
|
|
// Keep existing panel/cron executable paths stable after source reorganization.
|
|
for (const [name, entry] of Object.entries(require('./entrypoints.cjs'))) {
|
|
const target = path.join(root, 'dist', name);
|
|
let relative = path
|
|
.relative(path.dirname(target), path.join(root, 'dist', entry.module))
|
|
.split(path.sep)
|
|
.join('/');
|
|
if (!relative.startsWith('.')) relative = './' + relative;
|
|
const run = entry.method
|
|
? `
|
|
if (require.main === module) void entry.${entry.method}().then(code => { process.exitCode = code; });`
|
|
: '';
|
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
fs.writeFileSync(
|
|
target,
|
|
'#!/usr/bin/env node\nconst entry = require(' +
|
|
JSON.stringify(relative) +
|
|
');\nmodule.exports = entry;' +
|
|
run +
|
|
'\n',
|
|
{ mode: 0o755 },
|
|
);
|
|
}
|