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

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 CHANGED
@@ -29,22 +29,13 @@ MIAODA_APP_TYPE=3 npx @lark-apaas/miaoda-cli@<latest> app init \
29
29
 
30
30
  ## MCP UI 的类型与代码检查
31
31
 
32
- `server/mcp/ui` 是独立浏览器工程,主应用的 TypeScript 和 ESLint 配置排除该目录。
33
- `npm run lint` 通过现有 `scripts/lint.js` 统一调度检查:
32
+ MCP UI 使用平台预设提供的浏览器检查默认值。`npm run lint` 和 `npm run type:check` 自动覆盖 `server/mcp/ui`,模板统一提供 UI 子命令与类型配置;`lint -- --files` 保留按文件选择检查范围。没有 UI 源码时跳过 UI 检查。
34
33
 
35
- | 命令 | 检查范围 |
36
- | --- | --- |
37
- | `npm run type:check` | 服务端、客户端、MCP UI 类型检查 |
38
- | `npm run type:check:mcp-ui` | 仅 MCP UI 类型检查 |
39
- | `npm run eslint:mcp-ui` | 仅 MCP UI ESLint 检查 |
40
- | `npm run lint -- --files <files...>` | 根据改动文件选择检查范围 |
34
+ 应用增加 `type:check:mcp-ui` 子命令,与 `type:check:client`、`type:check:server` 一起由 `type:check` 聚合。`scripts/typecheck-mcp-ui.js` 只在 UI 源码存在时调用应用安装的 `tsc --noEmit --project tsconfig.mcp-ui.json`;无 UI 或目录为空时成功跳过。根目录 `tsconfig.mcp-ui.json` 提供浏览器、React JSX 和严格类型检查配置,可按应用需要修改;sync 仅在该文件不存在时创建。已有 `server/mcp/ui/tsconfig.json` 的应用优先沿用原配置,保留自定义 paths/types。
41
35
 
42
- 模板不预建 UI 目录。Agent 开发 MCP UI 时,按照 MCP 指南生成
43
- `server/mcp/ui/tsconfig.json` 和根目录 `eslint.mcp-ui.config.cjs`。
44
- 没有 UI 源码时跳过独立检查;存在源码但配置缺失或未覆盖源码时明确报错。
36
+ UI ESLint 默认配置由平台预设提供,也可用根目录 `eslint.mcp-ui.config.js` / `.cjs` / `.mjs` 定制。`npm run lint` 包含 UI 检查;`--files` 按影响范围检查,shared 变更触发三个环境的类型检查。应用脚本不使用 `node -e` 或 TypeScript 编译器 API。
45
37
 
46
- 存量应用通过本地 `miaoda app sync` 或沙箱 `fullstack-cli sync` 更新脚本、迁移已知模板命令,
47
- 并保留现有 TS 排除项。自定义检查命令会保留,开发者需自行接入独立 UI 检查。
38
+ 存量 sync 不改写 ESLint 源码;UI 全局排除项由平台 ESLint 预设提供。TS 仅向已有显式 `exclude` 数组追加目录,保留注释和原项;依赖继承且未显式声明 `exclude` 的自定义配置保持不变并提示人工调整。自定义检查命令保留。请与包含这些入口的新版 fullstack-presets 一起升级,旧版预设没有上述入口。
48
39
 
49
40
  ## 包结构
50
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-template-nestjs-react-fullstack",
3
- "version": "0.1.42-alpha.20260916160525",
3
+ "version": "0.1.42-alpha.20260917135900",
4
4
  "description": "NestJS + React fullstack template for miaoda coding",
5
5
  "type": "module",
6
6
  "files": [
@@ -9,8 +9,6 @@ module.exports = tseslint.config(
9
9
  'node_modules',
10
10
  'source_package',
11
11
  'client/src/api/gen',
12
- // MCP UI 使用独立浏览器配置,由 lint.js 使用 eslint.mcp-ui.config.cjs 独立检查。
13
- 'server/mcp/ui/**',
14
12
  '**/*.d.ts',
15
13
  '**/*.js.map',
16
14
  ],
@@ -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.62-alpha.20260916155509",
11
+ "@lark-apaas/fullstack-nestjs-core": "1.1.62-alpha.20260917134431",
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.23-alpha.20260915164951",
37
- "@lark-apaas/fullstack-presets": "^1.1.0",
36
+ "@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260917134427",
37
+ "@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917134434",
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.20260916155513",
1550
- "resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2-alpha.20260916155513.tgz",
1551
- "integrity": "sha512-GFwWlTnHu/V5CnB2p171sgDZGPXcH9bRfHmTn6nTKTv1L04i9G8GenH0h9dZpfeMI/wAZj3BE1Lw0if3vKqTrA==",
1549
+ "version": "0.1.2-alpha.20260917134428",
1550
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2-alpha.20260917134428.tgz",
1551
+ "integrity": "sha512-yOb8X6eKmP25/nGs7GACm51zkHERzwRCOSyKrSjbArK04GTv43ceq33hXW1yAbq824QbcnxHUSs7mA9wsd9djA==",
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.20260916155505",
1565
+ "@lark-apaas/nestjs-logger": "1.0.18-alpha.20260917134424",
1566
1566
  "@lark-apaas/nestjs-observable": "^0.0.12",
1567
1567
  "@nestjs/common": "^10.0.0",
1568
1568
  "@nestjs/core": "^10.0.0"
@@ -1634,15 +1634,16 @@
1634
1634
  "license": "MIT"
1635
1635
  },
1636
1636
  "node_modules/@lark-apaas/coding-preset-vite-react": {
1637
- "version": "1.0.23-alpha.20260915164951",
1638
- "resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.23-alpha.20260915164951.tgz",
1639
- "integrity": "sha512-5QRc/9rXGp9GYP7ISD9nN99Jt8/NHzro3BnSj3QezaAzBBzH5OMFQOySK3BKFVqvWvnXTNpTiAzt9EioGiVNWQ==",
1637
+ "version": "1.0.24-alpha.20260917134427",
1638
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.24-alpha.20260917134427.tgz",
1639
+ "integrity": "sha512-SYLR5P80cbKodxDDrM/zQ/aIYUP/oNqRAU3YxE22HZcoKSrmkfiSqGE/q90oLXzTpjSvZrtxKtD5VngkKKOriw==",
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",
1646
1647
  "@lark-apaas/vite-inspector-plugin": "^1.0.4",
1647
1648
  "@tailwindcss/vite": "^4.3.0",
1648
1649
  "@vitejs/plugin-react": "^6.0.0",
@@ -1655,8 +1656,6 @@
1655
1656
  "express": "^4.18.2",
1656
1657
  "html-minifier-terser": "^7.2.0",
1657
1658
  "magic-string": "~0.30.18",
1658
- "parse5": "^7.3.0",
1659
- "postcss-value-parser": "^4.2.0",
1660
1659
  "tailwind-merge": "^2.5.5"
1661
1660
  },
1662
1661
  "peerDependencies": {
@@ -1697,12 +1696,12 @@
1697
1696
  }
1698
1697
  },
1699
1698
  "node_modules/@lark-apaas/fullstack-nestjs-core": {
1700
- "version": "1.1.62-alpha.20260916155509",
1701
- "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.62-alpha.20260916155509.tgz",
1702
- "integrity": "sha512-Bjdx84abQUxCu10Y98w7hUZt0QtLeJI2g9CtxE0mXCjy9mg5r/WgcKORgNPUdQayETrzDQbvJYWo2Bn3BstRiA==",
1699
+ "version": "1.1.62-alpha.20260917134431",
1700
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.62-alpha.20260917134431.tgz",
1701
+ "integrity": "sha512-Ia1QwvIYJy+7nwJWyB5gc58rgYo2WrVSZF+U6GGxTPlc0Rvvy4CwEQYJN2sgVC3pIkRHi5LdQeGL431SFknmIQ==",
1703
1702
  "license": "MIT",
1704
1703
  "dependencies": {
1705
- "@lark-apaas/cache-service": "0.1.2-alpha.20260916155513",
1704
+ "@lark-apaas/cache-service": "0.1.2-alpha.20260917134428",
1706
1705
  "@lark-apaas/file-service": "^0.1.2",
1707
1706
  "@lark-apaas/http-client": "^0.1.7",
1708
1707
  "@lark-apaas/nestjs-authnpaas": "^1.0.6",
@@ -1711,8 +1710,8 @@
1711
1710
  "@lark-apaas/nestjs-common": "^0.1.9",
1712
1711
  "@lark-apaas/nestjs-datapaas": "^1.0.21",
1713
1712
  "@lark-apaas/nestjs-http-forwarder": "^0.1.3",
1714
- "@lark-apaas/nestjs-logger": "1.0.18-alpha.20260916155505",
1715
- "@lark-apaas/nestjs-mcp": "0.1.1-alpha.20260916155510",
1713
+ "@lark-apaas/nestjs-logger": "1.0.18-alpha.20260917134424",
1714
+ "@lark-apaas/nestjs-mcp": "0.1.1-alpha.20260917134425",
1716
1715
  "@lark-apaas/nestjs-observable": "^0.0.12",
1717
1716
  "@lark-apaas/nestjs-openapi-devtools": "^1.0.10",
1718
1717
  "@lark-apaas/nestjs-trigger": "^0.0.3",
@@ -1735,12 +1734,14 @@
1735
1734
  }
1736
1735
  },
1737
1736
  "node_modules/@lark-apaas/fullstack-presets": {
1738
- "version": "1.1.23",
1739
- "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.23.tgz",
1740
- "integrity": "sha512-hE1jr2kIs3H1AgU+EcBbT/lyjLFRrXVwEj72JT6t4TOLh7MYSR6IwTC4ZTdZE168utDlgx5n5GH53ttts7LdwA==",
1737
+ "version": "1.1.24-alpha.20260917134434",
1738
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.24-alpha.20260917134434.tgz",
1739
+ "integrity": "sha512-gXQn+Gm5eeTDmoPPJBfBxlWQDFuLtRJ5UL8rIzC6aZR4IHgJv1n6yds22hxwe8xjgfpzJyxby5zyWCAPSy36Kg==",
1741
1740
  "dev": true,
1742
1741
  "license": "MIT",
1743
1742
  "dependencies": {
1743
+ "@babel/parser": "^7.28.0",
1744
+ "@babel/traverse": "^7.28.0",
1744
1745
  "@darraghor/eslint-plugin-nestjs-typed": "^6.9.1",
1745
1746
  "@eslint/js": "^9.35.0",
1746
1747
  "@types/node": "^22.19.1",
@@ -1751,12 +1752,20 @@
1751
1752
  "eslint-plugin-react": "^7.37.5",
1752
1753
  "eslint-plugin-react-hooks": "^5.2.0",
1753
1754
  "globals": "^16.4.0",
1755
+ "parse5": "^7.3.0",
1756
+ "postcss-value-parser": "^4.2.0",
1754
1757
  "stylelint": "^17.3.0",
1755
1758
  "tailwindcss-animate": "^1.0.7"
1756
1759
  },
1757
1760
  "peerDependencies": {
1758
1761
  "eslint": "^9.0.0",
1759
- "typescript-eslint": "^8.44.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
+ }
1760
1769
  }
1761
1770
  },
1762
1771
  "node_modules/@lark-apaas/hey-api-custom-client-axios": {
@@ -1926,9 +1935,9 @@
1926
1935
  }
1927
1936
  },
1928
1937
  "node_modules/@lark-apaas/nestjs-logger": {
1929
- "version": "1.0.18-alpha.20260916155505",
1930
- "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18-alpha.20260916155505.tgz",
1931
- "integrity": "sha512-h+pNe2zobyku8PYxr49z64pr7rn/FyrPrF/Lb4KVcnnyvlxG5P+9ZMv0R4nFi24C1G5ZgZJ/JiSHgQGknpKmrw==",
1938
+ "version": "1.0.18-alpha.20260917134424",
1939
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18-alpha.20260917134424.tgz",
1940
+ "integrity": "sha512-o15uXqDlyov/L2iZmEuIzKKqvjZtebdisrYQo8goem241ZdJQYJEZvBLTstmVmaJsvHVSv7nVgpEwR3vG1fsqw==",
1932
1941
  "license": "MIT",
1933
1942
  "dependencies": {
1934
1943
  "@lark-apaas/nestjs-common": "^0.1.9",
@@ -1945,9 +1954,9 @@
1945
1954
  }
1946
1955
  },
1947
1956
  "node_modules/@lark-apaas/nestjs-mcp": {
1948
- "version": "0.1.1-alpha.20260916155510",
1949
- "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1-alpha.20260916155510.tgz",
1950
- "integrity": "sha512-J/cz53jY6nvzrsvVuV9/fsYwHKFbEjprAekPhB0sfPGp4839ycPULA3qFvkbqFzk8jSpXG9q0B3uyol4yI93ZQ==",
1957
+ "version": "0.1.1-alpha.20260917134425",
1958
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1-alpha.20260917134425.tgz",
1959
+ "integrity": "sha512-ddUclgr+QmUmq0IrM43BDMLdQyEEdbZ7qCn3X1UkxF0AgkfWgqEGEVpWUycAMRY9u123gEmufoN0pYV2qlhTlA==",
1951
1960
  "license": "MIT",
1952
1961
  "dependencies": {
1953
1962
  "@modelcontextprotocol/ext-apps": "^1.7.5",
@@ -9993,18 +10002,18 @@
9993
10002
  "license": "MIT"
9994
10003
  },
9995
10004
  "node_modules/array-includes": {
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==",
10005
+ "version": "3.2.0",
10006
+ "resolved": "https://registry.npmmirror.com/array-includes/-/array-includes-3.2.0.tgz",
10007
+ "integrity": "sha512-VXY5eFRarnXcYxwBjJzPmEhH55+rmP79/+ueDhi0F+TuqfHCItagIHqxeUZrmgrOPa31QTh9H85DjX3FfJ0FTg==",
9999
10008
  "dev": true,
10000
10009
  "license": "MIT",
10001
10010
  "dependencies": {
10002
- "call-bind": "^1.0.8",
10011
+ "call-bind": "^1.0.9",
10003
10012
  "call-bound": "^1.0.4",
10004
10013
  "define-properties": "^1.2.1",
10005
- "es-abstract": "^1.24.0",
10006
- "es-object-atoms": "^1.1.1",
10007
- "get-intrinsic": "^1.3.0",
10014
+ "es-abstract": "^1.24.2",
10015
+ "es-object-atoms": "^1.1.2",
10016
+ "es-shim-unscopables": "^1.1.0",
10008
10017
  "is-string": "^1.1.1",
10009
10018
  "math-intrinsics": "^1.1.0"
10010
10019
  },
@@ -12840,9 +12849,9 @@
12840
12849
  }
12841
12850
  },
12842
12851
  "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
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==",
12852
+ "version": "1.1.21",
12853
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.21.tgz",
12854
+ "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
12846
12855
  "dev": true,
12847
12856
  "license": "MIT",
12848
12857
  "dependencies": {
@@ -12896,16 +12905,6 @@
12896
12905
  "semver": "bin/semver.js"
12897
12906
  }
12898
12907
  },
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
- },
12909
12908
  "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": {
12910
12909
  "version": "3.15.0",
12911
12910
  "resolved": "https://registry.npmmirror.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
@@ -12966,9 +12965,9 @@
12966
12965
  }
12967
12966
  },
12968
12967
  "node_modules/eslint-plugin-react/node_modules/brace-expansion": {
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==",
12968
+ "version": "1.1.21",
12969
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.21.tgz",
12970
+ "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==",
12972
12971
  "dev": true,
12973
12972
  "license": "MIT",
12974
12973
  "dependencies": {
@@ -13541,9 +13540,9 @@
13541
13540
  "license": "MIT"
13542
13541
  },
13543
13542
  "node_modules/fast-uri": {
13544
- "version": "3.1.7",
13545
- "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.7.tgz",
13546
- "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
13543
+ "version": "3.1.8",
13544
+ "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.8.tgz",
13545
+ "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
13547
13546
  "funding": [
13548
13547
  {
13549
13548
  "type": "github",
@@ -14291,9 +14290,9 @@
14291
14290
  }
14292
14291
  },
14293
14292
  "node_modules/glob/node_modules/brace-expansion": {
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==",
14293
+ "version": "5.0.12",
14294
+ "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.12.tgz",
14295
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
14297
14296
  "dev": true,
14298
14297
  "license": "MIT",
14299
14298
  "dependencies": {
@@ -14685,9 +14684,9 @@
14685
14684
  }
14686
14685
  },
14687
14686
  "node_modules/hono": {
14688
- "version": "4.13.7",
14689
- "resolved": "https://registry.npmmirror.com/hono/-/hono-4.13.7.tgz",
14690
- "integrity": "sha512-c8/gF9ac8Y78/agExVocyLevgR+JlpNB444Py0FSX8pJoPdYUfUzRcXtYEYGwt6l19qIlVZPN5Mfsw9jFShmQQ==",
14687
+ "version": "4.13.8",
14688
+ "resolved": "https://registry.npmmirror.com/hono/-/hono-4.13.8.tgz",
14689
+ "integrity": "sha512-/Gng7NfoykZl2pjukW5Z6+8Yxm3BPRf86GTbQnt0SbySkvax4fyL4H3HhY1cCpBGmiW9XDRFzRV+CXK2W8QudQ==",
14691
14690
  "license": "MIT",
14692
14691
  "engines": {
14693
14692
  "node": ">=16.9.0"
@@ -15026,9 +15025,9 @@
15026
15025
  }
15027
15026
  },
15028
15027
  "node_modules/ip-address": {
15029
- "version": "10.7.0",
15030
- "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.7.0.tgz",
15031
- "integrity": "sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA==",
15028
+ "version": "10.7.2",
15029
+ "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.7.2.tgz",
15030
+ "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==",
15032
15031
  "license": "MIT",
15033
15032
  "engines": {
15034
15033
  "node": ">= 12"
@@ -16400,6 +16399,16 @@
16400
16399
  "url": "https://github.com/sponsors/sindresorhus"
16401
16400
  }
16402
16401
  },
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
+ },
16403
16412
  "node_modules/lucide-react": {
16404
16413
  "version": "0.577.0",
16405
16414
  "resolved": "https://registry.npmmirror.com/lucide-react/-/lucide-react-0.577.0.tgz",
@@ -18472,16 +18481,6 @@
18472
18481
  "url": "https://github.com/sponsors/isaacs"
18473
18482
  }
18474
18483
  },
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
- },
18485
18484
  "node_modules/path-to-regexp": {
18486
18485
  "version": "3.3.0",
18487
18486
  "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz",
@@ -21247,6 +21246,16 @@
21247
21246
  "node": ">=8"
21248
21247
  }
21249
21248
  },
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
+ },
21250
21259
  "node_modules/strip-dirs": {
21251
21260
  "version": "3.0.0",
21252
21261
  "resolved": "https://registry.npmmirror.com/strip-dirs/-/strip-dirs-3.0.0.tgz",
@@ -22201,16 +22210,6 @@
22201
22210
  "node": ">=10.13.0"
22202
22211
  }
22203
22212
  },
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
- },
22214
22213
  "node_modules/tslib": {
22215
22214
  "version": "2.8.1",
22216
22215
  "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
@@ -22302,19 +22301,18 @@
22302
22301
  }
22303
22302
  },
22304
22303
  "node_modules/typed-array-byte-offset": {
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==",
22304
+ "version": "1.0.5",
22305
+ "resolved": "https://registry.npmmirror.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.5.tgz",
22306
+ "integrity": "sha512-0FHJvLPqZ7KJzp17O13jfsAjsqazgrxBu2zEK95PmUz8lv2+GjRuxUInCr2Rk9Dms3ihN21zJ929ZO43yJ95QQ==",
22308
22307
  "dev": true,
22309
22308
  "license": "MIT",
22310
22309
  "dependencies": {
22311
22310
  "available-typed-arrays": "^1.0.7",
22312
- "call-bind": "^1.0.8",
22313
- "for-each": "^0.3.3",
22311
+ "call-bind": "^1.0.9",
22312
+ "for-each": "^0.3.5",
22314
22313
  "gopd": "^1.2.0",
22315
- "has-proto": "^1.2.0",
22316
22314
  "is-typed-array": "^1.1.15",
22317
- "reflect.getprototypeof": "^1.0.9"
22315
+ "reflect.getprototypeof": "^1.0.10"
22318
22316
  },
22319
22317
  "engines": {
22320
22318
  "node": ">= 0.4"
@@ -23416,9 +23414,9 @@
23416
23414
  }
23417
23415
  },
23418
23416
  "node_modules/which-typed-array": {
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==",
23417
+ "version": "1.1.23",
23418
+ "resolved": "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.23.tgz",
23419
+ "integrity": "sha512-JMh8aK+1B/0bk/YNupICmH5MgCq6yNLKYQUfsZtSDLLCCmxUkHjUY+oOlIa90lO7lHN1woAfpenLdlKpXy9o+A==",
23422
23420
  "dev": true,
23423
23421
  "license": "MIT",
23424
23422
  "dependencies": {
@@ -18,19 +18,18 @@
18
18
  "build:server": "NODE_ENV=production nest build",
19
19
  "build:client": "NODE_ENV=production vite build --config vite.config.ts",
20
20
  "start": "NODE_ENV=production node main.js",
21
- "eslint": "eslint . --quiet --ignore-pattern \"server/mcp/ui/**\"",
21
+ "eslint": "eslint . --quiet",
22
22
  "stylelint": "stylelint client/src/**/*.css --quiet",
23
- "type:check": "node ./scripts/lint.js --typecheck",
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\"",
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
28
  "upgrade": "npx -y @lark-apaas/fullstack-cli sync --disable-gen-openapi",
29
- "type:check:mcp-ui": "node ./scripts/lint.js --typecheck-mcp-ui",
30
- "eslint:mcp-ui": "node ./scripts/lint.js --eslint-mcp-ui"
29
+ "type:check:mcp-ui": "node ./scripts/typecheck-mcp-ui.js"
31
30
  },
32
31
  "dependencies": {
33
- "@lark-apaas/fullstack-nestjs-core": "1.1.62-alpha.20260916155509",
32
+ "@lark-apaas/fullstack-nestjs-core": "1.1.62-alpha.20260917134431",
34
33
  "@nestjs/axios": "^4.0.1",
35
34
  "@nestjs/cache-manager": "^3.1.3",
36
35
  "@nestjs/common": "^10.4.20",
@@ -55,8 +54,8 @@
55
54
  "devDependencies": {
56
55
  "@hookform/resolvers": "^5.2.2",
57
56
  "@lark-apaas/client-toolkit": "^1.2.70",
58
- "@lark-apaas/coding-preset-vite-react": "1.0.23-alpha.20260915164951",
59
- "@lark-apaas/fullstack-presets": "^1.1.0",
57
+ "@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260917134427",
58
+ "@lark-apaas/fullstack-presets": "1.1.24-alpha.20260917134434",
60
59
  "@nestjs/cli": "^10.4.9",
61
60
  "@radix-ui/react-accordion": "^1.2.12",
62
61
  "@radix-ui/react-alert-dialog": "^1.1.15",
@@ -1,41 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const path = require('node:path');
4
- const { spawn } = require('node:child_process');
5
4
  const fs = require('node:fs');
5
+ const { spawn } = require('node:child_process');
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 ?? 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
9
  function normalizeProjectFile(filePath) {
40
10
  const absolutePath = path.isAbsolute(filePath)
41
11
  ? filePath
@@ -46,7 +16,11 @@ function normalizeProjectFile(filePath) {
46
16
  }
47
17
 
48
18
  const relativePath = path.relative(cwd, absolutePath);
49
- if (relativePath.startsWith('..')) {
19
+ if (
20
+ relativePath === '..' ||
21
+ relativePath.startsWith(`..${path.sep}`) ||
22
+ path.isAbsolute(relativePath)
23
+ ) {
50
24
  console.warn(`[lint] Skip file outside project: ${filePath}`);
51
25
  return null;
52
26
  }
@@ -103,16 +77,43 @@ function canRunStylelint() {
103
77
 
104
78
  if (!pkg.scripts || !pkg.scripts.stylelint) return false;
105
79
 
106
- return STYLELINT_CONFIG_FILES.some(file => fs.existsSync(path.join(cwd, file)));
80
+ return STYLELINT_CONFIG_FILES.some(file =>
81
+ fs.existsSync(path.join(cwd, file))
82
+ );
107
83
  }
108
84
 
109
- const UI_DIR = 'server/mcp/ui';
110
- const UI_TYPECHECK = 'node ./scripts/lint.js --typecheck';
85
+ function getBinName(name) {
86
+ return process.platform === 'win32' ? `${name}.cmd` : name;
87
+ }
111
88
 
112
- function isUiFile(file) {
113
- return file.startsWith(`${UI_DIR}/`);
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
+ });
114
100
  }
115
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
+
116
117
  function uiSourceFiles() {
117
118
  const files = [];
118
119
  function visit(relative) {
@@ -124,9 +125,11 @@ function uiSourceFiles() {
124
125
  for (const entry of fs.readdirSync(absolute, { withFileTypes: true })) {
125
126
  if (['node_modules', 'dist', '.git'].includes(entry.name)) continue;
126
127
  const file = `${relative}/${entry.name}`;
127
- if (entry.isSymbolicLink()) throw new Error(`MCP UI 检查不支持符号链接: ${file}`);
128
+ if (entry.isSymbolicLink())
129
+ throw new Error(`MCP UI 检查不支持符号链接: ${file}`);
128
130
  if (entry.isDirectory()) visit(file);
129
- else if (isEslintTarget(file) && !/\.d\.(?:ts|mts|cts)$/.test(file)) files.push(file);
131
+ else if (isEslintTarget(file) && !/\.d\.(?:ts|mts|cts)$/.test(file))
132
+ files.push(file);
130
133
  }
131
134
  }
132
135
  visit(UI_DIR);
@@ -137,43 +140,50 @@ function uiTasks({ types = true, eslint = true } = {}) {
137
140
  const sources = uiSourceFiles();
138
141
  if (!sources.length) return [];
139
142
  const tasks = [];
140
- if (types) {
141
- const config = `${UI_DIR}/tsconfig.json`;
142
- if (!fs.existsSync(path.join(cwd, config))) {
143
- throw new Error(`MCP UI 缺少 ${config},请按 mcp-guide 补齐独立浏览器 TypeScript 配置。`);
144
- }
145
- const ts = require('typescript');
146
- const parsed = ts.getParsedCommandLineOfConfigFile(path.join(cwd, config), {}, {
147
- ...ts.sys,
148
- onUnRecoverableConfigFileDiagnostic: d => { throw new Error(ts.flattenDiagnosticMessageText(d.messageText, '\n')); },
149
- });
150
- if (!parsed || parsed.errors.length) throw new Error(`MCP UI TypeScript 配置无效: ${config}`);
151
- const included = new Set(parsed.fileNames.map(file => path.resolve(file)));
152
- const missing = sources.filter(file => !included.has(path.resolve(cwd, file)));
153
- if (missing.length) throw new Error(`MCP UI TypeScript 配置未覆盖源码: ${missing.join(', ')};请检查 include/exclude,JS 源码需开启 allowJs。`);
154
- tasks.push([getBinName('npx'), ['--no-install', 'tsc', '--noEmit', '-p', config]]);
155
- }
143
+ if (types) tasks.push([getBinName('npm'), ['run', 'type:check:mcp-ui']]);
156
144
  if (eslint) {
157
- const config = ['eslint.mcp-ui.config.js', 'eslint.mcp-ui.config.cjs', 'eslint.mcp-ui.config.mjs']
158
- .find(file => fs.existsSync(path.join(cwd, file)));
159
- if (!config) throw new Error('MCP UI 缺少独立 ESLint 配置,请按 mcp-guide 创建 eslint.mcp-ui.config.cjs。');
160
- tasks.push([getBinName('npx'), ['--no-install', 'eslint', '--config', config, '--quiet', '--max-warnings', '0', ...sources]]);
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
+ ]);
161
174
  }
162
175
  return tasks;
163
176
  }
164
177
 
165
178
  function packageScripts() {
166
- return JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8')).scripts || {};
179
+ return (
180
+ JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'))
181
+ .scripts || {}
182
+ );
167
183
  }
168
184
 
169
- async function runTypeCheck() {
170
- const scripts = packageScripts();
171
- const tasks = ['type:check:server', 'type:check:client'].map(name => {
172
- if (!scripts[name]) throw new Error(`缺少 scripts.${name},请保留应用原有类型检查命令。`);
173
- return [getBinName('npm'), ['run', name]];
174
- });
175
- tasks.push(...uiTasks({ eslint: false }));
176
- process.exit(await runTasksSerially(tasks));
185
+ function isUiFile(file) {
186
+ return file.startsWith('server/mcp/ui/');
177
187
  }
178
188
 
179
189
  async function runDefaultLint() {
@@ -182,13 +192,21 @@ async function runDefaultLint() {
182
192
  [getBinName('npm'), ['run', 'type:check']],
183
193
  ];
184
194
 
185
- // Customized type:check remains untouched; ensure full lint still checks UI.
186
- taskSpecs.push(...uiTasks({ types: packageScripts()['type:check'] !== UI_TYPECHECK }));
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
+ );
187
203
 
188
204
  if (canRunStylelint()) {
189
205
  taskSpecs.push([getBinName('npm'), ['run', 'stylelint']]);
190
206
  } else {
191
- console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
207
+ console.warn(
208
+ '[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
209
+ );
192
210
  }
193
211
 
194
212
  process.exit(await runTasksSerially(taskSpecs));
@@ -196,7 +214,7 @@ async function runDefaultLint() {
196
214
 
197
215
  async function runSelectiveLint(inputFiles) {
198
216
  const normalizedFiles = Array.from(
199
- new Set(inputFiles.map(normalizeProjectFile).filter(Boolean)),
217
+ new Set(inputFiles.map(normalizeProjectFile).filter(Boolean))
200
218
  );
201
219
 
202
220
  if (normalizedFiles.length === 0) {
@@ -204,15 +222,36 @@ async function runSelectiveLint(inputFiles) {
204
222
  process.exit(0);
205
223
  }
206
224
 
207
- const eslintFiles = normalizedFiles.filter(file => fs.existsSync(path.join(cwd, file)) && isEslintTarget(file) && !isUiFile(file) && !file.startsWith('eslint.mcp-ui.config.'));
208
- const stylelintFiles = normalizedFiles.filter(file => fs.existsSync(path.join(cwd, file)) && isStylelintTarget(file));
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
+ );
209
235
  const typeCheckFiles = normalizedFiles.filter(isTypeCheckTarget);
210
236
 
211
237
  const clientTypeFiles = [];
212
238
  const serverTypeFiles = [];
213
- const rootConfigChanged = normalizedFiles.some(file => /^tsconfig(?:\.[^/]*)?\.json$/.test(file));
214
- if (rootConfigChanged) { clientTypeFiles.push('config'); serverTypeFiles.push('config'); }
215
- let checkUi = rootConfigChanged || normalizedFiles.some(file => isUiFile(file) || file.startsWith('shared/') || file.startsWith('eslint.mcp-ui.config.'));
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
+ );
216
255
 
217
256
  for (const filePath of typeCheckFiles) {
218
257
  if (isUiFile(filePath)) {
@@ -234,9 +273,14 @@ async function runSelectiveLint(inputFiles) {
234
273
  }
235
274
 
236
275
  if (stylelintFiles.length > 0 && !canRunStylelint()) {
237
- console.warn('[lint] Skip stylelint: missing scripts.stylelint or stylelint config');
276
+ console.warn(
277
+ '[lint] Skip stylelint: missing scripts.stylelint or stylelint config'
278
+ );
238
279
  } else if (stylelintFiles.length > 0) {
239
- taskSpecs.push([getBinName('npx'), ['stylelint', '--quiet', ...stylelintFiles]]);
280
+ taskSpecs.push([
281
+ getBinName('npx'),
282
+ ['stylelint', '--quiet', ...stylelintFiles],
283
+ ]);
240
284
  }
241
285
 
242
286
  if (clientTypeFiles.length > 0) {
@@ -259,14 +303,15 @@ async function runSelectiveLint(inputFiles) {
259
303
 
260
304
  async function main() {
261
305
  const args = process.argv.slice(2);
262
- const modes = ['--typecheck', '--typecheck-mcp-ui', '--eslint-mcp-ui'];
263
- if (args.length && !(args[0] === '--files' && args.length > 1) && !(args.length === 1 && modes.includes(args[0]))) {
264
- throw new Error('用法: lint.js [--files <paths...> | --typecheck | --typecheck-mcp-ui | --eslint-mcp-ui]');
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...>]');
265
312
  }
266
- if (args[0] === '--files' && args.slice(1).some(arg => arg.startsWith('--'))) throw new Error('--files 不可与其他检查模式混用');
267
- if (args.includes('--typecheck')) return runTypeCheck();
268
- if (args.includes('--typecheck-mcp-ui')) return process.exit(await runTasksSerially(uiTasks({ eslint: false })));
269
- if (args.includes('--eslint-mcp-ui')) return process.exit(await runTasksSerially(uiTasks({ types: false })));
313
+ if (args[0] === '--files' && args.slice(1).some(arg => arg.startsWith('--')))
314
+ throw new Error('--files 不可与其他检查模式混用');
270
315
  const files = parseFilesArg(process.argv.slice(2));
271
316
  if (files === null) {
272
317
  await runDefaultLint();
@@ -281,7 +326,7 @@ async function main() {
281
326
  await runSelectiveLint(files);
282
327
  }
283
328
 
284
- main().catch((error) => {
329
+ main().catch(error => {
285
330
  const message = error instanceof Error ? error.message : String(error);
286
331
  console.error(`[lint] Failed to run lint: ${message}`);
287
332
  process.exit(1);
@@ -0,0 +1,32 @@
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
+ }
@@ -0,0 +1,33 @@
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
+ }