@lark-apaas/coding-template-nestjs-react-fullstack 0.1.43-alpha.20260918074821 → 0.1.43

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
@@ -27,16 +27,6 @@ MIAODA_APP_TYPE=3 npx @lark-apaas/miaoda-cli@<latest> app init \
27
27
  - `SANDBOX_PUBLIC_URL` —— 沙箱公网域
28
28
  - `CLIENT_BASE_PATH=/app/<app_id>/` —— React Router basename + Vite base
29
29
 
30
- ## MCP UI 的类型与代码检查
31
-
32
- 创建 MCP UI 时,Agent 在 `server/mcp/ui` 中同时生成 `tsconfig.json` 和 `eslint.config.cjs`,修改 UI 或其 shared 依赖后主动运行独立检查。模板和 CLI 不生成 UI 配置,也不将 UI 检查接入主工程 lint/type:check。
33
-
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
-
36
- CLI 不注入 MCP UI 检查命令;主工程保留原有 client/server 检查,UI 由 Agent 按独立配置执行标准 tsc/eslint。
37
-
38
- 存量 sync 不改写 ESLint 源码;UI 全局排除项由平台 ESLint 预设提供。TS 仅向已有显式 `exclude` 数组追加目录,保留注释和原项;依赖继承且未显式声明 `exclude` 的自定义配置保持不变并提示人工调整。自定义检查命令保留。UI ESLint 配置可显式引用 `fullstack-presets/lib/mcp/eslint-ui`。
39
-
40
30
  ## 包结构
41
31
 
42
32
  ```
@@ -49,11 +39,3 @@ CLI 不注入 MCP UI 检查命令;主工程保留原有 client/server 检查
49
39
  `template/` 内以下划线开头的占位文件(`_gitignore` / `_npmrc` / `_env.local`)在 `miaoda app init`
50
40
  渲染时会按 RENAME 映射改回正常名(npm pack 会特殊处理 `.gitignore`、且 `.npmrc` 直接放
51
41
  在包里会污染用户 `npm install` 行为,所以都要 underscore 前缀)。
52
-
53
- ## MCP 版本与 UI 检查
54
-
55
- 模板不生成 `mcp-build-id`,构建脚本沿用原流程。SDK 发布态使用 veFaaS 函数 ID 与发布 revision;开发态使用后端编译产物指纹,UI/Skill 内容继续独立计入修订。首次升级切换版本来源后,Host 应重新发现。
56
-
57
- MCP UI 的 `tsconfig.json` 和 `eslint.config.cjs` 由 Agent 随 UI 在 `server/mcp/ui` 中创建,执行命令与完整示例见 coding-steering 的 `mcp-ui-guide`。主工程的 TS/ESLint 排除该浏览器目录,不自动运行 UI 检查;不为无 UI 的应用创建配置或检查命令。
58
-
59
- `server/mcp/ui` 与 `server/mcp/skills` 变更应由平台判为后端发布;纯前端发布不替换已部署 MCP 产物,也不承诺热更 MCP UI。发布版本号仅在实际后端发布时更新。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/coding-template-nestjs-react-fullstack",
3
- "version": "0.1.43-alpha.20260918074821",
3
+ "version": "0.1.43",
4
4
  "description": "NestJS + React fullstack template for miaoda coding",
5
5
  "type": "module",
6
6
  "files": [
@@ -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.63-alpha.20260918073530",
11
+ "@lark-apaas/fullstack-nestjs-core": "^1.1.63",
12
12
  "@nestjs/axios": "^4.0.1",
13
13
  "@nestjs/cache-manager": "^3.1.3",
14
14
  "@nestjs/common": "^10.4.20",
@@ -32,9 +32,9 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@hookform/resolvers": "^5.2.2",
35
- "@lark-apaas/client-toolkit": "^1.2.70",
36
- "@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260918073537",
37
- "@lark-apaas/fullstack-presets": "1.1.24-alpha.20260918073533",
35
+ "@lark-apaas/client-toolkit": "^1.2.72",
36
+ "@lark-apaas/coding-preset-vite-react": "^1.0.24",
37
+ "@lark-apaas/fullstack-presets": "^1.1.24",
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.20260918073529",
1550
- "resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2-alpha.20260918073529.tgz",
1551
- "integrity": "sha512-clbSkhhZ3iRRrvaE2KAtwYJwF1X1YlFgrb4LtJDnGss61PTWGNIrFJuz0HXZKTecLEzwTrro6xrdk5d8Jo1PTA==",
1549
+ "version": "0.1.2",
1550
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/cache-service/-/cache-service-0.1.2.tgz",
1551
+ "integrity": "sha512-0n24sTo1QyH/8lHs8GUcM/E+zeDau2d5Wqga8QY0A/VbjxctCtmDc8SwN1Zl8mioLNalF3QotnBsNWnOHuOw/A==",
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.20260918073532",
1565
+ "@lark-apaas/nestjs-logger": "^1.0.18",
1566
1566
  "@lark-apaas/nestjs-observable": "^0.0.12",
1567
1567
  "@nestjs/common": "^10.0.0",
1568
1568
  "@nestjs/core": "^10.0.0"
@@ -1579,9 +1579,9 @@
1579
1579
  }
1580
1580
  },
1581
1581
  "node_modules/@lark-apaas/client-toolkit": {
1582
- "version": "1.2.70",
1583
- "resolved": "https://registry.npmmirror.com/@lark-apaas/client-toolkit/-/client-toolkit-1.2.70.tgz",
1584
- "integrity": "sha512-U6vGe1DF8gq/CGRQYG0Mjr42A3hlV3yPDmAs8UP6qttiFIdXPxovpP3aJ2e2Q1p58dZ03qxsuLKXQRprubz4Hg==",
1582
+ "version": "1.2.72",
1583
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/client-toolkit/-/client-toolkit-1.2.72.tgz",
1584
+ "integrity": "sha512-+oBqT1fGLESakZjQJ1MUULxsYkTEH8rBBenu0wG+r+aGm62Upd3RcstAKCkOPOTpohrV4jgiHOifyyU8mk2NFg==",
1585
1585
  "dev": true,
1586
1586
  "dependencies": {
1587
1587
  "@ant-design/colors": "^7.2.1",
@@ -1589,7 +1589,7 @@
1589
1589
  "@lark-apaas/aily-web-sdk": "^0.0.12",
1590
1590
  "@lark-apaas/auth-sdk": "^0.1.5",
1591
1591
  "@lark-apaas/client-capability": "^0.1.7",
1592
- "@lark-apaas/dataloom": "^0.1.4",
1592
+ "@lark-apaas/dataloom": "^0.1.5",
1593
1593
  "@lark-apaas/internal-slardar": "^0.0.3",
1594
1594
  "@lark-apaas/miaoda-inspector": "^1.0.24",
1595
1595
  "@lark-apaas/observable-web": "^1.0.6",
@@ -1634,9 +1634,9 @@
1634
1634
  "license": "MIT"
1635
1635
  },
1636
1636
  "node_modules/@lark-apaas/coding-preset-vite-react": {
1637
- "version": "1.0.24-alpha.20260918073537",
1638
- "resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.24-alpha.20260918073537.tgz",
1639
- "integrity": "sha512-LdMzK/qyS349cFYFlfzYFy51SMv8UuDp/EkJtFSJzW20A4CM/k7HzIR1WXL+9Nxv4/T5MNme77M60YIKqWLKpA==",
1637
+ "version": "1.0.24",
1638
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/coding-preset-vite-react/-/coding-preset-vite-react-1.0.24.tgz",
1639
+ "integrity": "sha512-GLha4NQ4yHYY6oRUYA0j4PryGrBjMGS5pN44+VVXSJgwbq7x9T4pFWyBQYIf+FmeYQBNbTIqg19oT7hr/CJ8OA==",
1640
1640
  "dev": true,
1641
1641
  "license": "MIT",
1642
1642
  "dependencies": {
@@ -1679,9 +1679,9 @@
1679
1679
  }
1680
1680
  },
1681
1681
  "node_modules/@lark-apaas/dataloom": {
1682
- "version": "0.1.4",
1683
- "resolved": "https://registry.npmmirror.com/@lark-apaas/dataloom/-/dataloom-0.1.4.tgz",
1684
- "integrity": "sha512-jiHACjhm1pYA+XsZxFdTCEvHC5SAZ7ygBCmfqVHAis/oYZIKw2sFtqNGaZaregFvOSVhSHViTXL4up67omwcJw==",
1682
+ "version": "0.1.5",
1683
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/dataloom/-/dataloom-0.1.5.tgz",
1684
+ "integrity": "sha512-pcVZeO7QtxjzcV1SXQtUSPHO88/f1rhc3Dp/ubXVHV92W+T65Z9Adlyh3f+OdGGMhhn2+hIUnYLsLyS9gS1vhA==",
1685
1685
  "dev": true,
1686
1686
  "dependencies": {
1687
1687
  "@lark-apaas/internal-slardar": "^0.0.3"
@@ -1697,12 +1697,12 @@
1697
1697
  }
1698
1698
  },
1699
1699
  "node_modules/@lark-apaas/fullstack-nestjs-core": {
1700
- "version": "1.1.63-alpha.20260918073530",
1701
- "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.63-alpha.20260918073530.tgz",
1702
- "integrity": "sha512-j+6ZIVFu2LDPeDpm9zNhjNt8yepqwKodaau9RNcwLGLygLcurcclv+CWbuB/Qa2zY6GDUuU8vuGPrAhOU4VmRw==",
1700
+ "version": "1.1.63",
1701
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-nestjs-core/-/fullstack-nestjs-core-1.1.63.tgz",
1702
+ "integrity": "sha512-ymtOIAkqGzmGv2mcllHdthgCggJSKpY9slKYA4TMtpB/im9QJTnOeTZ1cgtKw0SJTL9Pqb3GJEGjlSqQk3/s9A==",
1703
1703
  "license": "MIT",
1704
1704
  "dependencies": {
1705
- "@lark-apaas/cache-service": "0.1.2-alpha.20260918073529",
1705
+ "@lark-apaas/cache-service": "^0.1.2",
1706
1706
  "@lark-apaas/file-service": "^0.1.2",
1707
1707
  "@lark-apaas/http-client": "^0.1.7",
1708
1708
  "@lark-apaas/nestjs-authnpaas": "^1.0.6",
@@ -1711,8 +1711,8 @@
1711
1711
  "@lark-apaas/nestjs-common": "^0.1.9",
1712
1712
  "@lark-apaas/nestjs-datapaas": "^1.0.21",
1713
1713
  "@lark-apaas/nestjs-http-forwarder": "^0.1.3",
1714
- "@lark-apaas/nestjs-logger": "1.0.18-alpha.20260918073532",
1715
- "@lark-apaas/nestjs-mcp": "0.1.1-alpha.20260918073534",
1714
+ "@lark-apaas/nestjs-logger": "^1.0.18",
1715
+ "@lark-apaas/nestjs-mcp": "^0.1.1",
1716
1716
  "@lark-apaas/nestjs-observable": "^0.0.12",
1717
1717
  "@lark-apaas/nestjs-openapi-devtools": "^1.0.10",
1718
1718
  "@lark-apaas/nestjs-trigger": "^0.0.3",
@@ -1735,9 +1735,9 @@
1735
1735
  }
1736
1736
  },
1737
1737
  "node_modules/@lark-apaas/fullstack-presets": {
1738
- "version": "1.1.24-alpha.20260918073533",
1739
- "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.24-alpha.20260918073533.tgz",
1740
- "integrity": "sha512-UZfoFSgXYo0j9K40GvCusLj/Jp5SJCZJ9nDMj/T4rKkVkJLbgUbJEOzM9er5oQM/iIpr4FL1I56njg16WeFBSA==",
1738
+ "version": "1.1.24",
1739
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/fullstack-presets/-/fullstack-presets-1.1.24.tgz",
1740
+ "integrity": "sha512-Iq1Xsv65qAI555d7eJ+0PcuVUgmNnAjjBDNuHOmocFpqeXfpbNqgVN7cE6mZchjsSRtML762QFQLKxw9NyMsxw==",
1741
1741
  "dev": true,
1742
1742
  "license": "MIT",
1743
1743
  "dependencies": {
@@ -1926,9 +1926,9 @@
1926
1926
  }
1927
1927
  },
1928
1928
  "node_modules/@lark-apaas/nestjs-logger": {
1929
- "version": "1.0.18-alpha.20260918073532",
1930
- "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18-alpha.20260918073532.tgz",
1931
- "integrity": "sha512-Ds4swvHULFVmpmN6CHqwIZuDm74OnHm9SWIiDB+bBLuZEZMpxJPnNYTtB11zddpBq1Ahsbtyw0CIb0qqaMXVqQ==",
1929
+ "version": "1.0.18",
1930
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-logger/-/nestjs-logger-1.0.18.tgz",
1931
+ "integrity": "sha512-RjucJd+TmACoNfTFw20/ppAT3gaztm3qZagPDHEZabiZxg8UpF1twbmN/VLXTF/fgpyoRFS09CMxa7nfFnrT2A==",
1932
1932
  "license": "MIT",
1933
1933
  "dependencies": {
1934
1934
  "@lark-apaas/nestjs-common": "^0.1.9",
@@ -1945,9 +1945,9 @@
1945
1945
  }
1946
1946
  },
1947
1947
  "node_modules/@lark-apaas/nestjs-mcp": {
1948
- "version": "0.1.1-alpha.20260918073534",
1949
- "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1-alpha.20260918073534.tgz",
1950
- "integrity": "sha512-tvDRUs1iE/1bIHx/76mKexi9cV7DlFXdQM1JkX2WJnhnd5Jx0AkbNHHOK2vvSV2wV0swMEd+gnaABfPVxbBrsQ==",
1948
+ "version": "0.1.1",
1949
+ "resolved": "https://registry.npmmirror.com/@lark-apaas/nestjs-mcp/-/nestjs-mcp-0.1.1.tgz",
1950
+ "integrity": "sha512-l6b3Yn6yqSxf/mpTG4bF/FFZAZyXiK7G0vVF0V8GAXtaaToRu6tQ2KlWm6JF8M7S0RB+LAeUYjNd//Zs3WeIVw==",
1951
1951
  "license": "MIT",
1952
1952
  "dependencies": {
1953
1953
  "@modelcontextprotocol/ext-apps": "^1.7.5",
@@ -28,7 +28,7 @@
28
28
  "upgrade": "npx -y @lark-apaas/fullstack-cli sync --disable-gen-openapi"
29
29
  },
30
30
  "dependencies": {
31
- "@lark-apaas/fullstack-nestjs-core": "1.1.63-alpha.20260918073530",
31
+ "@lark-apaas/fullstack-nestjs-core": "^1.1.63",
32
32
  "@nestjs/axios": "^4.0.1",
33
33
  "@nestjs/cache-manager": "^3.1.3",
34
34
  "@nestjs/common": "^10.4.20",
@@ -52,9 +52,9 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@hookform/resolvers": "^5.2.2",
55
- "@lark-apaas/client-toolkit": "^1.2.70",
56
- "@lark-apaas/coding-preset-vite-react": "1.0.24-alpha.20260918073537",
57
- "@lark-apaas/fullstack-presets": "1.1.24-alpha.20260918073533",
55
+ "@lark-apaas/client-toolkit": "^1.2.72",
56
+ "@lark-apaas/coding-preset-vite-react": "^1.0.24",
57
+ "@lark-apaas/fullstack-presets": "^1.1.24",
58
58
  "@nestjs/cli": "^10.4.9",
59
59
  "@radix-ui/react-accordion": "^1.2.12",
60
60
  "@radix-ui/react-alert-dialog": "^1.1.15",
@@ -3,7 +3,7 @@
3
3
  set -euo pipefail
4
4
 
5
5
  ROOT_DIR="$(pwd)"
6
- DIST_DIR="$ROOT_DIR/dist"
6
+ OUT_DIR="$ROOT_DIR/dist/server"
7
7
 
8
8
  # 记录总开始时间
9
9
  TOTAL_START=$(node -e "console.log(Date.now())")
@@ -19,174 +19,94 @@ print_time() {
19
19
  }
20
20
 
21
21
  # ==================== 步骤 0 ====================
22
- echo "🗑️ [0/6] 安装插件"
22
+ echo "🗑️ [0/5] 安装插件"
23
23
  STEP_START=$(node -e "console.log(Date.now())")
24
24
  npx fullstack-cli action-plugin init
25
25
  print_time $STEP_START
26
26
  echo ""
27
27
 
28
28
  # ==================== 步骤 1 ====================
29
- echo "📝 [1/6] 更新 openapi 代码"
29
+ echo "📝 [1/5] 更新 openapi 代码"
30
30
  STEP_START=$(node -e "console.log(Date.now())")
31
31
  npm run gen:openapi
32
32
  print_time $STEP_START
33
33
  echo ""
34
34
 
35
35
  # ==================== 步骤 2 ====================
36
- echo "🗑️ [2/6] 清理 dist 目录"
36
+ echo "🗑️ [2/5] 清理 dist 目录"
37
37
  STEP_START=$(node -e "console.log(Date.now())")
38
38
  rm -rf "$ROOT_DIR/dist"
39
39
  print_time $STEP_START
40
40
  echo ""
41
41
 
42
42
  # ==================== 步骤 3 ====================
43
- echo "🗺️ [3/6] 生成路由定义"
43
+ echo "🔨 [3/5] 并行构建 server 和 client"
44
44
  STEP_START=$(node -e "console.log(Date.now())")
45
45
 
46
- # 在 client/server 构建之前生成到 dist/,供 DefinePlugin 注入前端 bundle
47
- # 注意:nest-cli.json 中 deleteOutDir 必须为 false(模板默认值),否则 nest build 会清掉 dist/
48
- echo " ├─ 生成 API 路由定义..."
49
- npx generate-api-routes --server-dir ./server --out-dir ./dist > /tmp/gen-api-routes.log 2>&1 &
50
- API_ROUTES_PID=$!
46
+ # 并行构建
47
+ echo " ├─ 启动 server 构建..."
48
+ npm run build:server > /tmp/build-server.log 2>&1 &
49
+ SERVER_PID=$!
51
50
 
52
- echo " ├─ 生成页面路由定义..."
53
- npx generate-page-routes --app-path ./client/src/app.tsx --out-dir ./dist > /tmp/gen-page-routes.log 2>&1 &
54
- PAGE_ROUTES_PID=$!
51
+ echo " ├─ 启动 client 构建..."
52
+ npm run build:client > /tmp/build-client.log 2>&1 &
53
+ CLIENT_PID=$!
55
54
 
56
- API_ROUTES_EXIT=0
57
- PAGE_ROUTES_EXIT=0
55
+ # 等待两个构建完成
56
+ SERVER_EXIT=0
57
+ CLIENT_EXIT=0
58
58
 
59
- wait $API_ROUTES_PID || API_ROUTES_EXIT=$?
60
- wait $PAGE_ROUTES_PID || PAGE_ROUTES_EXIT=$?
59
+ wait $SERVER_PID || SERVER_EXIT=$?
60
+ wait $CLIENT_PID || CLIENT_EXIT=$?
61
61
 
62
- if [ $API_ROUTES_EXIT -ne 0 ]; then
63
- echo " ⚠️ API 路由生成失败(不影响构建)"
64
- cat /tmp/gen-api-routes.log
65
- else
66
- echo " ✅ API 路由生成完成"
62
+ # 检查构建结果
63
+ if [ $SERVER_EXIT -ne 0 ]; then
64
+ echo " ❌ Server 构建失败"
65
+ cat /tmp/build-server.log
66
+ exit 1
67
67
  fi
68
68
 
69
- if [ $PAGE_ROUTES_EXIT -ne 0 ]; then
70
- echo " ⚠️ 页面路由生成失败(不影响构建)"
71
- cat /tmp/gen-page-routes.log
72
- else
73
- echo " ✅ 页面路由生成完成"
69
+ if [ $CLIENT_EXIT -ne 0 ]; then
70
+ echo " ❌ Client 构建失败"
71
+ cat /tmp/build-client.log
72
+ exit 1
74
73
  fi
74
+
75
+ echo " ✅ Server 构建完成"
76
+ echo " ✅ Client 构建完成"
75
77
  print_time $STEP_START
76
78
  echo ""
77
79
 
78
80
  # ==================== 步骤 4 ====================
79
- echo "🔨 [4/6] 并行构建 server 和 client"
81
+ echo "📦 [4/5] 准备 server 依赖产物"
80
82
  STEP_START=$(node -e "console.log(Date.now())")
81
83
 
82
- # 给 server/client 构建子进程预留 8GB heap,缓解 vite build transform 阶段 OOM
83
- # (典型错误:Reached heap limit Allocation failed)。
84
- # 仅在外部未设置 NODE_OPTIONS 时注入,允许 CI / 用户通过外部环境变量完全覆盖
85
- BUILD_NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=8192}"
86
-
87
- # 根据 only_frontend_change 决定是否构建 server
88
- if [[ "${only_frontend_change:-false}" == "true" ]]; then
89
- echo "🔨 [4/6] 仅构建 client (only_frontend_change=true)"
90
-
91
- echo " ├─ 启动 client 构建..."
92
- NODE_OPTIONS="$BUILD_NODE_OPTIONS" npm run build:client > /tmp/build-client.log 2>&1
93
- CLIENT_EXIT=$?
94
-
95
- if [ $CLIENT_EXIT -ne 0 ]; then
96
- echo " ❌ Client 构建失败"
97
- cat /tmp/build-client.log
98
- exit 1
99
- fi
100
-
101
- echo " ✅ Client 构建完成"
102
- else
103
- echo "🔨 [4/6] 并行构建 server 和 client"
104
-
105
- # 并行构建
106
- echo " ├─ 启动 server 构建..."
107
- NODE_OPTIONS="$BUILD_NODE_OPTIONS" npm run build:server > /tmp/build-server.log 2>&1 &
108
- SERVER_PID=$!
109
-
110
- echo " ├─ 启动 client 构建..."
111
- NODE_OPTIONS="$BUILD_NODE_OPTIONS" npm run build:client > /tmp/build-client.log 2>&1 &
112
- CLIENT_PID=$!
113
-
114
- # 等待两个构建完成
115
- SERVER_EXIT=0
116
- CLIENT_EXIT=0
117
-
118
- wait $SERVER_PID || SERVER_EXIT=$?
119
- wait $CLIENT_PID || CLIENT_EXIT=$?
120
-
121
- # 检查构建结果
122
- if [ $SERVER_EXIT -ne 0 ]; then
123
- echo " ❌ Server 构建失败"
124
- cat /tmp/build-server.log
125
- exit 1
126
- fi
127
-
128
- if [ $CLIENT_EXIT -ne 0 ]; then
129
- echo " ❌ Client 构建失败"
130
- cat /tmp/build-client.log
131
- exit 1
132
- fi
133
-
134
- echo " ✅ Server 构建完成"
135
- echo " ✅ Client 构建完成"
136
- fi
137
-
138
- print_time $STEP_START
139
- echo ""
140
-
141
- # ==================== 步骤 5 ====================
142
- echo "📦 [5/6] 准备产物"
143
- STEP_START=$(node -e "console.log(Date.now())")
84
+ mkdir -p "$OUT_DIR/dist/client"
144
85
 
145
- # 移动 client 下的 HTML 文件到 dist/dist/client,保证 views 路径在 dev/prod 下一致
146
- # 使用 mv 而非 cp:HTML 不能上传到公网 CDN,移走后 dist/client 中不再包含 HTML
147
- if [ -d "$DIST_DIR/client" ]; then
148
- mkdir -p "$DIST_DIR/dist/client"
149
- # public 先进(顶层 client 打包被排除;server setBaseViewsDir + 中间件同源 serve)
150
- if [ -d "$ROOT_DIR/client/public" ]; then
151
- cp -R "$ROOT_DIR/client/public/." "$DIST_DIR/dist/client/"
152
- fi
153
- # 构建产物 HTML 随后 move,覆盖 public 里的同名文件(保证入口页是构建版,不被 public 静默覆盖)
154
- find "$DIST_DIR/client" -maxdepth 1 -name "*.html" -exec mv {} "$DIST_DIR/dist/client/" \;
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/"
155
89
  fi
156
90
 
157
- # server 相关产物准备(only_frontend_change=true 时跳过)
158
- if [[ "${only_frontend_change:-false}" == "true" ]]; then
159
- echo " [skip] 跳过 run.sh/.env 复制 (only_frontend_change=true)"
160
- else
161
- # 拷贝 run.sh 到 dist/(prod 从 dist/ 启动,确保 cwd 一致性)
162
- cp "$ROOT_DIR/scripts/run.sh" "$DIST_DIR/"
163
-
164
- # 拷贝 .env 文件(如果存在)
165
- if [ -f "$ROOT_DIR/.env" ]; then
166
- cp "$ROOT_DIR/.env" "$DIST_DIR/"
167
- fi
168
- fi
91
+ # 构建产物 HTML 随后拷,覆盖 public 里的同名文件(保证入口页是构建版,不被 public 静默覆盖)
92
+ cp "$ROOT_DIR/dist/client/"*.html "$OUT_DIR/dist/client/" || true
93
+
94
+ # 拷贝 run.sh 文件
95
+ cp "$ROOT_DIR/scripts/run.sh" "$OUT_DIR/"
169
96
 
170
97
  # 清理无用文件
171
- rm -rf "$DIST_DIR/scripts"
172
- rm -rf "$DIST_DIR/tsconfig.node.tsbuildinfo"
98
+ rm -rf "$ROOT_DIR/dist/scripts"
99
+ rm -rf "$ROOT_DIR/dist/tsconfig.node.tsbuildinfo"
173
100
 
174
101
  print_time $STEP_START
175
102
  echo ""
176
103
 
177
- # ==================== 步骤 6 ====================
178
- echo "✂️ [6/6] 智能依赖裁剪"
104
+ # ==================== 步骤 5 ====================
105
+ echo "✂️ [5/5] 智能依赖裁剪"
179
106
  STEP_START=$(node -e "console.log(Date.now())")
180
107
 
181
- # 智能依赖裁剪(仅全量构建时执行,纯前端场景不打包 server,无需裁剪)
182
- if [[ "${only_frontend_change:-false}" == "true" ]]; then
183
- echo "✂️ [6/6] 跳过智能依赖裁剪 (only_frontend_change=true)"
184
- else
185
- echo "✂️ [6/6] 智能依赖裁剪"
186
-
187
- # 分析实际依赖、复制并裁剪 node_modules、生成精简的 package.json
188
- node "$ROOT_DIR/scripts/prune-smart.js"
189
- fi
108
+ # 分析实际依赖、复制并裁剪 node_modules、生成精简的 package.json
109
+ node "$ROOT_DIR/scripts/prune-smart.js"
190
110
 
191
111
  print_time $STEP_START
192
112
  echo ""
@@ -196,17 +116,10 @@ echo "构建完成"
196
116
  print_time $TOTAL_START
197
117
 
198
118
  # 输出产物信息
199
- DIST_SIZE=$(du -sh "$DIST_DIR" | cut -f1)
200
- if [[ "${only_frontend_change:-false}" == "true" ]]; then
201
- echo ""
202
- echo "📊 构建产物统计:"
203
- echo " 产物大小: $DIST_SIZE"
204
- echo ""
205
- else
206
- NODE_MODULES_SIZE=$(du -sh "$DIST_DIR/node_modules" | cut -f1)
207
- echo ""
208
- echo "📊 构建产物统计:"
209
- echo " 产物大小: $DIST_SIZE"
210
- echo " node_modules: $NODE_MODULES_SIZE"
211
- echo ""
212
- fi
119
+ DIST_SIZE=$(du -sh "$OUT_DIR" | cut -f1)
120
+ NODE_MODULES_SIZE=$(du -sh "$OUT_DIR/node_modules" | cut -f1)
121
+ echo ""
122
+ echo "📊 构建产物统计:"
123
+ echo " 总大小: $DIST_SIZE"
124
+ echo " node_modules: $NODE_MODULES_SIZE"
125
+ echo ""
@@ -6,53 +6,15 @@ const fs = require('fs');
6
6
  const path = require('path');
7
7
 
8
8
  const ROOT_DIR = path.resolve(__dirname, '..');
9
-
10
- // 加载提交的 .env,供读取构建期配置(如 MIAODA_RUNTIME_ENTRIES)。dotenv 不一定安装 → 静默降级。
11
- try {
12
- require('dotenv').config({ path: path.join(ROOT_DIR, '.env') });
13
- } catch {
14
- // dotenv 未安装:跳过;MIAODA_RUNTIME_ENTRIES 仍可来自真实环境变量
15
- }
16
- const DIST_DIR = path.join(ROOT_DIR, 'dist');
17
- const DIST_SERVER_DIR = path.join(DIST_DIR, 'server');
9
+ const DIST_SERVER_DIR = path.join(ROOT_DIR, 'dist/server');
18
10
  const ROOT_PACKAGE_JSON = path.join(ROOT_DIR, 'package.json');
19
11
  const ROOT_NODE_MODULES = path.join(ROOT_DIR, 'node_modules');
20
- const OUT_NODE_MODULES = path.join(DIST_DIR, 'node_modules');
21
- const OUT_PACKAGE_JSON = path.join(DIST_DIR, 'package.json');
12
+ const OUT_NODE_MODULES = path.join(DIST_SERVER_DIR, 'node_modules');
13
+ const OUT_PACKAGE_JSON = path.join(DIST_SERVER_DIR, 'package.json');
22
14
 
23
15
  // Server 入口文件
24
16
  const SERVER_ENTRY = path.join(DIST_SERVER_DIR, 'main.js');
25
17
 
26
- // nest sourceRoot(源码根,默认 server):把 .env 里声明的源码路径映射到构建产物位置
27
- let SOURCE_ROOT = 'server';
28
- try {
29
- const nestCli = JSON.parse(fs.readFileSync(path.join(ROOT_DIR, 'nest-cli.json'), 'utf8'));
30
- if (nestCli.sourceRoot) SOURCE_ROOT = nestCli.sourceRoot;
31
- } catch {
32
- // 读不到 nest-cli.json 则用默认 server
33
- }
34
- const SRC_TO_OUT_EXT = { '.mts': '.mjs', '.cts': '.cjs', '.ts': '.js' };
35
-
36
- // 额外 trace 入口:经 new Function/动态 import 加载、nft 无法从 main.js 静态发现的 ESM runtime。
37
- // 应用在提交的 .env 里用 MIAODA_RUNTIME_ENTRIES 声明【源码路径】(相对项目根,逗号分隔),例如:
38
- // MIAODA_RUNTIME_ENTRIES=server/modules/ethics/runtime/review-run.mjs,server/modules/ethics/runtime/parse-core.mjs
39
- // 脚本按 nest sourceRoot 自动映射到 dist/server 下的构建产物(并重写 .mts→.mjs / .ts→.js)。
40
- const RUNTIME_ENTRIES = (process.env.MIAODA_RUNTIME_ENTRIES || '')
41
- .split(',')
42
- .map((s) => s.trim())
43
- .filter(Boolean)
44
- .map((srcRel) => {
45
- const fromSrc = path.relative(SOURCE_ROOT, srcRel); // 去掉 sourceRoot 前缀
46
- const ext = path.extname(fromSrc);
47
- const outRel = SRC_TO_OUT_EXT[ext] ? fromSrc.slice(0, -ext.length) + SRC_TO_OUT_EXT[ext] : fromSrc;
48
- return path.join(DIST_SERVER_DIR, outRel);
49
- })
50
- .filter((p) => {
51
- if (fs.existsSync(p)) return true;
52
- console.warn(`⚠️ MIAODA_RUNTIME_ENTRIES 入口在构建产物中不存在,已忽略: ${path.relative(ROOT_DIR, p)}`);
53
- return false;
54
- });
55
-
56
18
  // Node.js 内置模块列表
57
19
  const BUILTIN_MODULES = new Set([
58
20
  'assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns',
@@ -182,15 +144,12 @@ async function smartPrune() {
182
144
  }
183
145
 
184
146
  console.log(`📂 分析入口文件: ${path.relative(ROOT_DIR, SERVER_ENTRY)}`);
185
- if (RUNTIME_ENTRIES.length) {
186
- console.log(`📎 额外 trace 入口 (${RUNTIME_ENTRIES.length}): ${RUNTIME_ENTRIES.map((p) => path.relative(DIST_SERVER_DIR, p)).join(', ')}`);
187
- }
188
147
 
189
148
  // 2. 使用 @vercel/nft 追踪依赖
190
149
  console.log('🔎 追踪实际依赖...');
191
150
  const analyzeStart = Date.now();
192
151
 
193
- const { fileList } = await nodeFileTrace([SERVER_ENTRY, ...RUNTIME_ENTRIES], {
152
+ const { fileList } = await nodeFileTrace([SERVER_ENTRY], {
194
153
  base: ROOT_DIR,
195
154
  processCwd: ROOT_DIR,
196
155
  ts: false, // 禁用 TS 解析
@@ -221,59 +180,8 @@ async function smartPrune() {
221
180
 
222
181
  console.log(`📦 静态分析需要 ${requiredPackages.size} 个 npm 包`);
223
182
 
224
- // 4. 从 nft 结果递归收集子依赖(处理动态 require 无法被静态分析追踪的问题)
225
- // 某些包(如 pdf-parse)使用 try-catch 动态加载依赖(如 @napi-rs/canvas),
226
- // @vercel/nft 无法追踪这类依赖,需要基于 package.json 声明补充
227
- // 策略:只对 nft 已追踪到的包递归,避免收集无关依赖
183
+ // 4. 处理 actionPlugins(动态加载的插件,无法被静态分析追踪)
228
184
  const originalPackage = JSON.parse(fs.readFileSync(ROOT_PACKAGE_JSON, 'utf8'));
229
-
230
- let addedSubDeps = 0;
231
- const visited = new Set(); // 防止循环依赖导致无限循环
232
- const queue = [...requiredPackages]; // BFS 队列,从 nft 结果开始(更精准)
233
-
234
- while (queue.length > 0) {
235
- const depName = queue.shift();
236
-
237
- // 跳过已访问的包(防止循环依赖)
238
- if (visited.has(depName)) continue;
239
- visited.add(depName);
240
-
241
- const depPkgPath = path.join(ROOT_NODE_MODULES, depName, 'package.json');
242
- if (!fs.existsSync(depPkgPath)) continue;
243
-
244
- try {
245
- const depPkg = JSON.parse(fs.readFileSync(depPkgPath, 'utf8'));
246
- const subDeps = {
247
- ...depPkg.dependencies,
248
- ...depPkg.optionalDependencies,
249
- };
250
-
251
- for (const subDep of Object.keys(subDeps)) {
252
- // 检查包是否存在于 node_modules 中
253
- const subDepPath = path.join(ROOT_NODE_MODULES, subDep);
254
- if (!fs.existsSync(subDepPath)) continue;
255
-
256
- // 如果是新发现的包,添加到结果集并加入队列继续遍历
257
- if (!requiredPackages.has(subDep)) {
258
- requiredPackages.add(subDep);
259
- addedSubDeps++;
260
- }
261
-
262
- // 无论是否已在 requiredPackages 中,都需要继续遍历其子依赖
263
- if (!visited.has(subDep)) {
264
- queue.push(subDep);
265
- }
266
- }
267
- } catch {
268
- // 忽略解析错误
269
- }
270
- }
271
-
272
- if (addedSubDeps > 0) {
273
- console.log(`📦 递归补充动态依赖,新增 ${addedSubDeps} 个包`);
274
- }
275
-
276
- // 5. 处理 actionPlugins(动态加载的插件,无法被静态分析追踪)
277
185
  const actionPlugins = originalPackage.actionPlugins || {};
278
186
  const actionPluginNames = Object.keys(actionPlugins);
279
187
 
@@ -304,7 +212,7 @@ async function smartPrune() {
304
212
 
305
213
  console.log(`📦 总共需要 ${requiredPackages.size} 个 npm 包\n`);
306
214
 
307
- // 6. 选择性复制包(只复制需要的)
215
+ // 5. 选择性复制包(只复制需要的)
308
216
  console.log('📋 选择性复制 node_modules(仅复制需要的包)...');
309
217
  const copyStart = Date.now();
310
218
 
@@ -316,7 +224,7 @@ async function smartPrune() {
316
224
  console.log(` 成功: ${copiedCount.success} 个包,失败: ${copiedCount.failed} 个`);
317
225
  console.log(` 硬链接: ${fileStats.hardLinks} 个文件,复制: ${fileStats.copies} 个文件\n`);
318
226
 
319
- // 7. 生成精简版 package.json
227
+ // 6. 生成精简版 package.json
320
228
  // 优化:直接构建 dependencies,避免多次对象展开
321
229
  const prunedDependencies = {};
322
230
  const allDeps = originalPackage.dependencies || {};
@@ -335,6 +243,9 @@ async function smartPrune() {
335
243
  version: originalPackage.version,
336
244
  private: true,
337
245
  dependencies: prunedDependencies,
246
+ scripts: {
247
+ start: originalPackage.scripts?.start || 'node main.js'
248
+ },
338
249
  engines: originalPackage.engines
339
250
  };
340
251
 
@@ -342,7 +253,7 @@ async function smartPrune() {
342
253
 
343
254
  const totalElapsed = Date.now() - totalStartTime;
344
255
 
345
- // 8. 输出统计信息
256
+ // 7. 输出统计信息
346
257
  console.log('='.repeat(60));
347
258
  console.log('📊 智能裁剪统计:');
348
259
  console.log('='.repeat(60));
@@ -2,7 +2,4 @@
2
2
  # This file is auto-generated by @lark-apaas/fullstack-cli
3
3
 
4
4
  # 生产环境下,启动服务
5
- # 从 dist/ 根目录执行,确保 process.cwd() 与 dev 模式一致
6
- # dev: cwd = 项目根, shared/ client/ 可达
7
- # prod: cwd = dist/, shared/ client/ 可达
8
- NODE_ENV=production node server/main.js
5
+ npm run start
@@ -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
  }