@h-ai/cli 0.1.0-alpha.19 → 0.1.0-alpha.21

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 (219) hide show
  1. package/README.md +10 -7
  2. package/dist/{chunk-GSMXGUYF.js → chunk-5IGMJVV5.js} +56 -38
  3. package/dist/chunk-5IGMJVV5.js.map +1 -0
  4. package/dist/{chunk-BPO34NRL.js → chunk-CFCXOKGV.js} +27 -5
  5. package/dist/chunk-CFCXOKGV.js.map +1 -0
  6. package/dist/cli-config-templates-5J5VKWWD.js +5 -0
  7. package/dist/{cli-config-templates-JCS7T3NU.js.map → cli-config-templates-5J5VKWWD.js.map} +1 -1
  8. package/dist/cli-skill-templates-JMSV2SVW.js +5 -0
  9. package/dist/{cli-skill-templates-IMYZPQRG.js.map → cli-skill-templates-JMSV2SVW.js.map} +1 -1
  10. package/dist/index.js +627 -107
  11. package/dist/index.js.map +1 -1
  12. package/dist/{src-N4NPS7AG.js → src-QNEJJ3BV.js} +261 -103
  13. package/dist/src-QNEJJ3BV.js.map +1 -0
  14. package/package.json +3 -2
  15. package/templates/README.md +40 -29
  16. package/templates/apps/admin/messages/en-US.json +5 -0
  17. package/templates/apps/admin/messages/zh-CN.json +5 -0
  18. package/templates/apps/admin/src/routes/+layout.svelte.hbs +5 -5
  19. package/templates/apps/admin/src/routes/+page.svelte.hbs +32 -12
  20. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +37 -20
  21. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
  22. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
  23. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +16 -0
  24. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +38 -0
  25. package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
  26. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +33 -0
  27. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +3 -0
  28. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +12 -0
  29. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
  30. package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
  31. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
  32. package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
  33. package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +17 -0
  34. package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +19 -0
  35. package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +26 -0
  36. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +55 -0
  37. package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +98 -0
  38. package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +21 -0
  39. package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +184 -0
  40. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +49 -0
  41. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +18 -0
  42. package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +168 -0
  43. package/templates/apps/api/apps/{{projectName}}-service/tsconfig.json.hbs +16 -0
  44. package/templates/apps/api/apps/{{projectName}}-service/tsup.config.ts.hbs +11 -0
  45. package/templates/apps/api/apps/{{projectName}}-service/vitest.config.ts.hbs +9 -0
  46. package/templates/apps/api/e2e/api-service.spec.ts.hbs +18 -0
  47. package/templates/apps/api/eslint.config.js +32 -0
  48. package/templates/apps/api/package.json.hbs +29 -0
  49. package/templates/apps/api/playwright.config.ts.hbs +58 -0
  50. package/templates/apps/api/pnpm-workspace.yaml.hbs +14 -0
  51. package/templates/apps/api/tsconfig.base.json +15 -0
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -7
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +18 -0
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +1 -1
  56. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +16 -0
  57. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +6 -0
  58. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +6 -0
  59. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +51 -29
  60. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +186 -0
  61. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +2 -0
  62. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +0 -1
  63. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +18 -0
  64. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +14 -0
  65. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +1 -5
  66. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +10 -4
  67. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +4 -3
  68. package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
  69. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +20 -6
  70. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +1 -1
  71. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +15 -0
  72. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +33 -30
  73. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +152 -0
  74. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +1 -2
  75. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +13 -0
  76. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +22 -0
  77. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
  78. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +12 -0
  79. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
  80. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
  81. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
  82. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
  83. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
  84. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +16 -0
  85. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
  86. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +41 -0
  87. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +2 -8
  88. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +9 -4
  89. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +44 -21
  90. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +15 -6
  91. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +1 -1
  92. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +15 -0
  93. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +25 -27
  94. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +153 -0
  95. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +0 -1
  96. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
  97. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +1 -5
  98. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +10 -4
  99. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +3 -2
  100. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +2 -1
  101. package/templates/apps/fullstack/eslint.config.js +0 -1
  102. package/templates/apps/fullstack/package.json.hbs +18 -17
  103. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +3 -3
  104. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +5 -2
  105. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +14 -0
  106. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +13 -0
  107. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +2 -2
  108. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/{server-app.ts.hbs → app-server.ts.hbs} +23 -3
  109. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +4 -1
  110. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/{server-app.test.ts.hbs → app-server.test.ts.hbs} +1 -1
  111. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +9 -8
  112. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +1 -1
  113. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +5 -1
  114. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +1 -1
  115. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +1 -1
  116. package/templates/apps/fullstack/playwright.config.ts.hbs +41 -4
  117. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +15 -0
  118. package/templates/apps/h5/messages/en-US.json +3 -0
  119. package/templates/apps/h5/messages/zh-CN.json +3 -0
  120. package/templates/apps/h5/src/routes/+layout.svelte.hbs +30 -29
  121. package/templates/apps/h5/src/routes/+page.svelte.hbs +17 -6
  122. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
  123. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
  124. package/templates/apps/mobile-app/.env.hbs +3 -0
  125. package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
  126. package/templates/apps/mobile-app/index.html.hbs +13 -0
  127. package/templates/apps/mobile-app/messages/en-US.json +36 -0
  128. package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
  129. package/templates/apps/mobile-app/src/App.svelte.hbs +162 -0
  130. package/templates/apps/mobile-app/src/lib/api.ts.hbs +54 -0
  131. package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
  132. package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
  133. package/templates/apps/website/src/routes/+layout.svelte.hbs +35 -26
  134. package/templates/apps/website/src/routes/+page.svelte.hbs +28 -10
  135. package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
  136. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +37 -34
  137. package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
  138. package/templates/base/.gitignore.hbs +16 -0
  139. package/templates/base/{eslint.config.js → eslint.config.js.hbs} +4 -1
  140. package/templates/base/package.json.hbs +55 -31
  141. package/templates/base/playwright.config.ts +30 -3
  142. package/templates/base/pnpm-workspace.yaml.hbs +14 -0
  143. package/templates/base/src/app.d.ts.hbs +3 -0
  144. package/templates/base/src/app.html.hbs +7 -0
  145. package/templates/base/src/hooks.server.ts.hbs +17 -7
  146. package/templates/base/src/lib/server/init.ts.hbs +20 -12
  147. package/templates/base/static/favicon.png +0 -0
  148. package/templates/base/svelte.config.js.hbs +43 -3
  149. package/templates/base/tests/scaffold.test.ts.hbs +16 -1
  150. package/templates/base/tsconfig.json.hbs +50 -0
  151. package/templates/base/vite.config.ts.hbs +13 -3
  152. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +5 -5
  153. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +34 -32
  154. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +46 -48
  155. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +35 -31
  156. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +41 -38
  157. package/templates/skills/AGENTS.md +60 -17
  158. package/templates/skills/CLAUDE.md +18 -6
  159. package/templates/skills/bridges/admin/AGENTS.md +66 -0
  160. package/templates/skills/bridges/admin/CLAUDE.md +19 -0
  161. package/templates/skills/bridges/admin/copilot-instructions.md +46 -0
  162. package/templates/skills/bridges/api/AGENTS.md +65 -0
  163. package/templates/skills/bridges/api/CLAUDE.md +19 -0
  164. package/templates/skills/bridges/api/copilot-instructions.md +46 -0
  165. package/templates/skills/bridges/fullstack/AGENTS.md +84 -0
  166. package/templates/skills/bridges/fullstack/CLAUDE.md +19 -0
  167. package/templates/skills/bridges/fullstack/copilot-instructions.md +54 -0
  168. package/templates/skills/bridges/h5/AGENTS.md +65 -0
  169. package/templates/skills/bridges/h5/CLAUDE.md +19 -0
  170. package/templates/skills/bridges/h5/copilot-instructions.md +44 -0
  171. package/templates/skills/bridges/mobile-app/AGENTS.md +77 -0
  172. package/templates/skills/bridges/mobile-app/CLAUDE.md +19 -0
  173. package/templates/skills/bridges/mobile-app/copilot-instructions.md +45 -0
  174. package/templates/skills/bridges/website/AGENTS.md +65 -0
  175. package/templates/skills/bridges/website/CLAUDE.md +19 -0
  176. package/templates/skills/bridges/website/copilot-instructions.md +44 -0
  177. package/templates/skills/copilot-instructions.md +29 -50
  178. package/templates/skills/hai-ai/SKILL.md +115 -648
  179. package/templates/skills/hai-ai/reference.md +197 -0
  180. package/templates/skills/hai-api-client/SKILL.md +3 -1
  181. package/templates/skills/hai-app-create/SKILL.md +2 -1
  182. package/templates/skills/hai-app-review/SKILL.md +2 -2
  183. package/templates/skills/hai-app-tests/SKILL.md +28 -3
  184. package/templates/skills/hai-capacitor/SKILL.md +14 -22
  185. package/templates/skills/hai-deploy/SKILL.md +12 -9
  186. package/templates/skills/hai-kit/SKILL.md +5 -3
  187. package/templates/skills/hai-serv/SKILL.md +2 -0
  188. package/templates/skills/hai-ui/SKILL.md +25 -11
  189. package/templates/skills/opencode.json +1 -6
  190. package/dist/chunk-BPO34NRL.js.map +0 -1
  191. package/dist/chunk-GSMXGUYF.js.map +0 -1
  192. package/dist/cli-config-templates-JCS7T3NU.js +0 -5
  193. package/dist/cli-skill-templates-IMYZPQRG.js +0 -5
  194. package/dist/src-N4NPS7AG.js.map +0 -1
  195. package/templates/apps/android-app/.env.hbs +0 -3
  196. package/templates/apps/android-app/messages/en-US.json +0 -24
  197. package/templates/apps/android-app/messages/zh-CN.json +0 -24
  198. package/templates/apps/android-app/src/lib/api.ts.hbs +0 -31
  199. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
  200. package/templates/apps/android-app/src/routes/+layout.ts +0 -7
  201. package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
  202. package/templates/apps/api/src/routes/+layout.svelte +0 -14
  203. package/templates/apps/api/src/routes/+page.svelte +0 -11
  204. package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
  205. package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
  206. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
  207. package/templates/apps/api/tests/health.test.ts.hbs +0 -26
  208. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +0 -14
  209. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +0 -18
  210. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +0 -162
  211. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +0 -14
  212. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +0 -18
  213. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +0 -162
  214. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +0 -14
  215. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +0 -18
  216. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +0 -162
  217. package/templates/apps/fullstack/pnpm-workspace.yaml +0 -7
  218. package/templates/base/tsconfig.json +0 -20
  219. /package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/{theme.svelte.ts.hbs → theme-store.svelte.ts.hbs} +0 -0
package/dist/index.js CHANGED
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
- import { generateConfigFile } from './chunk-BPO34NRL.js';
3
- import './chunk-GSMXGUYF.js';
2
+ import { generateConfigFile } from './chunk-CFCXOKGV.js';
3
+ import './chunk-5IGMJVV5.js';
4
4
  import './chunk-2H7UOFLK.js';
5
- import { readFileSync, existsSync } from 'fs';
6
- import path2, { resolve } from 'path';
7
5
  import process3 from 'process';
8
- import { fileURLToPath } from 'url';
9
6
  import { core } from '@h-ai/core';
10
7
  import { cac } from 'cac';
11
8
  import chalk from 'chalk';
12
- import { createRequire } from 'module';
9
+ import path2, { resolve } from 'path';
10
+ import { fileURLToPath } from 'url';
13
11
  import fse from 'fs-extra';
12
+ import Handlebars from 'handlebars';
14
13
  import ora from 'ora';
15
14
  import prompts from 'prompts';
16
- import Handlebars from 'handlebars';
15
+ import { Buffer } from 'buffer';
17
16
  import { execSync, execFileSync } from 'child_process';
17
+ import { existsSync, readFileSync } from 'fs';
18
18
  import { parse } from 'yaml';
19
19
 
20
20
  var CAMEL_CASE_SEPARATOR_REGEX = /[-_\s]+(.)?/g;
@@ -53,6 +53,22 @@ async function fileExists(filePath) {
53
53
  return false;
54
54
  }
55
55
  }
56
+ function getCliVersion() {
57
+ let dir = path2.dirname(fileURLToPath(import.meta.url));
58
+ for (let i = 0; i < 6; i++) {
59
+ try {
60
+ const pkg = fse.readJsonSync(path2.join(dir, "package.json"));
61
+ if (pkg.name === "@h-ai/cli")
62
+ return pkg.version ?? "0.0.0";
63
+ } catch {
64
+ }
65
+ const parent = path2.dirname(dir);
66
+ if (parent === dir)
67
+ break;
68
+ dir = parent;
69
+ }
70
+ return "0.0.0";
71
+ }
56
72
  async function detectPackageManager(cwd) {
57
73
  if (await fileExists(path2.join(cwd, "pnpm-lock.yaml"))) {
58
74
  return "pnpm";
@@ -83,20 +99,30 @@ registerHelpers();
83
99
  Handlebars.registerHelper("if_eq", function(a, b, options) {
84
100
  return a === b ? options.fn(this) : options.inverse(this);
85
101
  });
86
- var HAI_VERSION = `^${fse.readJsonSync(fileURLToPath(new URL("../../package.json", import.meta.url))).version}`;
87
102
  var TEMPLATE_SKIP_IF_EMPTY_MARKER = "@skipIfEmpty";
88
103
  var NORMALIZED_RENDER_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".js", ".svelte", ".json", ".css"]);
104
+ var CAPACITOR_SKIPPED_SERVER_FILES = /* @__PURE__ */ new Set([
105
+ "src/hooks.server.ts",
106
+ "src/lib/server/init.ts"
107
+ ]);
89
108
  var VERSIONS = {
90
109
  antfuEslintConfig: "^9.0.0",
91
- apiContract: HAI_VERSION,
92
- apiClient: HAI_VERSION,
93
- core: HAI_VERSION,
94
- serv: HAI_VERSION,
95
- ui: HAI_VERSION,
110
+ capacitorSecureStorage: "^8.0.0",
96
111
  // UI / Icon
97
112
  bitsUi: "^2.18.1",
98
113
  iconifyJsonTabler: "^1.2.35",
99
114
  iconifyTailwind: "^1.2.3",
115
+ // Capacitor
116
+ capacitorAndroid: "^8.3.4",
117
+ capacitorApp: "^8.0.1",
118
+ capacitorCamera: "^8.0.1",
119
+ capacitorCli: "^8.3.4",
120
+ capacitorCore: "^8.3.4",
121
+ capacitorDevice: "^8.0.1",
122
+ capacitorIos: "^8.3.4",
123
+ capacitorPreferences: "^8.0.1",
124
+ capacitorPushNotifications: "^8.0.1",
125
+ capacitorStatusBar: "^8.0.1",
100
126
  // Tailwind / DaisyUI
101
127
  daisyui: "^5.5.20",
102
128
  tailwindcss: "^4.3.0",
@@ -104,13 +130,10 @@ var VERSIONS = {
104
130
  // i18n
105
131
  inlangParaglide: "^2.18.1",
106
132
  inlangMessageFormat: "^4.4.0",
107
- // Svelte / Kit
133
+ // Svelte / Vite
108
134
  svelte: "^5.55.9",
109
- svelteKit: "^2.61.1",
110
135
  svelteCheck: "^4.4.8",
111
136
  sveltePlugin: "^7.1.2",
112
- adapterAuto: "^7.0.1",
113
- adapterStatic: "^3.0.10",
114
137
  // Build / Test
115
138
  vite: "^8.0.14",
116
139
  vitest: "^4.1.7",
@@ -127,12 +150,14 @@ var VERSIONS = {
127
150
  // E2E
128
151
  playwright: "^1.60.0",
129
152
  // Validation
130
- zod: "^4.4.3"
153
+ zod: "^4.4.3",
154
+ // Tauri
155
+ tauriCli: "^2.10.1"
131
156
  };
132
157
  var FRONTEND_PORTS_DEFAULT = {
133
158
  web: 4173,
134
- app: 4174,
135
- desktop: 4175
159
+ app: 5175,
160
+ desktop: 5176
136
161
  };
137
162
  var FRONTEND_LABELS = {
138
163
  web: "Web",
@@ -144,6 +169,277 @@ var IMPLEMENTED_FRONTENDS = ["web", "app", "desktop"];
144
169
  var DEFAULT_FULLSTACK_FRONTENDS = ["web", "app", "desktop"];
145
170
  var DEFAULT_THEMES = ["light", "dark"];
146
171
  var DEFAULT_THEME_NAME = "light";
172
+ var HAI_PACKAGE_VERSION = `^${getCliVersion()}`;
173
+ var HAI_PACKAGE_SPECIFIER_CATALOG = "catalog:";
174
+ var HAI_CATALOG_PACKAGE_NAMES = [
175
+ "@h-ai/ai",
176
+ "@h-ai/api-client",
177
+ "@h-ai/api-contract",
178
+ "@h-ai/audit",
179
+ "@h-ai/cache",
180
+ "@h-ai/capacitor",
181
+ "@h-ai/core",
182
+ "@h-ai/crypto",
183
+ "@h-ai/datapipe",
184
+ "@h-ai/deploy",
185
+ "@h-ai/iam",
186
+ "@h-ai/kit",
187
+ "@h-ai/payment",
188
+ "@h-ai/reach",
189
+ "@h-ai/reldb",
190
+ "@h-ai/scheduler",
191
+ "@h-ai/serv",
192
+ "@h-ai/storage",
193
+ "@h-ai/ui",
194
+ "@h-ai/vecdb"
195
+ ];
196
+ var HAI_CATALOG_PACKAGES = Object.fromEntries(
197
+ HAI_CATALOG_PACKAGE_NAMES.map((packageName) => [packageName, HAI_PACKAGE_VERSION])
198
+ );
199
+ var FULLSTACK_EXTERNAL_CATALOG_PACKAGES = {
200
+ "@antfu/eslint-config": VERSIONS.antfuEslintConfig,
201
+ "@aparajita/capacitor-secure-storage": VERSIONS.capacitorSecureStorage,
202
+ "@capacitor/android": VERSIONS.capacitorAndroid,
203
+ "@capacitor/app": VERSIONS.capacitorApp,
204
+ "@capacitor/camera": VERSIONS.capacitorCamera,
205
+ "@capacitor/cli": VERSIONS.capacitorCli,
206
+ "@capacitor/core": VERSIONS.capacitorCore,
207
+ "@capacitor/device": VERSIONS.capacitorDevice,
208
+ "@capacitor/ios": VERSIONS.capacitorIos,
209
+ "@capacitor/preferences": VERSIONS.capacitorPreferences,
210
+ "@capacitor/push-notifications": VERSIONS.capacitorPushNotifications,
211
+ "@capacitor/status-bar": VERSIONS.capacitorStatusBar,
212
+ "@iconify-json/tabler": VERSIONS.iconifyJsonTabler,
213
+ "@iconify/tailwind4": VERSIONS.iconifyTailwind,
214
+ "@inlang/paraglide-js": VERSIONS.inlangParaglide,
215
+ "@inlang/plugin-message-format": VERSIONS.inlangMessageFormat,
216
+ "@playwright/test": VERSIONS.playwright,
217
+ "@sveltejs/vite-plugin-svelte": VERSIONS.sveltePlugin,
218
+ "@tailwindcss/vite": VERSIONS.tailwindcssVite,
219
+ "@tauri-apps/cli": VERSIONS.tauriCli,
220
+ "@types/node": VERSIONS.nodeTypes,
221
+ "bits-ui": VERSIONS.bitsUi,
222
+ "daisyui": VERSIONS.daisyui,
223
+ "eslint": VERSIONS.eslint,
224
+ "eslint-plugin-format": VERSIONS.eslintPluginFormat,
225
+ "eslint-plugin-svelte": VERSIONS.eslintPluginSvelte,
226
+ "rimraf": VERSIONS.rimraf,
227
+ "svelte": VERSIONS.svelte,
228
+ "svelte-check": VERSIONS.svelteCheck,
229
+ "svelte-eslint-parser": VERSIONS.svelteEslintParser,
230
+ "tailwindcss": VERSIONS.tailwindcss,
231
+ "tsup": VERSIONS.tsup,
232
+ "typescript": VERSIONS.typescript,
233
+ "vite": VERSIONS.vite,
234
+ "vitest": VERSIONS.vitest,
235
+ "zod": VERSIONS.zod
236
+ };
237
+ var FULLSTACK_CATALOG_PACKAGES = {
238
+ ...HAI_CATALOG_PACKAGES,
239
+ ...FULLSTACK_EXTERNAL_CATALOG_PACKAGES
240
+ };
241
+ var FULLSTACK_ROOT_CATALOG_PACKAGE_NAMES = [
242
+ "@antfu/eslint-config",
243
+ "@playwright/test",
244
+ "@sveltejs/vite-plugin-svelte",
245
+ "@types/node",
246
+ "eslint",
247
+ "eslint-plugin-format",
248
+ "eslint-plugin-svelte",
249
+ "rimraf",
250
+ "svelte",
251
+ "svelte-check",
252
+ "svelte-eslint-parser",
253
+ "tsup",
254
+ "typescript",
255
+ "vite",
256
+ "vitest"
257
+ ];
258
+ var FULLSTACK_CONTRACT_CATALOG_PACKAGE_NAMES = [
259
+ "@h-ai/api-contract",
260
+ "@h-ai/core",
261
+ "zod"
262
+ ];
263
+ var FULLSTACK_SERV_CATALOG_PACKAGE_NAMES = [
264
+ "@h-ai/core",
265
+ "@h-ai/serv"
266
+ ];
267
+ var FULLSTACK_SHARED_CATALOG_PACKAGE_NAMES = [
268
+ "@h-ai/api-client",
269
+ "@h-ai/ui",
270
+ "@inlang/paraglide-js",
271
+ "@inlang/plugin-message-format",
272
+ "svelte",
273
+ "svelte-check",
274
+ "typescript",
275
+ "vite",
276
+ "vitest"
277
+ ];
278
+ var FULLSTACK_WEB_CATALOG_PACKAGE_NAMES = [
279
+ "@antfu/eslint-config",
280
+ "@h-ai/ui",
281
+ "@iconify-json/tabler",
282
+ "@iconify/tailwind4",
283
+ "@inlang/paraglide-js",
284
+ "@inlang/plugin-message-format",
285
+ "@sveltejs/vite-plugin-svelte",
286
+ "@tailwindcss/vite",
287
+ "bits-ui",
288
+ "daisyui",
289
+ "eslint",
290
+ "eslint-plugin-format",
291
+ "eslint-plugin-svelte",
292
+ "svelte",
293
+ "svelte-check",
294
+ "svelte-eslint-parser",
295
+ "tailwindcss",
296
+ "typescript",
297
+ "vite",
298
+ "vitest"
299
+ ];
300
+ var FULLSTACK_APP_CATALOG_PACKAGE_NAMES = [
301
+ ...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES,
302
+ "@aparajita/capacitor-secure-storage",
303
+ "@capacitor/android",
304
+ "@capacitor/app",
305
+ "@capacitor/camera",
306
+ "@capacitor/cli",
307
+ "@capacitor/core",
308
+ "@capacitor/device",
309
+ "@capacitor/ios",
310
+ "@capacitor/preferences",
311
+ "@capacitor/push-notifications",
312
+ "@capacitor/status-bar",
313
+ "@h-ai/capacitor"
314
+ ];
315
+ var FULLSTACK_DESKTOP_CATALOG_PACKAGE_NAMES = [
316
+ ...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES,
317
+ "@tauri-apps/cli"
318
+ ];
319
+ var API_WORKSPACE_EXTERNAL_CATALOG_PACKAGE_NAMES = [
320
+ "@antfu/eslint-config",
321
+ "@playwright/test",
322
+ "@types/node",
323
+ "eslint",
324
+ "eslint-plugin-format",
325
+ "rimraf",
326
+ "tsup",
327
+ "typescript",
328
+ "vitest",
329
+ "zod"
330
+ ];
331
+ function pickCatalogPackages(packageNames, availableCatalogPackages) {
332
+ return Object.fromEntries(
333
+ [...new Set(packageNames)].sort((left, right) => left.localeCompare(right)).map((packageName) => {
334
+ const version = availableCatalogPackages[packageName];
335
+ if (!version) {
336
+ throw new Error(`Missing catalog version for package "${packageName}"`);
337
+ }
338
+ return [packageName, version];
339
+ })
340
+ );
341
+ }
342
+ function buildFullstackPackageSpecifiers(useCatalogProtocol) {
343
+ return Object.fromEntries(
344
+ Object.entries(VERSIONS).map(([key, version]) => [key, useCatalogProtocol ? HAI_PACKAGE_SPECIFIER_CATALOG : version])
345
+ );
346
+ }
347
+ function buildApiWorkspaceCatalogPackages(featureMap) {
348
+ const packageNames = [
349
+ ...API_WORKSPACE_EXTERNAL_CATALOG_PACKAGE_NAMES,
350
+ "@h-ai/api-client",
351
+ "@h-ai/api-contract",
352
+ "@h-ai/core",
353
+ "@h-ai/serv"
354
+ ];
355
+ if (featureMap.db)
356
+ packageNames.push("@h-ai/reldb");
357
+ if (featureMap.cache)
358
+ packageNames.push("@h-ai/cache");
359
+ if (featureMap.iam)
360
+ packageNames.push("@h-ai/iam");
361
+ if (featureMap.crypto)
362
+ packageNames.push("@h-ai/crypto");
363
+ if (featureMap.storage)
364
+ packageNames.push("@h-ai/storage");
365
+ if (featureMap.ai)
366
+ packageNames.push("@h-ai/ai");
367
+ if (featureMap.audit)
368
+ packageNames.push("@h-ai/audit");
369
+ if (featureMap.reach)
370
+ packageNames.push("@h-ai/reach");
371
+ if (featureMap.payment)
372
+ packageNames.push("@h-ai/payment");
373
+ if (featureMap.vecdb)
374
+ packageNames.push("@h-ai/vecdb");
375
+ if (featureMap.datapipe)
376
+ packageNames.push("@h-ai/datapipe");
377
+ if (featureMap.scheduler)
378
+ packageNames.push("@h-ai/scheduler");
379
+ if (featureMap.deploy)
380
+ packageNames.push("@h-ai/deploy");
381
+ return pickCatalogPackages(packageNames, FULLSTACK_CATALOG_PACKAGES);
382
+ }
383
+ function buildAppHaiCatalogPackages(options) {
384
+ const packageNames = [];
385
+ if (options.isSvelteOnlyApp) {
386
+ packageNames.push("@h-ai/api-client", "@h-ai/capacitor", "@h-ai/ui");
387
+ return pickCatalogPackages(packageNames, HAI_CATALOG_PACKAGES);
388
+ }
389
+ packageNames.push("@h-ai/core", "@h-ai/kit");
390
+ if (options.hasUi)
391
+ packageNames.push("@h-ai/ui");
392
+ if (options.featureMap.db)
393
+ packageNames.push("@h-ai/reldb");
394
+ if (options.featureMap.cache)
395
+ packageNames.push("@h-ai/cache");
396
+ if (options.featureMap.iam)
397
+ packageNames.push("@h-ai/iam");
398
+ if (options.featureMap.crypto)
399
+ packageNames.push("@h-ai/crypto");
400
+ if (options.featureMap.storage)
401
+ packageNames.push("@h-ai/storage");
402
+ if (options.featureMap.ai)
403
+ packageNames.push("@h-ai/ai");
404
+ if (options.featureMap.audit)
405
+ packageNames.push("@h-ai/audit");
406
+ if (options.featureMap.reach)
407
+ packageNames.push("@h-ai/reach");
408
+ if (options.featureMap.payment)
409
+ packageNames.push("@h-ai/payment");
410
+ if (options.featureMap.vecdb)
411
+ packageNames.push("@h-ai/vecdb");
412
+ if (options.featureMap.datapipe)
413
+ packageNames.push("@h-ai/datapipe");
414
+ if (options.featureMap.scheduler)
415
+ packageNames.push("@h-ai/scheduler");
416
+ if (options.featureMap.deploy)
417
+ packageNames.push("@h-ai/deploy");
418
+ if (options.featureMap["api-client"])
419
+ packageNames.push("@h-ai/api-client");
420
+ if (options.featureMap.capacitor)
421
+ packageNames.push("@h-ai/capacitor");
422
+ if (options.isCapacitorApp && !options.featureMap["api-client"])
423
+ packageNames.push("@h-ai/api-client");
424
+ if (options.isCapacitorApp && !options.featureMap.capacitor)
425
+ packageNames.push("@h-ai/capacitor");
426
+ return pickCatalogPackages(packageNames, HAI_CATALOG_PACKAGES);
427
+ }
428
+ function buildFullstackCatalogPackages(frontends) {
429
+ const packageNames = [
430
+ ...FULLSTACK_ROOT_CATALOG_PACKAGE_NAMES,
431
+ ...FULLSTACK_CONTRACT_CATALOG_PACKAGE_NAMES,
432
+ ...FULLSTACK_SERV_CATALOG_PACKAGE_NAMES,
433
+ ...FULLSTACK_SHARED_CATALOG_PACKAGE_NAMES
434
+ ];
435
+ if (frontends.includes("web"))
436
+ packageNames.push(...FULLSTACK_WEB_CATALOG_PACKAGE_NAMES);
437
+ if (frontends.includes("app"))
438
+ packageNames.push(...FULLSTACK_APP_CATALOG_PACKAGE_NAMES);
439
+ if (frontends.includes("desktop"))
440
+ packageNames.push(...FULLSTACK_DESKTOP_CATALOG_PACKAGE_NAMES);
441
+ return pickCatalogPackages(packageNames, FULLSTACK_CATALOG_PACKAGES);
442
+ }
147
443
  var FEATURE_ROUTE_DIRS = {
148
444
  iam: ["routes-shared"],
149
445
  storage: ["routes"],
@@ -160,6 +456,7 @@ var FEATURE_APP_ROUTE_DIRS = {
160
456
  };
161
457
  var FEATURE_ID_REGEX = /^[a-z0-9-]+$/;
162
458
  var HBS_SUFFIX_REGEX = /\.hbs$/;
459
+ var FULLSTACK_FRONTEND_TEMPLATE_PATH_REGEX = /^apps\/\{\{projectName\}\}-(web|app|desktop|miniapp)\//;
163
460
  var NON_IDENTIFIER_CHAR_REGEX = /[^a-z0-9]+/i;
164
461
  var IDENTIFIER_START_REGEX = /^[a-z_$]/i;
165
462
  function getTemplatesRoot() {
@@ -210,6 +507,28 @@ async function findHbsFiles(dir) {
210
507
  await walk(dir);
211
508
  return results;
212
509
  }
510
+ async function findRenderedStaticPathFiles(dir) {
511
+ if (!await fse.pathExists(dir)) {
512
+ return [];
513
+ }
514
+ const results = [];
515
+ async function walk(current) {
516
+ const entries = await fse.readdir(current, { withFileTypes: true });
517
+ for (const entry of entries) {
518
+ const fullPath = path2.join(current, entry.name);
519
+ if (entry.isDirectory()) {
520
+ await walk(fullPath);
521
+ continue;
522
+ }
523
+ const relPath = path2.relative(dir, fullPath);
524
+ if (!entry.name.endsWith(".hbs") && (relPath.includes("{{") || relPath.includes("}}"))) {
525
+ results.push(relPath);
526
+ }
527
+ }
528
+ }
529
+ await walk(dir);
530
+ return results;
531
+ }
213
532
  function buildTemplateContext(options) {
214
533
  const featureMap = {};
215
534
  for (const f of options.features) {
@@ -225,24 +544,62 @@ function buildTemplateContext(options) {
225
544
  }
226
545
  const isApi = options.appType === "api";
227
546
  const isFullstack = options.appType === "fullstack";
228
- const isCapacitorApp = options.appType === "android-app";
547
+ const isCapacitorApp = options.appType === "mobile-app";
548
+ const isSvelteOnlyApp = isCapacitorApp;
549
+ const useCatalogProtocol = options.packageManager === "pnpm";
550
+ const hasUi = !isApi && !isFullstack;
551
+ const selectedFrontends = options.frontends ?? DEFAULT_FULLSTACK_FRONTENDS;
552
+ let haiCatalogPackages;
553
+ if (isFullstack) {
554
+ haiCatalogPackages = buildFullstackCatalogPackages(selectedFrontends);
555
+ } else if (isApi) {
556
+ haiCatalogPackages = buildApiWorkspaceCatalogPackages(featureMap);
557
+ } else {
558
+ haiCatalogPackages = buildAppHaiCatalogPackages({
559
+ featureMap,
560
+ hasUi,
561
+ isCapacitorApp,
562
+ isSvelteOnlyApp
563
+ });
564
+ }
229
565
  return {
230
566
  projectName: options.name,
567
+ useCatalogProtocol,
568
+ haiPackageSpecifier: useCatalogProtocol ? HAI_PACKAGE_SPECIFIER_CATALOG : HAI_PACKAGE_VERSION,
569
+ haiPackageVersion: HAI_PACKAGE_VERSION,
570
+ haiCatalogPackages,
231
571
  appType: options.appType,
232
572
  features: featureMap,
233
- hasUi: !isApi && !isFullstack,
573
+ hasUi,
234
574
  hasI18n: !isApi && !isFullstack,
235
575
  isCapacitorApp,
576
+ isApiWorkspace: isApi,
577
+ isSvelteOnlyApp,
236
578
  defaultLocale: options.moduleConfigs?.core?.defaultLocale ?? "zh-CN",
237
579
  packageManager: options.packageManager,
580
+ api: isApi ? buildApiWorkspaceTemplateContext(options.name, useCatalogProtocol) : void 0,
238
581
  fullstack: isFullstack ? buildFullstackTemplateContext(
239
582
  options.name,
240
- options.frontends ?? DEFAULT_FULLSTACK_FRONTENDS,
241
- options.moduleConfigs
583
+ selectedFrontends,
584
+ options.moduleConfigs,
585
+ useCatalogProtocol
242
586
  ) : void 0
243
587
  };
244
588
  }
245
- function buildFullstackTemplateContext(projectName, frontendsInput, moduleConfigs) {
589
+ function buildApiWorkspaceTemplateContext(projectName, useCatalogProtocol = false) {
590
+ const identifier = toIdentifier(projectName);
591
+ const pascalName = toPascalIdentifier(identifier);
592
+ return {
593
+ versions: VERSIONS,
594
+ packageSpecifiers: buildFullstackPackageSpecifiers(useCatalogProtocol),
595
+ contractPackageName: `${projectName}-contract`,
596
+ contractExportName: `${identifier}Contract`,
597
+ servicePackageName: `${projectName}-service`,
598
+ serviceAppFactoryName: `create${pascalName}App`,
599
+ serviceProceduresFactoryName: `create${pascalName}Procedures`
600
+ };
601
+ }
602
+ function buildFullstackTemplateContext(projectName, frontendsInput, moduleConfigs, useCatalogProtocol = false) {
246
603
  const selectedFrontends = [...new Set(frontendsInput.length > 0 ? frontendsInput : DEFAULT_FULLSTACK_FRONTENDS)];
247
604
  const portsConfig = moduleConfigs?.fullstack?.ports ?? {};
248
605
  const portFor = (target) => portsConfig[target] ?? FRONTEND_PORTS_DEFAULT[target];
@@ -254,9 +611,11 @@ function buildFullstackTemplateContext(projectName, frontendsInput, moduleConfig
254
611
  }));
255
612
  return {
256
613
  versions: VERSIONS,
614
+ packageSpecifiers: buildFullstackPackageSpecifiers(useCatalogProtocol),
257
615
  contractPackageName: `${projectName}-contract`,
258
616
  contractExportName: `${toIdentifier(projectName)}Contract`,
259
617
  servPackageName: `${projectName}-serv`,
618
+ nativeAppIdSegment: toIdentifier(projectName).toLowerCase(),
260
619
  sharedPackageName: `${projectName}-shared`,
261
620
  selectedFrontends,
262
621
  selectedFrontendsJson: `[${selectedFrontends.map((f) => `'${f}'`).join(", ")}]`,
@@ -311,9 +670,14 @@ function toIdentifier(value) {
311
670
  return "app";
312
671
  return IDENTIFIER_START_REGEX.test(camel) ? camel : `app${camel}`;
313
672
  }
673
+ function toPascalIdentifier(value) {
674
+ if (!value)
675
+ return "App";
676
+ return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
677
+ }
314
678
  async function generateFromTemplates(projectPath, context) {
315
679
  const root = getTemplatesRoot();
316
- const includeBaseTemplate = context.appType !== "fullstack";
680
+ const includeBaseTemplate = context.appType !== "fullstack" && !context.isApiWorkspace;
317
681
  if (includeBaseTemplate) {
318
682
  await copyStaticDir(path2.join(root, "base"), projectPath);
319
683
  }
@@ -322,29 +686,37 @@ async function generateFromTemplates(projectPath, context) {
322
686
  const appExcludes = context.hasI18n ? [] : ["messages"];
323
687
  await copyStaticDir(appDir, projectPath, appExcludes);
324
688
  }
325
- for (const featureId of Object.keys(context.features)) {
326
- if (!context.features[featureId]) {
327
- continue;
328
- }
329
- if (!FEATURE_ID_REGEX.test(featureId)) {
330
- continue;
331
- }
332
- const featureDir = path2.join(root, "features", featureId);
333
- if (!await fse.pathExists(featureDir)) {
334
- continue;
335
- }
336
- const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
337
- for (const dirName of sharedDirs) {
338
- const routesSrc = path2.join(featureDir, dirName);
339
- if (await fse.pathExists(routesSrc)) {
340
- await copyStaticDir(routesSrc, path2.join(projectPath, "src", "routes"));
689
+ if (!context.isApiWorkspace) {
690
+ for (const featureId of Object.keys(context.features)) {
691
+ if (context.isSvelteOnlyApp) {
692
+ continue;
341
693
  }
342
- }
343
- const appSpecificTypes = FEATURE_APP_ROUTE_DIRS[featureId] || [];
344
- if (appSpecificTypes.includes(context.appType)) {
345
- const appRouteSrc = path2.join(featureDir, `routes-${context.appType}`);
346
- if (await fse.pathExists(appRouteSrc)) {
347
- await copyStaticDir(appRouteSrc, path2.join(projectPath, "src", "routes"));
694
+ if (!context.features[featureId]) {
695
+ continue;
696
+ }
697
+ if (!FEATURE_ID_REGEX.test(featureId)) {
698
+ continue;
699
+ }
700
+ const featureDir = path2.join(root, "features", featureId);
701
+ if (!await fse.pathExists(featureDir)) {
702
+ continue;
703
+ }
704
+ const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
705
+ for (const dirName of sharedDirs) {
706
+ if (context.isCapacitorApp && dirName === "routes-shared") {
707
+ continue;
708
+ }
709
+ const routesSrc = path2.join(featureDir, dirName);
710
+ if (await fse.pathExists(routesSrc)) {
711
+ await copyStaticDir(routesSrc, path2.join(projectPath, "src", "routes"));
712
+ }
713
+ }
714
+ const appSpecificTypes = FEATURE_APP_ROUTE_DIRS[featureId] || [];
715
+ if (appSpecificTypes.includes(context.appType)) {
716
+ const appRouteSrc = path2.join(featureDir, `routes-${context.appType}`);
717
+ if (await fse.pathExists(appRouteSrc)) {
718
+ await copyStaticDir(appRouteSrc, path2.join(projectPath, "src", "routes"));
719
+ }
348
720
  }
349
721
  }
350
722
  }
@@ -360,15 +732,22 @@ async function generateFromTemplates(projectPath, context) {
360
732
  }
361
733
  }
362
734
  async function renderDynamicFiles(templatesRoot, projectPath, context) {
363
- const rootDirs = context.appType === "fullstack" ? [path2.join(templatesRoot, "apps", context.appType)] : [
735
+ const rootDirs = context.appType === "fullstack" || context.isApiWorkspace ? [path2.join(templatesRoot, "apps", context.appType)] : [
364
736
  path2.join(templatesRoot, "base"),
365
737
  path2.join(templatesRoot, "apps", context.appType)
366
738
  ];
367
739
  for (const dir of rootDirs) {
368
740
  await renderHbsInDir(dir, projectPath, context);
741
+ await copyRenderedStaticPathFiles(dir, projectPath, context);
742
+ }
743
+ if (context.isApiWorkspace) {
744
+ return;
369
745
  }
370
746
  const routesDest = path2.join(projectPath, "src", "routes");
371
747
  for (const featureId of Object.keys(context.features)) {
748
+ if (context.isSvelteOnlyApp) {
749
+ continue;
750
+ }
372
751
  if (!context.features[featureId]) {
373
752
  continue;
374
753
  }
@@ -378,6 +757,9 @@ async function renderDynamicFiles(templatesRoot, projectPath, context) {
378
757
  }
379
758
  const sharedDirs = FEATURE_ROUTE_DIRS[featureId] || [];
380
759
  for (const dirName of sharedDirs) {
760
+ if (context.isCapacitorApp && dirName === "routes-shared") {
761
+ continue;
762
+ }
381
763
  await renderHbsInDir(path2.join(featureDir, dirName), routesDest, context);
382
764
  }
383
765
  const appSpecificTypes = FEATURE_APP_ROUTE_DIRS[featureId] || [];
@@ -405,12 +787,43 @@ async function renderHbsInDir(dir, destRoot, context) {
405
787
  if (!isSafeRelativePath(outRelPath)) {
406
788
  continue;
407
789
  }
790
+ if (context.isCapacitorApp && CAPACITOR_SKIPPED_SERVER_FILES.has(outRelPath.split(path2.sep).join("/"))) {
791
+ continue;
792
+ }
408
793
  const destPath = path2.join(destRoot, outRelPath);
409
794
  const normalizedRendered = normalizeRenderedContent(rendered, outRelPath);
410
795
  await fse.ensureDir(path2.dirname(destPath));
411
796
  await fse.writeFile(destPath, normalizedRendered, "utf-8");
412
797
  }
413
798
  }
799
+ async function copyRenderedStaticPathFiles(dir, destRoot, context) {
800
+ const staticFiles = await findRenderedStaticPathFiles(dir);
801
+ for (const relPath of staticFiles) {
802
+ if (!shouldCopyRenderedStaticPathFile(relPath, context)) {
803
+ continue;
804
+ }
805
+ const outRelPath = renderOutputPath(relPath, context);
806
+ if (!isSafeRelativePath(outRelPath)) {
807
+ continue;
808
+ }
809
+ const srcPath = path2.join(dir, relPath);
810
+ const destPath = path2.join(destRoot, outRelPath);
811
+ await fse.ensureDir(path2.dirname(destPath));
812
+ await fse.copyFile(srcPath, destPath);
813
+ }
814
+ }
815
+ function shouldCopyRenderedStaticPathFile(relPath, context) {
816
+ if (context.appType !== "fullstack" || !context.fullstack) {
817
+ return true;
818
+ }
819
+ const normalizedPath = relPath.split(path2.sep).join("/");
820
+ const frontendMatch = FULLSTACK_FRONTEND_TEMPLATE_PATH_REGEX.exec(normalizedPath);
821
+ if (!frontendMatch) {
822
+ return true;
823
+ }
824
+ const target = frontendMatch[1];
825
+ return Boolean(context.fullstack.frontends[target]);
826
+ }
414
827
  function normalizeRenderedContent(content, outRelPath) {
415
828
  const normalizedLineEndings = content.replace(/\r\n/g, "\n");
416
829
  const ext = path2.extname(outRelPath);
@@ -454,13 +867,13 @@ var APP_TYPES = {
454
867
  },
455
868
  "api": {
456
869
  name: "API \u670D\u52A1",
457
- description: "\u7EAF API \u540E\u7AEF\u670D\u52A1\uFF0CRESTful \u8DEF\u7531\u3001\u65E0 UI",
870
+ description: "typed API workspace\uFF0C\u542B contract + service \u53CC\u5DE5\u7A0B\u3001\u65E0 UI",
458
871
  defaultFeatures: ["db", "cache"]
459
872
  },
460
- "android-app": {
461
- name: "Android \u5E94\u7528",
462
- description: "Android \u539F\u751F\u5E94\u7528\uFF08Capacitor + SvelteKit SPA\uFF09\uFF0C\u53EF\u6253\u5305\u4E3A APK",
463
- defaultFeatures: ["iam", "db", "cache", "crypto", "api-client", "capacitor"]
873
+ "mobile-app": {
874
+ name: "\u79FB\u52A8\u5E94\u7528",
875
+ description: "\u79FB\u52A8\u7AEF\u5E94\u7528\uFF08Capacitor + Svelte 5 + Vite\uFF09\uFF0C\u53EF\u6253\u5305\u4E3A Android/iOS",
876
+ defaultFeatures: ["api-client", "capacitor"]
464
877
  },
465
878
  "fullstack": {
466
879
  name: "\u524D\u540E\u7AEF\u5206\u79BB\u5DE5\u7A0B",
@@ -470,9 +883,9 @@ var APP_TYPES = {
470
883
  };
471
884
  var FRONTEND_TARGETS = {
472
885
  web: { name: "Web", description: "\u6D4F\u89C8\u5668 Web \u5E94\u7528", implemented: true },
473
- app: { name: "App", description: "\u79FB\u52A8\u7AEF H5/App \u524D\u7AEF", implemented: true },
886
+ app: { name: "App", description: "\u79FB\u52A8\u7AEF Capacitor App / H5 \u524D\u7AEF", implemented: true },
474
887
  miniapp: { name: "\u5C0F\u7A0B\u5E8F", description: "\u9884\u7559\u76EE\u6807\uFF0C\u5F53\u524D\u53EA\u751F\u6210\u8BF4\u660E\u5360\u4F4D", implemented: false },
475
- desktop: { name: "\u684C\u9762\u7AEF", description: "\u684C\u9762\u7AEF\u524D\u7AEF\u5DE5\u7A0B\uFF08Tauri \u9884\u7559\uFF09", implemented: true }
888
+ desktop: { name: "\u684C\u9762\u7AEF", description: "Tauri \u684C\u9762\u7AEF\u524D\u7AEF\u5DE5\u7A0B", implemented: true }
476
889
  };
477
890
  var DEFAULT_FULLSTACK_FRONTENDS2 = ["web", "app", "desktop"];
478
891
  var FEATURES = {
@@ -663,29 +1076,36 @@ async function createProject(options) {
663
1076
  });
664
1077
  await generateFromTemplates(projectPath, context);
665
1078
  if (resolvedOptions.appType !== "fullstack") {
666
- const { generateConfigFile: generateConfigFile2 } = await import('./cli-config-templates-JCS7T3NU.js');
1079
+ const { generateConfigFile: generateConfigFile2, generateEnvExample } = await import('./cli-config-templates-5J5VKWWD.js');
667
1080
  const configs = resolvedOptions.moduleConfigs;
1081
+ const isApiWorkspace = resolvedOptions.appType === "api";
1082
+ const configDir = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-service`, "config") : path2.join(projectPath, "config");
1083
+ const envExamplePath = isApiWorkspace ? path2.join(projectPath, "apps", `${resolvedOptions.name}-service`, ".env.example") : path2.join(projectPath, ".env.example");
668
1084
  for (const featureId of resolvedOptions.features) {
669
1085
  const configKey = getFeatureConfigKey(featureId);
670
1086
  if (configKey) {
671
1087
  const content = generateConfigFile2(configKey, configs);
672
- await writeFile(path2.join(projectPath, "config", `_${configKey}.yml`), content);
1088
+ await writeFile(path2.join(configDir, `_${configKey}.yml`), content);
673
1089
  }
674
1090
  }
675
- await writeFile(
676
- path2.join(projectPath, "config", "_core.yml"),
677
- generateConfigFile2("core", configs)
678
- );
679
- const { generateEnvExample } = await import('./cli-config-templates-JCS7T3NU.js');
680
- await writeFile(
681
- path2.join(projectPath, ".env.example"),
682
- generateEnvExample(resolvedOptions.features, configs)
683
- );
1091
+ if (!isApiWorkspace) {
1092
+ await writeFile(
1093
+ path2.join(configDir, "_core.yml"),
1094
+ generateConfigFile2("core", configs)
1095
+ );
1096
+ }
1097
+ const envExample = isApiWorkspace ? `${generateEnvExample(resolvedOptions.features, configs)}
1098
+ # =============================================================================
1099
+ # Service Runtime
1100
+ # =============================================================================
1101
+ PORT=3000
1102
+ ` : generateEnvExample(resolvedOptions.features, configs);
1103
+ await writeFile(envExamplePath, envExample);
684
1104
  }
685
- const { generateSkillFiles } = await import('./cli-skill-templates-IMYZPQRG.js');
1105
+ const { generateSkillFiles } = await import('./cli-skill-templates-JMSV2SVW.js');
686
1106
  await generateSkillFiles(projectPath, resolvedOptions.features, resolvedOptions.appType);
687
1107
  const appTypeLabel = APP_TYPES[resolvedOptions.appType].name;
688
- const readmeContent = resolvedOptions.appType === "fullstack" ? generateFullstackReadme(resolvedOptions.name, resolvedOptions.packageManager, resolvedOptions.frontends) : generateReadme(resolvedOptions.name, appTypeLabel, resolvedOptions.packageManager);
1108
+ const readmeContent = resolvedOptions.appType === "fullstack" ? generateFullstackReadme(resolvedOptions.name, resolvedOptions.packageManager, resolvedOptions.frontends) : resolvedOptions.appType === "api" ? generateApiWorkspaceReadme(resolvedOptions.name, resolvedOptions.packageManager) : generateReadme(resolvedOptions.name, appTypeLabel, resolvedOptions.packageManager);
689
1109
  await writeFile(
690
1110
  path2.join(projectPath, "README.md"),
691
1111
  readmeContent
@@ -706,8 +1126,7 @@ async function createProject(options) {
706
1126
  }
707
1127
  if (resolvedOptions.install) {
708
1128
  spinner.start(`\u5B89\u88C5\u4F9D\u8D56 (${resolvedOptions.packageManager})...`);
709
- const installCmd = getInstallCommand(resolvedOptions.packageManager);
710
- execSync(installCmd, { cwd: projectPath, stdio: "ignore" });
1129
+ installDependencies(projectPath, resolvedOptions.packageManager);
711
1130
  spinner.succeed();
712
1131
  }
713
1132
  printCompletionMessage(resolvedOptions);
@@ -827,7 +1246,7 @@ async function resolveOptions(options) {
827
1246
  addExamples = examples;
828
1247
  }
829
1248
  const detected = await detectPackageManager(options.cwd ?? ".");
830
- let packageManager = selectedAppType === "fullstack" ? "pnpm" : options.packageManager;
1249
+ let packageManager = selectedAppType === "fullstack" || selectedAppType === "api" ? "pnpm" : options.packageManager;
831
1250
  if (!packageManager && useDefaults) {
832
1251
  packageManager = detected;
833
1252
  }
@@ -1141,31 +1560,119 @@ function getInstallCommand(pm) {
1141
1560
  return "npm install";
1142
1561
  }
1143
1562
  }
1563
+ function getRunCommand(pm, script) {
1564
+ return pm === "npm" ? `npm run ${script}` : `${pm} ${script}`;
1565
+ }
1566
+ function installDependencies(projectPath, pm) {
1567
+ const installCmd = getInstallCommand(pm);
1568
+ try {
1569
+ execSync(installCmd, {
1570
+ cwd: projectPath,
1571
+ stdio: "pipe",
1572
+ encoding: "utf-8",
1573
+ maxBuffer: 10 * 1024 * 1024
1574
+ });
1575
+ } catch (error) {
1576
+ const details = formatCommandFailure(installCmd, error);
1577
+ throw new Error(`\u5B89\u88C5\u4F9D\u8D56\u5931\u8D25\uFF08${pm}\uFF09\u3002
1578
+ ${details}`);
1579
+ }
1580
+ }
1581
+ function formatCommandFailure(command, error) {
1582
+ if (!error || typeof error !== "object") {
1583
+ return `\u547D\u4EE4: ${command}`;
1584
+ }
1585
+ const failure = error;
1586
+ const stdout = normalizeChildOutput(failure.stdout);
1587
+ const stderr = normalizeChildOutput(failure.stderr);
1588
+ const status = typeof failure.status === "number" ? `\u9000\u51FA\u7801: ${failure.status}` : "";
1589
+ const signal = typeof failure.signal === "string" ? `\u4FE1\u53F7: ${failure.signal}` : "";
1590
+ const output = [
1591
+ `\u547D\u4EE4: ${command}`,
1592
+ status,
1593
+ signal,
1594
+ stderr ? `stderr:
1595
+ ${stderr}` : "",
1596
+ stdout ? `stdout:
1597
+ ${stdout}` : ""
1598
+ ].filter(Boolean);
1599
+ return output.join("\n\n");
1600
+ }
1601
+ function normalizeChildOutput(output) {
1602
+ if (typeof output === "string") {
1603
+ return output.trim();
1604
+ }
1605
+ if (Buffer.isBuffer(output)) {
1606
+ return output.toString("utf-8").trim();
1607
+ }
1608
+ return "";
1609
+ }
1144
1610
  function generateReadme(name, appTypeLabel, pm) {
1611
+ const install = getInstallCommand(pm);
1145
1612
  return `# ${name}
1146
1613
 
1147
1614
  \u57FA\u4E8E hai Agent Framework \u6784\u5EFA\u7684${appTypeLabel}\u5E94\u7528\u3002
1148
1615
 
1149
1616
  ## \u5F00\u53D1
1150
1617
 
1618
+ \`\`\`bash
1619
+ ${install}
1620
+ ${getRunCommand(pm, "dev")}
1621
+ \`\`\`
1622
+
1623
+ ## \u6784\u5EFA
1624
+
1625
+ \`\`\`bash
1626
+ ${getRunCommand(pm, "build")}
1627
+ ${getRunCommand(pm, "i18n:compile")}
1628
+ ${getRunCommand(pm, "preview")}
1629
+ \`\`\`
1630
+
1631
+ ## \u6587\u6863
1632
+
1633
+ - [hai Agent Framework](https://github.com/hai-series/hai-framework)
1634
+ - [Svelte 5](https://svelte.dev/)
1635
+ `;
1636
+ }
1637
+ function generateApiWorkspaceReadme(name, pm) {
1638
+ return `# ${name}
1639
+
1640
+ \u57FA\u4E8E hai Agent Framework \u6784\u5EFA\u7684 typed API workspace\u3002
1641
+
1642
+ ## \u5DE5\u7A0B\u7ED3\u6784
1643
+
1644
+ - \`apps/${name}-contract\`\uFF1A\u5171\u4EAB API contract\u3001Zod schema \u4E0E\u7C7B\u578B
1645
+ - \`apps/${name}-service\`\uFF1A\u540E\u7AEF API service\uFF0C\u57FA\u4E8E \`@h-ai/serv\` \u66B4\u9732 HTTP \u5E94\u7528
1646
+
1647
+ ## \u5F00\u53D1
1648
+
1151
1649
  \`\`\`bash
1152
1650
  ${pm} install
1153
1651
  ${pm} dev
1154
1652
  \`\`\`
1155
1653
 
1156
- ## \u6784\u5EFA
1654
+ ## \u8D28\u91CF\u95E8\u7981
1157
1655
 
1158
1656
  \`\`\`bash
1657
+ ${pm} typecheck
1658
+ ${pm} lint
1159
1659
  ${pm} build
1160
- ${pm} i18n:compile
1161
- ${pm} preview
1660
+ ${pm} test
1661
+ ${pm} test:e2e
1162
1662
  \`\`\`
1163
1663
 
1664
+ ## \u6269\u5C55\u5EFA\u8BAE
1665
+
1666
+ - \u5728 \`${name}-contract\` \u4E2D\u7EF4\u62A4\u5E94\u7528\u7EA7 contract\uFF0C\u524D\u540E\u7AEF\u5171\u7528\u540C\u4E00\u4EFD\u7C7B\u578B\u4E0E\u8DEF\u5F84\u5B9A\u4E49\u3002
1667
+ - \u5728 \`${name}-service\` \u4E2D\u6269\u5C55 procedures\u3001\u6A21\u5757\u521D\u59CB\u5316\u4E0E\u914D\u7F6E\u3002
1668
+ - \u9700\u8981 IAM / storage / ai \u65F6\uFF0C\u4F18\u5148\u590D\u7528 \`@h-ai/api-contract\` \u4E0E \`@h-ai/serv/features/*\`\u3002
1669
+
1164
1670
  ## \u6587\u6863
1165
1671
 
1166
1672
  - [hai Agent Framework](https://github.com/hai-series/hai-framework)
1167
- - [SvelteKit](https://kit.svelte.dev/)
1168
- - [Svelte 5](https://svelte.dev/)
1673
+ - [@h-ai/serv](./.agents/skills/hai-serv/SKILL.md)
1674
+ - [@h-ai/api-contract](./.agents/skills/hai-api-contract/SKILL.md)
1675
+ - [@h-ai/api-client](./.agents/skills/hai-api-client/SKILL.md)
1169
1676
  `;
1170
1677
  }
1171
1678
  function generateFullstackReadme(name, pm, frontends) {
@@ -1186,13 +1693,28 @@ function generateFullstackReadme(name, pm, frontends) {
1186
1693
 
1187
1694
  \u5DF2\u542F\u7528\u524D\u7AEF\uFF1A${enabledFrontends || "Web / App / Desktop"}
1188
1695
 
1189
- ## \u5F00\u53D1
1696
+ ## \u5F00\u53D1\u3001\u7F16\u8BD1\u4E0E\u6253\u5305
1190
1697
 
1191
1698
  \`\`\`bash
1192
1699
  ${pm} install
1193
1700
  ${pm} dev
1701
+
1702
+ # \u4E00\u952E\u7F16\u8BD1\uFF1A\u7C7B\u578B\u68C0\u67E5 + \u5168\u5DE5\u4F5C\u533A\u6784\u5EFA
1703
+ ${pm} compile
1704
+
1705
+ # \u4E00\u952E\u6253\u5305\uFF1AWeb build\u3001App Capacitor sync\u3001Desktop Tauri build\uFF08\u6309\u542F\u7528\u524D\u7AEF\u6267\u884C\uFF09
1706
+ ${pm} package
1707
+
1708
+ # \u90E8\u7F72\u5165\u53E3\uFF1A\u9ED8\u8BA4\u6267\u884C package\uFF0C\u53EF\u66FF\u6362\u4E3A\u56E2\u961F\u81EA\u5DF1\u7684 CI/CD \u53D1\u5E03\u811A\u672C
1709
+ ${pm} deploy
1194
1710
  \`\`\`
1195
1711
 
1712
+ \u524D\u7AEF\u5355\u72EC\u4EA4\u4ED8\u547D\u4EE4\uFF1A
1713
+
1714
+ - Web\uFF1A\`${pm} --filter ${name}-web build\` / \`${pm} --filter ${name}-web package\`
1715
+ - App\uFF1A\`${pm} --filter ${name}-app package\`\uFF0CAndroid/iOS \u53EF\u7528 \`cap:build:android:debug\` / \`cap:build:android:release\` / \`cap:build:ios\`
1716
+ - Desktop\uFF1A\`${pm} --filter ${name}-desktop tauri:dev\` / \`${pm} --filter ${name}-desktop package\`
1717
+
1196
1718
  ## i18n \u4E0E shared \u534F\u540C
1197
1719
 
1198
1720
  - shared\uFF1A\`packages/${name}-shared/project.inlang\` + \`messages/\`\uFF0C\u53EA\u653E\u8DE8\u7AEF\u5171\u4EAB\u7EC4\u4EF6\u6587\u6848\u3002
@@ -1219,7 +1741,6 @@ ${pm} test:e2e
1219
1741
  ## \u6587\u6863
1220
1742
 
1221
1743
  - [hai Agent Framework](https://github.com/hai-series/hai-framework)
1222
- - [SvelteKit](https://kit.svelte.dev/)
1223
1744
  - [@h-ai/serv](./.agents/skills/hai-serv/SKILL.md)
1224
1745
  - [@h-ai/ui](./.agents/skills/hai-ui/SKILL.md)
1225
1746
  `;
@@ -1241,14 +1762,15 @@ function printCompletionMessage(options) {
1241
1762
  core.logger.info("\u4E0B\u4E00\u6B65\uFF1A");
1242
1763
  core.logger.info(chalk.cyan(` cd ${options.name}`));
1243
1764
  if (!options.install) {
1244
- core.logger.info(chalk.cyan(` ${options.packageManager} install`));
1765
+ core.logger.info(chalk.cyan(` ${getInstallCommand(options.packageManager)}`));
1245
1766
  }
1246
- if (options.appType === "fullstack") {
1247
- core.logger.info(chalk.cyan(` ${options.packageManager} typecheck`));
1248
- core.logger.info(chalk.cyan(` ${options.packageManager} test`));
1249
- core.logger.info(chalk.cyan(` ${options.packageManager} test:e2e`));
1767
+ if (options.appType === "fullstack" || options.appType === "api") {
1768
+ core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "dev")}`));
1769
+ core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "typecheck")}`));
1770
+ core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "test")}`));
1771
+ core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "test:e2e")}`));
1250
1772
  } else {
1251
- core.logger.info(chalk.cyan(` ${options.packageManager} dev`));
1773
+ core.logger.info(chalk.cyan(` ${getRunCommand(options.packageManager, "dev")}`));
1252
1774
  }
1253
1775
  core.logger.info("", {});
1254
1776
  }
@@ -1332,7 +1854,7 @@ async function addModule(options) {
1332
1854
  core.logger.info(`\u53EF\u7528\u6A21\u5757: ${Object.keys(MODULE_MAP).join(", ")}`);
1333
1855
  return;
1334
1856
  }
1335
- const { generateProjectAiSupport, resolveSkillNamesForPackages } = await import('./cli-skill-templates-IMYZPQRG.js');
1857
+ const { generateProjectAiSupport, resolveSkillNamesForPackages } = await import('./cli-skill-templates-JMSV2SVW.js');
1336
1858
  if (moduleDef.packages.every((p) => project.haiPackages.includes(p))) {
1337
1859
  const generatedFiles2 = await generateProjectAiSupport(
1338
1860
  cwd,
@@ -1368,9 +1890,8 @@ async function addModule(options) {
1368
1890
  const pkg = await fse.readJson(pkgPath);
1369
1891
  if (!pkg.dependencies)
1370
1892
  pkg.dependencies = {};
1371
- const require2 = createRequire(import.meta.url);
1372
- const cliPkg = require2("../../package.json");
1373
- const depVersion = `^${cliPkg.version}`;
1893
+ const existingHaiSpecifier = Object.entries(pkg.dependencies).find(([pkgName]) => pkgName.startsWith("@h-ai/"))?.[1];
1894
+ const depVersion = existingHaiSpecifier === "catalog:" ? "catalog:" : `^${getCliVersion()}`;
1374
1895
  for (const pkgName of allPackages) {
1375
1896
  if (!pkg.dependencies[pkgName]) {
1376
1897
  pkg.dependencies[pkgName] = depVersion;
@@ -1443,18 +1964,19 @@ async function deployCommand(options) {
1443
1964
  const spinner = ora();
1444
1965
  const cwd = options.cwd ?? process3.cwd();
1445
1966
  const appDir = resolve(cwd, options.appDir ?? ".");
1967
+ let closeDeploy = null;
1446
1968
  try {
1447
1969
  let deployModule;
1448
1970
  try {
1449
- deployModule = await import('./src-N4NPS7AG.js');
1971
+ deployModule = await import('./src-QNEJJ3BV.js');
1450
1972
  } catch {
1451
1973
  core.logger.error(chalk.red("Deploy module not found. Install @h-ai/deploy first:"));
1452
1974
  core.logger.info(chalk.cyan(" pnpm add @h-ai/deploy"));
1453
1975
  return;
1454
1976
  }
1455
- const { deploy, loadCredentials, scanApp } = deployModule;
1977
+ const { deploy } = deployModule;
1456
1978
  spinner.start("Loading credentials...");
1457
- const credResult = loadCredentials();
1979
+ const credResult = deploy.credentials.load();
1458
1980
  if (!credResult.success) {
1459
1981
  spinner.fail(chalk.red(`Failed to load credentials: ${credResult.error.message}`));
1460
1982
  return;
@@ -1472,7 +1994,7 @@ async function deployCommand(options) {
1472
1994
  const deployConfig = parse(rawConfig);
1473
1995
  spinner.succeed("Deploy config loaded");
1474
1996
  spinner.start("Scanning application...");
1475
- const scanResult = await scanApp(appDir);
1997
+ const scanResult = await deploy.scan(appDir);
1476
1998
  if (!scanResult.success) {
1477
1999
  spinner.fail(chalk.red(`Scan failed: ${scanResult.error.message}`));
1478
2000
  return;
@@ -1485,6 +2007,7 @@ async function deployCommand(options) {
1485
2007
  spinner.fail(chalk.red(`Init failed: ${initResult.error.message}`));
1486
2008
  return;
1487
2009
  }
2010
+ closeDeploy = () => deploy.close();
1488
2011
  spinner.succeed("Deploy module initialized");
1489
2012
  spinner.start("Deploying application...");
1490
2013
  const deployResult = await deploy.deployApp(appDir, {
@@ -1494,7 +2017,6 @@ async function deployCommand(options) {
1494
2017
  });
1495
2018
  if (!deployResult.success) {
1496
2019
  spinner.fail(chalk.red(`Deploy failed: ${deployResult.error.message}`));
1497
- await deploy.close();
1498
2020
  return;
1499
2021
  }
1500
2022
  spinner.succeed(chalk.green("Deployment successful!"));
@@ -1505,11 +2027,18 @@ async function deployCommand(options) {
1505
2027
  core.logger.info(chalk.gray(` Env: ${deployResult.data.envVarsSet.join(", ")}`));
1506
2028
  }
1507
2029
  core.logger.info("");
1508
- await deploy.close();
1509
2030
  } catch (error) {
1510
2031
  spinner.fail(chalk.red("Deploy command failed"));
1511
2032
  core.logger.error(error instanceof Error ? error.message : String(error));
1512
2033
  throw error;
2034
+ } finally {
2035
+ if (closeDeploy) {
2036
+ try {
2037
+ await closeDeploy();
2038
+ } catch (error) {
2039
+ core.logger.error("Failed to close deploy module", { error });
2040
+ }
2041
+ }
1513
2042
  }
1514
2043
  }
1515
2044
  function interpolateEnvFallback(content) {
@@ -1808,6 +2337,7 @@ export const down: MigrationFn = async (db) => {
1808
2337
  }
1809
2338
  var MODULE_CONFIG_MAP = {
1810
2339
  "@h-ai/core": { configKey: "core", label: "Core" },
2340
+ "@h-ai/serv": { configKey: "serv", label: "Service" },
1811
2341
  "@h-ai/reldb": { configKey: "db", label: "Database" },
1812
2342
  "@h-ai/cache": { configKey: "cache", label: "Cache" },
1813
2343
  "@h-ai/iam": { configKey: "iam", label: "IAM" },
@@ -1923,21 +2453,11 @@ async function initProject(options) {
1923
2453
  }
1924
2454
 
1925
2455
  // src/cli-main.ts
1926
- function readCliVersion() {
1927
- try {
1928
- const here = path2.dirname(fileURLToPath(import.meta.url));
1929
- const pkgPath = path2.resolve(here, "../package.json");
1930
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1931
- return pkg.version ?? "0.0.0";
1932
- } catch {
1933
- return "0.0.0";
1934
- }
1935
- }
1936
- var VERSION = readCliVersion();
2456
+ var VERSION = getCliVersion();
1937
2457
  var cli = cac("hai");
1938
2458
  cli.option("-v, --verbose", "\u663E\u793A\u8BE6\u7EC6\u8F93\u51FA");
1939
2459
  cli.option("-C, --cwd <path>", "\u5DE5\u4F5C\u76EE\u5F55");
1940
- cli.command("create [name]", "\u521B\u5EFA\u65B0\u7684 hai \u9879\u76EE").option("--type <type>", "\u5E94\u7528\u7C7B\u578B (admin, website, h5, api, android-app, fullstack)").option("--frontends <targets>", "\u524D\u540E\u7AEF\u5206\u79BB\u5DE5\u7A0B\u524D\u7AEF\u76EE\u6807 (\u9017\u53F7\u5206\u9694: web,app,miniapp,desktop)").option("-t, --template <template>", "\u9879\u76EE\u6A21\u677F (minimal, default, full, custom)").option("-f, --features <features>", "\u529F\u80FD\u5217\u8868 (\u9017\u53F7\u5206\u9694: iam,db,cache,ai,storage,crypto)").option("--examples", "\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-examples", "\u4E0D\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-install", "\u4E0D\u5B89\u88C5\u4F9D\u8D56").option("-p, --package-manager <pm>", "\u5305\u7BA1\u7406\u5668 (pnpm, npm, yarn)").option("--no-git", "\u4E0D\u521D\u59CB\u5316 Git").option("--git-remote <url>", "Git \u8FDC\u7A0B\u4ED3\u5E93\u5730\u5740").option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (name, options) => {
2460
+ cli.command("create [name]", "\u521B\u5EFA\u65B0\u7684 hai \u9879\u76EE").option("--type <type>", "\u5E94\u7528\u7C7B\u578B (admin, website, h5, api, mobile-app, fullstack)").option("--frontends <targets>", "\u524D\u540E\u7AEF\u5206\u79BB\u5DE5\u7A0B\u524D\u7AEF\u76EE\u6807 (\u9017\u53F7\u5206\u9694: web,app,miniapp,desktop)").option("-t, --template <template>", "\u9879\u76EE\u6A21\u677F (minimal, default, full, custom)").option("-f, --features <features>", "\u529F\u80FD\u5217\u8868 (\u9017\u53F7\u5206\u9694: iam,db,cache,ai,storage,crypto)").option("--examples", "\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-examples", "\u4E0D\u6DFB\u52A0\u793A\u4F8B\u4EE3\u7801").option("--no-install", "\u4E0D\u5B89\u88C5\u4F9D\u8D56").option("-p, --package-manager <pm>", "\u5305\u7BA1\u7406\u5668 (pnpm, npm, yarn)").option("--no-git", "\u4E0D\u521D\u59CB\u5316 Git").option("--git-remote <url>", "Git \u8FDC\u7A0B\u4ED3\u5E93\u5730\u5740").option("-y, --yes", "\u4F7F\u7528\u9ED8\u8BA4\u914D\u7F6E\uFF0C\u8DF3\u8FC7\u4EA4\u4E92").action(async (name, options) => {
1941
2461
  try {
1942
2462
  const features = typeof options.features === "string" ? options.features.split(",").map((f) => f.trim()) : void 0;
1943
2463
  const frontends = typeof options.frontends === "string" ? options.frontends.split(",").map((f) => f.trim()).filter(Boolean) : void 0;