autosnippet 3.2.17 → 3.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +46 -42
- package/dist/lib/http/HttpServer.js +15 -2
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -35,7 +35,11 @@ process.on('uncaughtException', (error) => {
|
|
|
35
35
|
});
|
|
36
36
|
process.on('unhandledRejection', (reason) => {
|
|
37
37
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
38
|
+
const stack = reason instanceof Error ? reason.stack : undefined;
|
|
38
39
|
process.stderr.write(`[asd] Unhandled Rejection: ${msg}\n`);
|
|
40
|
+
if (stack) {
|
|
41
|
+
process.stderr.write(`${stack}\n`);
|
|
42
|
+
}
|
|
39
43
|
process.exit(1);
|
|
40
44
|
});
|
|
41
45
|
// 优雅关闭 — 统一 shutdown 协调器
|
|
@@ -819,6 +823,48 @@ program
|
|
|
819
823
|
}
|
|
820
824
|
else if (process.env.ASD_DEBUG === '1') {
|
|
821
825
|
}
|
|
826
|
+
if (opts.apiOnly) {
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
// 2. 启动 Dashboard UI
|
|
830
|
+
const dashboardDir = DASHBOARD_DIR;
|
|
831
|
+
const distDir = join(dashboardDir, 'dist');
|
|
832
|
+
const hasPrebuilt = existsSync(join(distDir, 'index.html'));
|
|
833
|
+
const hasSrc = existsSync(join(dashboardDir, 'src'));
|
|
834
|
+
if (hasPrebuilt && !hasSrc) {
|
|
835
|
+
// ── 生产模式:npm 安装的包,在 API 服务器上直接托管预构建产物 ──
|
|
836
|
+
// 同端口同 origin → /api 路由自然可达,无跨域问题
|
|
837
|
+
httpServer.mountDashboard(distDir);
|
|
838
|
+
if (opts.browser) {
|
|
839
|
+
const open = (await import('open')).default;
|
|
840
|
+
open(`http://127.0.0.1:${port}/`);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
// ── 开发模式:有源码,启动 Vite Dev Server ──
|
|
845
|
+
if (!existsSync(join(dashboardDir, 'node_modules'))) {
|
|
846
|
+
const install = spawn('npm', ['install'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
847
|
+
await new Promise((resolve, reject) => {
|
|
848
|
+
install.on('close', (code) => code === 0 ? resolve(undefined) : reject(new Error(`npm install exited with ${code}`)));
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
const viteArgs = ['--host'];
|
|
852
|
+
if (opts.browser) {
|
|
853
|
+
viteArgs.push('--open');
|
|
854
|
+
}
|
|
855
|
+
const vite = spawn('npx', ['vite', ...viteArgs], {
|
|
856
|
+
cwd: dashboardDir,
|
|
857
|
+
stdio: 'inherit',
|
|
858
|
+
env: { ...process.env, VITE_API_URL: `http://127.0.0.1:${port}` },
|
|
859
|
+
});
|
|
860
|
+
vite.on('error', (err) => {
|
|
861
|
+
cli.error(`❌ Vite failed to start: ${err.message}`);
|
|
862
|
+
});
|
|
863
|
+
process.on('SIGINT', () => {
|
|
864
|
+
vite.kill();
|
|
865
|
+
process.exit(0);
|
|
866
|
+
});
|
|
867
|
+
}
|
|
822
868
|
}
|
|
823
869
|
catch (err) {
|
|
824
870
|
cli.error(`❌ API server failed to start: ${err.message}`);
|
|
@@ -827,48 +873,6 @@ program
|
|
|
827
873
|
}
|
|
828
874
|
process.exit(1);
|
|
829
875
|
}
|
|
830
|
-
if (opts.apiOnly) {
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
// 2. 启动 Dashboard UI
|
|
834
|
-
const dashboardDir = DASHBOARD_DIR;
|
|
835
|
-
const distDir = join(dashboardDir, 'dist');
|
|
836
|
-
const hasPrebuilt = existsSync(join(distDir, 'index.html'));
|
|
837
|
-
const hasSrc = existsSync(join(dashboardDir, 'src'));
|
|
838
|
-
if (hasPrebuilt && !hasSrc) {
|
|
839
|
-
// ── 生产模式:npm 安装的包,在 API 服务器上直接托管预构建产物 ──
|
|
840
|
-
// 同端口同 origin → /api 路由自然可达,无跨域问题
|
|
841
|
-
httpServer.mountDashboard(distDir);
|
|
842
|
-
if (opts.browser) {
|
|
843
|
-
const open = (await import('open')).default;
|
|
844
|
-
open(`http://127.0.0.1:${port}/`);
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
else {
|
|
848
|
-
// ── 开发模式:有源码,启动 Vite Dev Server ──
|
|
849
|
-
if (!existsSync(join(dashboardDir, 'node_modules'))) {
|
|
850
|
-
const install = spawn('npm', ['install'], { cwd: dashboardDir, stdio: 'inherit' });
|
|
851
|
-
await new Promise((resolve, reject) => {
|
|
852
|
-
install.on('close', (code) => code === 0 ? resolve(undefined) : reject(new Error(`npm install exited with ${code}`)));
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
const viteArgs = ['--host'];
|
|
856
|
-
if (opts.browser) {
|
|
857
|
-
viteArgs.push('--open');
|
|
858
|
-
}
|
|
859
|
-
const vite = spawn('npx', ['vite', ...viteArgs], {
|
|
860
|
-
cwd: dashboardDir,
|
|
861
|
-
stdio: 'inherit',
|
|
862
|
-
env: { ...process.env, VITE_API_URL: `http://127.0.0.1:${port}` },
|
|
863
|
-
});
|
|
864
|
-
vite.on('error', (err) => {
|
|
865
|
-
cli.error(`❌ Vite failed to start: ${err.message}`);
|
|
866
|
-
});
|
|
867
|
-
process.on('SIGINT', () => {
|
|
868
|
-
vite.kill();
|
|
869
|
-
process.exit(0);
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
876
|
});
|
|
873
877
|
// ─────────────────────────────────────────────────────
|
|
874
878
|
// status 命令
|
|
@@ -380,8 +380,21 @@ export class HttpServer {
|
|
|
380
380
|
*/
|
|
381
381
|
mountDashboard(distDir) {
|
|
382
382
|
// 从路由栈中移除最后的 404 catch-all 和根路径 handler
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
// Express 5 使用 app.router(Express 4 为 app._router)
|
|
384
|
+
const router = this.app.router ?? this.app._router;
|
|
385
|
+
if (!router) {
|
|
386
|
+
this.logger.warn('mountDashboard: Express router not available, mounting without route reordering');
|
|
387
|
+
this.app.use(express.static(distDir));
|
|
388
|
+
this.app.get('{*path}', (req, res, next) => {
|
|
389
|
+
if (req.path.startsWith('/api') || req.path.startsWith('/socket.io')) {
|
|
390
|
+
return next();
|
|
391
|
+
}
|
|
392
|
+
res.sendFile(join(distDir, 'index.html'));
|
|
393
|
+
});
|
|
394
|
+
this.logger.info('Dashboard mounted (production mode, fallback)', { distDir });
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const layers = router.stack;
|
|
385
398
|
// 倒序弹出最后 2 层(404 + root handler)
|
|
386
399
|
const removedLayers = [];
|
|
387
400
|
for (let i = layers.length - 1; i >= 0; i--) {
|