@tokcalc/mcp-server 0.1.1 → 0.1.3

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.
Files changed (192) hide show
  1. package/.zscripts/build.sh +175 -0
  2. package/.zscripts/database-runtime-build.sh +33 -0
  3. package/.zscripts/dev.pid +1 -0
  4. package/.zscripts/dev.sh +154 -0
  5. package/.zscripts/mini-services-build.sh +78 -0
  6. package/.zscripts/mini-services-install.sh +65 -0
  7. package/.zscripts/mini-services-start.sh +123 -0
  8. package/.zscripts/python-runtime-build.sh +120 -0
  9. package/.zscripts/start.sh +145 -0
  10. package/CAPACITY_STUDY.md +283 -0
  11. package/CODE_OF_CONDUCT.md +55 -0
  12. package/CONTRIBUTING.md +177 -0
  13. package/Caddyfile +23 -0
  14. package/LICENSE +204 -0
  15. package/README.md +406 -86
  16. package/bun.lock +1965 -0
  17. package/components.json +21 -0
  18. package/db/custom.db +0 -0
  19. package/download/README.md +1 -0
  20. package/download/tokcalc-dark-calculator.png +0 -0
  21. package/download/tokcalc-dark-default.png +0 -0
  22. package/download/tokcalc-demo.webm +0 -0
  23. package/download/tokcalc-github-link.png +0 -0
  24. package/download/tokcalc-hydration-fixed.png +0 -0
  25. package/download/tokcalc-issue-resolved.png +0 -0
  26. package/download/tokcalc-light-mode.png +0 -0
  27. package/download/tokcalc-light-reference.png +0 -0
  28. package/download/tokcalc-long-context-qwen.png +0 -0
  29. package/download/tokcalc-long-context.png +0 -0
  30. package/download/tokcalc-og-image-preview.png +0 -0
  31. package/download/tokcalc-phase2-3.png +0 -0
  32. package/download/tokcalc-plain-english.png +0 -0
  33. package/download/tokcalc-preview.png +0 -0
  34. package/download/tokcalc-share-bvb.png +0 -0
  35. package/download/tokcalc-share-feature.png +0 -0
  36. package/download/tokcalc-tab-build-vs-buy.png +0 -0
  37. package/download/tokcalc-tab-calculator.png +0 -0
  38. package/download/tokcalc-tab-reference.png +0 -0
  39. package/eslint.config.mjs +50 -0
  40. package/examples/websocket/frontend.tsx +196 -0
  41. package/examples/websocket/server.ts +138 -0
  42. package/mini-services/.gitkeep +0 -0
  43. package/mini-services/mcp-server/README.md +86 -0
  44. package/mini-services/mcp-server/bun.lock +202 -0
  45. package/mini-services/mcp-server/index.ts +504 -0
  46. package/mini-services/mcp-server/package.json +40 -0
  47. package/next.config.ts +12 -0
  48. package/package.json +92 -35
  49. package/postcss.config.mjs +5 -0
  50. package/prisma/schema.prisma +32 -0
  51. package/public/google6f58ca6be85fa903.html +1 -0
  52. package/public/logo.svg +29 -0
  53. package/public/manifest.json +51 -0
  54. package/public/og-icon-256.png +0 -0
  55. package/public/og.png +0 -0
  56. package/public/robots.txt +25 -0
  57. package/public/sitemap.xml +23 -0
  58. package/public/tokcalc-demo.gif +0 -0
  59. package/scripts/og-template.html +120 -0
  60. package/scripts/render-og.mjs +43 -0
  61. package/server.json +21 -0
  62. package/src/app/api/pricing/aws/route.ts +186 -0
  63. package/src/app/api/pricing/azure/route.ts +168 -0
  64. package/src/app/api/pricing/gcp/route.ts +230 -0
  65. package/src/app/api/pricing/vast-ai/route.ts +164 -0
  66. package/src/app/api/route.ts +5 -0
  67. package/src/app/compare/h100-vs-h200/layout.tsx +30 -0
  68. package/src/app/compare/h100-vs-h200/page.tsx +328 -0
  69. package/src/app/globals.css +122 -0
  70. package/src/app/layout.tsx +276 -0
  71. package/src/app/page.tsx +2670 -0
  72. package/src/components/azure-live-pricing.tsx +185 -0
  73. package/src/components/benchmark-import.tsx +340 -0
  74. package/src/components/confidence-badge.tsx +116 -0
  75. package/src/components/live-pricing-comparison.tsx +241 -0
  76. package/src/components/theme-provider.tsx +11 -0
  77. package/src/components/theme-toggle.tsx +55 -0
  78. package/src/components/ui/accordion.tsx +66 -0
  79. package/src/components/ui/alert-dialog.tsx +157 -0
  80. package/src/components/ui/alert.tsx +66 -0
  81. package/src/components/ui/aspect-ratio.tsx +11 -0
  82. package/src/components/ui/avatar.tsx +53 -0
  83. package/src/components/ui/badge.tsx +46 -0
  84. package/src/components/ui/breadcrumb.tsx +109 -0
  85. package/src/components/ui/button.tsx +59 -0
  86. package/src/components/ui/calendar.tsx +213 -0
  87. package/src/components/ui/card.tsx +92 -0
  88. package/src/components/ui/carousel.tsx +241 -0
  89. package/src/components/ui/chart.tsx +353 -0
  90. package/src/components/ui/checkbox.tsx +32 -0
  91. package/src/components/ui/collapsible.tsx +33 -0
  92. package/src/components/ui/command.tsx +184 -0
  93. package/src/components/ui/context-menu.tsx +252 -0
  94. package/src/components/ui/dialog.tsx +143 -0
  95. package/src/components/ui/drawer.tsx +135 -0
  96. package/src/components/ui/dropdown-menu.tsx +257 -0
  97. package/src/components/ui/form.tsx +167 -0
  98. package/src/components/ui/hover-card.tsx +44 -0
  99. package/src/components/ui/input-otp.tsx +77 -0
  100. package/src/components/ui/input.tsx +21 -0
  101. package/src/components/ui/label.tsx +24 -0
  102. package/src/components/ui/menubar.tsx +276 -0
  103. package/src/components/ui/navigation-menu.tsx +168 -0
  104. package/src/components/ui/pagination.tsx +127 -0
  105. package/src/components/ui/popover.tsx +48 -0
  106. package/src/components/ui/progress.tsx +31 -0
  107. package/src/components/ui/radio-group.tsx +45 -0
  108. package/src/components/ui/resizable.tsx +56 -0
  109. package/src/components/ui/scroll-area.tsx +58 -0
  110. package/src/components/ui/select.tsx +185 -0
  111. package/src/components/ui/separator.tsx +28 -0
  112. package/src/components/ui/sheet.tsx +139 -0
  113. package/src/components/ui/sidebar.tsx +726 -0
  114. package/src/components/ui/skeleton.tsx +13 -0
  115. package/src/components/ui/slider.tsx +63 -0
  116. package/src/components/ui/sonner.tsx +25 -0
  117. package/src/components/ui/switch.tsx +31 -0
  118. package/src/components/ui/table.tsx +116 -0
  119. package/src/components/ui/tabs.tsx +66 -0
  120. package/src/components/ui/textarea.tsx +18 -0
  121. package/src/components/ui/toast.tsx +129 -0
  122. package/src/components/ui/toaster.tsx +35 -0
  123. package/src/components/ui/toggle-group.tsx +73 -0
  124. package/src/components/ui/toggle.tsx +47 -0
  125. package/src/components/ui/tooltip.tsx +61 -0
  126. package/src/components/vast-ai-live-pricing.tsx +176 -0
  127. package/src/hooks/use-mobile.ts +19 -0
  128. package/src/hooks/use-toast.ts +194 -0
  129. package/src/lib/benchmark-parser-sglang.ts +150 -0
  130. package/src/lib/benchmark-parser-tokcalc.ts +247 -0
  131. package/src/lib/benchmark-parser-trtllm.ts +152 -0
  132. package/src/lib/benchmark-parser-vllm.ts +198 -0
  133. package/src/lib/benchmark-schema.ts +263 -0
  134. package/src/lib/db.ts +13 -0
  135. package/src/lib/engine-presets.ts +183 -0
  136. package/src/lib/price-schema.ts +141 -0
  137. package/src/lib/token-calc.ts +808 -0
  138. package/src/lib/track.ts +31 -0
  139. package/src/lib/url-state.ts +256 -0
  140. package/src/lib/utils.ts +6 -0
  141. package/tailwind.config.ts +64 -0
  142. package/tests/database-runtime-build.sh +75 -0
  143. package/tests/python-runtime-build.sh +64 -0
  144. package/tests/python-runtime-container.sh +31 -0
  145. package/tool-results/bash_1789888171144_2c5381860539.txt +161 -0
  146. package/tool-results/bash_1789888175925_49c53ba3c61b.txt +191 -0
  147. package/tool-results/bash_1789888181202_49c53ba3c61b.txt +191 -0
  148. package/tool-results/bash_1789888195219_4a86a5c91411.txt +200 -0
  149. package/tool-results/bash_1789888203128_6cca13c71b47.txt +199 -0
  150. package/tool-results/bash_1789929256963_2a52aff0d0a8.txt +160 -0
  151. package/tool-results/read_1789888151021_69f58eec6a5b.txt +653 -0
  152. package/tool-results/read_1789888153837_1d3a8bfc2a94.txt +653 -0
  153. package/tool-results/read_1789888163087_ccc406d47505.txt +122 -0
  154. package/tool-results/read_1789888167347_67d1d7c9830a.txt +122 -0
  155. package/tool-results/read_1789929252529_d90e8f383a25.txt +285 -0
  156. package/tsconfig.json +42 -0
  157. package/upload/Pasted Content_1789887800864.txt +652 -0
  158. package/upload/Pasted Content_1789887909561.txt +652 -0
  159. package/upload/Pasted Content_1789887918428.txt +652 -0
  160. package/upload/Pasted Content_1789887959420.txt +652 -0
  161. package/upload/Pasted Content_1789888020485.txt +652 -0
  162. package/upload/Pasted Content_1789888058079.txt +652 -0
  163. package/upload/Pasted Content_1789888885033.txt +686 -0
  164. package/upload/Pasted Content_1789928912741.txt +285 -0
  165. package/upload/Pasted Content_1789928938402.txt +285 -0
  166. package/upload/Pasted Content_1789929160389.txt +285 -0
  167. package/upload/Pasted Content_1789929176660.txt +285 -0
  168. package/upload/issue_vision.json +28 -0
  169. package/upload/pasted_image_1789883175209.png +0 -0
  170. package/upload/pasted_image_1789899056690.png +0 -0
  171. package/upload/pasted_image_1789900371483.png +0 -0
  172. package/upload/pasted_image_1789900472823.png +0 -0
  173. package/upload/pasted_image_1789900490374.png +0 -0
  174. package/upload/pasted_image_1789900585552.png +0 -0
  175. package/upload/pasted_image_1789900606519.png +0 -0
  176. package/upload/pasted_image_1789901598705.png +0 -0
  177. package/upload/pasted_image_1789901613545.png +0 -0
  178. package/upload/pasted_image_1789978382674.png +0 -0
  179. package/upload/pasted_image_1789978392749.png +0 -0
  180. package/upload/pasted_image_1789978474879.png +0 -0
  181. package/upload/pasted_image_1789978523652.png +0 -0
  182. package/upload/pasted_image_1789984219089.png +0 -0
  183. package/upload/pasted_image_1789984491896.png +0 -0
  184. package/upload/pasted_image_1789985017950.png +0 -0
  185. package/upload/pasted_image_1789985036765.png +0 -0
  186. package/upload/pasted_image_1789985049848.png +0 -0
  187. package/upload/pasted_image_1790002427833.png +0 -0
  188. package/upload/pasted_image_1790002659944.png +0 -0
  189. package/upload/pasted_image_1790037038476.png +0 -0
  190. package/upload/screenshot_analysis.json +28 -0
  191. package/upload/vision_output.json +28 -0
  192. package/dist/index.js +0 -21014
@@ -0,0 +1,175 @@
1
+ #!/bin/bash
2
+
3
+ # 将 stderr 重定向到 stdout,避免 execute_command 因为 stderr 输出而报错
4
+ exec 2>&1
5
+
6
+ set -e
7
+
8
+ # 获取脚本所在目录(.zscripts 目录,即 workspace-agent/.zscripts)
9
+ # 使用 $0 获取脚本路径(兼容 sh 和 bash)
10
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
11
+
12
+ # Next.js 项目路径
13
+ NEXTJS_PROJECT_DIR="/home/z/my-project"
14
+
15
+ # 检查 Next.js 项目目录是否存在
16
+ if [ ! -d "$NEXTJS_PROJECT_DIR" ]; then
17
+ echo "❌ 错误: Next.js 项目目录不存在: $NEXTJS_PROJECT_DIR"
18
+ exit 1
19
+ fi
20
+
21
+ echo "🚀 开始构建 Next.js 应用和 mini-services..."
22
+ echo "📁 Next.js 项目路径: $NEXTJS_PROJECT_DIR"
23
+
24
+ # 切换到 Next.js 项目目录
25
+ cd "$NEXTJS_PROJECT_DIR" || exit 1
26
+
27
+ # 设置环境变量
28
+ export NEXT_TELEMETRY_DISABLED=1
29
+
30
+ BUILD_DIR="/tmp/build_fullstack_$BUILD_ID"
31
+ echo "📁 清理并创建构建目录: $BUILD_DIR"
32
+ mkdir -p "$BUILD_DIR"
33
+
34
+ # 安装依赖
35
+ echo "📦 安装依赖..."
36
+ bun install
37
+
38
+ # 构建 Next.js 应用
39
+ echo "🔨 构建 Next.js 应用..."
40
+ bun run build
41
+
42
+ # 校验 standalone 服务端入口是否生成(部署成功率守卫)。
43
+ # Next 仅在 next.config 含 output:"standalone" 时产出 .next/standalone/server.js。
44
+ # 若用户/AI 编辑项目时改写或删除了该配置,bun run build 仍会成功(static 照常
45
+ # 产出、退出码 0),但 standalone 缺失——打出的包里没有 server.js,部署到 FC 后
46
+ # start.sh 找不到 next-service-dist/server.js → 不启动 Next → Caddy:81 反代空的
47
+ # 3000 → FC 健康检查 120s 超时失败(线上 warmup_412 / FunctionNotStarted 的主因)。
48
+ # 这里做一次自愈:仅在确实缺失时,给 next.config 补回 output:"standalone" 并重建。
49
+ # 正常项目(已生成 server.js)整段跳过,不读写任何用户文件。
50
+ if [ ! -f ".next/standalone/server.js" ]; then
51
+ echo "⚠️ 构建未产出 .next/standalone/server.js,开始自愈 next.config 的 output 配置..."
52
+ NEXT_CONFIG_FILE="$(ls next.config.ts next.config.js next.config.mjs next.config.cjs 2>/dev/null | head -1)"
53
+
54
+ if [ -z "$NEXT_CONFIG_FILE" ]; then
55
+ echo "❌ 构建失败:未找到 next.config.*,无法生成 standalone 部署产物。"
56
+ exit 1
57
+ fi
58
+
59
+ if grep -Eq "output\s*:\s*['\"]standalone['\"]" "$NEXT_CONFIG_FILE"; then
60
+ # 已声明 standalone 却仍没产出 server.js,说明不是配置缺失(可能 build 真
61
+ # 出错、自定义 distDir 等)。不臆改用户配置,直接失败并暴露原因。
62
+ echo "❌ 构建失败:$NEXT_CONFIG_FILE 已含 output:\"standalone\",但仍未生成 .next/standalone/server.js。"
63
+ echo " 请检查上方构建日志中的报错或项目自定义的构建配置。"
64
+ exit 1
65
+ fi
66
+
67
+ if grep -Eq "output\s*:\s*['\"]" "$NEXT_CONFIG_FILE"; then
68
+ # 已显式声明了其它 output(如 "export" 静态导出 / "standalone" 之外的值)。
69
+ # "export" 与本部署模型(standalone + 自定义 server)互斥——不能注入第二个
70
+ # output 覆盖用户意图(JS 对象重复 key 后者生效,注入也无效)。明确失败。
71
+ echo "❌ 构建失败:$NEXT_CONFIG_FILE 已声明非 standalone 的 output(如 \"export\" 静态导出),与当前部署模型不兼容。"
72
+ echo " 当前部署需要 output:\"standalone\"。请改为 standalone,或确认该项目是否应走静态托管而非部署沙箱。"
73
+ exit 1
74
+ fi
75
+
76
+ echo "🔧 检测到 $NEXT_CONFIG_FILE 缺少 output:\"standalone\",自动注入后重新构建..."
77
+ cp "$NEXT_CONFIG_FILE" "${NEXT_CONFIG_FILE}.zbak"
78
+ # 在第一个配置对象字面量起始的 { 之后插入 output:"standalone",
79
+ # 覆盖脚手架常见写法:const nextConfig...= { / export default { / module.exports = {
80
+ perl -0pi -e 's/((?:const\s+\w+[^=]*=|export\s+default|module\.exports\s*=)\s*\{)/$1\n output: "standalone",/' "$NEXT_CONFIG_FILE"
81
+
82
+ if ! grep -Eq "output\s*:\s*['\"]standalone['\"]" "$NEXT_CONFIG_FILE"; then
83
+ echo "❌ 未能匹配到可注入的配置对象,next.config 写法非常规,需人工添加 output:\"standalone\"。"
84
+ echo " 当前 $NEXT_CONFIG_FILE 内容:"
85
+ cat "$NEXT_CONFIG_FILE"
86
+ mv "${NEXT_CONFIG_FILE}.zbak" "$NEXT_CONFIG_FILE"
87
+ exit 1
88
+ fi
89
+
90
+ echo "🔨 已注入 output:\"standalone\",重新构建..."
91
+ bun run build
92
+
93
+ if [ ! -f ".next/standalone/server.js" ]; then
94
+ echo "❌ 注入 output:\"standalone\" 并重建后,仍未生成 .next/standalone/server.js。"
95
+ exit 1
96
+ fi
97
+ echo "✅ 自愈成功:standalone 服务端入口已生成。"
98
+ fi
99
+
100
+ # 构建 mini-services
101
+ # 检查 Next.js 项目目录下是否有 mini-services 目录
102
+ if [ -d "$NEXTJS_PROJECT_DIR/mini-services" ]; then
103
+ echo "🔨 构建 mini-services..."
104
+ # 使用 workspace-agent 目录下的 mini-services 脚本
105
+ sh "$SCRIPT_DIR/mini-services-install.sh"
106
+ sh "$SCRIPT_DIR/mini-services-build.sh"
107
+
108
+ # 复制 mini-services-start.sh 到 mini-services-dist 目录
109
+ echo " - 复制 mini-services-start.sh 到 $BUILD_DIR"
110
+ cp "$SCRIPT_DIR/mini-services-start.sh" "$BUILD_DIR/mini-services-start.sh"
111
+ chmod +x "$BUILD_DIR/mini-services-start.sh"
112
+ else
113
+ echo "ℹ️ mini-services 目录不存在,跳过"
114
+ fi
115
+
116
+ # 将所有构建产物复制到临时构建目录
117
+ echo "📦 收集构建产物到 $BUILD_DIR..."
118
+
119
+ # 复制 Next.js standalone 构建输出
120
+ if [ -d ".next/standalone" ]; then
121
+ echo " - 复制 .next/standalone"
122
+ cp -r .next/standalone "$BUILD_DIR/next-service-dist/"
123
+ fi
124
+
125
+ # 复制 Next.js 静态文件
126
+ if [ -d ".next/static" ]; then
127
+ echo " - 复制 .next/static"
128
+ mkdir -p "$BUILD_DIR/next-service-dist/.next"
129
+ cp -r .next/static "$BUILD_DIR/next-service-dist/.next/"
130
+ fi
131
+
132
+ # 复制 public 目录
133
+ if [ -d "public" ]; then
134
+ echo " - 复制 public"
135
+ cp -r public "$BUILD_DIR/next-service-dist/"
136
+ fi
137
+
138
+ # Python 不继承 workspace-agent 的 /home/z/.venv。若项目包含 Python 源码或
139
+ # 依赖清单,在构建期将生产依赖固化到产物,并保持 Python 源码的项目相对路径。
140
+ PROJECT_DIR="$NEXTJS_PROJECT_DIR" BUILD_DIR="$BUILD_DIR" \
141
+ bash "$SCRIPT_DIR/python-runtime-build.sh"
142
+
143
+ # 有 Preview 数据库时复制现有数据;没有时直接在部署产物中初始化空库。
144
+ # 模板源码不携带 db/custom.db,不能依赖 dev.sh 必须在 Deploy 前成功运行过。
145
+ PROJECT_DIR="$NEXTJS_PROJECT_DIR" BUILD_DIR="$BUILD_DIR" \
146
+ bash "$SCRIPT_DIR/database-runtime-build.sh"
147
+
148
+ # 复制 Caddyfile(如果存在)
149
+ if [ -f "Caddyfile" ]; then
150
+ echo " - 复制 Caddyfile"
151
+ cp Caddyfile "$BUILD_DIR/"
152
+ else
153
+ echo "ℹ️ Caddyfile 不存在,跳过"
154
+ fi
155
+
156
+ # 复制 start.sh 脚本
157
+ echo " - 复制 start.sh 到 $BUILD_DIR"
158
+ cp "$SCRIPT_DIR/start.sh" "$BUILD_DIR/start.sh"
159
+ chmod +x "$BUILD_DIR/start.sh"
160
+
161
+ # 打包到 $BUILD_DIR.tar.gz
162
+ PACKAGE_FILE="${BUILD_DIR}.tar.gz"
163
+ echo ""
164
+ echo "📦 打包构建产物到 $PACKAGE_FILE..."
165
+ cd "$BUILD_DIR" || exit 1
166
+ tar -czf "$PACKAGE_FILE" .
167
+ cd - > /dev/null || exit 1
168
+
169
+ # # 清理临时目录
170
+ # rm -rf "$BUILD_DIR"
171
+
172
+ echo ""
173
+ echo "✅ 构建完成!所有产物已打包到 $PACKAGE_FILE"
174
+ echo "📊 打包文件大小:"
175
+ ls -lh "$PACKAGE_FILE"
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ PROJECT_DIR="${PROJECT_DIR:-/home/z/my-project}"
6
+ BUILD_DIR="${BUILD_DIR:?BUILD_DIR is required}"
7
+ SOURCE_DB_DIR="$PROJECT_DIR/db"
8
+ SOURCE_DB_PATH="$SOURCE_DB_DIR/custom.db"
9
+ TARGET_DB_DIR="$BUILD_DIR/db"
10
+ TARGET_DB_PATH="$TARGET_DB_DIR/custom.db"
11
+
12
+ mkdir -p "$TARGET_DB_DIR"
13
+
14
+ if [ -f "$SOURCE_DB_PATH" ]; then
15
+ echo "🗄️ 复制 Preview 数据库到构建产物..."
16
+ cp -a "$SOURCE_DB_DIR/." "$TARGET_DB_DIR/"
17
+ else
18
+ echo "ℹ️ 未找到 Preview 数据库 db/custom.db,将初始化空的生产数据库"
19
+ fi
20
+
21
+ echo "🗄️ 同步构建产物中的数据库结构..."
22
+ (
23
+ cd "$PROJECT_DIR"
24
+ DATABASE_URL="file:$TARGET_DB_PATH" bun run db:push
25
+ )
26
+
27
+ if [ ! -f "$TARGET_DB_PATH" ]; then
28
+ echo "❌ 数据库初始化命令执行成功,但未生成 $TARGET_DB_PATH"
29
+ exit 1
30
+ fi
31
+
32
+ echo "✅ 构建产物数据库已准备完成"
33
+ ls -lah "$TARGET_DB_DIR"
@@ -0,0 +1 @@
1
+ 1204
@@ -0,0 +1,154 @@
1
+ #!/bin/bash
2
+
3
+ set -euo pipefail
4
+
5
+ # 获取脚本所在目录(.zscripts)
6
+ # 使用 $0 获取脚本路径(与 build.sh 保持一致)
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
9
+
10
+ log_step_start() {
11
+ local step_name="$1"
12
+ echo "=========================================="
13
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting: $step_name"
14
+ echo "=========================================="
15
+ export STEP_START_TIME
16
+ STEP_START_TIME=$(date +%s)
17
+ }
18
+
19
+ log_step_end() {
20
+ local step_name="${1:-Unknown step}"
21
+ local end_time
22
+ end_time=$(date +%s)
23
+ local duration=$((end_time - STEP_START_TIME))
24
+ echo "=========================================="
25
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] Completed: $step_name"
26
+ echo "[LOG] Step: $step_name | Duration: ${duration}s"
27
+ echo "=========================================="
28
+ echo ""
29
+ }
30
+
31
+ start_mini_services() {
32
+ local mini_services_dir="$PROJECT_DIR/mini-services"
33
+ local started_count=0
34
+
35
+ log_step_start "Starting mini-services"
36
+ if [ ! -d "$mini_services_dir" ]; then
37
+ echo "Mini-services directory not found, skipping..."
38
+ log_step_end "Starting mini-services"
39
+ return 0
40
+ fi
41
+
42
+ echo "Found mini-services directory, scanning for sub-services..."
43
+
44
+ for service_dir in "$mini_services_dir"/*; do
45
+ if [ ! -d "$service_dir" ]; then
46
+ continue
47
+ fi
48
+
49
+ local service_name
50
+ service_name=$(basename "$service_dir")
51
+ echo "Checking service: $service_name"
52
+
53
+ if [ ! -f "$service_dir/package.json" ]; then
54
+ echo "[$service_name] No package.json found, skipping..."
55
+ continue
56
+ fi
57
+
58
+ if ! grep -q '"dev"' "$service_dir/package.json"; then
59
+ echo "[$service_name] No dev script found, skipping..."
60
+ continue
61
+ fi
62
+
63
+ echo "Starting $service_name in background..."
64
+ (
65
+ cd "$service_dir"
66
+ echo "[$service_name] Installing dependencies..."
67
+ bun install
68
+ echo "[$service_name] Running bun run dev..."
69
+ exec bun run dev
70
+ ) >"$PROJECT_DIR/.zscripts/mini-service-${service_name}.log" 2>&1 &
71
+
72
+ local service_pid=$!
73
+ echo "[$service_name] Started in background (PID: $service_pid)"
74
+ echo "[$service_name] Log: $PROJECT_DIR/.zscripts/mini-service-${service_name}.log"
75
+ disown "$service_pid" 2>/dev/null || true
76
+ started_count=$((started_count + 1))
77
+ done
78
+
79
+ echo "Mini-services startup completed. Started $started_count service(s)."
80
+ log_step_end "Starting mini-services"
81
+ }
82
+
83
+ wait_for_service() {
84
+ local host="$1"
85
+ local port="$2"
86
+ local service_name="$3"
87
+ local max_attempts="${4:-60}"
88
+ local attempt=1
89
+
90
+ echo "Waiting for $service_name to be ready on $host:$port..."
91
+
92
+ while [ "$attempt" -le "$max_attempts" ]; do
93
+ if curl -s --connect-timeout 2 --max-time 5 "http://$host:$port" >/dev/null 2>&1; then
94
+ echo "$service_name is ready!"
95
+ return 0
96
+ fi
97
+
98
+ echo "Attempt $attempt/$max_attempts: $service_name not ready yet, waiting..."
99
+ sleep 1
100
+ attempt=$((attempt + 1))
101
+ done
102
+
103
+ echo "ERROR: $service_name failed to start within $max_attempts seconds"
104
+ return 1
105
+ }
106
+
107
+ cleanup() {
108
+ if [ -n "${DEV_PID:-}" ] && kill -0 "$DEV_PID" >/dev/null 2>&1; then
109
+ echo "Stopping Next.js dev server (PID: $DEV_PID)..."
110
+ kill "$DEV_PID" >/dev/null 2>&1 || true
111
+ fi
112
+ }
113
+
114
+ trap cleanup EXIT INT TERM
115
+
116
+ cd "$PROJECT_DIR"
117
+
118
+ if ! command -v bun >/dev/null 2>&1; then
119
+ echo "ERROR: bun is not installed or not in PATH"
120
+ exit 1
121
+ fi
122
+
123
+ log_step_start "bun install"
124
+ echo "[BUN] Installing dependencies..."
125
+ bun install
126
+ log_step_end "bun install"
127
+
128
+ log_step_start "bun run db:push"
129
+ echo "[BUN] Setting up database..."
130
+ bun run db:push
131
+ log_step_end "bun run db:push"
132
+
133
+ log_step_start "Starting Next.js dev server"
134
+ echo "[BUN] Starting development server..."
135
+ bun run dev &
136
+ DEV_PID=$!
137
+ log_step_end "Starting Next.js dev server"
138
+
139
+ log_step_start "Waiting for Next.js dev server"
140
+ wait_for_service "localhost" "3000" "Next.js dev server"
141
+ log_step_end "Waiting for Next.js dev server"
142
+
143
+ log_step_start "Health check"
144
+ echo "[BUN] Performing health check..."
145
+ curl -fsS localhost:3000 >/dev/null
146
+ echo "[BUN] Health check passed"
147
+ log_step_end "Health check"
148
+
149
+ start_mini_services
150
+
151
+ echo "Next.js dev server is running in background (PID: $DEV_PID)."
152
+ echo "Use 'kill $DEV_PID' to stop it."
153
+ disown "$DEV_PID" 2>/dev/null || true
154
+ unset DEV_PID
@@ -0,0 +1,78 @@
1
+ #!/bin/bash
2
+
3
+ # 配置项
4
+ ROOT_DIR="/home/z/my-project/mini-services"
5
+ DIST_DIR="/tmp/build_fullstack_$BUILD_ID/mini-services-dist"
6
+
7
+ main() {
8
+ echo "🚀 开始批量构建..."
9
+
10
+ # 检查 rootdir 是否存在
11
+ if [ ! -d "$ROOT_DIR" ]; then
12
+ echo "ℹ️ 目录 $ROOT_DIR 不存在,跳过构建"
13
+ return
14
+ fi
15
+
16
+ # 创建输出目录(如果不存在)
17
+ mkdir -p "$DIST_DIR"
18
+
19
+ # 统计变量
20
+ success_count=0
21
+ fail_count=0
22
+
23
+ # 遍历 mini-services 目录下的所有文件夹
24
+ for dir in "$ROOT_DIR"/*; do
25
+ # 检查是否是目录且包含 package.json
26
+ if [ -d "$dir" ] && [ -f "$dir/package.json" ]; then
27
+ project_name=$(basename "$dir")
28
+
29
+ # 智能查找入口文件 (按优先级查找)
30
+ entry_path=""
31
+ for entry in "src/index.ts" "index.ts" "src/index.js" "index.js"; do
32
+ if [ -f "$dir/$entry" ]; then
33
+ entry_path="$dir/$entry"
34
+ break
35
+ fi
36
+ done
37
+
38
+ if [ -z "$entry_path" ]; then
39
+ echo "⚠️ 跳过 $project_name: 未找到入口文件 (index.ts/js)"
40
+ continue
41
+ fi
42
+
43
+ echo ""
44
+ echo "📦 正在构建: $project_name..."
45
+
46
+ # 使用 bun build CLI 构建
47
+ output_file="$DIST_DIR/mini-service-$project_name.js"
48
+
49
+ if bun build "$entry_path" \
50
+ --outfile "$output_file" \
51
+ --target bun \
52
+ --minify; then
53
+ echo "✅ $project_name 构建成功 -> $output_file"
54
+ success_count=$((success_count + 1))
55
+ else
56
+ echo "❌ $project_name 构建失败"
57
+ fail_count=$((fail_count + 1))
58
+ fi
59
+ fi
60
+ done
61
+
62
+ if [ -f ./.zscripts/mini-services-start.sh ]; then
63
+ cp ./.zscripts/mini-services-start.sh "$DIST_DIR/mini-services-start.sh"
64
+ chmod +x "$DIST_DIR/mini-services-start.sh"
65
+ fi
66
+
67
+ echo ""
68
+ echo "🎉 所有任务完成!"
69
+ if [ $success_count -gt 0 ] || [ $fail_count -gt 0 ]; then
70
+ echo "✅ 成功: $success_count 个"
71
+ if [ $fail_count -gt 0 ]; then
72
+ echo "❌ 失败: $fail_count 个"
73
+ fi
74
+ fi
75
+ }
76
+
77
+ main
78
+
@@ -0,0 +1,65 @@
1
+ #!/bin/bash
2
+
3
+ # 配置项
4
+ ROOT_DIR="/home/z/my-project/mini-services"
5
+
6
+ main() {
7
+ echo "🚀 开始批量安装依赖..."
8
+
9
+ # 检查 rootdir 是否存在
10
+ if [ ! -d "$ROOT_DIR" ]; then
11
+ echo "ℹ️ 目录 $ROOT_DIR 不存在,跳过安装"
12
+ return
13
+ fi
14
+
15
+ # 统计变量
16
+ success_count=0
17
+ fail_count=0
18
+ failed_projects=""
19
+
20
+ # 遍历 mini-services 目录下的所有文件夹
21
+ for dir in "$ROOT_DIR"/*; do
22
+ # 检查是否是目录且包含 package.json
23
+ if [ -d "$dir" ] && [ -f "$dir/package.json" ]; then
24
+ project_name=$(basename "$dir")
25
+ echo ""
26
+ echo "📦 正在安装依赖: $project_name..."
27
+
28
+ # 进入项目目录并执行 bun install
29
+ if (cd "$dir" && bun install); then
30
+ echo "✅ $project_name 依赖安装成功"
31
+ success_count=$((success_count + 1))
32
+ else
33
+ echo "❌ $project_name 依赖安装失败"
34
+ fail_count=$((fail_count + 1))
35
+ if [ -z "$failed_projects" ]; then
36
+ failed_projects="$project_name"
37
+ else
38
+ failed_projects="$failed_projects $project_name"
39
+ fi
40
+ fi
41
+ fi
42
+ done
43
+
44
+ # 汇总结果
45
+ echo ""
46
+ echo "=================================================="
47
+ if [ $success_count -gt 0 ] || [ $fail_count -gt 0 ]; then
48
+ echo "🎉 安装完成!"
49
+ echo "✅ 成功: $success_count 个"
50
+ if [ $fail_count -gt 0 ]; then
51
+ echo "❌ 失败: $fail_count 个"
52
+ echo ""
53
+ echo "失败的项目:"
54
+ for project in $failed_projects; do
55
+ echo " - $project"
56
+ done
57
+ fi
58
+ else
59
+ echo "ℹ️ 未找到任何包含 package.json 的项目"
60
+ fi
61
+ echo "=================================================="
62
+ }
63
+
64
+ main
65
+
@@ -0,0 +1,123 @@
1
+ #!/bin/sh
2
+
3
+ # 配置项
4
+ DIST_DIR="./mini-services-dist"
5
+
6
+ # 存储所有子进程的 PID
7
+ pids=""
8
+
9
+ # 清理函数:优雅关闭所有服务
10
+ cleanup() {
11
+ echo ""
12
+ echo "🛑 正在关闭所有服务..."
13
+
14
+ # 发送 SIGTERM 信号给所有子进程
15
+ for pid in $pids; do
16
+ if kill -0 "$pid" 2>/dev/null; then
17
+ service_name=$(ps -p "$pid" -o comm= 2>/dev/null || echo "unknown")
18
+ echo " 关闭进程 $pid ($service_name)..."
19
+ kill -TERM "$pid" 2>/dev/null
20
+ fi
21
+ done
22
+
23
+ # 等待所有进程退出(最多等待 5 秒)
24
+ sleep 1
25
+ for pid in $pids; do
26
+ if kill -0 "$pid" 2>/dev/null; then
27
+ # 如果还在运行,等待最多 4 秒
28
+ timeout=4
29
+ while [ $timeout -gt 0 ] && kill -0 "$pid" 2>/dev/null; do
30
+ sleep 1
31
+ timeout=$((timeout - 1))
32
+ done
33
+ # 如果仍然在运行,强制关闭
34
+ if kill -0 "$pid" 2>/dev/null; then
35
+ echo " 强制关闭进程 $pid..."
36
+ kill -KILL "$pid" 2>/dev/null
37
+ fi
38
+ fi
39
+ done
40
+
41
+ echo "✅ 所有服务已关闭"
42
+ }
43
+
44
+ main() {
45
+ echo "🚀 开始启动所有 mini services..."
46
+
47
+ # 检查 dist 目录是否存在
48
+ if [ ! -d "$DIST_DIR" ]; then
49
+ echo "ℹ️ 目录 $DIST_DIR 不存在"
50
+ return
51
+ fi
52
+
53
+ # 查找所有 mini-service-*.js 文件
54
+ service_files=""
55
+ for file in "$DIST_DIR"/mini-service-*.js; do
56
+ if [ -f "$file" ]; then
57
+ if [ -z "$service_files" ]; then
58
+ service_files="$file"
59
+ else
60
+ service_files="$service_files $file"
61
+ fi
62
+ fi
63
+ done
64
+
65
+ # 计算服务文件数量
66
+ service_count=0
67
+ for file in $service_files; do
68
+ service_count=$((service_count + 1))
69
+ done
70
+
71
+ if [ $service_count -eq 0 ]; then
72
+ echo "ℹ️ 未找到任何 mini service 文件"
73
+ return
74
+ fi
75
+
76
+ echo "📦 找到 $service_count 个服务,开始启动..."
77
+ echo ""
78
+
79
+ # 启动每个服务
80
+ for file in $service_files; do
81
+ service_name=$(basename "$file" .js | sed 's/mini-service-//')
82
+ echo "▶️ 启动服务: $service_name..."
83
+
84
+ # 使用 bun 运行服务(后台运行)
85
+ bun "$file" &
86
+ pid=$!
87
+ if [ -z "$pids" ]; then
88
+ pids="$pid"
89
+ else
90
+ pids="$pids $pid"
91
+ fi
92
+
93
+ # 等待一小段时间检查进程是否成功启动
94
+ sleep 0.5
95
+ if ! kill -0 "$pid" 2>/dev/null; then
96
+ echo "❌ $service_name 启动失败"
97
+ # 从字符串中移除失败的 PID
98
+ pids=$(echo "$pids" | sed "s/\b$pid\b//" | sed 's/ */ /g' | sed 's/^ *//' | sed 's/ *$//')
99
+ else
100
+ echo "✅ $service_name 已启动 (PID: $pid)"
101
+ fi
102
+ done
103
+
104
+ # 计算运行中的服务数量
105
+ running_count=0
106
+ for pid in $pids; do
107
+ if kill -0 "$pid" 2>/dev/null; then
108
+ running_count=$((running_count + 1))
109
+ fi
110
+ done
111
+
112
+ echo ""
113
+ echo "🎉 所有服务已启动!共 $running_count 个服务正在运行"
114
+ echo ""
115
+ echo "💡 按 Ctrl+C 停止所有服务"
116
+ echo ""
117
+
118
+ # 等待所有后台进程
119
+ wait
120
+ }
121
+
122
+ main
123
+