@lark-apaas/coding-template-nestjs-react-fullstack 0.1.42-alpha.20260917135900 → 0.1.42

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.
@@ -20,16 +20,15 @@
20
20
  "start": "NODE_ENV=production node main.js",
21
21
  "eslint": "eslint . --quiet",
22
22
  "stylelint": "stylelint client/src/**/*.css --quiet",
23
- "type:check": "concurrently -n \"server,client,mcp-ui\" -c \"blue,green,magenta\" \"npm run type:check:server\" \"npm run type:check:client\" \"npm run type:check:mcp-ui\"",
23
+ "type:check": "concurrently -n \"server,client\" -c \"blue,green\" \"npm run type:check:server\" \"npm run type:check:client\"",
24
24
  "type:check:client": "tsc --noEmit --project tsconfig.app.json",
25
25
  "type:check:server": "tsc --noEmit --project tsconfig.node.json",
26
26
  "lint": "node ./scripts/lint.js",
27
27
  "precommit": "node scripts/hooks/run-precommit.js",
28
- "upgrade": "npx -y @lark-apaas/fullstack-cli sync --disable-gen-openapi",
29
- "type:check:mcp-ui": "node ./scripts/typecheck-mcp-ui.js"
28
+ "upgrade": "npx -y @lark-apaas/fullstack-cli sync --disable-gen-openapi"
30
29
  },
31
30
  "dependencies": {
32
- "@lark-apaas/fullstack-nestjs-core": "1.1.62-alpha.20260917134431",
31
+ "@lark-apaas/fullstack-nestjs-core": "^1.1.62",
33
32
  "@nestjs/axios": "^4.0.1",
34
33
  "@nestjs/cache-manager": "^3.1.3",
35
34
  "@nestjs/common": "^10.4.20",
@@ -53,9 +52,9 @@
53
52
  },
54
53
  "devDependencies": {
55
54
  "@hookform/resolvers": "^5.2.2",
56
- "@lark-apaas/client-toolkit": "^1.2.70",
57
- "@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260917134427",
58
- "@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917134434",
55
+ "@lark-apaas/client-toolkit": "^1.2.71",
56
+ "@lark-apaas/coding-preset-vite-react": "^1.0.23",
57
+ "@lark-apaas/fullstack-presets": "^1.1.0",
59
58
  "@nestjs/cli": "^10.4.9",
60
59
  "@radix-ui/react-accordion": "^1.2.12",
61
60
  "@radix-ui/react-alert-dialog": "^1.1.15",
@@ -43,43 +43,37 @@ echo ""
43
43
  echo "🔨 [3/5] 并行构建 server 和 client"
44
44
  STEP_START=$(node -e "console.log(Date.now())")
45
45
 
46
- # server/mcp(含 UI/Skill)变更必须由平台判定为全构建。
47
- if [[ "${only_frontend_change:-false}" == "true" ]]; then
48
- echo " ├─ 仅构建 client (only_frontend_change=true)"
49
- npm run build:client > /tmp/build-client.log 2>&1
50
- else
51
- # 并行构建
52
- echo " ├─ 启动 server 构建..."
53
- npm run build:server > /tmp/build-server.log 2>&1 &
54
- SERVER_PID=$!
55
-
56
- echo " ├─ 启动 client 构建..."
57
- npm run build:client > /tmp/build-client.log 2>&1 &
58
- CLIENT_PID=$!
59
-
60
- # 等待两个构建完成
61
- SERVER_EXIT=0
62
- CLIENT_EXIT=0
63
-
64
- wait $SERVER_PID || SERVER_EXIT=$?
65
- wait $CLIENT_PID || CLIENT_EXIT=$?
66
-
67
- # 检查构建结果
68
- if [ $SERVER_EXIT -ne 0 ]; then
69
- echo " ❌ Server 构建失败"
70
- cat /tmp/build-server.log
71
- exit 1
72
- fi
73
-
74
- if [ $CLIENT_EXIT -ne 0 ]; then
75
- echo " ❌ Client 构建失败"
76
- cat /tmp/build-client.log
77
- exit 1
78
- fi
79
-
80
- echo " ✅ Server 构建完成"
81
- echo " ✅ Client 构建完成"
46
+ # 并行构建
47
+ echo " ├─ 启动 server 构建..."
48
+ npm run build:server > /tmp/build-server.log 2>&1 &
49
+ SERVER_PID=$!
50
+
51
+ echo " ├─ 启动 client 构建..."
52
+ npm run build:client > /tmp/build-client.log 2>&1 &
53
+ CLIENT_PID=$!
54
+
55
+ # 等待两个构建完成
56
+ SERVER_EXIT=0
57
+ CLIENT_EXIT=0
58
+
59
+ wait $SERVER_PID || SERVER_EXIT=$?
60
+ wait $CLIENT_PID || CLIENT_EXIT=$?
61
+
62
+ # 检查构建结果
63
+ if [ $SERVER_EXIT -ne 0 ]; then
64
+ echo " ❌ Server 构建失败"
65
+ cat /tmp/build-server.log
66
+ exit 1
82
67
  fi
68
+
69
+ if [ $CLIENT_EXIT -ne 0 ]; then
70
+ echo " ❌ Client 构建失败"
71
+ cat /tmp/build-client.log
72
+ exit 1
73
+ fi
74
+
75
+ echo " ✅ Server 构建完成"
76
+ echo " ✅ Client 构建完成"
83
77
  print_time $STEP_START
84
78
  echo ""
85
79
 
@@ -87,21 +81,18 @@ echo ""
87
81
  echo "📦 [4/5] 准备 server 依赖产物"
88
82
  STEP_START=$(node -e "console.log(Date.now())")
89
83
 
90
- if [[ "${only_frontend_change:-false}" != "true" ]]; then
91
- mkdir -p "$OUT_DIR/dist/client"
84
+ mkdir -p "$OUT_DIR/dist/client"
92
85
 
93
- # public 先进(server setBaseViewsDir + nestjs-core 中间件同源 serve)
94
- if [ -d "$ROOT_DIR/client/public" ]; then
95
- cp -R "$ROOT_DIR/client/public/." "$OUT_DIR/dist/client/"
96
- fi
97
-
98
- # 构建产物 HTML 随后拷,覆盖 public 里的同名文件(保证入口页是构建版,不被 public 静默覆盖)
99
- cp "$ROOT_DIR/dist/client/"*.html "$OUT_DIR/dist/client/" || true
86
+ # public 先进(server setBaseViewsDir + nestjs-core 中间件同源 serve)
87
+ if [ -d "$ROOT_DIR/client/public" ]; then
88
+ cp -R "$ROOT_DIR/client/public/." "$OUT_DIR/dist/client/"
89
+ fi
100
90
 
101
- # 拷贝 run.sh 文件
102
- cp "$ROOT_DIR/scripts/run.sh" "$OUT_DIR/"
91
+ # 构建产物 HTML 随后拷,覆盖 public 里的同名文件(保证入口页是构建版,不被 public 静默覆盖)
92
+ cp "$ROOT_DIR/dist/client/"*.html "$OUT_DIR/dist/client/" || true
103
93
 
104
- fi
94
+ # 拷贝 run.sh 文件
95
+ cp "$ROOT_DIR/scripts/run.sh" "$OUT_DIR/"
105
96
 
106
97
  # 清理无用文件
107
98
  rm -rf "$ROOT_DIR/dist/scripts"
@@ -115,9 +106,7 @@ echo "✂️ [5/5] 智能依赖裁剪"
115
106
  STEP_START=$(node -e "console.log(Date.now())")
116
107
 
117
108
  # 分析实际依赖、复制并裁剪 node_modules、生成精简的 package.json
118
- if [[ "${only_frontend_change:-false}" != "true" ]]; then
119
- node "$ROOT_DIR/scripts/prune-smart.js"
120
- fi
109
+ node "$ROOT_DIR/scripts/prune-smart.js"
121
110
 
122
111
  print_time $STEP_START
123
112
  echo ""
@@ -127,37 +116,10 @@ echo "构建完成"
127
116
  print_time $TOTAL_START
128
117
 
129
118
  # 输出产物信息
130
- DIST_SIZE=$(du -sh "$ROOT_DIR/dist" | cut -f1)
119
+ DIST_SIZE=$(du -sh "$OUT_DIR" | cut -f1)
120
+ NODE_MODULES_SIZE=$(du -sh "$OUT_DIR/node_modules" | cut -f1)
131
121
  echo ""
132
122
  echo "📊 构建产物统计:"
133
123
  echo " 总大小: $DIST_SIZE"
134
- if [[ "${only_frontend_change:-false}" != "true" ]]; then
135
- NODE_MODULES_SIZE=$(du -sh "$OUT_DIR/node_modules" | cut -f1)
136
- echo " node_modules: $NODE_MODULES_SIZE"
137
- fi
124
+ echo " node_modules: $NODE_MODULES_SIZE"
138
125
  echo ""
139
-
140
- # 仅成功的全构建生成 backendBuildID;必须在构建、产物准备和依赖裁剪之后。
141
- # UI/Skill 内容由 SDK 独立计入总 hash;纯前端发布不替换已部署的 backendBuildID。
142
- if [[ "${only_frontend_change:-false}" != "true" ]]; then
143
- node - "$ROOT_DIR/dist" <<'NODE'
144
- const fs = require('node:fs');
145
- const path = require('node:path');
146
- const { randomUUID } = require('node:crypto');
147
- const dist = process.argv[2];
148
- // 防止 build:server 空跑成功、却没有可交付的服务端入口。
149
- if (!fs.statSync(path.join(dist, 'server/main.js')).isFile()) {
150
- throw new Error('Missing server build output: dist/server/main.js');
151
- }
152
- // runtime cwd 分别为工程根、dist/(或整包解压到 dist-server/)、旧版 dist/server/。
153
- // 与 MCP UI/Skill 的交付布局一致:复制产物时保留同一个 UUID,不在启动时生成。
154
- const files = [
155
- path.join(dist, 'mcp-build-id'),
156
- path.join(dist, 'dist/mcp-build-id'),
157
- path.join(dist, 'server/dist/mcp-build-id'),
158
- ];
159
- for (const file of files) fs.mkdirSync(path.dirname(file), { recursive: true });
160
- const buildID = randomUUID();
161
- for (const file of files) fs.writeFileSync(file, buildID, 'utf8');
162
- NODE
163
- fi
@@ -1,26 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const path = require('node:path');
4
- const fs = require('node:fs');
5
4
  const { spawn } = require('node:child_process');
5
+ const fs = require('node:fs');
6
6
 
7
7
  const cwd = process.cwd();
8
8
 
9
+ function getBinName(name) {
10
+ return process.platform === 'win32' ? `${name}.cmd` : name;
11
+ }
12
+
13
+ function runCommand(command, args) {
14
+ return new Promise((resolve) => {
15
+ const child = spawn(command, args, {
16
+ cwd,
17
+ stdio: 'inherit',
18
+ shell: false,
19
+ });
20
+
21
+ child.on('close', (code) => resolve(code || 0));
22
+ child.on('error', () => resolve(1));
23
+ });
24
+ }
25
+
9
26
  function normalizeProjectFile(filePath) {
10
27
  const absolutePath = path.isAbsolute(filePath)
11
28
  ? filePath
12
29
  : path.resolve(cwd, filePath);
13
30
 
14
31
  if (!fs.existsSync(absolutePath)) {
15
- console.log(`[lint] Deleted file: ${filePath}; checking affected projects`);
32
+ console.warn(`[lint] Skip missing file: ${filePath}`);
33
+ return null;
16
34
  }
17
35
 
18
36
  const relativePath = path.relative(cwd, absolutePath);
19
- if (
20
- relativePath === '..' ||
21
- relativePath.startsWith(`..${path.sep}`) ||
22
- path.isAbsolute(relativePath)
23
- ) {
37
+ if (relativePath.startsWith('..')) {
24
38
  console.warn(`[lint] Skip file outside project: ${filePath}`);
25
39
  return null;
26
40
  }
@@ -77,144 +91,25 @@ function canRunStylelint() {
77
91
 
78
92
  if (!pkg.scripts || !pkg.scripts.stylelint) return false;
79
93
 
80
- return STYLELINT_CONFIG_FILES.some(file =>
81
- fs.existsSync(path.join(cwd, file))
82
- );
83
- }
84
-
85
- function getBinName(name) {
86
- return process.platform === 'win32' ? `${name}.cmd` : name;
87
- }
88
-
89
- function runCommand(command, args) {
90
- return new Promise(resolve => {
91
- const child = spawn(command, args, {
92
- cwd,
93
- stdio: 'inherit',
94
- shell: false,
95
- });
96
-
97
- child.on('close', code => resolve(code ?? 1));
98
- child.on('error', () => resolve(1));
99
- });
100
- }
101
-
102
- // 串行依次执行每个任务,全部跑完后再聚合退出码:
103
- // 降低并发资源占用、让各任务输出按顺序清晰可读,同时保留“一次暴露所有 lint 问题”的行为。
104
- async function runTasksSerially(taskSpecs) {
105
- let exitCode = 0;
106
- for (const [command, args] of taskSpecs) {
107
- const code = await runCommand(command, args);
108
- if (code !== 0) {
109
- exitCode = 1;
110
- }
111
- }
112
- return exitCode;
113
- }
114
-
115
- const UI_DIR = 'server/mcp/ui';
116
-
117
- function uiSourceFiles() {
118
- const files = [];
119
- function visit(relative) {
120
- const absolute = path.join(cwd, relative);
121
- if (!fs.existsSync(absolute)) return;
122
- if (fs.lstatSync(absolute).isSymbolicLink()) {
123
- throw new Error(`MCP UI 检查不支持符号链接: ${relative}`);
124
- }
125
- for (const entry of fs.readdirSync(absolute, { withFileTypes: true })) {
126
- if (['node_modules', 'dist', '.git'].includes(entry.name)) continue;
127
- const file = `${relative}/${entry.name}`;
128
- if (entry.isSymbolicLink())
129
- throw new Error(`MCP UI 检查不支持符号链接: ${file}`);
130
- if (entry.isDirectory()) visit(file);
131
- else if (isEslintTarget(file) && !/\.d\.(?:ts|mts|cts)$/.test(file))
132
- files.push(file);
133
- }
134
- }
135
- visit(UI_DIR);
136
- return files.sort();
137
- }
138
-
139
- function uiTasks({ types = true, eslint = true } = {}) {
140
- const sources = uiSourceFiles();
141
- if (!sources.length) return [];
142
- const tasks = [];
143
- if (types) tasks.push([getBinName('npm'), ['run', 'type:check:mcp-ui']]);
144
- if (eslint) {
145
- const config = [
146
- 'eslint.mcp-ui.config.js',
147
- 'eslint.mcp-ui.config.cjs',
148
- 'eslint.mcp-ui.config.mjs',
149
- ].find(file => fs.existsSync(path.join(cwd, file)));
150
- let resolvedConfig = config;
151
- if (!resolvedConfig) {
152
- try {
153
- resolvedConfig =
154
- require.resolve('@lark-apaas/fullstack-presets/lib/mcp/eslint-ui.js');
155
- } catch {
156
- throw new Error(
157
- '请升级 @lark-apaas/fullstack-presets 以使用 MCP UI 默认 ESLint 配置,或提供 eslint.mcp-ui.config.cjs'
158
- );
159
- }
160
- }
161
- tasks.push([
162
- getBinName('npx'),
163
- [
164
- '--no-install',
165
- 'eslint',
166
- '--config',
167
- resolvedConfig,
168
- '--quiet',
169
- '--max-warnings',
170
- '0',
171
- ...sources,
172
- ],
173
- ]);
174
- }
175
- return tasks;
176
- }
177
-
178
- function packageScripts() {
179
- return (
180
- JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'))
181
- .scripts || {}
182
- );
183
- }
184
-
185
- function isUiFile(file) {
186
- return file.startsWith('server/mcp/ui/');
94
+ return STYLELINT_CONFIG_FILES.some(file => fs.existsSync(path.join(cwd, file)));
187
95
  }
188
96
 
189
97
  async function runDefaultLint() {
190
- const taskSpecs = [
191
- [getBinName('npm'), ['run', 'eslint']],
192
- [getBinName('npm'), ['run', 'type:check']],
193
- ];
194
-
195
- // 保留用户的 type:check;未聚合 UI 时由 lint 补查。
196
- taskSpecs.push(
197
- ...uiTasks({
198
- types: !/\bnpm\s+run\s+type:check:mcp-ui(?=[\s"';&|)]|$)/.test(
199
- packageScripts()['type:check'] || ''
200
- ),
201
- })
202
- );
98
+ const commands = ['npm run eslint', 'npm run type:check'];
203
99
 
204
100
  if (canRunStylelint()) {
205
- taskSpecs.push([getBinName('npm'), ['run', 'stylelint']]);
101
+ commands.push('npm run stylelint');
206
102
  } else {
207
- console.warn(
208
- '[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
209
- );
103
+ console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
210
104
  }
211
105
 
212
- process.exit(await runTasksSerially(taskSpecs));
106
+ const code = await runCommand(getBinName('npx'), ['concurrently', ...commands]);
107
+ process.exit(code);
213
108
  }
214
109
 
215
110
  async function runSelectiveLint(inputFiles) {
216
111
  const normalizedFiles = Array.from(
217
- new Set(inputFiles.map(normalizeProjectFile).filter(Boolean))
112
+ new Set(inputFiles.map(normalizeProjectFile).filter(Boolean)),
218
113
  );
219
114
 
220
115
  if (normalizedFiles.length === 0) {
@@ -222,41 +117,15 @@ async function runSelectiveLint(inputFiles) {
222
117
  process.exit(0);
223
118
  }
224
119
 
225
- const eslintFiles = normalizedFiles.filter(
226
- file =>
227
- fs.existsSync(path.join(cwd, file)) &&
228
- isEslintTarget(file) &&
229
- !isUiFile(file) &&
230
- !file.startsWith('eslint.mcp-ui.config.')
231
- );
232
- const stylelintFiles = normalizedFiles.filter(
233
- file => fs.existsSync(path.join(cwd, file)) && isStylelintTarget(file)
234
- );
120
+ const eslintFiles = normalizedFiles.filter(isEslintTarget);
121
+ const stylelintFiles = normalizedFiles.filter(isStylelintTarget);
235
122
  const typeCheckFiles = normalizedFiles.filter(isTypeCheckTarget);
236
123
 
237
124
  const clientTypeFiles = [];
238
125
  const serverTypeFiles = [];
239
- const rootConfigChanged = normalizedFiles.some(file =>
240
- /^tsconfig(?:\.[^/]*)?\.json$/.test(file)
241
- );
242
- if (rootConfigChanged) {
243
- clientTypeFiles.push('config');
244
- serverTypeFiles.push('config');
245
- }
246
- let checkUi =
247
- rootConfigChanged ||
248
- normalizedFiles.some(
249
- file =>
250
- isUiFile(file) ||
251
- file.startsWith('shared/') ||
252
- file.startsWith('eslint.mcp-ui.config.') ||
253
- file === 'package.json'
254
- );
255
126
 
256
127
  for (const filePath of typeCheckFiles) {
257
- if (isUiFile(filePath)) {
258
- checkUi = true;
259
- } else if (filePath.startsWith('client/')) {
128
+ if (filePath.startsWith('client/')) {
260
129
  clientTypeFiles.push(filePath);
261
130
  } else if (filePath.startsWith('server/')) {
262
131
  serverTypeFiles.push(filePath);
@@ -266,52 +135,36 @@ async function runSelectiveLint(inputFiles) {
266
135
  }
267
136
  }
268
137
 
269
- const taskSpecs = [];
138
+ const tasks = [];
270
139
 
271
140
  if (eslintFiles.length > 0) {
272
- taskSpecs.push([getBinName('npx'), ['eslint', '--quiet', ...eslintFiles]]);
141
+ tasks.push(runCommand(getBinName('npx'), ['eslint', '--quiet', ...eslintFiles]));
273
142
  }
274
143
 
275
144
  if (stylelintFiles.length > 0 && !canRunStylelint()) {
276
- console.warn(
277
- '[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
278
- );
145
+ console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
279
146
  } else if (stylelintFiles.length > 0) {
280
- taskSpecs.push([
281
- getBinName('npx'),
282
- ['stylelint', '--quiet', ...stylelintFiles],
283
- ]);
147
+ tasks.push(runCommand(getBinName('npx'), ['stylelint', '--quiet', ...stylelintFiles]));
284
148
  }
285
149
 
286
150
  if (clientTypeFiles.length > 0) {
287
- taskSpecs.push([getBinName('npm'), ['run', 'type:check:client']]);
151
+ tasks.push(runCommand(getBinName('npm'), ['run', 'type:check:client']));
288
152
  }
289
153
 
290
154
  if (serverTypeFiles.length > 0) {
291
- taskSpecs.push([getBinName('npm'), ['run', 'type:check:server']]);
155
+ tasks.push(runCommand(getBinName('npm'), ['run', 'type:check:server']));
292
156
  }
293
157
 
294
- if (checkUi) taskSpecs.push(...uiTasks());
295
-
296
- if (taskSpecs.length === 0) {
158
+ if (tasks.length === 0) {
297
159
  console.log('[lint] No supported files matched for lint');
298
160
  process.exit(0);
299
161
  }
300
162
 
301
- process.exit(await runTasksSerially(taskSpecs));
163
+ const results = await Promise.all(tasks);
164
+ process.exit(results.some(code => code !== 0) ? 1 : 0);
302
165
  }
303
166
 
304
167
  async function main() {
305
- const args = process.argv.slice(2);
306
- if (args.length === 1 && args[0] === '--eslint-mcp-ui') {
307
- process.exit(await runTasksSerially(uiTasks({ types: false })));
308
- return;
309
- }
310
- if (args.length && !(args[0] === '--files' && args.length > 1)) {
311
- throw new Error('用法: lint.js [--files <paths...>]');
312
- }
313
- if (args[0] === '--files' && args.slice(1).some(arg => arg.startsWith('--')))
314
- throw new Error('--files 不可与其他检查模式混用');
315
168
  const files = parseFilesArg(process.argv.slice(2));
316
169
  if (files === null) {
317
170
  await runDefaultLint();
@@ -326,7 +179,7 @@ async function main() {
326
179
  await runSelectiveLint(files);
327
180
  }
328
181
 
329
- main().catch(error => {
182
+ main().catch((error) => {
330
183
  const message = error instanceof Error ? error.message : String(error);
331
184
  console.error(`[lint] Failed to run lint: ${message}`);
332
185
  process.exit(1);
@@ -13,6 +13,5 @@
13
13
  "excludeDirectories": ["node_modules/**"]
14
14
  },
15
15
  "include": ["server/**/*", "shared/**/*.ts"],
16
- // MCP UI 是独立浏览器工程,不使用服务端的 TypeScript 配置。
17
- "exclude": ["server/mcp/ui", "node_modules", "dist", "client", "source_package", "**/*.spec.ts", "**/*.e2e-spec.ts"],
16
+ "exclude": ["node_modules", "dist", "client", "source_package", "**/*.spec.ts", "**/*.e2e-spec.ts"],
18
17
  }
@@ -1,32 +0,0 @@
1
- // MCP UI 是可选浏览器工程;没有源码时跳过,否则直接交给 tsc。
2
- const fs = require('node:fs');
3
- const path = require('node:path');
4
- const { spawnSync } = require('node:child_process');
5
-
6
- function hasSource(dir) {
7
- if (!fs.existsSync(dir)) return false;
8
- return fs.readdirSync(dir, { withFileTypes: true }).some(entry => {
9
- if (['node_modules', 'dist'].includes(entry.name)) return false;
10
- if (entry.isDirectory()) return hasSource(path.join(dir, entry.name));
11
- return entry.isFile() && /\.(?:[cm]?[jt]sx?)$/.test(entry.name);
12
- });
13
- }
14
-
15
- if (hasSource('server/mcp/ui')) {
16
- // 已有应用的独立 UI 配置继续生效,避免升级覆盖自定义 paths/types。
17
- const config = fs.existsSync('server/mcp/ui/tsconfig.json')
18
- ? 'server/mcp/ui/tsconfig.json'
19
- : 'tsconfig.mcp-ui.json';
20
- const result = spawnSync(
21
- process.execPath,
22
- [
23
- require.resolve('typescript/bin/tsc'),
24
- '--noEmit',
25
- '--project',
26
- config,
27
- ],
28
- { stdio: 'inherit' }
29
- );
30
- if (result.error) console.error(result.error.message);
31
- process.exitCode = result.status ?? 1;
32
- }
@@ -1,33 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "moduleResolution": "Bundler",
6
- "jsx": "react-jsx",
7
- "types": [],
8
- "strict": true,
9
- "checkJs": true,
10
- "lib": [
11
- "ES2020",
12
- "DOM",
13
- "DOM.Iterable"
14
- ],
15
- "allowJs": true,
16
- "skipLibCheck": true,
17
- "esModuleInterop": true,
18
- "noEmit": true,
19
- "baseUrl": ".",
20
- "paths": {
21
- "@shared/*": [
22
- "shared/*"
23
- ]
24
- }
25
- },
26
- "include": [
27
- "server/mcp/ui/**/*"
28
- ],
29
- "exclude": [
30
- "node_modules",
31
- "dist"
32
- ]
33
- }