@lark-apaas/fullstack-cli 1.1.63-alpha.20260826185602 → 1.1.63-alpha.20260826190313
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/index.js +96 -13
- package/package.json +1 -1
- package/templates/scripts/build.sh +0 -12
- package/templates/scripts/dev-server.js +285 -0
package/dist/index.js
CHANGED
|
@@ -2514,6 +2514,17 @@ function buildDefaultRules(opts) {
|
|
|
2514
2514
|
command: "node scripts/hooks/run-precommit.js",
|
|
2515
2515
|
overwrite: false
|
|
2516
2516
|
},
|
|
2517
|
+
// 1d. Nest 开发态由平台 launcher 选择 SWC;已有声明保持用户版本/依赖分区。
|
|
2518
|
+
{
|
|
2519
|
+
type: "ensure-dev-dependency",
|
|
2520
|
+
name: "@swc/cli",
|
|
2521
|
+
version: "^0.5.2"
|
|
2522
|
+
},
|
|
2523
|
+
{
|
|
2524
|
+
type: "ensure-dev-dependency",
|
|
2525
|
+
name: "@swc/core",
|
|
2526
|
+
version: "^1.16.1"
|
|
2527
|
+
},
|
|
2517
2528
|
// 2. 智能合并 nest-cli.json 配置(保留用户自定义的 assets、plugins 等)
|
|
2518
2529
|
{
|
|
2519
2530
|
from: "templates/nest-cli.json",
|
|
@@ -2588,6 +2599,19 @@ function buildDefaultRules(opts) {
|
|
|
2588
2599
|
name: "lint",
|
|
2589
2600
|
to: "node ./scripts/lint.js",
|
|
2590
2601
|
ifStartsWith: "concurrently "
|
|
2602
|
+
},
|
|
2603
|
+
// 9a. 只迁移模板生成的精确默认值;用户追加参数或自定义命令保持不动。
|
|
2604
|
+
{
|
|
2605
|
+
type: "patch-script",
|
|
2606
|
+
name: "dev:server",
|
|
2607
|
+
to: "NODE_ENV=development node ./scripts/dev-server.js",
|
|
2608
|
+
ifEquals: "NODE_ENV=development nest start --watch"
|
|
2609
|
+
},
|
|
2610
|
+
{
|
|
2611
|
+
type: "patch-script",
|
|
2612
|
+
name: "dev:server",
|
|
2613
|
+
to: "NODE_ENV=development node ./scripts/dev-server.js",
|
|
2614
|
+
ifEquals: "nest start --watch"
|
|
2591
2615
|
}
|
|
2592
2616
|
];
|
|
2593
2617
|
if (!opts.disableGenOpenapi) {
|
|
@@ -2767,7 +2791,9 @@ async function run2(options) {
|
|
|
2767
2791
|
}
|
|
2768
2792
|
const stack = resolveStack(userProjectRoot);
|
|
2769
2793
|
try {
|
|
2770
|
-
console.log(
|
|
2794
|
+
console.log(
|
|
2795
|
+
`[fullstack-cli] Starting sync${stack ? ` (stack: ${stack})` : ""}...`
|
|
2796
|
+
);
|
|
2771
2797
|
const config = genSyncConfig(stack, {
|
|
2772
2798
|
disableGenOpenapi: options.disableGenOpenapi ?? false
|
|
2773
2799
|
});
|
|
@@ -2786,7 +2812,9 @@ async function run2(options) {
|
|
|
2786
2812
|
activateGitHooks(userProjectRoot);
|
|
2787
2813
|
} catch (error) {
|
|
2788
2814
|
const message = error instanceof Error ? error.message : String(error);
|
|
2789
|
-
console.warn(
|
|
2815
|
+
console.warn(
|
|
2816
|
+
`[fullstack-cli] \u26A0 Failed to activate git hooks: ${message}`
|
|
2817
|
+
);
|
|
2790
2818
|
}
|
|
2791
2819
|
}
|
|
2792
2820
|
console.log("[fullstack-cli] Sync completed successfully \u2705");
|
|
@@ -2806,7 +2834,9 @@ function resolveStack(userProjectRoot) {
|
|
|
2806
2834
|
return typeof meta.stack === "string" ? meta.stack : void 0;
|
|
2807
2835
|
} catch (error) {
|
|
2808
2836
|
const message = error instanceof Error ? error.message : String(error);
|
|
2809
|
-
console.warn(
|
|
2837
|
+
console.warn(
|
|
2838
|
+
`[fullstack-cli] \u26A0 Failed to read .spark/meta.json, fallback to default sync: ${message}`
|
|
2839
|
+
);
|
|
2810
2840
|
return void 0;
|
|
2811
2841
|
}
|
|
2812
2842
|
}
|
|
@@ -2827,12 +2857,22 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
2827
2857
|
}
|
|
2828
2858
|
if (rule.type === "add-script") {
|
|
2829
2859
|
const packageJsonPath = path5.join(userProjectRoot, "package.json");
|
|
2830
|
-
addScript(
|
|
2860
|
+
addScript(
|
|
2861
|
+
packageJsonPath,
|
|
2862
|
+
rule.name,
|
|
2863
|
+
rule.command,
|
|
2864
|
+
rule.overwrite ?? false
|
|
2865
|
+
);
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
if (rule.type === "ensure-dev-dependency") {
|
|
2869
|
+
const packageJsonPath = path5.join(userProjectRoot, "package.json");
|
|
2870
|
+
ensureDevDependency(packageJsonPath, rule.name, rule.version);
|
|
2831
2871
|
return;
|
|
2832
2872
|
}
|
|
2833
2873
|
if (rule.type === "patch-script") {
|
|
2834
2874
|
const packageJsonPath = path5.join(userProjectRoot, "package.json");
|
|
2835
|
-
patchScript(packageJsonPath, rule
|
|
2875
|
+
patchScript(packageJsonPath, rule);
|
|
2836
2876
|
return;
|
|
2837
2877
|
}
|
|
2838
2878
|
if (rule.type === "add-line") {
|
|
@@ -2860,7 +2900,12 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
2860
2900
|
syncDirectory(srcPath, destPath, rule.overwrite ?? true);
|
|
2861
2901
|
break;
|
|
2862
2902
|
case "file":
|
|
2863
|
-
syncFile(
|
|
2903
|
+
syncFile(
|
|
2904
|
+
srcPath,
|
|
2905
|
+
destPath,
|
|
2906
|
+
rule.overwrite ?? true,
|
|
2907
|
+
rule.onlyIfExists ?? false
|
|
2908
|
+
);
|
|
2864
2909
|
break;
|
|
2865
2910
|
case "append":
|
|
2866
2911
|
appendToFile(srcPath, destPath);
|
|
@@ -2869,7 +2914,9 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
|
|
|
2869
2914
|
}
|
|
2870
2915
|
function syncFile(src, dest, overwrite = true, onlyIfExists = false) {
|
|
2871
2916
|
if (onlyIfExists && !fs7.existsSync(dest)) {
|
|
2872
|
-
console.log(
|
|
2917
|
+
console.log(
|
|
2918
|
+
`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, target not exists)`
|
|
2919
|
+
);
|
|
2873
2920
|
return;
|
|
2874
2921
|
}
|
|
2875
2922
|
const destDir = path5.dirname(dest);
|
|
@@ -2877,7 +2924,9 @@ function syncFile(src, dest, overwrite = true, onlyIfExists = false) {
|
|
|
2877
2924
|
fs7.mkdirSync(destDir, { recursive: true });
|
|
2878
2925
|
}
|
|
2879
2926
|
if (fs7.existsSync(dest) && !overwrite) {
|
|
2880
|
-
console.log(
|
|
2927
|
+
console.log(
|
|
2928
|
+
`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, already exists)`
|
|
2929
|
+
);
|
|
2881
2930
|
return;
|
|
2882
2931
|
}
|
|
2883
2932
|
fs7.copyFileSync(src, dest);
|
|
@@ -2904,7 +2953,9 @@ function syncDirectory(src, dest, overwrite = true) {
|
|
|
2904
2953
|
}
|
|
2905
2954
|
});
|
|
2906
2955
|
if (count > 0) {
|
|
2907
|
-
console.log(
|
|
2956
|
+
console.log(
|
|
2957
|
+
`[fullstack-cli] Synced ${count} files to ${path5.basename(dest)}/`
|
|
2958
|
+
);
|
|
2908
2959
|
}
|
|
2909
2960
|
}
|
|
2910
2961
|
function appendToFile(src, dest) {
|
|
@@ -2914,7 +2965,9 @@ function appendToFile(src, dest) {
|
|
|
2914
2965
|
existingContent = fs7.readFileSync(dest, "utf-8");
|
|
2915
2966
|
}
|
|
2916
2967
|
if (existingContent.includes(content.trim())) {
|
|
2917
|
-
console.log(
|
|
2968
|
+
console.log(
|
|
2969
|
+
`[fullstack-cli] \u25CB ${path5.basename(dest)} (already contains content)`
|
|
2970
|
+
);
|
|
2918
2971
|
return;
|
|
2919
2972
|
}
|
|
2920
2973
|
fs7.appendFileSync(dest, content);
|
|
@@ -2972,7 +3025,34 @@ function addScript(packageJsonPath, name, command, overwrite) {
|
|
|
2972
3025
|
fs7.writeFileSync(packageJsonPath, JSON.stringify(pkg2, null, 2) + "\n");
|
|
2973
3026
|
console.log(`[fullstack-cli] \u2713 scripts.${name}`);
|
|
2974
3027
|
}
|
|
2975
|
-
function
|
|
3028
|
+
function ensureDevDependency(packageJsonPath, name, version) {
|
|
3029
|
+
if (!fs7.existsSync(packageJsonPath)) {
|
|
3030
|
+
console.log("[fullstack-cli] \u25CB package.json (not found)");
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
try {
|
|
3034
|
+
const content = fs7.readFileSync(packageJsonPath, "utf-8");
|
|
3035
|
+
const pkg2 = JSON.parse(content);
|
|
3036
|
+
const existingVersion = pkg2.dependencies?.[name] ?? pkg2.devDependencies?.[name];
|
|
3037
|
+
if (existingVersion !== void 0) {
|
|
3038
|
+
console.log(
|
|
3039
|
+
`[fullstack-cli] \u25CB ${name} (already declared as ${existingVersion})`
|
|
3040
|
+
);
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
pkg2.devDependencies ?? (pkg2.devDependencies = {});
|
|
3044
|
+
pkg2.devDependencies[name] = version;
|
|
3045
|
+
fs7.writeFileSync(packageJsonPath, JSON.stringify(pkg2, null, 2) + "\n");
|
|
3046
|
+
console.log(`[fullstack-cli] \u2713 devDependencies.${name} = ${version}`);
|
|
3047
|
+
} catch (error) {
|
|
3048
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3049
|
+
console.warn(
|
|
3050
|
+
`[fullstack-cli] \u26A0 Could not ensure dependency ${name}: ${message}`
|
|
3051
|
+
);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
function patchScript(packageJsonPath, rule) {
|
|
3055
|
+
const { name, to } = rule;
|
|
2976
3056
|
if (!fs7.existsSync(packageJsonPath)) {
|
|
2977
3057
|
console.log(`[fullstack-cli] \u25CB package.json (not found)`);
|
|
2978
3058
|
return;
|
|
@@ -2989,7 +3069,8 @@ function patchScript(packageJsonPath, name, to, ifStartsWith) {
|
|
|
2989
3069
|
console.log(`[fullstack-cli] \u25CB scripts.${name} (already patched)`);
|
|
2990
3070
|
return;
|
|
2991
3071
|
}
|
|
2992
|
-
|
|
3072
|
+
const matches = rule.ifEquals !== void 0 ? current === rule.ifEquals : current.startsWith(rule.ifStartsWith);
|
|
3073
|
+
if (!matches) {
|
|
2993
3074
|
console.warn(
|
|
2994
3075
|
`[fullstack-cli] \u26A0 Skipped patching scripts.${name} because it has been customized`
|
|
2995
3076
|
);
|
|
@@ -3000,7 +3081,9 @@ function patchScript(packageJsonPath, name, to, ifStartsWith) {
|
|
|
3000
3081
|
console.log(`[fullstack-cli] \u2713 Patched scripts.${name}`);
|
|
3001
3082
|
} catch (error) {
|
|
3002
3083
|
const message = error instanceof Error ? error.message : String(error);
|
|
3003
|
-
console.warn(
|
|
3084
|
+
console.warn(
|
|
3085
|
+
`[fullstack-cli] \u26A0 Could not patch scripts.${name}: ${message}`
|
|
3086
|
+
);
|
|
3004
3087
|
}
|
|
3005
3088
|
}
|
|
3006
3089
|
function addLineToFile(filePath, line) {
|
package/package.json
CHANGED
|
@@ -154,18 +154,6 @@ if [ -d "$DIST_DIR/client" ]; then
|
|
|
154
154
|
find "$DIST_DIR/client" -maxdepth 1 -name "*.html" -exec mv {} "$DIST_DIR/dist/client/" \;
|
|
155
155
|
fi
|
|
156
156
|
|
|
157
|
-
# 拷贝 shared/static → dist/shared/static
|
|
158
|
-
# Nest server 生产从 process.cwd() + shared/static 读 (nestjs-core static.controller.ts:100),
|
|
159
|
-
# 生产 cwd = dist/, 所以目标是 dist/shared/static。coding-preset 的 static-assets plugin
|
|
160
|
-
# 之前 closeBundle 拷贝, 现在删除后交给 build.sh 显式做 (跟 jsPage 的 output_static rsync 对齐)。
|
|
161
|
-
# 排除 .ts/.tsx/.js/.jsx: 避免 shared/static/ 里若有开发脚本被误传到生产。
|
|
162
|
-
if [ -d "$ROOT_DIR/shared/static" ]; then
|
|
163
|
-
mkdir -p "$DIST_DIR/shared/static"
|
|
164
|
-
rsync -a --exclude='*.ts' --exclude='*.tsx' --exclude='*.js' --exclude='*.jsx' \
|
|
165
|
-
"$ROOT_DIR/shared/static/" "$DIST_DIR/shared/static/"
|
|
166
|
-
echo " Static → dist/shared/static/"
|
|
167
|
-
fi
|
|
168
|
-
|
|
169
157
|
# server 相关产物准备(only_frontend_change=true 时跳过)
|
|
170
158
|
if [[ "${only_frontend_change:-false}" == "true" ]]; then
|
|
171
159
|
echo " [skip] 跳过 run.sh/.env 复制 (only_frontend_change=true)"
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('node:fs');
|
|
4
|
+
const path = require('node:path');
|
|
5
|
+
const { spawn } = require('node:child_process');
|
|
6
|
+
|
|
7
|
+
const FORWARDED_SIGNALS = ['SIGINT', 'SIGTERM'];
|
|
8
|
+
|
|
9
|
+
function resolveBuilder(projectRoot) {
|
|
10
|
+
const configPath = path.join(projectRoot, 'nest-cli.json');
|
|
11
|
+
if (!fs.existsSync(configPath)) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
16
|
+
const builder = config?.compilerOptions?.builder;
|
|
17
|
+
if (typeof builder === 'string') {
|
|
18
|
+
return builder;
|
|
19
|
+
}
|
|
20
|
+
if (
|
|
21
|
+
builder &&
|
|
22
|
+
typeof builder === 'object' &&
|
|
23
|
+
typeof builder.type === 'string'
|
|
24
|
+
) {
|
|
25
|
+
return builder.type;
|
|
26
|
+
}
|
|
27
|
+
return builder === undefined ? undefined : 'custom';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function findMissingSwcDependency(projectRoot) {
|
|
31
|
+
for (const dependency of ['@swc/cli', '@swc/core']) {
|
|
32
|
+
try {
|
|
33
|
+
require.resolve(`${dependency}/package.json`, { paths: [projectRoot] });
|
|
34
|
+
} catch {
|
|
35
|
+
return dependency;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolveNestEntrypoint(projectRoot) {
|
|
42
|
+
return require.resolve('@nestjs/cli/bin/nest.js', { paths: [projectRoot] });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function resolveInsideProject(projectRoot, configuredPath) {
|
|
46
|
+
const resolvedPath = path.resolve(projectRoot, configuredPath);
|
|
47
|
+
const relativePath = path.relative(projectRoot, resolvedPath);
|
|
48
|
+
if (
|
|
49
|
+
relativePath === '..' ||
|
|
50
|
+
relativePath.startsWith(`..${path.sep}`) ||
|
|
51
|
+
path.isAbsolute(relativePath)
|
|
52
|
+
) {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
return resolvedPath;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readJsonStringProperty(filePath, propertyName, fallback) {
|
|
59
|
+
if (!fs.existsSync(filePath)) {
|
|
60
|
+
return fallback;
|
|
61
|
+
}
|
|
62
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
63
|
+
const match = content.match(
|
|
64
|
+
new RegExp(`"${propertyName}"\\s*:\\s*"([^"\\r\\n]+)"`)
|
|
65
|
+
);
|
|
66
|
+
return match?.[1] ?? fallback;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function cleanStaleSwcOutputs(projectRoot) {
|
|
70
|
+
const nestConfigPath = path.join(projectRoot, 'nest-cli.json');
|
|
71
|
+
const nestConfig = JSON.parse(fs.readFileSync(nestConfigPath, 'utf8'));
|
|
72
|
+
const sourceRootName =
|
|
73
|
+
typeof nestConfig.sourceRoot === 'string' ? nestConfig.sourceRoot : 'src';
|
|
74
|
+
const tsConfigName =
|
|
75
|
+
typeof nestConfig.compilerOptions?.tsConfigPath === 'string'
|
|
76
|
+
? nestConfig.compilerOptions.tsConfigPath
|
|
77
|
+
: 'tsconfig.json';
|
|
78
|
+
const tsConfigPath = resolveInsideProject(projectRoot, tsConfigName);
|
|
79
|
+
const sourceRoot = resolveInsideProject(projectRoot, sourceRootName);
|
|
80
|
+
if (!tsConfigPath || !sourceRoot || !fs.existsSync(sourceRoot)) {
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const outDirName = readJsonStringProperty(tsConfigPath, 'outDir', 'dist');
|
|
85
|
+
const rootDirName = readJsonStringProperty(
|
|
86
|
+
tsConfigPath,
|
|
87
|
+
'rootDir',
|
|
88
|
+
sourceRootName
|
|
89
|
+
);
|
|
90
|
+
const outDir = resolveInsideProject(projectRoot, outDirName);
|
|
91
|
+
const rootDir = resolveInsideProject(projectRoot, rootDirName);
|
|
92
|
+
if (!outDir) {
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
const emitRoots = [sourceRoot];
|
|
96
|
+
if (rootDir && rootDir !== sourceRoot) {
|
|
97
|
+
emitRoots.push(rootDir);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let removed = 0;
|
|
101
|
+
const pendingDirectories = [sourceRoot];
|
|
102
|
+
while (pendingDirectories.length > 0) {
|
|
103
|
+
const currentDirectory = pendingDirectories.pop();
|
|
104
|
+
for (const entry of fs.readdirSync(currentDirectory, {
|
|
105
|
+
withFileTypes: true,
|
|
106
|
+
})) {
|
|
107
|
+
const sourcePath = path.join(currentDirectory, entry.name);
|
|
108
|
+
if (entry.isDirectory()) {
|
|
109
|
+
pendingDirectories.push(sourcePath);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (!entry.isFile() || entry.name.endsWith('.d.ts')) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const sourceExtension = ['.tsx', '.mts', '.cts', '.ts'].find(extension =>
|
|
117
|
+
entry.name.endsWith(extension)
|
|
118
|
+
);
|
|
119
|
+
if (!sourceExtension) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const outputExtension =
|
|
123
|
+
sourceExtension === '.mts'
|
|
124
|
+
? '.mjs'
|
|
125
|
+
: sourceExtension === '.cts'
|
|
126
|
+
? '.cjs'
|
|
127
|
+
: '.js';
|
|
128
|
+
const declarationExtension =
|
|
129
|
+
sourceExtension === '.mts'
|
|
130
|
+
? '.d.mts'
|
|
131
|
+
: sourceExtension === '.cts'
|
|
132
|
+
? '.d.cts'
|
|
133
|
+
: '.d.ts';
|
|
134
|
+
const sourceBasePath = sourcePath.slice(0, -sourceExtension.length);
|
|
135
|
+
for (const suffix of [
|
|
136
|
+
outputExtension,
|
|
137
|
+
`${outputExtension}.map`,
|
|
138
|
+
declarationExtension,
|
|
139
|
+
`${declarationExtension}.map`,
|
|
140
|
+
]) {
|
|
141
|
+
const generatedSourceSibling = `${sourceBasePath}${suffix}`;
|
|
142
|
+
if (fs.existsSync(generatedSourceSibling)) {
|
|
143
|
+
fs.rmSync(generatedSourceSibling, { force: true });
|
|
144
|
+
removed += 1;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
for (const emitRoot of emitRoots) {
|
|
149
|
+
const relativeSourcePath = path.relative(emitRoot, sourcePath);
|
|
150
|
+
if (
|
|
151
|
+
relativeSourcePath === '..' ||
|
|
152
|
+
relativeSourcePath.startsWith(`..${path.sep}`) ||
|
|
153
|
+
path.isAbsolute(relativeSourcePath)
|
|
154
|
+
) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const outputBasePath = path.join(
|
|
159
|
+
outDir,
|
|
160
|
+
relativeSourcePath.slice(0, -sourceExtension.length)
|
|
161
|
+
);
|
|
162
|
+
for (const suffix of [
|
|
163
|
+
outputExtension,
|
|
164
|
+
`${outputExtension}.map`,
|
|
165
|
+
declarationExtension,
|
|
166
|
+
`${declarationExtension}.map`,
|
|
167
|
+
]) {
|
|
168
|
+
const outputPath = `${outputBasePath}${suffix}`;
|
|
169
|
+
if (fs.existsSync(outputPath)) {
|
|
170
|
+
fs.rmSync(outputPath, { force: true });
|
|
171
|
+
removed += 1;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return removed;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function startNest(projectRoot, nestArgs) {
|
|
181
|
+
const child = spawn(
|
|
182
|
+
process.execPath,
|
|
183
|
+
[resolveNestEntrypoint(projectRoot), ...nestArgs],
|
|
184
|
+
{
|
|
185
|
+
cwd: projectRoot,
|
|
186
|
+
env: process.env,
|
|
187
|
+
stdio: 'inherit',
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const signalHandlers = new Map();
|
|
192
|
+
for (const signal of FORWARDED_SIGNALS) {
|
|
193
|
+
const handler = () => child.kill(signal);
|
|
194
|
+
signalHandlers.set(signal, handler);
|
|
195
|
+
process.once(signal, handler);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function removeSignalHandlers() {
|
|
199
|
+
for (const [signal, handler] of signalHandlers) {
|
|
200
|
+
process.removeListener(signal, handler);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
child.once('error', error => {
|
|
205
|
+
removeSignalHandlers();
|
|
206
|
+
console.error(
|
|
207
|
+
`[miaoda:nest-compiler] failed to start Nest CLI: ${error.message}`
|
|
208
|
+
);
|
|
209
|
+
process.exitCode = 1;
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
child.once('exit', (code, signal) => {
|
|
213
|
+
removeSignalHandlers();
|
|
214
|
+
if (signal) {
|
|
215
|
+
process.kill(process.pid, signal);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
process.exitCode = code ?? 1;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function main() {
|
|
223
|
+
const projectRoot = process.cwd();
|
|
224
|
+
const forwardedArgs = process.argv.slice(2);
|
|
225
|
+
let explicitBuilder;
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
explicitBuilder = resolveBuilder(projectRoot);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error(
|
|
231
|
+
`[miaoda:nest-compiler] MIAODA_NEST_SWC_FALLBACK reason=invalid_nest_cli_config message=${JSON.stringify(error.message)}`
|
|
232
|
+
);
|
|
233
|
+
console.log('[miaoda:nest-compiler] MIAODA_NEST_COMPILER=tsc');
|
|
234
|
+
startNest(projectRoot, ['start', '--watch', ...forwardedArgs]);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (explicitBuilder && explicitBuilder !== 'swc') {
|
|
239
|
+
console.log(
|
|
240
|
+
`[miaoda:nest-compiler] MIAODA_NEST_COMPILER=${explicitBuilder}`
|
|
241
|
+
);
|
|
242
|
+
startNest(projectRoot, ['start', '--watch', ...forwardedArgs]);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const missingDependency = findMissingSwcDependency(projectRoot);
|
|
247
|
+
if (missingDependency) {
|
|
248
|
+
console.error(
|
|
249
|
+
`[miaoda:nest-compiler] MIAODA_NEST_SWC_FALLBACK reason=missing_dependency dependency=${missingDependency}`
|
|
250
|
+
);
|
|
251
|
+
console.log('[miaoda:nest-compiler] MIAODA_NEST_COMPILER=tsc');
|
|
252
|
+
startNest(projectRoot, ['start', '--watch', ...forwardedArgs]);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
try {
|
|
257
|
+
const removed = cleanStaleSwcOutputs(projectRoot);
|
|
258
|
+
console.log(
|
|
259
|
+
`[miaoda:nest-compiler] MIAODA_NEST_SWC_CLEANUP removed=${removed}`
|
|
260
|
+
);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
console.error(
|
|
263
|
+
`[miaoda:nest-compiler] MIAODA_NEST_SWC_CLEANUP_FAILED message=${JSON.stringify(error.message)}`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
console.log('[miaoda:nest-compiler] MIAODA_NEST_COMPILER=swc');
|
|
267
|
+
startNest(projectRoot, [
|
|
268
|
+
'start',
|
|
269
|
+
'--watch',
|
|
270
|
+
'--builder',
|
|
271
|
+
'swc',
|
|
272
|
+
'--type-check',
|
|
273
|
+
...forwardedArgs,
|
|
274
|
+
]);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (require.main === module) {
|
|
278
|
+
main();
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = {
|
|
282
|
+
cleanStaleSwcOutputs,
|
|
283
|
+
findMissingSwcDependency,
|
|
284
|
+
resolveBuilder,
|
|
285
|
+
};
|