@lark-apaas/coding-template-nestjs-react-fullstack 0.1.42-alpha.20260917142620 → 0.1.43-alpha.20260917183850
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/README.md +8 -27
- package/package.json +1 -1
- package/template/package-lock.json +84 -82
- package/template/package.json +5 -6
- package/template/scripts/build.sh +43 -81
- package/template/scripts/lint.js +27 -169
- package/template/scripts/typecheck-mcp-ui.js +0 -32
- package/template/tsconfig.mcp-ui.json +0 -33
package/README.md
CHANGED
|
@@ -29,13 +29,13 @@ MIAODA_APP_TYPE=3 npx @lark-apaas/miaoda-cli@<latest> app init \
|
|
|
29
29
|
|
|
30
30
|
## MCP UI 的类型与代码检查
|
|
31
31
|
|
|
32
|
-
MCP UI
|
|
32
|
+
创建 MCP UI 时,Agent 在 `server/mcp/ui` 中同时生成 `tsconfig.json` 和 `eslint.config.cjs`,修改 UI 或其 shared 依赖后主动运行独立检查。模板和 CLI 不生成 UI 配置,也不将 UI 检查接入主工程 lint/type:check。
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
主工程保留原 client/server 检查。Agent 从工程根执行 `npx --no-install tsc --noEmit --project server/mcp/ui/tsconfig.json`,再执行 `npx --no-install eslint --config server/mcp/ui/eslint.config.cjs "server/mcp/ui/**/*.{ts,tsx,js,jsx}" --max-warnings 0`;必须检查退出码并修复错误。无需辅助脚本或新增 npm 命令。
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
CLI 不注入 MCP UI 检查命令;主工程保留原有 client/server 检查,UI 由 Agent 按独立配置执行标准 tsc/eslint。
|
|
37
37
|
|
|
38
|
-
存量 sync 不改写 ESLint 源码;UI 全局排除项由平台 ESLint 预设提供。TS 仅向已有显式 `exclude` 数组追加目录,保留注释和原项;依赖继承且未显式声明 `exclude`
|
|
38
|
+
存量 sync 不改写 ESLint 源码;UI 全局排除项由平台 ESLint 预设提供。TS 仅向已有显式 `exclude` 数组追加目录,保留注释和原项;依赖继承且未显式声明 `exclude` 的自定义配置保持不变并提示人工调整。自定义检查命令保留。UI ESLint 配置可显式引用 `fullstack-presets/lib/mcp/eslint-ui`。
|
|
39
39
|
|
|
40
40
|
## 包结构
|
|
41
41
|
|
|
@@ -50,29 +50,10 @@ UI ESLint 默认配置由平台预设提供,也可用根目录 `eslint.mcp-ui.
|
|
|
50
50
|
渲染时会按 RENAME 映射改回正常名(npm pack 会特殊处理 `.gitignore`、且 `.npmrc` 直接放
|
|
51
51
|
在包里会污染用户 `npm install` 行为,所以都要 underscore 前缀)。
|
|
52
52
|
|
|
53
|
-
## MCP
|
|
53
|
+
## MCP 版本与 UI 检查
|
|
54
54
|
|
|
55
|
-
`
|
|
56
|
-
用 Node 内置 `crypto.randomUUID()` 生成一次纯文本 UUID(36 字符,无需发布环境变量)。
|
|
57
|
-
同次构建写入下列文件,内容完全相同:
|
|
55
|
+
模板不生成 `mcp-build-id`,构建脚本沿用原流程。SDK 发布态使用 veFaaS 函数 ID 与发布 revision;开发态使用后端编译产物指纹,UI/Skill 内容继续独立计入修订。首次升级切换版本来源后,Host 应重新发现。
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
| --- | --- |
|
|
61
|
-
| `dist/mcp-build-id` | 工程根 |
|
|
62
|
-
| `dist/dist/mcp-build-id` | `dist/`,或整个 `dist/` 复制/解压到的 `dist-server/` |
|
|
63
|
-
| `dist/server/dist/mcp-build-id` | 旧布局 `dist/server/`,或该目录复制/解压到的 `dist-server/` |
|
|
57
|
+
MCP UI 的 `tsconfig.json` 和 `eslint.config.cjs` 由 Agent 随 UI 在 `server/mcp/ui` 中创建,执行命令与完整示例见 coding-steering 的 `mcp-ui-guide`。主工程的 TS/ESLint 排除该浏览器目录,不自动运行 UI 检查;不为无 UI 的应用创建配置或检查命令。
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
复制/部署同一产物必须保留文件,不在启动时重新生成 UUID;再次成功全构建会得到新的 UUID。
|
|
67
|
-
直接运行 `build:server` 不完成交付流程,不能替代 `npm run build`。
|
|
68
|
-
SDK 在文件缺失时不返回 `appRevision`,标准 MCP 仍可用;开发态使用进程单例 UUID,不读构建文件。
|
|
69
|
-
UI/Skill 内容仍由 SDK 计入总 hash,独立修改这些产物不会重写 `backendBuildID`。
|
|
70
|
-
|
|
71
|
-
`only_frontend_change=true` 跳过服务端构建、依赖裁剪和 UUID 生成。
|
|
72
|
-
构建目录仍按原逻辑清空;平台跳过服务端包上传,所以已部署服务的旧 ID 保持不变。
|
|
73
|
-
`server/mcp/ui`、`server/mcp/skills` 的源码变更应由平台判为全构建;它们不属于 `client/`。
|
|
74
|
-
平台实际根据配置的前端路径前缀匹配变更前后路径,不能把 `server/mcp` 列为前端前缀。
|
|
75
|
-
即使 client build 在本地写出了 `mcp-ui`,纯前端发布也不携带服务端 MCP 产物,**不承诺热更 MCP UI**。
|
|
76
|
-
|
|
77
|
-
存量应用通过既有 `fullstack-cli sync` 或 `miaoda app sync` 的 `scripts/` 目录覆盖同步获得此脚本,
|
|
78
|
-
同步本身不生成 UUID、不修改已有构建标识,无新增用户 CLI 命令。
|
|
59
|
+
`server/mcp/ui` 与 `server/mcp/skills` 变更应由平台判为后端发布;纯前端发布不替换已部署 MCP 产物,也不承诺热更 MCP UI。发布版本号仅在实际后端发布时更新。
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"name": "fullstack-nestjs-template",
|
|
9
9
|
"version": "2.3.0",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@lark-apaas/fullstack-nestjs-core": "1.1.
|
|
11
|
+
"@lark-apaas/fullstack-nestjs-core": "1.1.63-alpha.20260917183019",
|
|
12
12
|
"@nestjs/axios": "^4.0.1",
|
|
13
13
|
"@nestjs/cache-manager": "^3.1.3",
|
|
14
14
|
"@nestjs/common": "^10.4.20",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@hookform/resolvers": "^5.2.2",
|
|
35
35
|
"@lark-apaas/client-toolkit": "^1.2.70",
|
|
36
|
-
"@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.
|
|
37
|
-
"@lark-apaas/fullstack-presets": "1.1.24-alpha.
|
|
36
|
+
"@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260917183012",
|
|
37
|
+
"@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917183016",
|
|
38
38
|
"@nestjs/cli": "^10.4.9",
|
|
39
39
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
40
40
|
"@radix-ui/react-alert-dialog": "^1.1.15",
|
|
@@ -1546,9 +1546,9 @@
|
|
|
1546
1546
|
}
|
|
1547
1547
|
},
|
|
1548
1548
|
"node_modules/@lark-apaas/cache-service": {
|
|
1549
|
-
"version": "0.1.2-alpha.
|
|
1550
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2-alpha.
|
|
1551
|
-
"integrity": "sha512-
|
|
1549
|
+
"version": "0.1.2-alpha.20260917183013",
|
|
1550
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2-alpha.20260917183013.tgz",
|
|
1551
|
+
"integrity": "sha512-rBlYRoGntBl/JyOabalVt+RC9blm53f+eu8yJhb2/Eytw5vF/K1YxDNRFBHAsKGupEfiYlll/XYcF3Qn/7OJEA==",
|
|
1552
1552
|
"license": "MIT",
|
|
1553
1553
|
"dependencies": {
|
|
1554
1554
|
"@keyv/redis": "^5.1.6",
|
|
@@ -1562,7 +1562,7 @@
|
|
|
1562
1562
|
},
|
|
1563
1563
|
"peerDependencies": {
|
|
1564
1564
|
"@lark-apaas/nestjs-common": "^0.1.9",
|
|
1565
|
-
"@lark-apaas/nestjs-logger": "1.0.18-alpha.
|
|
1565
|
+
"@lark-apaas/nestjs-logger": "1.0.18-alpha.20260917183014",
|
|
1566
1566
|
"@lark-apaas/nestjs-observable": "^0.0.12",
|
|
1567
1567
|
"@nestjs/common": "^10.0.0",
|
|
1568
1568
|
"@nestjs/core": "^10.0.0"
|
|
@@ -1634,16 +1634,15 @@
|
|
|
1634
1634
|
"license": "MIT"
|
|
1635
1635
|
},
|
|
1636
1636
|
"node_modules/@lark-apaas/coding-preset-vite-react": {
|
|
1637
|
-
"version": "1.0.24-alpha.
|
|
1638
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.24-alpha.
|
|
1639
|
-
"integrity": "sha512-
|
|
1637
|
+
"version": "1.0.24-alpha.20260917183012",
|
|
1638
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.24-alpha.20260917183012.tgz",
|
|
1639
|
+
"integrity": "sha512-Bp2GksGRAf7CZEsyYojHLmSLdm4OTuj14Lj9Smse9ElJ7K3m41wLSCT6PJNcyxs6Dq4Pbc2ZSZixyO2wAM5LLA==",
|
|
1640
1640
|
"dev": true,
|
|
1641
1641
|
"license": "MIT",
|
|
1642
1642
|
"dependencies": {
|
|
1643
1643
|
"@babel/parser": "^7.28.0",
|
|
1644
1644
|
"@babel/traverse": "^7.28.0",
|
|
1645
1645
|
"@babel/types": "^7.28.0",
|
|
1646
|
-
"@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917134434",
|
|
1647
1646
|
"@lark-apaas/vite-inspector-plugin": "^1.0.4",
|
|
1648
1647
|
"@tailwindcss/vite": "^4.3.0",
|
|
1649
1648
|
"@vitejs/plugin-react": "^6.0.0",
|
|
@@ -1656,6 +1655,8 @@
|
|
|
1656
1655
|
"express": "^4.18.2",
|
|
1657
1656
|
"html-minifier-terser": "^7.2.0",
|
|
1658
1657
|
"magic-string": "~0.30.18",
|
|
1658
|
+
"parse5": "^7.3.0",
|
|
1659
|
+
"postcss-value-parser": "^4.2.0",
|
|
1659
1660
|
"tailwind-merge": "^2.5.5"
|
|
1660
1661
|
},
|
|
1661
1662
|
"peerDependencies": {
|
|
@@ -1696,12 +1697,12 @@
|
|
|
1696
1697
|
}
|
|
1697
1698
|
},
|
|
1698
1699
|
"node_modules/@lark-apaas/fullstack-nestjs-core": {
|
|
1699
|
-
"version": "1.1.
|
|
1700
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.
|
|
1701
|
-
"integrity": "sha512-
|
|
1700
|
+
"version": "1.1.63-alpha.20260917183019",
|
|
1701
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.63-alpha.20260917183019.tgz",
|
|
1702
|
+
"integrity": "sha512-OuR9wl/9H7VLkpkDj1f6Fj0aM8ZAm4gtrNWHH5a9jyhvZlhT87JCkYaS9SY7Jgy6ijBhb8iXvm/dPhLwoLYifw==",
|
|
1702
1703
|
"license": "MIT",
|
|
1703
1704
|
"dependencies": {
|
|
1704
|
-
"@lark-apaas/cache-service": "0.1.2-alpha.
|
|
1705
|
+
"@lark-apaas/cache-service": "0.1.2-alpha.20260917183013",
|
|
1705
1706
|
"@lark-apaas/file-service": "^0.1.2",
|
|
1706
1707
|
"@lark-apaas/http-client": "^0.1.7",
|
|
1707
1708
|
"@lark-apaas/nestjs-authnpaas": "^1.0.6",
|
|
@@ -1710,8 +1711,8 @@
|
|
|
1710
1711
|
"@lark-apaas/nestjs-common": "^0.1.9",
|
|
1711
1712
|
"@lark-apaas/nestjs-datapaas": "^1.0.21",
|
|
1712
1713
|
"@lark-apaas/nestjs-http-forwarder": "^0.1.3",
|
|
1713
|
-
"@lark-apaas/nestjs-logger": "1.0.18-alpha.
|
|
1714
|
-
"@lark-apaas/nestjs-mcp": "0.1.1-alpha.
|
|
1714
|
+
"@lark-apaas/nestjs-logger": "1.0.18-alpha.20260917183014",
|
|
1715
|
+
"@lark-apaas/nestjs-mcp": "0.1.1-alpha.20260917183017",
|
|
1715
1716
|
"@lark-apaas/nestjs-observable": "^0.0.12",
|
|
1716
1717
|
"@lark-apaas/nestjs-openapi-devtools": "^1.0.10",
|
|
1717
1718
|
"@lark-apaas/nestjs-trigger": "^0.0.3",
|
|
@@ -1734,14 +1735,12 @@
|
|
|
1734
1735
|
}
|
|
1735
1736
|
},
|
|
1736
1737
|
"node_modules/@lark-apaas/fullstack-presets": {
|
|
1737
|
-
"version": "1.1.24-alpha.
|
|
1738
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.24-alpha.
|
|
1739
|
-
"integrity": "sha512-
|
|
1738
|
+
"version": "1.1.24-alpha.20260917183016",
|
|
1739
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.24-alpha.20260917183016.tgz",
|
|
1740
|
+
"integrity": "sha512-bve5BSoHF2BsK7QppudsSOx5T8HEdVS/vytSBBwEOwDzKLtjSlFSY6JH8AccrgEbn5ZZkkdU+zrSwqR62pPArw==",
|
|
1740
1741
|
"dev": true,
|
|
1741
1742
|
"license": "MIT",
|
|
1742
1743
|
"dependencies": {
|
|
1743
|
-
"@babel/parser": "^7.28.0",
|
|
1744
|
-
"@babel/traverse": "^7.28.0",
|
|
1745
1744
|
"@darraghor/eslint-plugin-nestjs-typed": "^6.9.1",
|
|
1746
1745
|
"@eslint/js": "^9.35.0",
|
|
1747
1746
|
"@types/node": "^22.19.1",
|
|
@@ -1752,20 +1751,12 @@
|
|
|
1752
1751
|
"eslint-plugin-react": "^7.37.5",
|
|
1753
1752
|
"eslint-plugin-react-hooks": "^5.2.0",
|
|
1754
1753
|
"globals": "^16.4.0",
|
|
1755
|
-
"parse5": "^7.3.0",
|
|
1756
|
-
"postcss-value-parser": "^4.2.0",
|
|
1757
1754
|
"stylelint": "^17.3.0",
|
|
1758
1755
|
"tailwindcss-animate": "^1.0.7"
|
|
1759
1756
|
},
|
|
1760
1757
|
"peerDependencies": {
|
|
1761
1758
|
"eslint": "^9.0.0",
|
|
1762
|
-
"typescript-eslint": "^8.44.0"
|
|
1763
|
-
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
1764
|
-
},
|
|
1765
|
-
"peerDependenciesMeta": {
|
|
1766
|
-
"vite": {
|
|
1767
|
-
"optional": true
|
|
1768
|
-
}
|
|
1759
|
+
"typescript-eslint": "^8.44.0"
|
|
1769
1760
|
}
|
|
1770
1761
|
},
|
|
1771
1762
|
"node_modules/@lark-apaas/hey-api-custom-client-axios": {
|
|
@@ -1935,9 +1926,9 @@
|
|
|
1935
1926
|
}
|
|
1936
1927
|
},
|
|
1937
1928
|
"node_modules/@lark-apaas/nestjs-logger": {
|
|
1938
|
-
"version": "1.0.18-alpha.
|
|
1939
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18-alpha.
|
|
1940
|
-
"integrity": "sha512-
|
|
1929
|
+
"version": "1.0.18-alpha.20260917183014",
|
|
1930
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18-alpha.20260917183014.tgz",
|
|
1931
|
+
"integrity": "sha512-z1hUbygUOKmeh7DkFgyUtqrtS8UJZUHTK+umINT2nFxOg/Pczhi0eJijmZb62ZBIv3ZHB0ABwJ/wlXu8tVMTLQ==",
|
|
1941
1932
|
"license": "MIT",
|
|
1942
1933
|
"dependencies": {
|
|
1943
1934
|
"@lark-apaas/nestjs-common": "^0.1.9",
|
|
@@ -1954,9 +1945,9 @@
|
|
|
1954
1945
|
}
|
|
1955
1946
|
},
|
|
1956
1947
|
"node_modules/@lark-apaas/nestjs-mcp": {
|
|
1957
|
-
"version": "0.1.1-alpha.
|
|
1958
|
-
"resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1-alpha.
|
|
1959
|
-
"integrity": "sha512-
|
|
1948
|
+
"version": "0.1.1-alpha.20260917183017",
|
|
1949
|
+
"resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1-alpha.20260917183017.tgz",
|
|
1950
|
+
"integrity": "sha512-EQL62bFmCP2i1FIQuDGZ/ZlYJ5ooAhLWW9DqJpwnr94qhC58P2d5E35SeJGXxEOWe3o3Ros4aYj+Pr3LbVoU6g==",
|
|
1960
1951
|
"license": "MIT",
|
|
1961
1952
|
"dependencies": {
|
|
1962
1953
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
@@ -10002,18 +9993,18 @@
|
|
|
10002
9993
|
"license": "MIT"
|
|
10003
9994
|
},
|
|
10004
9995
|
"node_modules/array-includes": {
|
|
10005
|
-
"version": "3.
|
|
10006
|
-
"resolved": "https://registry.npmmirror.com/array-includes/-/array-includes-3.
|
|
10007
|
-
"integrity": "sha512-
|
|
9996
|
+
"version": "3.1.9",
|
|
9997
|
+
"resolved": "https://registry.npmmirror.com/array-includes/-/array-includes-3.1.9.tgz",
|
|
9998
|
+
"integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
|
|
10008
9999
|
"dev": true,
|
|
10009
10000
|
"license": "MIT",
|
|
10010
10001
|
"dependencies": {
|
|
10011
|
-
"call-bind": "^1.0.
|
|
10002
|
+
"call-bind": "^1.0.8",
|
|
10012
10003
|
"call-bound": "^1.0.4",
|
|
10013
10004
|
"define-properties": "^1.2.1",
|
|
10014
|
-
"es-abstract": "^1.24.
|
|
10015
|
-
"es-object-atoms": "^1.1.
|
|
10016
|
-
"
|
|
10005
|
+
"es-abstract": "^1.24.0",
|
|
10006
|
+
"es-object-atoms": "^1.1.1",
|
|
10007
|
+
"get-intrinsic": "^1.3.0",
|
|
10017
10008
|
"is-string": "^1.1.1",
|
|
10018
10009
|
"math-intrinsics": "^1.1.0"
|
|
10019
10010
|
},
|
|
@@ -12849,9 +12840,9 @@
|
|
|
12849
12840
|
}
|
|
12850
12841
|
},
|
|
12851
12842
|
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
|
12852
|
-
"version": "1.1.
|
|
12853
|
-
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.
|
|
12854
|
-
"integrity": "sha512-
|
|
12843
|
+
"version": "1.1.18",
|
|
12844
|
+
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.18.tgz",
|
|
12845
|
+
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
|
|
12855
12846
|
"dev": true,
|
|
12856
12847
|
"license": "MIT",
|
|
12857
12848
|
"dependencies": {
|
|
@@ -12905,6 +12896,16 @@
|
|
|
12905
12896
|
"semver": "bin/semver.js"
|
|
12906
12897
|
}
|
|
12907
12898
|
},
|
|
12899
|
+
"node_modules/eslint-plugin-import/node_modules/strip-bom": {
|
|
12900
|
+
"version": "3.0.0",
|
|
12901
|
+
"resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz",
|
|
12902
|
+
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
|
12903
|
+
"dev": true,
|
|
12904
|
+
"license": "MIT",
|
|
12905
|
+
"engines": {
|
|
12906
|
+
"node": ">=4"
|
|
12907
|
+
}
|
|
12908
|
+
},
|
|
12908
12909
|
"node_modules/eslint-plugin-import/node_modules/tsconfig-paths": {
|
|
12909
12910
|
"version": "3.15.0",
|
|
12910
12911
|
"resolved": "https://registry.npmmirror.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
|
@@ -12965,9 +12966,9 @@
|
|
|
12965
12966
|
}
|
|
12966
12967
|
},
|
|
12967
12968
|
"node_modules/eslint-plugin-react/node_modules/brace-expansion": {
|
|
12968
|
-
"version": "1.1.
|
|
12969
|
-
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.
|
|
12970
|
-
"integrity": "sha512-
|
|
12969
|
+
"version": "1.1.18",
|
|
12970
|
+
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.18.tgz",
|
|
12971
|
+
"integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==",
|
|
12971
12972
|
"dev": true,
|
|
12972
12973
|
"license": "MIT",
|
|
12973
12974
|
"dependencies": {
|
|
@@ -14290,9 +14291,9 @@
|
|
|
14290
14291
|
}
|
|
14291
14292
|
},
|
|
14292
14293
|
"node_modules/glob/node_modules/brace-expansion": {
|
|
14293
|
-
"version": "5.0.
|
|
14294
|
-
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.
|
|
14295
|
-
"integrity": "sha512-
|
|
14294
|
+
"version": "5.0.9",
|
|
14295
|
+
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.9.tgz",
|
|
14296
|
+
"integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
|
|
14296
14297
|
"dev": true,
|
|
14297
14298
|
"license": "MIT",
|
|
14298
14299
|
"dependencies": {
|
|
@@ -16399,16 +16400,6 @@
|
|
|
16399
16400
|
"url": "https://github.com/sponsors/sindresorhus"
|
|
16400
16401
|
}
|
|
16401
16402
|
},
|
|
16402
|
-
"node_modules/lru-cache": {
|
|
16403
|
-
"version": "11.5.2",
|
|
16404
|
-
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.2.tgz",
|
|
16405
|
-
"integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
|
|
16406
|
-
"dev": true,
|
|
16407
|
-
"license": "BlueOak-1.0.0",
|
|
16408
|
-
"engines": {
|
|
16409
|
-
"node": "20 || >=22"
|
|
16410
|
-
}
|
|
16411
|
-
},
|
|
16412
16403
|
"node_modules/lucide-react": {
|
|
16413
16404
|
"version": "0.577.0",
|
|
16414
16405
|
"resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.577.0.tgz",
|
|
@@ -18481,6 +18472,16 @@
|
|
|
18481
18472
|
"url": "https://github.com/sponsors/isaacs"
|
|
18482
18473
|
}
|
|
18483
18474
|
},
|
|
18475
|
+
"node_modules/path-scurry/node_modules/lru-cache": {
|
|
18476
|
+
"version": "11.5.2",
|
|
18477
|
+
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.2.tgz",
|
|
18478
|
+
"integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
|
|
18479
|
+
"dev": true,
|
|
18480
|
+
"license": "BlueOak-1.0.0",
|
|
18481
|
+
"engines": {
|
|
18482
|
+
"node": "20 || >=22"
|
|
18483
|
+
}
|
|
18484
|
+
},
|
|
18484
18485
|
"node_modules/path-to-regexp": {
|
|
18485
18486
|
"version": "3.3.0",
|
|
18486
18487
|
"resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz",
|
|
@@ -21246,16 +21247,6 @@
|
|
|
21246
21247
|
"node": ">=8"
|
|
21247
21248
|
}
|
|
21248
21249
|
},
|
|
21249
|
-
"node_modules/strip-bom": {
|
|
21250
|
-
"version": "3.0.0",
|
|
21251
|
-
"resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz",
|
|
21252
|
-
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
|
21253
|
-
"dev": true,
|
|
21254
|
-
"license": "MIT",
|
|
21255
|
-
"engines": {
|
|
21256
|
-
"node": ">=4"
|
|
21257
|
-
}
|
|
21258
|
-
},
|
|
21259
21250
|
"node_modules/strip-dirs": {
|
|
21260
21251
|
"version": "3.0.0",
|
|
21261
21252
|
"resolved": "https://registry.npmmirror.com/strip-dirs/-/strip-dirs-3.0.0.tgz",
|
|
@@ -22210,6 +22201,16 @@
|
|
|
22210
22201
|
"node": ">=10.13.0"
|
|
22211
22202
|
}
|
|
22212
22203
|
},
|
|
22204
|
+
"node_modules/tsconfig-paths/node_modules/strip-bom": {
|
|
22205
|
+
"version": "3.0.0",
|
|
22206
|
+
"resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz",
|
|
22207
|
+
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
|
22208
|
+
"dev": true,
|
|
22209
|
+
"license": "MIT",
|
|
22210
|
+
"engines": {
|
|
22211
|
+
"node": ">=4"
|
|
22212
|
+
}
|
|
22213
|
+
},
|
|
22213
22214
|
"node_modules/tslib": {
|
|
22214
22215
|
"version": "2.8.1",
|
|
22215
22216
|
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
|
|
@@ -22301,18 +22302,19 @@
|
|
|
22301
22302
|
}
|
|
22302
22303
|
},
|
|
22303
22304
|
"node_modules/typed-array-byte-offset": {
|
|
22304
|
-
"version": "1.0.
|
|
22305
|
-
"resolved": "https://registry.npmmirror.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.
|
|
22306
|
-
"integrity": "sha512-
|
|
22305
|
+
"version": "1.0.4",
|
|
22306
|
+
"resolved": "https://registry.npmmirror.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
|
|
22307
|
+
"integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
|
|
22307
22308
|
"dev": true,
|
|
22308
22309
|
"license": "MIT",
|
|
22309
22310
|
"dependencies": {
|
|
22310
22311
|
"available-typed-arrays": "^1.0.7",
|
|
22311
|
-
"call-bind": "^1.0.
|
|
22312
|
-
"for-each": "^0.3.
|
|
22312
|
+
"call-bind": "^1.0.8",
|
|
22313
|
+
"for-each": "^0.3.3",
|
|
22313
22314
|
"gopd": "^1.2.0",
|
|
22315
|
+
"has-proto": "^1.2.0",
|
|
22314
22316
|
"is-typed-array": "^1.1.15",
|
|
22315
|
-
"reflect.getprototypeof": "^1.0.
|
|
22317
|
+
"reflect.getprototypeof": "^1.0.9"
|
|
22316
22318
|
},
|
|
22317
22319
|
"engines": {
|
|
22318
22320
|
"node": ">= 0.4"
|
|
@@ -23414,9 +23416,9 @@
|
|
|
23414
23416
|
}
|
|
23415
23417
|
},
|
|
23416
23418
|
"node_modules/which-typed-array": {
|
|
23417
|
-
"version": "1.1.
|
|
23418
|
-
"resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.
|
|
23419
|
-
"integrity": "sha512-
|
|
23419
|
+
"version": "1.1.22",
|
|
23420
|
+
"resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.22.tgz",
|
|
23421
|
+
"integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==",
|
|
23420
23422
|
"dev": true,
|
|
23421
23423
|
"license": "MIT",
|
|
23422
23424
|
"dependencies": {
|
package/template/package.json
CHANGED
|
@@ -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
|
|
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.
|
|
31
|
+
"@lark-apaas/fullstack-nestjs-core": "1.1.63-alpha.20260917183019",
|
|
33
32
|
"@nestjs/axios": "^4.0.1",
|
|
34
33
|
"@nestjs/cache-manager": "^3.1.3",
|
|
35
34
|
"@nestjs/common": "^10.4.20",
|
|
@@ -54,8 +53,8 @@
|
|
|
54
53
|
"devDependencies": {
|
|
55
54
|
"@hookform/resolvers": "^5.2.2",
|
|
56
55
|
"@lark-apaas/client-toolkit": "^1.2.70",
|
|
57
|
-
"@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.
|
|
58
|
-
"@lark-apaas/fullstack-presets": "1.1.24-alpha.
|
|
56
|
+
"@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260917183012",
|
|
57
|
+
"@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917183016",
|
|
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
|
-
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
91
|
-
mkdir -p "$OUT_DIR/dist/client"
|
|
84
|
+
mkdir -p "$OUT_DIR/dist/client"
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
-
|
|
102
|
-
|
|
91
|
+
# 构建产物 HTML 随后拷,覆盖 public 里的同名文件(保证入口页是构建版,不被 public 静默覆盖)
|
|
92
|
+
cp "$ROOT_DIR/dist/client/"*.html "$OUT_DIR/dist/client/" || true
|
|
103
93
|
|
|
104
|
-
|
|
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
|
-
|
|
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 "$
|
|
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
|
-
|
|
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
|
package/template/scripts/lint.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
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
|
|
|
@@ -11,50 +11,30 @@ function getBinName(name) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
function runCommand(command, args) {
|
|
14
|
-
return new Promise(resolve => {
|
|
14
|
+
return new Promise((resolve) => {
|
|
15
15
|
const child = spawn(command, args, {
|
|
16
16
|
cwd,
|
|
17
17
|
stdio: 'inherit',
|
|
18
18
|
shell: false,
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
child.on('close', code => resolve(code
|
|
21
|
+
child.on('close', (code) => resolve(code || 0));
|
|
22
22
|
child.on('error', () => resolve(1));
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
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) {
|
|
26
|
+
function normalizeProjectFile(filePath) {
|
|
40
27
|
const absolutePath = path.isAbsolute(filePath)
|
|
41
28
|
? filePath
|
|
42
29
|
: path.resolve(cwd, filePath);
|
|
43
30
|
|
|
44
31
|
if (!fs.existsSync(absolutePath)) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
console.log(`[lint] Deleted file: ${filePath}; checking affected projects`);
|
|
32
|
+
console.warn(`[lint] Skip missing file: ${filePath}`);
|
|
33
|
+
return null;
|
|
50
34
|
}
|
|
51
35
|
|
|
52
36
|
const relativePath = path.relative(cwd, absolutePath);
|
|
53
|
-
if (
|
|
54
|
-
relativePath === '..' ||
|
|
55
|
-
relativePath.startsWith(`..${path.sep}`) ||
|
|
56
|
-
path.isAbsolute(relativePath)
|
|
57
|
-
) {
|
|
37
|
+
if (relativePath.startsWith('..')) {
|
|
58
38
|
console.warn(`[lint] Skip file outside project: ${filePath}`);
|
|
59
39
|
return null;
|
|
60
40
|
}
|
|
@@ -111,106 +91,25 @@ function canRunStylelint() {
|
|
|
111
91
|
|
|
112
92
|
if (!pkg.scripts || !pkg.scripts.stylelint) return false;
|
|
113
93
|
|
|
114
|
-
return STYLELINT_CONFIG_FILES.some(file =>
|
|
115
|
-
fs.existsSync(path.join(cwd, file))
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const UI_DIR = 'server/mcp/ui';
|
|
120
|
-
|
|
121
|
-
function uiSourceFiles() {
|
|
122
|
-
const files = [];
|
|
123
|
-
function visit(relative) {
|
|
124
|
-
const absolute = path.join(cwd, relative);
|
|
125
|
-
if (!fs.existsSync(absolute)) return;
|
|
126
|
-
if (fs.lstatSync(absolute).isSymbolicLink()) {
|
|
127
|
-
throw new Error(`MCP UI 检查不支持符号链接: ${relative}`);
|
|
128
|
-
}
|
|
129
|
-
for (const entry of fs.readdirSync(absolute, { withFileTypes: true })) {
|
|
130
|
-
if (['node_modules', 'dist', '.git'].includes(entry.name)) continue;
|
|
131
|
-
const file = `${relative}/${entry.name}`;
|
|
132
|
-
if (entry.isSymbolicLink())
|
|
133
|
-
throw new Error(`MCP UI 检查不支持符号链接: ${file}`);
|
|
134
|
-
if (entry.isDirectory()) visit(file);
|
|
135
|
-
else if (isEslintTarget(file) && !/\.d\.(?:ts|mts|cts)$/.test(file))
|
|
136
|
-
files.push(file);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
visit(UI_DIR);
|
|
140
|
-
return files.sort();
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
function uiTasks({ types = true, eslint = true, aggregate = false } = {}) {
|
|
144
|
-
const sources = uiSourceFiles();
|
|
145
|
-
if (!sources.length) return [];
|
|
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
|
-
}
|
|
152
|
-
if (types) tasks.push([getBinName('npm'), ['run', 'type:check:mcp-ui']]);
|
|
153
|
-
if (eslint) {
|
|
154
|
-
const config = [
|
|
155
|
-
'eslint.mcp-ui.config.js',
|
|
156
|
-
'eslint.mcp-ui.config.cjs',
|
|
157
|
-
'eslint.mcp-ui.config.mjs',
|
|
158
|
-
].find(file => fs.existsSync(path.join(cwd, file)));
|
|
159
|
-
let resolvedConfig = config;
|
|
160
|
-
if (!resolvedConfig) {
|
|
161
|
-
try {
|
|
162
|
-
resolvedConfig =
|
|
163
|
-
require.resolve('@lark-apaas/fullstack-presets/lib/mcp/eslint-ui.js');
|
|
164
|
-
} catch {
|
|
165
|
-
throw new Error(
|
|
166
|
-
'请升级 @lark-apaas/fullstack-presets 以使用 MCP UI 默认 ESLint 配置,或提供 eslint.mcp-ui.config.cjs'
|
|
167
|
-
);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
tasks.push([
|
|
171
|
-
getBinName('npx'),
|
|
172
|
-
[
|
|
173
|
-
'--no-install',
|
|
174
|
-
'eslint',
|
|
175
|
-
'--config',
|
|
176
|
-
resolvedConfig,
|
|
177
|
-
'--quiet',
|
|
178
|
-
'--max-warnings',
|
|
179
|
-
'0',
|
|
180
|
-
...sources,
|
|
181
|
-
],
|
|
182
|
-
]);
|
|
183
|
-
}
|
|
184
|
-
return tasks;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function isUiFile(file) {
|
|
188
|
-
return file.startsWith('server/mcp/ui/');
|
|
94
|
+
return STYLELINT_CONFIG_FILES.some(file => fs.existsSync(path.join(cwd, file)));
|
|
189
95
|
}
|
|
190
96
|
|
|
191
97
|
async function runDefaultLint() {
|
|
192
|
-
const
|
|
193
|
-
[getBinName('npm'), ['run', 'eslint']],
|
|
194
|
-
[getBinName('npm'), ['run', 'type:check']],
|
|
195
|
-
];
|
|
196
|
-
|
|
197
|
-
taskSpecs.push(...uiTasks({ aggregate: true }));
|
|
98
|
+
const commands = ['npm run eslint', 'npm run type:check'];
|
|
198
99
|
|
|
199
100
|
if (canRunStylelint()) {
|
|
200
|
-
|
|
101
|
+
commands.push('npm run stylelint');
|
|
201
102
|
} else {
|
|
202
|
-
console.warn(
|
|
203
|
-
'[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
|
|
204
|
-
);
|
|
103
|
+
console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
|
|
205
104
|
}
|
|
206
105
|
|
|
207
|
-
|
|
106
|
+
const code = await runCommand(getBinName('npx'), ['concurrently', ...commands]);
|
|
107
|
+
process.exit(code);
|
|
208
108
|
}
|
|
209
109
|
|
|
210
110
|
async function runSelectiveLint(inputFiles) {
|
|
211
|
-
const hasUiSources = uiSourceFiles().length > 0;
|
|
212
111
|
const normalizedFiles = Array.from(
|
|
213
|
-
new Set(inputFiles.map(
|
|
112
|
+
new Set(inputFiles.map(normalizeProjectFile).filter(Boolean)),
|
|
214
113
|
);
|
|
215
114
|
|
|
216
115
|
if (normalizedFiles.length === 0) {
|
|
@@ -218,40 +117,15 @@ async function runSelectiveLint(inputFiles) {
|
|
|
218
117
|
process.exit(0);
|
|
219
118
|
}
|
|
220
119
|
|
|
221
|
-
const eslintFiles = normalizedFiles.filter(
|
|
222
|
-
|
|
223
|
-
fs.existsSync(path.join(cwd, file)) &&
|
|
224
|
-
isEslintTarget(file) &&
|
|
225
|
-
(!hasUiSources || (!isUiFile(file) && !file.startsWith('eslint.mcp-ui.config.')))
|
|
226
|
-
);
|
|
227
|
-
const stylelintFiles = normalizedFiles.filter(
|
|
228
|
-
file => fs.existsSync(path.join(cwd, file)) && isStylelintTarget(file)
|
|
229
|
-
);
|
|
120
|
+
const eslintFiles = normalizedFiles.filter(isEslintTarget);
|
|
121
|
+
const stylelintFiles = normalizedFiles.filter(isStylelintTarget);
|
|
230
122
|
const typeCheckFiles = normalizedFiles.filter(isTypeCheckTarget);
|
|
231
123
|
|
|
232
124
|
const clientTypeFiles = [];
|
|
233
125
|
const serverTypeFiles = [];
|
|
234
|
-
const rootConfigChanged = hasUiSources && normalizedFiles.some(file =>
|
|
235
|
-
/^tsconfig(?:\.[^/]*)?\.json$/.test(file)
|
|
236
|
-
);
|
|
237
|
-
if (rootConfigChanged) {
|
|
238
|
-
clientTypeFiles.push('config');
|
|
239
|
-
serverTypeFiles.push('config');
|
|
240
|
-
}
|
|
241
|
-
let checkUi =
|
|
242
|
-
rootConfigChanged ||
|
|
243
|
-
normalizedFiles.some(
|
|
244
|
-
file =>
|
|
245
|
-
isUiFile(file) ||
|
|
246
|
-
file.startsWith('shared/') ||
|
|
247
|
-
file.startsWith('eslint.mcp-ui.config.') ||
|
|
248
|
-
file === 'package.json'
|
|
249
|
-
);
|
|
250
126
|
|
|
251
127
|
for (const filePath of typeCheckFiles) {
|
|
252
|
-
if (
|
|
253
|
-
checkUi = true;
|
|
254
|
-
} else if (filePath.startsWith('client/')) {
|
|
128
|
+
if (filePath.startsWith('client/')) {
|
|
255
129
|
clientTypeFiles.push(filePath);
|
|
256
130
|
} else if (filePath.startsWith('server/')) {
|
|
257
131
|
serverTypeFiles.push(filePath);
|
|
@@ -261,52 +135,36 @@ async function runSelectiveLint(inputFiles) {
|
|
|
261
135
|
}
|
|
262
136
|
}
|
|
263
137
|
|
|
264
|
-
const
|
|
138
|
+
const tasks = [];
|
|
265
139
|
|
|
266
140
|
if (eslintFiles.length > 0) {
|
|
267
|
-
|
|
141
|
+
tasks.push(runCommand(getBinName('npx'), ['eslint', '--quiet', ...eslintFiles]));
|
|
268
142
|
}
|
|
269
143
|
|
|
270
144
|
if (stylelintFiles.length > 0 && !canRunStylelint()) {
|
|
271
|
-
console.warn(
|
|
272
|
-
'[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
|
|
273
|
-
);
|
|
145
|
+
console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
|
|
274
146
|
} else if (stylelintFiles.length > 0) {
|
|
275
|
-
|
|
276
|
-
getBinName('npx'),
|
|
277
|
-
['stylelint', '--quiet', ...stylelintFiles],
|
|
278
|
-
]);
|
|
147
|
+
tasks.push(runCommand(getBinName('npx'), ['stylelint', '--quiet', ...stylelintFiles]));
|
|
279
148
|
}
|
|
280
149
|
|
|
281
150
|
if (clientTypeFiles.length > 0) {
|
|
282
|
-
|
|
151
|
+
tasks.push(runCommand(getBinName('npm'), ['run', 'type:check:client']));
|
|
283
152
|
}
|
|
284
153
|
|
|
285
154
|
if (serverTypeFiles.length > 0) {
|
|
286
|
-
|
|
155
|
+
tasks.push(runCommand(getBinName('npm'), ['run', 'type:check:server']));
|
|
287
156
|
}
|
|
288
157
|
|
|
289
|
-
if (
|
|
290
|
-
|
|
291
|
-
if (taskSpecs.length === 0) {
|
|
158
|
+
if (tasks.length === 0) {
|
|
292
159
|
console.log('[lint] No supported files matched for lint');
|
|
293
160
|
process.exit(0);
|
|
294
161
|
}
|
|
295
162
|
|
|
296
|
-
|
|
163
|
+
const results = await Promise.all(tasks);
|
|
164
|
+
process.exit(results.some(code => code !== 0) ? 1 : 0);
|
|
297
165
|
}
|
|
298
166
|
|
|
299
167
|
async function main() {
|
|
300
|
-
const args = process.argv.slice(2);
|
|
301
|
-
if (args.length === 1 && args[0] === '--eslint-mcp-ui') {
|
|
302
|
-
process.exit(await runTasksSerially(uiTasks({ types: false })));
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
if (args.length && !(args[0] === '--files' && args.length > 1)) {
|
|
306
|
-
throw new Error('用法: lint.js [--files <paths...>]');
|
|
307
|
-
}
|
|
308
|
-
if (args[0] === '--files' && args.slice(1).some(arg => arg.startsWith('--')))
|
|
309
|
-
throw new Error('--files 不可与其他检查模式混用');
|
|
310
168
|
const files = parseFilesArg(process.argv.slice(2));
|
|
311
169
|
if (files === null) {
|
|
312
170
|
await runDefaultLint();
|
|
@@ -321,7 +179,7 @@ async function main() {
|
|
|
321
179
|
await runSelectiveLint(files);
|
|
322
180
|
}
|
|
323
181
|
|
|
324
|
-
main().catch(error => {
|
|
182
|
+
main().catch((error) => {
|
|
325
183
|
const message = error instanceof Error ? error.message : String(error);
|
|
326
184
|
console.error(`[lint] Failed to run lint: ${message}`);
|
|
327
185
|
process.exit(1);
|
|
@@ -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
|
-
}
|