@lark-apaas/fullstack-cli 1.1.67-alpha.20260917134435 → 1.1.67-alpha.20260917143103

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-cli",
3
- "version": "1.1.67-alpha.20260917134435",
3
+ "version": "1.1.67-alpha.20260917143103",
4
4
  "description": "CLI tool for fullstack template management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -6,12 +6,46 @@ const { spawn } = require('node:child_process');
6
6
 
7
7
  const cwd = process.cwd();
8
8
 
9
- function normalizeProjectFile(filePath) {
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 ?? 1));
22
+ child.on('error', () => resolve(1));
23
+ });
24
+ }
25
+
26
+ // 串行依次执行每个任务,全部跑完后再聚合退出码:
27
+ // 降低并发资源占用、让各任务输出按顺序清晰可读,同时保留“一次暴露所有 lint 问题”的行为。
28
+ async function runTasksSerially(taskSpecs) {
29
+ let exitCode = 0;
30
+ for (const [command, args] of taskSpecs) {
31
+ const code = await runCommand(command, args);
32
+ if (code !== 0) {
33
+ exitCode = 1;
34
+ }
35
+ }
36
+ return exitCode;
37
+ }
38
+
39
+ function normalizeProjectFile(filePath, checkDeleted = false) {
10
40
  const absolutePath = path.isAbsolute(filePath)
11
41
  ? filePath
12
42
  : path.resolve(cwd, filePath);
13
43
 
14
44
  if (!fs.existsSync(absolutePath)) {
45
+ if (!checkDeleted) {
46
+ console.warn(`[lint] Skip missing file: ${filePath}`);
47
+ return null;
48
+ }
15
49
  console.log(`[lint] Deleted file: ${filePath}; checking affected projects`);
16
50
  }
17
51
 
@@ -82,36 +116,6 @@ function canRunStylelint() {
82
116
  );
83
117
  }
84
118
 
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
119
  const UI_DIR = 'server/mcp/ui';
116
120
 
117
121
  function uiSourceFiles() {
@@ -136,10 +140,15 @@ function uiSourceFiles() {
136
140
  return files.sort();
137
141
  }
138
142
 
139
- function uiTasks({ types = true, eslint = true } = {}) {
143
+ function uiTasks({ types = true, eslint = true, aggregate = false } = {}) {
140
144
  const sources = uiSourceFiles();
141
145
  if (!sources.length) return [];
142
146
  const tasks = [];
147
+ // 只在有 UI 源码时读取聚合命令;普通应用不依赖 MCP 配置或脚本。
148
+ if (types && aggregate) {
149
+ const scripts = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).scripts || {};
150
+ types = !/\bnpm\s+run\s+type:check:mcp-ui(?=[\s"';&|)]|$)/.test(scripts['type:check'] || '');
151
+ }
143
152
  if (types) tasks.push([getBinName('npm'), ['run', 'type:check:mcp-ui']]);
144
153
  if (eslint) {
145
154
  const config = [
@@ -175,13 +184,6 @@ function uiTasks({ types = true, eslint = true } = {}) {
175
184
  return tasks;
176
185
  }
177
186
 
178
- function packageScripts() {
179
- return (
180
- JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'))
181
- .scripts || {}
182
- );
183
- }
184
-
185
187
  function isUiFile(file) {
186
188
  return file.startsWith('server/mcp/ui/');
187
189
  }
@@ -192,14 +194,7 @@ async function runDefaultLint() {
192
194
  [getBinName('npm'), ['run', 'type:check']],
193
195
  ];
194
196
 
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
- );
197
+ taskSpecs.push(...uiTasks({ aggregate: true }));
203
198
 
204
199
  if (canRunStylelint()) {
205
200
  taskSpecs.push([getBinName('npm'), ['run', 'stylelint']]);
@@ -213,8 +208,9 @@ async function runDefaultLint() {
213
208
  }
214
209
 
215
210
  async function runSelectiveLint(inputFiles) {
211
+ const hasUiSources = uiSourceFiles().length > 0;
216
212
  const normalizedFiles = Array.from(
217
- new Set(inputFiles.map(normalizeProjectFile).filter(Boolean))
213
+ new Set(inputFiles.map(file => normalizeProjectFile(file, hasUiSources)).filter(Boolean))
218
214
  );
219
215
 
220
216
  if (normalizedFiles.length === 0) {
@@ -226,8 +222,7 @@ async function runSelectiveLint(inputFiles) {
226
222
  file =>
227
223
  fs.existsSync(path.join(cwd, file)) &&
228
224
  isEslintTarget(file) &&
229
- !isUiFile(file) &&
230
- !file.startsWith('eslint.mcp-ui.config.')
225
+ (!hasUiSources || (!isUiFile(file) && !file.startsWith('eslint.mcp-ui.config.')))
231
226
  );
232
227
  const stylelintFiles = normalizedFiles.filter(
233
228
  file => fs.existsSync(path.join(cwd, file)) && isStylelintTarget(file)
@@ -236,7 +231,7 @@ async function runSelectiveLint(inputFiles) {
236
231
 
237
232
  const clientTypeFiles = [];
238
233
  const serverTypeFiles = [];
239
- const rootConfigChanged = normalizedFiles.some(file =>
234
+ const rootConfigChanged = hasUiSources && normalizedFiles.some(file =>
240
235
  /^tsconfig(?:\.[^/]*)?\.json$/.test(file)
241
236
  );
242
237
  if (rootConfigChanged) {
@@ -254,7 +249,7 @@ async function runSelectiveLint(inputFiles) {
254
249
  );
255
250
 
256
251
  for (const filePath of typeCheckFiles) {
257
- if (isUiFile(filePath)) {
252
+ if (hasUiSources && isUiFile(filePath)) {
258
253
  checkUi = true;
259
254
  } else if (filePath.startsWith('client/')) {
260
255
  clientTypeFiles.push(filePath);