@h-ai/cli 0.1.0-alpha.20 → 0.1.0-alpha.22

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 (182) 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-3BBXDQ4Y.js → chunk-CFCXOKGV.js} +24 -2
  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-IGGO7P45.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 +567 -75
  11. package/dist/index.js.map +1 -1
  12. package/package.json +3 -2
  13. package/templates/README.md +40 -29
  14. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +16 -0
  15. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +38 -0
  16. package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
  17. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +33 -0
  18. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +3 -0
  19. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +12 -0
  20. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
  21. package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
  22. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
  23. package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
  24. package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +17 -0
  25. package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +19 -0
  26. package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +26 -0
  27. package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +55 -0
  28. package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +98 -0
  29. package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +21 -0
  30. package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +184 -0
  31. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +49 -0
  32. package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +18 -0
  33. package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +168 -0
  34. package/templates/apps/api/apps/{{projectName}}-service/tsconfig.json.hbs +16 -0
  35. package/templates/apps/api/apps/{{projectName}}-service/tsup.config.ts.hbs +11 -0
  36. package/templates/apps/api/apps/{{projectName}}-service/vitest.config.ts.hbs +9 -0
  37. package/templates/apps/api/e2e/api-service.spec.ts.hbs +18 -0
  38. package/templates/apps/api/eslint.config.js +32 -0
  39. package/templates/apps/api/package.json.hbs +29 -0
  40. package/templates/apps/api/playwright.config.ts.hbs +58 -0
  41. package/templates/apps/api/pnpm-workspace.yaml.hbs +14 -0
  42. package/templates/apps/api/tsconfig.base.json +15 -0
  43. package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -7
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +18 -0
  46. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +1 -1
  47. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +16 -0
  48. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +6 -0
  49. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +6 -0
  50. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +51 -29
  51. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +186 -0
  52. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +2 -0
  53. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +0 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +18 -0
  55. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +14 -0
  56. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +1 -5
  57. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +10 -4
  58. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +4 -3
  59. package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
  60. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +20 -6
  61. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +1 -1
  62. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +15 -0
  63. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +33 -30
  64. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +152 -0
  65. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +1 -2
  66. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +13 -0
  67. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +22 -0
  68. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
  69. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +12 -0
  70. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
  71. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
  72. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
  73. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
  74. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
  75. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +16 -0
  76. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
  77. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +41 -0
  78. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +2 -8
  79. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +9 -4
  80. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +44 -21
  81. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +15 -6
  82. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +1 -1
  83. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +15 -0
  84. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +25 -27
  85. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +153 -0
  86. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +0 -1
  87. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
  88. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +1 -5
  89. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +10 -4
  90. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +3 -2
  91. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +2 -1
  92. package/templates/apps/fullstack/eslint.config.js +0 -1
  93. package/templates/apps/fullstack/package.json.hbs +18 -17
  94. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +3 -3
  95. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +2 -2
  96. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +2 -2
  97. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +1 -1
  98. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/{server-app.test.ts.hbs → app-server.test.ts.hbs} +1 -1
  99. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +9 -8
  100. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +1 -1
  101. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +5 -1
  102. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +1 -1
  103. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +1 -1
  104. package/templates/apps/fullstack/playwright.config.ts.hbs +41 -4
  105. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +15 -0
  106. package/templates/apps/mobile-app/.env.hbs +3 -0
  107. package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
  108. package/templates/apps/mobile-app/index.html.hbs +13 -0
  109. package/templates/apps/mobile-app/messages/en-US.json +36 -0
  110. package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
  111. package/templates/apps/mobile-app/src/App.svelte.hbs +162 -0
  112. package/templates/apps/mobile-app/src/lib/api.ts.hbs +54 -0
  113. package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +5 -6
  114. package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
  115. package/templates/base/.gitignore.hbs +16 -0
  116. package/templates/base/{eslint.config.js → eslint.config.js.hbs} +4 -1
  117. package/templates/base/package.json.hbs +52 -33
  118. package/templates/base/playwright.config.ts +30 -3
  119. package/templates/base/pnpm-workspace.yaml.hbs +14 -0
  120. package/templates/base/src/app.d.ts.hbs +3 -0
  121. package/templates/base/src/app.html.hbs +3 -0
  122. package/templates/base/svelte.config.js.hbs +43 -3
  123. package/templates/base/tests/scaffold.test.ts.hbs +7 -0
  124. package/templates/base/tsconfig.json.hbs +50 -0
  125. package/templates/base/vite.config.ts.hbs +10 -0
  126. package/templates/skills/AGENTS.md +57 -24
  127. package/templates/skills/CLAUDE.md +18 -7
  128. package/templates/skills/bridges/admin/AGENTS.md +66 -0
  129. package/templates/skills/bridges/admin/CLAUDE.md +19 -0
  130. package/templates/skills/bridges/admin/copilot-instructions.md +46 -0
  131. package/templates/skills/bridges/api/AGENTS.md +65 -0
  132. package/templates/skills/bridges/api/CLAUDE.md +19 -0
  133. package/templates/skills/bridges/api/copilot-instructions.md +46 -0
  134. package/templates/skills/bridges/fullstack/AGENTS.md +84 -0
  135. package/templates/skills/bridges/fullstack/CLAUDE.md +19 -0
  136. package/templates/skills/bridges/fullstack/copilot-instructions.md +54 -0
  137. package/templates/skills/bridges/h5/AGENTS.md +65 -0
  138. package/templates/skills/bridges/h5/CLAUDE.md +19 -0
  139. package/templates/skills/bridges/h5/copilot-instructions.md +44 -0
  140. package/templates/skills/bridges/mobile-app/AGENTS.md +77 -0
  141. package/templates/skills/bridges/mobile-app/CLAUDE.md +19 -0
  142. package/templates/skills/bridges/mobile-app/copilot-instructions.md +45 -0
  143. package/templates/skills/bridges/website/AGENTS.md +65 -0
  144. package/templates/skills/bridges/website/CLAUDE.md +19 -0
  145. package/templates/skills/bridges/website/copilot-instructions.md +44 -0
  146. package/templates/skills/copilot-instructions.md +27 -64
  147. package/templates/skills/hai-app-create/SKILL.md +1 -0
  148. package/templates/skills/hai-app-review/SKILL.md +1 -1
  149. package/templates/skills/hai-app-tests/SKILL.md +28 -3
  150. package/templates/skills/hai-capacitor/SKILL.md +14 -22
  151. package/templates/skills/hai-ui/SKILL.md +8 -2
  152. package/templates/skills/opencode.json +1 -6
  153. package/dist/chunk-3BBXDQ4Y.js.map +0 -1
  154. package/dist/chunk-GSMXGUYF.js.map +0 -1
  155. package/dist/cli-config-templates-IGGO7P45.js +0 -5
  156. package/dist/cli-skill-templates-IMYZPQRG.js +0 -5
  157. package/templates/apps/android-app/.env.hbs +0 -3
  158. package/templates/apps/android-app/messages/en-US.json +0 -24
  159. package/templates/apps/android-app/messages/zh-CN.json +0 -24
  160. package/templates/apps/android-app/src/lib/api.ts.hbs +0 -32
  161. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -43
  162. package/templates/apps/android-app/src/routes/+layout.ts +0 -7
  163. package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -38
  164. package/templates/apps/api/src/routes/+layout.svelte +0 -14
  165. package/templates/apps/api/src/routes/+page.svelte +0 -11
  166. package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
  167. package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
  168. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
  169. package/templates/apps/api/tests/health.test.ts.hbs +0 -26
  170. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +0 -14
  171. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +0 -18
  172. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +0 -162
  173. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +0 -14
  174. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +0 -18
  175. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +0 -162
  176. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +0 -14
  177. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +0 -18
  178. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +0 -162
  179. package/templates/apps/fullstack/pnpm-workspace.yaml +0 -7
  180. package/templates/base/tsconfig.json +0 -20
  181. /package/templates/apps/fullstack/packages/{{projectName}}-serv/src/{server-app.ts.hbs → app-server.ts.hbs} +0 -0
  182. /package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/{theme.svelte.ts.hbs → theme-store.svelte.ts.hbs} +0 -0
@@ -5,7 +5,7 @@ description: 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构
5
5
 
6
6
  # hai-ui
7
7
 
8
- > `@h-ai/ui` 是基于 Svelte 5 Runes 的多端 UI 组件库,采用 DaisyUI v5 + Tailwind CSS v4 + Bits UI v2,内置 15 个精选 DaisyUI 主题、内置中英文 i18n、自动导入。内置 Shiki 代码高亮、Design Token 系统和 7 个移动端组件。
8
+ > `@h-ai/ui` 是基于 Svelte 5 Runes 的多端 UI 组件库,采用 DaisyUI v5 + Tailwind CSS v4 + Bits UI v2,内置 15 个精选 DaisyUI 主题、内置中英文 i18n、自动导入。内置 Shiki 代码高亮、Mermaid 图表渲染、Design Token 系统和 7 个移动端组件。
9
9
 
10
10
  ---
11
11
 
@@ -23,6 +23,7 @@ description: 使用 @h-ai/ui 构建多端应用界面,包含三层组件架构
23
23
  - 使用 IAM 场景组件(登录/注册/密码/权限守卫/用户资料表单)
24
24
  - 使用 Storage 场景组件(文件上传/图片上传/头像上传/文件列表)
25
25
  - 使用 CRUD 场景组件(列表过滤、详情抽屉、编辑抽屉、删除确认)
26
+ - 渲染 AI 输出(Markdown / Mermaid 文档、代码产物预览)
26
27
  - 配置主题切换与 i18n 多语言
27
28
  - 多端平台检测与适配
28
29
 
@@ -316,10 +317,15 @@ const p = usePlatform()
316
317
  | -------------------- | --------------------------------- |
317
318
  | `MarkdownRenderer` | Markdown 渲染(内置 Shiki 高亮) |
318
319
  | `AiDocumentDownloadMenu` | AI 文档下载菜单 |
319
- | `AiDocumentEditor` | AI 文档编辑器(支持受控代码预览) |
320
+ | `AiDocumentEditor` | AI 文档编辑器(支持 Mermaid 与受控代码预览) |
320
321
  | `AiTableEditor` | AI 表格编辑器 |
321
322
 
322
323
  > AI 场景组件使用 Shiki(纯 ESM)进行代码高亮,支持 27 种语言,通过 CSS 变量 `--hai-hl-*` 自定义颜色。无需额外安装 Shiki,已内置。`AiDocumentEditor` 默认只允许 Markdown 内置预览;HTML / JS / CSS 等高风险预览需要显式启用 `allowUnsafeCodePreview`,或通过 `oncoderun` 返回受控的预览结果。
324
+ >
325
+ > Mermaid 开箱即用:
326
+ > - `sourceKind='document'` 时,文档中的 ```` ```mermaid ```` 代码块会在阅读态自动渲染为图表;
327
+ > - `sourceKind='code'` + `showCodePreviewToggle` 时,可在「代码 / 预览」之间切换查看 Mermaid 图表;
328
+ > - Mermaid 以 `securityLevel: 'strict'` 渲染为消毒后的 SVG,无需开启 `allowUnsafeCodePreview`。
323
329
 
324
330
  #### CRUD 场景组件
325
331
 
@@ -1,11 +1,6 @@
1
1
  {
2
2
  "$schema": "https://opencode.ai/config.json",
3
- "skills": {
4
- "paths": [
5
- ".agents/skills"
6
- ]
7
- },
8
3
  "instructions": [
9
- "AGENTS.md"
4
+ ".github/copilot-instructions.md"
10
5
  ]
11
6
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/cli-config-templates.ts"],"names":[],"mappings":"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","file":"chunk-3BBXDQ4Y.js","sourcesContent":["/**\n * @h-ai/cli — 配置文件模板\n *\n * 为各模块生成默认配置文件内容。\n * @module cli-config-templates\n */\n\nimport type { AiModuleConfig, CacheModuleConfig, CoreModuleConfig, DbModuleConfig, FeatureId, IamModuleConfig, ModuleConfigs, StorageModuleConfig } from '../cli-types.js'\n\n/**\n * 生成模块配置文件内容\n *\n * @param moduleKey - 模块标识(core/db/cache/iam/storage/ai)\n * @param configs - 用户自定义配置值\n * @returns YAML 格式的配置内容\n */\nexport function generateConfigFile(moduleKey: string, configs?: ModuleConfigs): string {\n switch (moduleKey) {\n case 'core':\n return generateCoreConfig(configs?.core)\n case 'db':\n return generateDbConfig(configs?.db)\n case 'cache':\n return generateCacheConfig(configs?.cache)\n case 'iam':\n return generateIamConfig(configs?.iam)\n case 'storage':\n return generateStorageConfig(configs?.storage)\n case 'ai':\n return generateAiConfig(configs?.ai)\n case 'deploy':\n return generateDeployConfig()\n case 'vecdb':\n return generateVecdbConfig()\n case 'reach':\n return generateReachConfig()\n case 'scheduler':\n return generateSchedulerConfig()\n case 'audit':\n return generateAuditConfig()\n case 'payment':\n return generatePaymentConfig()\n default:\n return `# ${moduleKey} 配置\\n`\n }\n}\n\nfunction generateCoreConfig(cfg?: CoreModuleConfig): string {\n const name = cfg?.name ?? 'my-app'\n const locale = cfg?.defaultLocale ?? 'zh-CN'\n const supportedLocales = locale === 'en-US'\n ? ` - en-US\\n - zh-CN`\n : ` - zh-CN\\n - en-US`\n\n return `# =============================================================================\n# 应用配置\n# =============================================================================\n\nname: ${name}\nversion: 0.1.0\nenv: \\${HAI_ENV:development}\ndebug: \\${HAI_DEBUG:false}\n\ndefaultLocale: ${locale}\nsupportedLocales:\n${supportedLocales}\n`\n}\n\nfunction generateDbConfig(cfg?: DbModuleConfig): string {\n const dbType = cfg?.type ?? 'sqlite'\n const database = cfg?.database ?? (dbType === 'sqlite' ? './data/app.db' : 'hai')\n const host = cfg?.host ?? 'localhost'\n const port = cfg?.port ?? (dbType === 'postgresql' ? 5432 : 3306)\n\n if (dbType === 'sqlite') {\n return `# =============================================================================\n# 数据库配置\n# =============================================================================\n\n# 数据库类型: sqlite | postgresql | mysql\ntype: sqlite\n\n# SQLite 数据库路径\ndatabase: \\${HAI_RELDB_DATABASE:${database}}\n\n# PostgreSQL/MySQL 配置(可选)\n# host: \\${HAI_RELDB_HOST:localhost}\n# port: \\${HAI_RELDB_PORT:5432}\n# user: \\${HAI_RELDB_USER:postgres}\n# password: \\${HAI_RELDB_PASSWORD:}\n`\n }\n\n const user = dbType === 'postgresql' ? 'postgres' : 'root'\n\n return `# =============================================================================\n# 数据库配置\n# =============================================================================\n\n# 数据库类型: sqlite | postgresql | mysql\ntype: ${dbType}\n\n# 数据库名称\ndatabase: \\${HAI_RELDB_DATABASE:${database}}\n\n# 连接配置\nhost: \\${HAI_RELDB_HOST:${host}}\nport: \\${HAI_RELDB_PORT:${port}}\nuser: \\${HAI_RELDB_USER:${user}}\npassword: \\${HAI_RELDB_PASSWORD:}\n`\n}\n\nfunction generateCacheConfig(cfg?: CacheModuleConfig): string {\n const cacheType = cfg?.type ?? 'memory'\n\n if (cacheType === 'memory') {\n return `# =============================================================================\n# 缓存配置\n# =============================================================================\n\n# 缓存类型: memory | redis\ntype: memory\n\n# Redis 配置(当 type 为 redis 时使用)\n# url: \\${HAI_CACHE_REDIS_URL:redis://localhost:6379/0}\n# host: \\${HAI_CACHE_REDIS_HOST:localhost}\n# port: \\${HAI_CACHE_REDIS_PORT:6379}\n# password: \\${HAI_CACHE_REDIS_PASSWORD:}\n# keyPrefix: \\${HAI_CACHE_KEY_PREFIX:hai:}\n`\n }\n\n const host = cfg?.host ?? 'localhost'\n const port = cfg?.port ?? 6379\n\n return `# =============================================================================\n# 缓存配置\n# =============================================================================\n\n# 缓存类型: memory | redis\ntype: redis\n\n# Redis 配置\nhost: \\${HAI_CACHE_REDIS_HOST:${host}}\nport: \\${HAI_CACHE_REDIS_PORT:${port}}\npassword: \\${HAI_CACHE_REDIS_PASSWORD:}\nkeyPrefix: \\${HAI_CACHE_KEY_PREFIX:hai:}\n`\n}\n\nfunction generateIamConfig(cfg?: IamModuleConfig): string {\n const loginPassword = cfg?.loginPassword ?? true\n const loginOtp = cfg?.loginOtp ?? false\n\n return `# =============================================================================\n# IAM 配置\n# =============================================================================\n\n# 登录配置\nlogin:\n password: ${loginPassword}\n otp: ${loginOtp}\n ldap: false\n\n# 密码策略\npassword:\n minLength: 8\n maxLength: 128\n requireUppercase: false\n requireLowercase: false\n requireNumber: false\n requireSpecialChar: false\n\n# 会话配置\nsession:\n maxAge: 86400 # 会话超时(秒),默认 24 小时\n sliding: true # 滑动窗口(每次请求刷新过期时间)\n singleDevice: false # 单设备登录\n refreshTokenMaxAge: 604800 # refreshToken 过期(秒),默认 7 天\n\n# RBAC 配置\nrbac:\n defaultRole: user\n\n# 是否自动创建默认数据\nseedDefaultData: true\n`\n}\n\nfunction generateStorageConfig(cfg?: StorageModuleConfig): string {\n const storageType = cfg?.type ?? 'local'\n\n if (storageType === 'local') {\n const localPath = cfg?.localPath ?? './data/uploads'\n return `# =============================================================================\n# 存储配置\n# =============================================================================\n\n# 默认 Provider\ndefaultProvider: local\n\n# Provider 配置\nproviders:\n local:\n type: local\n root: \\${HAI_STORAGE_PATH:${localPath}}\n maxFileSize: 10485760 # 10MB\n\n # S3 配置(可选)\n # s3:\n # type: s3\n # bucket: \\${HAI_STORAGE_S3_BUCKET}\n # region: \\${HAI_STORAGE_S3_REGION:us-east-1}\n # accessKeyId: \\${HAI_STORAGE_S3_ACCESS_KEY}\n # secretAccessKey: \\${HAI_STORAGE_S3_SECRET_KEY}\n # endpoint: \\${HAI_STORAGE_S3_ENDPOINT}\n # forcePathStyle: \\${HAI_STORAGE_S3_FORCE_PATH_STYLE:false}\n`\n }\n\n return `# =============================================================================\n# 存储配置\n# =============================================================================\n\n# 默认 Provider\ndefaultProvider: s3\n\n# Provider 配置\nproviders:\n s3:\n type: s3\n bucket: \\${HAI_STORAGE_S3_BUCKET}\n region: \\${HAI_STORAGE_S3_REGION:us-east-1}\n accessKeyId: \\${HAI_STORAGE_S3_ACCESS_KEY}\n secretAccessKey: \\${HAI_STORAGE_S3_SECRET_KEY}\n # endpoint: \\${HAI_STORAGE_S3_ENDPOINT}\n # forcePathStyle: \\${HAI_STORAGE_S3_FORCE_PATH_STYLE:false}\n\n # 本地存储(可选)\n # local:\n # type: local\n # root: \\${HAI_STORAGE_PATH:./data/uploads}\n # maxFileSize: 10485760 # 10MB\n`\n}\n\nfunction generateAiConfig(cfg?: AiModuleConfig): string {\n const model = cfg?.model ?? 'gpt-4o-mini'\n\n // AIConfigSchema 结构:llm(必填)+ 可选子模块\n // LLMConfigSchema 支持顶层 apiKey/model,以及多模型 models 数组\n return `# =============================================================================\n# AI 配置\n# =============================================================================\n\n# LLM 配置(必填)\nllm:\n # API Key(留空时自动读取 HAI_AI_LLM_API_KEY / OPENAI_API_KEY 环境变量)\n apiKey: \\${HAI_AI_LLM_API_KEY:}\n # Base URL(留空时自动读取 HAI_AI_LLM_BASE_URL / OPENAI_BASE_URL,默认 https://api.openai.com/v1)\n # baseUrl: \\${HAI_AI_LLM_BASE_URL:}\n # 默认模型\n model: ${model}\n # 全局最大 Token 数(默认 4096)\n # maxTokens: 4096\n # 采样温度(0-2,默认 0.7)\n # temperature: 0.7\n # 请求超时(毫秒,默认 60000)\n # timeout: 60000\n\n # 多模型配置(可选,用于场景路由)\n # models:\n # - id: fast\n # model: gpt-4o-mini\n # - id: smart\n # model: gpt-4o\n # apiKey: \\${HAI_AI_LLM_API_KEY:}\n\n # 场景模型映射(可选)\n # scenarios:\n # default: fast\n # analysis: smart\n`\n}\n\n/**\n * 根据选中的功能模块生成 .env.example 内容\n *\n * @param features - 选中的功能模块列表\n * @param configs - 用户自定义配置值\n * @returns .env.example 文件内容\n */\nexport function generateEnvExample(features: FeatureId[], configs?: ModuleConfigs): string {\n const sections: string[] = []\n\n // 文件头\n sections.push(`# =============================================================================\n# Environment Variables\n# =============================================================================\n#\n# Copy this file to .env and fill in actual values.\n# Config files in config/ reference these variables via \\${VAR_NAME:default} syntax.\n#\n# Naming convention: HAI_<MODULE>_<SETTING>\n# =============================================================================`)\n\n // 应用基础(始终生成)\n sections.push(`\n# =============================================================================\n# Application\n# =============================================================================\n# Environment: development | production | test\nHAI_ENV=development\n# Enable debug mode\nHAI_DEBUG=false`)\n\n // 数据库\n if (features.includes('db')) {\n const dbType = configs?.db?.type ?? 'sqlite'\n const dbDatabase = configs?.db?.database ?? (dbType === 'sqlite' ? './data/app.db' : 'hai')\n const isSqlite = dbType === 'sqlite'\n sections.push(`\n# =============================================================================\n# Database (@h-ai/reldb)\n# =============================================================================\n# Database type: sqlite | postgresql | mysql\nHAI_RELDB_TYPE=${dbType}\n# SQLite: file path; PostgreSQL/MySQL: database name\nHAI_RELDB_DATABASE=${dbDatabase}${isSqlite\n ? `\n# PostgreSQL/MySQL connection (uncomment when not using sqlite)\n# HAI_RELDB_HOST=localhost\n# HAI_RELDB_PORT=5432\n# HAI_RELDB_USER=postgres\n# HAI_RELDB_PASSWORD=`\n : `\n# Connection\nHAI_RELDB_HOST=${configs?.db?.host ?? 'localhost'}\nHAI_RELDB_PORT=${configs?.db?.port ?? (dbType === 'postgresql' ? 5432 : 3306)}\nHAI_RELDB_USER=${dbType === 'postgresql' ? 'postgres' : 'root'}\nHAI_RELDB_PASSWORD=`}`)\n }\n\n // IAM / Session\n if (features.includes('iam')) {\n sections.push(`\n# =============================================================================\n# IAM (@h-ai/iam)\n# =============================================================================\nHAI_IAM_SESSION_SECRET=change-me-to-a-strong-random-string-min-32-chars\n# HAI_IAM_PASSWORD_MIN_LENGTH=8\n# HAI_IAM_SESSION_MAX_AGE=86400\n# HAI_IAM_REFRESH_TOKEN_MAX_AGE=604800\n# HAI_IAM_MAX_LOGIN_ATTEMPTS=5\n# HAI_KIT_COOKIE_KEY= # 32-char hex for SM4-CBC cookie encryption\n`)\n }\n\n // 缓存\n if (features.includes('cache')) {\n const cacheType = configs?.cache?.type ?? 'memory'\n if (cacheType === 'redis') {\n sections.push(`\n# =============================================================================\n# Cache (@h-ai/cache)\n# =============================================================================\n# Cache type: memory | redis\nHAI_CACHE_TYPE=redis\n# Redis connection\nHAI_CACHE_REDIS_HOST=${configs?.cache?.host ?? 'localhost'}\nHAI_CACHE_REDIS_PORT=${configs?.cache?.port ?? 6379}\nHAI_CACHE_REDIS_PASSWORD=\n# HAI_CACHE_REDIS_URL=redis://localhost:6379/0\n# HAI_CACHE_REDIS_DB=0\n# HAI_CACHE_CONNECT_TIMEOUT=10000\n# HAI_CACHE_COMMAND_TIMEOUT=5000\n# HAI_CACHE_KEY_PREFIX=hai:`)\n }\n else {\n sections.push(`\n# =============================================================================\n# Cache (@h-ai/cache)\n# =============================================================================\n# Cache type: memory | redis\nHAI_CACHE_TYPE=memory\n# Redis connection (uncomment when type=redis)\n# HAI_CACHE_REDIS_URL=redis://localhost:6379/0\n# HAI_CACHE_REDIS_HOST=localhost\n# HAI_CACHE_REDIS_PORT=6379\n# HAI_CACHE_REDIS_PASSWORD=\n# HAI_CACHE_REDIS_DB=0\n# HAI_CACHE_CONNECT_TIMEOUT=10000\n# HAI_CACHE_COMMAND_TIMEOUT=5000\n# HAI_CACHE_KEY_PREFIX=hai:`)\n }\n }\n\n // 存储\n if (features.includes('storage')) {\n const storageType = configs?.storage?.type ?? 'local'\n if (storageType === 's3') {\n sections.push(`\n# =============================================================================\n# Storage (@h-ai/storage)\n# =============================================================================\n# Storage type: local | s3\nHAI_STORAGE_TYPE=s3\n# S3 / S3-compatible\nHAI_STORAGE_S3_BUCKET=\nHAI_STORAGE_S3_REGION=us-east-1\nHAI_STORAGE_S3_ACCESS_KEY=\nHAI_STORAGE_S3_SECRET_KEY=\n# HAI_STORAGE_S3_ENDPOINT= # Custom endpoint for MinIO / Aliyun OSS etc.\n# HAI_STORAGE_S3_FORCE_PATH_STYLE=false\n# Local storage (uncomment when type=local)\n# HAI_STORAGE_PATH=./data/uploads`)\n }\n else {\n sections.push(`\n# =============================================================================\n# Storage (@h-ai/storage)\n# =============================================================================\n# Storage type: local | s3\nHAI_STORAGE_TYPE=local\n# Local storage root path\nHAI_STORAGE_PATH=${configs?.storage?.localPath ?? './data/uploads'}\n# S3 / S3-compatible (uncomment when type=s3)\n# HAI_STORAGE_S3_BUCKET=\n# HAI_STORAGE_S3_REGION=us-east-1\n# HAI_STORAGE_S3_ACCESS_KEY=\n# HAI_STORAGE_S3_SECRET_KEY=\n# HAI_STORAGE_S3_ENDPOINT= # Custom endpoint for MinIO / Aliyun OSS etc.\n# HAI_STORAGE_S3_FORCE_PATH_STYLE=false`)\n }\n }\n\n // AI\n if (features.includes('ai')) {\n const provider = configs?.ai?.defaultProvider ?? 'openai'\n if (provider === 'anthropic') {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI-compatible API Key (Anthropic models via OpenAI-compatible proxy)\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n else if (provider === 'openai') {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI / OpenAI-compatible\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL (e.g. local proxy, Azure)\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n else {\n sections.push(`\n# =============================================================================\n# AI (@h-ai/ai)\n# =============================================================================\n# OpenAI-compatible provider\nHAI_AI_LLM_API_KEY=\n# HAI_AI_LLM_BASE_URL= # Custom base URL\n# Optional compatibility fallback\n# OPENAI_API_KEY=`)\n }\n }\n\n // VecDB\n if (features.includes('vecdb')) {\n sections.push(`\n# =============================================================================\n# Vector Database (@h-ai/vecdb)\n# =============================================================================\n# Backend type: lancedb | pgvector | qdrant\nHAI_VECDB_TYPE=lancedb\n# LanceDB data path\nHAI_VECDB_PATH=./data/vecdb\n# Qdrant (uncomment when type=qdrant)\n# HAI_VECDB_QDRANT_URL=http://localhost:6333\n# HAI_VECDB_QDRANT_API_KEY=\n`)\n }\n\n // Reach\n if (features.includes('reach')) {\n sections.push(`\n# =============================================================================\n# Reach (@h-ai/reach)\n# =============================================================================\n# SMTP (uncomment when enabling email provider)\n# HAI_REACH_SMTP_HOST=smtp.example.com\n# HAI_REACH_SMTP_PORT=465\n# HAI_REACH_SMTP_USER=\n# HAI_REACH_SMTP_PASS=\n# HAI_REACH_SMTP_FROM=noreply@example.com\n`)\n }\n\n // Payment\n if (features.includes('payment')) {\n sections.push(`\n# =============================================================================\n# Payment (@h-ai/payment)\n# =============================================================================\n# WeChat Pay\n# HAI_PAYMENT_WECHAT_MCH_ID=\n# HAI_PAYMENT_WECHAT_API_V3_KEY=\n# HAI_PAYMENT_WECHAT_SERIAL_NO=\n# HAI_PAYMENT_WECHAT_PRIVATE_KEY=\n# HAI_PAYMENT_WECHAT_APP_ID=\n# Alipay\n# HAI_PAYMENT_ALIPAY_APP_ID=\n# HAI_PAYMENT_ALIPAY_PRIVATE_KEY=\n# HAI_PAYMENT_ALIPAY_PUBLIC_KEY=\n# Stripe\n# HAI_PAYMENT_STRIPE_SECRET_KEY=\n# HAI_PAYMENT_STRIPE_WEBHOOK_SECRET=\n`)\n }\n\n // 测试(始终生成)\n sections.push(`\n# =============================================================================\n# Testing\n# =============================================================================\n# E2E test mode (relaxes rate limiting etc.)\n# HAI_E2E=1\n`)\n\n return sections.join('\\n')\n}\n\nfunction generateDeployConfig(): string {\n return `# =============================================================================\n# 部署配置 (@h-ai/deploy)\n# =============================================================================\n# 部署平台凭证通过 ~/.hai/credentials.yml 管理\n# 环境变量引用格式: \\${VAR_NAME:default_value}\n\n# 部署平台\nprovider:\n type: vercel\n token: \\${HAI_DEPLOY_VERCEL_TOKEN}\n\n# 基础设施服务(按需开启)\nservices:\n # PostgreSQL 数据库 (Neon)\n # db:\n # provisioner: neon\n # apiKey: \\${HAI_DEPLOY_NEON_API_KEY}\n\n # Redis 缓存 (Upstash)\n # cache:\n # provisioner: upstash\n # email: \\${HAI_DEPLOY_UPSTASH_EMAIL}\n # apiKey: \\${HAI_DEPLOY_UPSTASH_API_KEY}\n\n # S3 存储 (Cloudflare R2)\n # storage:\n # provisioner: cloudflare-r2\n # accountId: \\${HAI_DEPLOY_CF_ACCOUNT_ID}\n # apiToken: \\${HAI_DEPLOY_CF_API_TOKEN}\n\n # 邮件 (Resend)\n # email:\n # provisioner: resend\n # apiKey: \\${HAI_DEPLOY_RESEND_API_KEY}\n\n # 短信 (阿里云)\n # sms:\n # provisioner: aliyun\n # accessKeyId: \\${HAI_DEPLOY_ALIYUN_ACCESS_KEY_ID}\n # accessKeySecret: \\${HAI_DEPLOY_ALIYUN_ACCESS_KEY_SECRET}\n`\n}\n\nfunction generateVecdbConfig(): string {\n return `# =============================================================================\n# 向量数据库配置 (@h-ai/vecdb)\n# =============================================================================\n\n# 数据库类型: lancedb | pgvector | qdrant\ntype: lancedb\n\n# LanceDB 数据目录\npath: \\${HAI_VECDB_PATH:./data/vecdb}\n\n# 距离度量: cosine | euclidean | dot\n# metric: cosine\n\n# pgvector 配置(当 type 为 pgvector 时使用)\n# type: pgvector\n# host: \\${HAI_RELDB_HOST:localhost}\n# port: \\${HAI_RELDB_PORT:5432}\n# database: \\${HAI_RELDB_DATABASE:hai}\n# user: \\${HAI_RELDB_USER:postgres}\n# password: \\${HAI_RELDB_PASSWORD:}\n# indexType: hnsw\n# tablePrefix: vec_\n\n# Qdrant 配置(当 type 为 qdrant 时使用)\n# type: qdrant\n# url: \\${HAI_VECDB_QDRANT_URL:http://localhost:6333}\n# apiKey: \\${HAI_VECDB_QDRANT_API_KEY:}\n`\n}\n\nfunction generateReachConfig(): string {\n return `# =============================================================================\n# 消息推送配置 (@h-ai/reach)\n# =============================================================================\n\nproviders:\n # 控制台输出(开发/测试用)\n - name: console_dev\n type: console\n\n # SMTP 邮件(按需开启)\n # - name: email\n # type: smtp\n # host: \\${HAI_REACH_SMTP_HOST:smtp.example.com}\n # port: \\${HAI_REACH_SMTP_PORT:465}\n # secure: true\n # user: \\${HAI_REACH_SMTP_USER:}\n # pass: \\${HAI_REACH_SMTP_PASS:}\n # from: \\${HAI_REACH_SMTP_FROM:noreply@example.com}\n\n # 阿里云短信(按需开启)\n # - name: sms\n # type: aliyun-sms\n # accessKeyId: \\${HAI_REACH_SMS_ACCESS_KEY}\n # accessKeySecret: \\${HAI_REACH_SMS_SECRET_KEY}\n # signName: MyApp\n\n# 模板(可选)\n# templates:\n# - name: verification_code\n# provider: email\n# subject: \"验证码: {code}\"\n# body: \"您的验证码是 {code},有效期 {minutes} 分钟。\"\n\n# 免打扰(可选)\n# dnd:\n# enabled: true\n# strategy: delay\n# start: \"22:00\"\n# end: \"08:00\"\n`\n}\n\nfunction generateSchedulerConfig(): string {\n return `# =============================================================================\n# 任务调度配置 (@h-ai/scheduler)\n# =============================================================================\n\n# 是否启用数据库日志(需要 @h-ai/reldb)\nenableDb: true\n\n# 执行日志表名\ntableName: hai_scheduler_logs\n\n# 任务定义表名\ntaskTableName: hai_scheduler_tasks\n\n# 分布式锁表名\nlockTableName: hai_scheduler_locks\n\n# 检查间隔(毫秒)\ntickInterval: 1000\n\n# 锁过期时间(毫秒)\nlockExpireMs: 300000\n`\n}\n\nfunction generateAuditConfig(): string {\n return `# =============================================================================\n# 审计日志配置 (@h-ai/audit)\n# =============================================================================\n\n# 审计日志表名\ntableName: hai_audit_logs\n\n# 用户表名(用于 JOIN 查询)\nuserTable: hai_iam_users\n\n# 用户表主键列名\nuserIdColumn: id\n\n# 用户名列名\nuserNameColumn: username\n`\n}\n\nfunction generatePaymentConfig(): string {\n return `# =============================================================================\n# 支付配置 (@h-ai/payment)\n# =============================================================================\n\n# 微信支付(按需开启)\n# wechat:\n# mchId: \\${HAI_PAYMENT_WECHAT_MCH_ID}\n# apiV3Key: \\${HAI_PAYMENT_WECHAT_API_V3_KEY}\n# serialNo: \\${HAI_PAYMENT_WECHAT_SERIAL_NO}\n# privateKey: \\${HAI_PAYMENT_WECHAT_PRIVATE_KEY}\n# appId: \\${HAI_PAYMENT_WECHAT_APP_ID}\n\n# 支付宝(按需开启)\n# alipay:\n# appId: \\${HAI_PAYMENT_ALIPAY_APP_ID}\n# privateKey: \\${HAI_PAYMENT_ALIPAY_PRIVATE_KEY}\n# alipayPublicKey: \\${HAI_PAYMENT_ALIPAY_PUBLIC_KEY}\n# signType: RSA2\n# sandbox: false\n\n# Stripe(按需开启)\n# stripe:\n# secretKey: \\${HAI_PAYMENT_STRIPE_SECRET_KEY}\n# webhookSecret: \\${HAI_PAYMENT_STRIPE_WEBHOOK_SECRET}\n`\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/cli-skill-templates.ts"],"names":[],"mappings":";;;;;AAcA,IAAM,gBAAA,GAA2C;AAAA,EAC/C,IAAA,EAAM,WAAA;AAAA,EACN,OAAA,EAAS,WAAA;AAAA,EACT,OAAA,EAAS,WAAA;AAAA,EACT,KAAA,EAAO,SAAA;AAAA,EACP,SAAA,EAAW,aAAA;AAAA,EACX,IAAA,EAAM,QAAA;AAAA,EACN,QAAA,EAAU,YAAA;AAAA,EACV,SAAA,EAAW,aAAA;AAAA,EACX,OAAA,EAAS,WAAA;AAAA,EACT,UAAA,EAAY,cAAA;AAAA,EACZ,OAAA,EAAS,WAAA;AAAA,EACT,WAAA,EAAa,eAAA;AAAA,EACb,OAAA,EAAS,WAAA;AAAA,EACT,QAAA,EAAU,YAAA;AAAA,EACV,KAAA,EAAO,SAAA;AAAA,EACP,IAAA,EAAM,QAAA;AAAA,EACN,YAAA,EAAc,gBAAA;AAAA,EACd,WAAA,EAAa;AACf,CAAA;AAKA,IAAM,WAAA,GAAc;AAAA,EAClB,WAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,gBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAA;AAKA,IAAM,gBAAA,GAAmB,CAAC,UAAA,EAAY,kBAAA,EAAoB,gBAAgB,CAAA;AAK1E,IAAM,gBAAA,GAAmB,CAAC,gBAAA,EAAkB,eAAe,CAAA;AAK3D,IAAM,SAAA,GAAY,CAAC,QAAQ,CAAA;AAE3B,IAAM,eAAA,GAAkB;AAAA,EACtB,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,gBAAA;AAAA,EACA;AACF,CAAA;AAEA,IAAM,iBAAA,GAA4C;AAAA,EAChD,YAAA,EAAc,UAAA;AAAA,EACd,WAAA,EAAa,SAAA;AAAA,EACb,UAAA,EAAY,QAAA;AAAA,EACZ,aAAA,EAAe,WAAA;AAAA,EACf,aAAA,EAAe,WAAA;AAAA,EACf,WAAA,EAAa,SAAA;AAAA,EACb,eAAA,EAAiB,aAAA;AAAA,EACjB,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,YAAA;AAAA,EAChB,eAAA,EAAiB,aAAA;AAAA,EACjB,aAAA,EAAe,WAAA;AAAA,EACf,gBAAA,EAAkB,cAAA;AAAA,EAClB,aAAA,EAAe,WAAA;AAAA,EACf,iBAAA,EAAmB,eAAA;AAAA,EACnB,aAAA,EAAe,WAAA;AAAA,EACf,cAAA,EAAgB,YAAA;AAAA,EAChB,kBAAA,EAAoB,gBAAA;AAAA,EACpB,iBAAA,EAAmB;AACrB,CAAA;AAEA,IAAM,iBAAA,GAAoB,CAAC,gBAAgB,CAAA;AAE3C,IAAM,YAAA,GAAe;AAAA,EACnB;AAAA,IACE,MAAA,EAAQ,yBAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AAAA,EACA;AAAA,IACE,MAAA,EAAQ,WAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AAAA,EACA;AAAA,IACE,MAAA,EAAQ,WAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AAAA,EACA;AAAA,IACE,MAAA,EAAQ,eAAA;AAAA,IACR,WAAA,EAAa;AAAA;AAEjB,CAAA;AASA,SAAS,oBAAA,GAA+B;AACtC,EAAA,MAAM,aAAa,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAC,CAAA;AAC9D,EAAA,MAAM,WAAW,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAM,aAAa,QAAQ,CAAA;AACrE,EAAA,IAAI,GAAA,CAAI,cAAA,CAAe,QAAQ,CAAA,EAAG;AAChC,IAAA,OAAO,QAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAK,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAM,IAAA,EAAM,aAAa,QAAQ,CAAA;AACnE;AASA,eAAe,UACb,YAAA,EACA,SAAA,EACA,aACA,UAAA,GAAgC,iBAAA,EAChC,YAAY,IAAA,EACO;AACnB,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,SAAS,CAAA;AAE7C,EAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EAAI;AAChC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAClC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,WAAW,SAAS,CAAA;AACxD,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,IAAA,CAAK,IAAA,EAAM,UAAU,CAAA;AAEhD,IAAA,IAAI,CAAC,SAAA,IAAa,MAAM,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA,EAAG;AACrD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,IAAA,CAAK,GAAA,EAAK,MAAM,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,IAAA,WAAA,CAAY,IAAA,CAAK,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,SAAS,CAAA,SAAA,CAAW,CAAA;AAAA,EACvD;AAEA,EAAA,OAAO,WAAA;AACT;AAEA,eAAe,WACb,YAAA,EACA,UAAA,EACA,aACA,UAAA,GAAgC,iBAAA,EAChC,YAAY,IAAA,EACO;AACnB,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,SAAA,IAAa,IAAI,GAAA,CAAI,UAAU,CAAA,EAAG;AAC3C,IAAA,WAAA,CAAY,IAAA,CAAK,GAAG,MAAM,SAAA,CAAU,cAAc,SAAA,EAAW,WAAA,EAAa,UAAA,EAAY,SAAS,CAAC,CAAA;AAAA,EAClG;AAEA,EAAA,OAAO,WAAA;AACT;AAQA,eAAe,eAAA,CACb,YAAA,EACA,WAAA,EACA,SAAA,GAAY,IAAA,EACO;AACnB,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,QAAQ,YAAA,EAAc;AAC/B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,YAAA,EAAc,KAAK,MAAM,CAAA;AAC/C,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,KAAK,WAAW,CAAA;AAEpD,IAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EAAI;AAChC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,SAAA,IAAa,MAAM,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,EAAG;AAC5C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,IAAA,CAAK,GAAA,EAAK,IAAA,EAAM,EAAE,WAAW,CAAA;AACvC,IAAA,WAAA,CAAY,IAAA,CAAK,KAAK,WAAW,CAAA;AAAA,EACnC;AAEA,EAAA,OAAO,WAAA;AACT;AAWA,eAAsB,kBAAA,CACpB,WAAA,EACA,QAAA,EACA,OAAA,EACmB;AACnB,EAAA,MAAM,eAAe,oBAAA,EAAqB;AAE1C,EAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EAAI;AACzC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,cAAwB,EAAC;AAG/B,EAAA,MAAM,UAAA,GAAa,OAAA,KAAY,KAAA,GAC3B,WAAA,CAAY,OAAO,CAAA,CAAA,KAAK,CAAC,SAAA,CAAU,QAAA,CAAS,CAAC,CAAC,CAAA,GAC9C,CAAC,GAAG,WAAW,CAAA;AAGnB,EAAA,IAAI,YAAY,aAAA,EAAe;AAC7B,IAAA,UAAA,CAAW,IAAA,CAAK,GAAG,gBAAgB,CAAA;AAAA,EACrC;AAGA,EAAA,IAAI,YAAY,WAAA,EAAa;AAC3B,IAAA,UAAA,CAAW,IAAA,CAAK,GAAG,gBAAgB,CAAA;AAAA,EACrC;AAGA,EAAA,WAAA,CAAY,KAAK,GAAG,MAAM,WAAW,YAAA,EAAc,UAAA,EAAY,WAAW,CAAC,CAAA;AAG3E,EAAA,MAAM,gBAA0B,EAAC;AACjC,EAAA,KAAA,MAAW,aAAa,QAAA,EAAU;AAChC,IAAA,MAAM,SAAA,GAAY,iBAAiB,SAAS,CAAA;AAC5C,IAAA,IAAI,SAAA,IAAa,CAAC,UAAA,CAAW,QAAA,CAAS,SAAS,CAAA,EAAG;AAChD,MAAA,aAAA,CAAc,KAAK,SAAS,CAAA;AAAA,IAC9B;AAAA,EACF;AACA,EAAA,WAAA,CAAY,KAAK,GAAG,MAAM,WAAW,YAAA,EAAc,aAAA,EAAe,WAAW,CAAC,CAAA;AAG9E,EAAA,WAAA,CAAY,KAAK,GAAG,MAAM,eAAA,CAAgB,YAAA,EAAc,WAAW,CAAC,CAAA;AAEpE,EAAA,OAAO,WAAA;AACT;AAWA,eAAsB,uBAAA,CACpB,aACA,QAAA,EAC0B;AAC1B,EAAA,MAAM,SAAA,GAAY,iBAAiB,QAAQ,CAAA;AAC3C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,eAAe,oBAAA,EAAqB;AAC1C,EAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EAAI;AACzC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,MAAM,oBAA8B,EAAC;AAErC,EAAA,KAAA,MAAW,aAAa,iBAAA,EAAmB;AACzC,IAAA,MAAM,gBAAgB,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,SAAA,EAAW,WAAW,UAAU,CAAA;AAC7E,IAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,aAAa,CAAA,EAAI;AAC1C,MAAA,iBAAA,CAAkB,KAAK,SAAS,CAAA;AAAA,IAClC;AAAA,EACF;AAEA,EAAA,MAAM,iBAAA,GAAoB,MAAM,eAAA,CAAgB,YAAA,EAAc,aAAa,KAAK,CAAA;AAChF,EAAA,IAAI,iBAAA,CAAkB,WAAW,CAAA,EAAG;AAClC,IAAA,OAAO,iBAAA,CAAkB,MAAA,GAAS,CAAA,GAAI,iBAAA,GAAoB,IAAA;AAAA,EAC5D;AAEA,EAAA,MAAM,mBAAmB,MAAM,SAAA,CAAU,YAAA,EAAc,SAAA,EAAW,aAAa,iBAAiB,CAAA;AAChG,EAAA,MAAM,WAAA,GAAc,CAAC,GAAG,iBAAA,EAAmB,GAAG,gBAAgB,CAAA;AAE9D,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAO,WAAA;AACT;AAEO,SAAS,6BAA6B,YAAA,EAAkC;AAC7E,EAAA,MAAM,UAAA,GAAa,CAAC,GAAG,eAAe,CAAA;AAEtC,EAAA,KAAA,MAAW,eAAe,YAAA,EAAc;AACtC,IAAA,MAAM,SAAA,GAAY,kBAAkB,WAAW,CAAA;AAC/C,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,UAAA,CAAW,KAAK,SAAS,CAAA;AAAA,IAC3B;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,UAAU,CAAC,CAAA;AAChC;AAEA,eAAsB,wBAAA,CACpB,WAAA,EACA,UAAA,EACA,OAAA,GAGI,EAAC,EACc;AACnB,EAAA,MAAM,eAAe,oBAAA,EAAqB;AAE1C,EAAA,IAAI,CAAE,MAAM,GAAA,CAAI,UAAA,CAAW,YAAY,CAAA,EAAI;AACzC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM;AAAA,IACJ,eAAA,GAAkB,IAAA;AAAA,IAClB,oBAAA,GAAuB;AAAA,GACzB,GAAI,OAAA;AAEJ,EAAA,MAAM,cAAwB,EAAC;AAC/B,EAAA,WAAA,CAAY,IAAA,CAAK,GAAG,MAAM,UAAA,CAAW,cAAc,UAAA,EAAY,WAAA,EAAa,iBAAA,EAAmB,eAAe,CAAC,CAAA;AAC/G,EAAA,WAAA,CAAY,KAAK,GAAG,MAAM,gBAAgB,YAAA,EAAc,WAAA,EAAa,oBAAoB,CAAC,CAAA;AAE1F,EAAA,OAAO,WAAA;AACT","file":"chunk-GSMXGUYF.js","sourcesContent":["/**\n * @h-ai/cli — Skill 模板生成\n *\n * 将 Skill 模板文件复制到用户项目中,供 AI 编程助手使用。\n * @module cli-skill-templates\n */\n\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport fse from 'fs-extra'\n\n/**\n * 模块名到 Skill 目录名的映射\n */\nconst MODULE_SKILL_MAP: Record<string, string> = {\n 'db': 'hai-reldb',\n 'reldb': 'hai-reldb',\n 'cache': 'hai-cache',\n 'iam': 'hai-iam',\n 'storage': 'hai-storage',\n 'ai': 'hai-ai',\n 'crypto': 'hai-crypto',\n 'payment': 'hai-payment',\n 'vecdb': 'hai-vecdb',\n 'datapipe': 'hai-datapipe',\n 'reach': 'hai-reach',\n 'scheduler': 'hai-scheduler',\n 'audit': 'hai-audit',\n 'deploy': 'hai-deploy',\n 'kit': 'hai-kit',\n 'ui': 'hai-ui',\n 'api-client': 'hai-api-client',\n 'capacitor': 'hai-capacitor',\n}\n\n/**\n * 基础 Skill(所有项目都需要的)\n */\nconst BASE_SKILLS = [\n 'hai-build',\n 'hai-core',\n 'hai-kit',\n 'hai-ui',\n 'hai-app-create',\n 'hai-app-review',\n 'hai-app-tests',\n]\n\n/**\n * 前后端分离工程额外需要的 Skill\n */\nconst FULLSTACK_SKILLS = ['hai-serv', 'hai-api-contract', 'hai-api-client']\n\n/**\n * Capacitor 应用额外需要的 Skill\n */\nconst CAPACITOR_SKILLS = ['hai-api-client', 'hai-capacitor']\n\n/**\n * API 类型项目不需要的 UI 相关 Skill\n */\nconst UI_SKILLS = ['hai-ui']\n\nconst WORKFLOW_SKILLS = [\n 'hai-build',\n 'hai-app-create',\n 'hai-app-review',\n 'hai-app-tests',\n]\n\nconst PACKAGE_SKILL_MAP: Record<string, string> = {\n '@h-ai/core': 'hai-core',\n '@h-ai/kit': 'hai-kit',\n '@h-ai/ui': 'hai-ui',\n '@h-ai/reldb': 'hai-reldb',\n '@h-ai/cache': 'hai-cache',\n '@h-ai/iam': 'hai-iam',\n '@h-ai/storage': 'hai-storage',\n '@h-ai/ai': 'hai-ai',\n '@h-ai/crypto': 'hai-crypto',\n '@h-ai/payment': 'hai-payment',\n '@h-ai/vecdb': 'hai-vecdb',\n '@h-ai/datapipe': 'hai-datapipe',\n '@h-ai/reach': 'hai-reach',\n '@h-ai/scheduler': 'hai-scheduler',\n '@h-ai/audit': 'hai-audit',\n '@h-ai/deploy': 'hai-deploy',\n '@h-ai/api-client': 'hai-api-client',\n '@h-ai/capacitor': 'hai-capacitor',\n}\n\nconst SKILL_TARGET_DIRS = ['.agents/skills'] as const\n\nconst BRIDGE_FILES = [\n {\n source: 'copilot-instructions.md',\n destination: '.github/copilot-instructions.md',\n },\n {\n source: 'CLAUDE.md',\n destination: 'CLAUDE.md',\n },\n {\n source: 'AGENTS.md',\n destination: 'AGENTS.md',\n },\n {\n source: 'opencode.json',\n destination: 'opencode.json',\n },\n] as const\n\n/**\n * 获取 templates/skills/ 目录的绝对路径\n *\n * 兼容两种运行环境:\n * - 构建后:dist/cli-skill-templates.js → ../templates/skills\n * - 测试时:src/commands/cli-skill-templates.ts → ../../templates/skills\n */\nfunction getSkillTemplatesDir(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url))\n const distPath = path.resolve(currentDir, '..', 'templates', 'skills')\n if (fse.pathExistsSync(distPath)) {\n return distPath\n }\n return path.resolve(currentDir, '..', '..', 'templates', 'skills')\n}\n\n/**\n * 复制单个 Skill 目录到项目\n *\n * @param templatesDir - Skill 模板根目录\n * @param skillName - Skill 目录名(如 'hai-reldb')\n * @param projectPath - 用户项目根目录\n */\nasync function copySkill(\n templatesDir: string,\n skillName: string,\n projectPath: string,\n targetDirs: readonly string[] = SKILL_TARGET_DIRS,\n overwrite = true,\n): Promise<string[]> {\n const src = path.join(templatesDir, skillName)\n\n if (!(await fse.pathExists(src))) {\n return []\n }\n\n const copiedFiles: string[] = []\n\n for (const targetDir of targetDirs) {\n const dest = path.join(projectPath, targetDir, skillName)\n const skillFilePath = path.join(dest, 'SKILL.md')\n\n if (!overwrite && await fse.pathExists(skillFilePath)) {\n continue\n }\n\n await fse.copy(src, dest, { overwrite: true })\n copiedFiles.push(`${targetDir}/${skillName}/SKILL.md`)\n }\n\n return copiedFiles\n}\n\nasync function copySkills(\n templatesDir: string,\n skillNames: string[],\n projectPath: string,\n targetDirs: readonly string[] = SKILL_TARGET_DIRS,\n overwrite = true,\n): Promise<string[]> {\n const copiedFiles: string[] = []\n\n for (const skillName of new Set(skillNames)) {\n copiedFiles.push(...await copySkill(templatesDir, skillName, projectPath, targetDirs, overwrite))\n }\n\n return copiedFiles\n}\n\n/**\n * 复制桥接文件到项目\n *\n * @param templatesDir - Skill 模板根目录\n * @param projectPath - 用户项目根目录\n */\nasync function copyBridgeFiles(\n templatesDir: string,\n projectPath: string,\n overwrite = true,\n): Promise<string[]> {\n const copiedFiles: string[] = []\n\n for (const file of BRIDGE_FILES) {\n const src = path.join(templatesDir, file.source)\n const dest = path.join(projectPath, file.destination)\n\n if (!(await fse.pathExists(src))) {\n continue\n }\n\n if (!overwrite && await fse.pathExists(dest)) {\n continue\n }\n\n await fse.copy(src, dest, { overwrite })\n copiedFiles.push(file.destination)\n }\n\n return copiedFiles\n}\n\n/**\n * 为新项目生成完整的 Skill 文件\n *\n * 根据用户选择的功能模块,复制基础 Skill 和模块 Skill 到项目中。\n *\n * @param projectPath - 用户项目根目录\n * @param features - 用户选择的功能模块列表(如 ['db', 'iam', 'cache'])\n * @param appType - 应用类型(api 类型不复制 UI Skill)\n */\nexport async function generateSkillFiles(\n projectPath: string,\n features: string[],\n appType?: string,\n): Promise<string[]> {\n const templatesDir = getSkillTemplatesDir()\n\n if (!(await fse.pathExists(templatesDir))) {\n return []\n }\n\n const copiedFiles: string[] = []\n\n // 确定需要的基础 Skill\n const baseSkills = appType === 'api'\n ? BASE_SKILLS.filter(s => !UI_SKILLS.includes(s))\n : [...BASE_SKILLS]\n\n // Capacitor 应用额外添加 api-client 和 capacitor Skill\n if (appType === 'android-app') {\n baseSkills.push(...CAPACITOR_SKILLS)\n }\n\n // 前后端分离工程额外添加 contract / service / typed client 相关 Skill\n if (appType === 'fullstack') {\n baseSkills.push(...FULLSTACK_SKILLS)\n }\n\n // 复制基础 Skill\n copiedFiles.push(...await copySkills(templatesDir, baseSkills, projectPath))\n\n // 复制模块 Skill\n const featureSkills: string[] = []\n for (const featureId of features) {\n const skillName = MODULE_SKILL_MAP[featureId]\n if (skillName && !baseSkills.includes(skillName)) {\n featureSkills.push(skillName)\n }\n }\n copiedFiles.push(...await copySkills(templatesDir, featureSkills, projectPath))\n\n // 复制桥接文件\n copiedFiles.push(...await copyBridgeFiles(templatesDir, projectPath))\n\n return copiedFiles\n}\n\n/**\n * 为已有项目添加单个模块的 Skill 文件\n *\n * 在 `hai add <module>` 时调用,仅复制对应模块的 Skill 文件。\n *\n * @param projectPath - 用户项目根目录\n * @param moduleId - 模块标识(如 'db'、'iam')\n * @returns 复制的文件路径,若模块无对应 Skill 则返回 null\n */\nexport async function generateModuleSkillFile(\n projectPath: string,\n moduleId: string,\n): Promise<string[] | null> {\n const skillName = MODULE_SKILL_MAP[moduleId]\n if (!skillName) {\n return null\n }\n\n const templatesDir = getSkillTemplatesDir()\n if (!(await fse.pathExists(templatesDir))) {\n return null\n }\n\n const missingTargetDirs: string[] = []\n\n for (const targetDir of SKILL_TARGET_DIRS) {\n const skillFilePath = path.join(projectPath, targetDir, skillName, 'SKILL.md')\n if (!(await fse.pathExists(skillFilePath))) {\n missingTargetDirs.push(targetDir)\n }\n }\n\n const copiedBridgeFiles = await copyBridgeFiles(templatesDir, projectPath, false)\n if (missingTargetDirs.length === 0) {\n return copiedBridgeFiles.length > 0 ? copiedBridgeFiles : null\n }\n\n const copiedSkillFiles = await copySkill(templatesDir, skillName, projectPath, missingTargetDirs)\n const copiedFiles = [...copiedBridgeFiles, ...copiedSkillFiles]\n\n if (copiedFiles.length === 0) {\n return null\n }\n\n return copiedFiles\n}\n\nexport function resolveSkillNamesForPackages(packageNames: string[]): string[] {\n const skillNames = [...WORKFLOW_SKILLS]\n\n for (const packageName of packageNames) {\n const skillName = PACKAGE_SKILL_MAP[packageName]\n if (skillName) {\n skillNames.push(skillName)\n }\n }\n\n return [...new Set(skillNames)]\n}\n\nexport async function generateProjectAiSupport(\n projectPath: string,\n skillNames: string[],\n options: {\n overwriteSkills?: boolean\n overwriteBridgeFiles?: boolean\n } = {},\n): Promise<string[]> {\n const templatesDir = getSkillTemplatesDir()\n\n if (!(await fse.pathExists(templatesDir))) {\n return []\n }\n\n const {\n overwriteSkills = true,\n overwriteBridgeFiles = true,\n } = options\n\n const copiedFiles: string[] = []\n copiedFiles.push(...await copySkills(templatesDir, skillNames, projectPath, SKILL_TARGET_DIRS, overwriteSkills))\n copiedFiles.push(...await copyBridgeFiles(templatesDir, projectPath, overwriteBridgeFiles))\n\n return copiedFiles\n}\n"]}
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- export { generateConfigFile, generateEnvExample } from './chunk-3BBXDQ4Y.js';
3
- import './chunk-2H7UOFLK.js';
4
- //# sourceMappingURL=cli-config-templates-IGGO7P45.js.map
5
- //# sourceMappingURL=cli-config-templates-IGGO7P45.js.map
@@ -1,5 +0,0 @@
1
- #!/usr/bin/env node
2
- export { generateModuleSkillFile, generateProjectAiSupport, generateSkillFiles, resolveSkillNamesForPackages } from './chunk-GSMXGUYF.js';
3
- import './chunk-2H7UOFLK.js';
4
- //# sourceMappingURL=cli-skill-templates-IMYZPQRG.js.map
5
- //# sourceMappingURL=cli-skill-templates-IMYZPQRG.js.map
@@ -1,3 +0,0 @@
1
- # {{projectName}} — 环境变量
2
- # Android 模拟器使用 10.0.2.2 访问宿主机
3
- PUBLIC_API_BASE=http://10.0.2.2:3000
@@ -1,24 +0,0 @@
1
- {
2
- "app_title": "Android App",
3
- "app_description": "Android app built with hai Agent Framework + Capacitor",
4
- "nav_home": "Home",
5
- "nav_discover": "Discover",
6
- "nav_profile": "Profile",
7
- "page_home_title": "Home",
8
- "page_home_desc": "Welcome to the Android App",
9
- "page_discover_title": "Discover",
10
- "page_discover_desc": "Explore more content.",
11
- "page_profile_title": "Profile",
12
- "page_profile_username": "Username",
13
- "page_profile_login_hint": "Tap to login",
14
- "auth_login_title": "Login",
15
- "auth_login_submit": "Login",
16
- "auth_login_loading": "Logging in...",
17
- "auth_login_failed": "Login failed",
18
- "auth_login_to_register": "No account? Register now",
19
- "auth_register_title": "Register",
20
- "auth_register_submit": "Register",
21
- "auth_register_loading": "Registering...",
22
- "auth_register_failed": "Registration failed",
23
- "auth_register_to_login": "Already have an account? Login"
24
- }
@@ -1,24 +0,0 @@
1
- {
2
- "app_title": "Android 应用",
3
- "app_description": "基于 hai Agent Framework + Capacitor 构建的 Android 应用",
4
- "nav_home": "首页",
5
- "nav_discover": "发现",
6
- "nav_profile": "我的",
7
- "page_home_title": "首页",
8
- "page_home_desc": "欢迎使用 Android 应用",
9
- "page_discover_title": "发现",
10
- "page_discover_desc": "探索更多精彩内容。",
11
- "page_profile_title": "我的",
12
- "page_profile_username": "用户名",
13
- "page_profile_login_hint": "点击登录",
14
- "auth_login_title": "登录",
15
- "auth_login_submit": "登录",
16
- "auth_login_loading": "登录中...",
17
- "auth_login_failed": "登录失败",
18
- "auth_login_to_register": "没有账号?立即注册",
19
- "auth_register_title": "注册",
20
- "auth_register_submit": "注册",
21
- "auth_register_loading": "注册中...",
22
- "auth_register_failed": "注册失败",
23
- "auth_register_to_login": "已有账号?去登录"
24
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * {{projectName}} — API 客户端初始化
3
- *
4
- * 使用 @h-ai/api-client 单例模式构建统一 HTTP 客户端,
5
- * 搭配 @h-ai/capacitor 的原生 Token 存储。
6
- */
7
- import { apiClient } from '@h-ai/api-client'
8
- import { createCapacitorTokenStorage } from '@h-ai/capacitor'
9
-
10
- // Capacitor 静态构建后通过 Vite 的 import.meta.env 注入 PUBLIC_* 变量
11
- // 此处不使用 SvelteKit 的 $env/static/public,避免脱离 SvelteKit SSR 上下文时的类型/运行时缺失
12
- const API_BASE = (import.meta.env.PUBLIC_API_BASE as string | undefined) ?? 'http://localhost:3000'
13
-
14
- /**
15
- * 初始化 API 客户端
16
- *
17
- * 应在应用启动时调用一次。
18
- * - Token 存储使用 Capacitor 原生安全存储插件(仅原生环境启用)
19
- * - 自动附加 Bearer Token、401 自动刷新重试
20
- */
21
- export async function initApi() {
22
- // 公共入口统一命名为 apiClient;不要使用历史 api 别名,避免生成项目类型不匹配。
23
- return apiClient.init({
24
- baseUrl: `${API_BASE}/api/v1`,
25
- auth: {
26
- storage: createCapacitorTokenStorage(),
27
- refreshPath: '/auth/refresh',
28
- },
29
- })
30
- }
31
-
32
- export { apiClient }
@@ -1,43 +0,0 @@
1
- {{!-- Android App 根布局 --}}
2
- <script lang='ts'>
3
- /**
4
- * Android App 根布局
5
- *
6
- * - 初始化 Capacitor 原生能力
7
- * - 使用 SafeArea 包裹确保安全区域
8
- */
9
- import type { Snippet } from 'svelte'
10
- {{#if hasI18n}}
11
- import { browser } from '$app/environment'
12
- {{/if}}
13
- import { initCapacitor } from '$lib/capacitor'
14
- {{#if hasI18n}}
15
- import { getLocale } from '$lib/paraglide/runtime.js'
16
- import { setGlobalLocale } from '@h-ai/ui'
17
- {{/if}}
18
- import { onMount } from 'svelte'
19
- import '../app.css'
20
-
21
- interface Props {
22
- children: Snippet
23
- }
24
-
25
- const { children }: Props = $props()
26
-
27
- onMount(() => {
28
- initCapacitor()
29
- })
30
- {{#if hasI18n}}
31
-
32
- if (browser) {
33
- const paraglideLocale = getLocale()
34
- setGlobalLocale(paraglideLocale)
35
- }
36
- {{/if}}
37
- </script>
38
-
39
- <div class='hai-safe-all min-h-screen flex flex-col bg-base-200'>
40
- <main class='flex-1'>
41
- {@render children()}
42
- </main>
43
- </div>
@@ -1,7 +0,0 @@
1
- /**
2
- * 全局 Layout 配置
3
- *
4
- * Capacitor 应用必须使用 SPA 模式(prerender + 禁用 SSR)。
5
- */
6
- export const prerender = true
7
- export const ssr = false
@@ -1,38 +0,0 @@
1
- {{!-- Android App 首页 --}}
2
- <script lang='ts'>
3
- /**
4
- * Android App 首页
5
- */
6
- {{#if hasI18n}}
7
- import * as m from '$lib/paraglide/messages'
8
- {{/if}}
9
- import { Card } from '@h-ai/ui'
10
- </script>
11
-
12
- <svelte:head>
13
- {{#if hasI18n}}
14
- <title>{m.app_title()}</title>
15
- {{else}}
16
- <title>{{projectName}}</title>
17
- {{/if}}
18
- </svelte:head>
19
-
20
- <section class='p-4 space-y-4'>
21
- {{#if hasI18n}}
22
- <h1 class='text-2xl font-black tracking-tight'>{m.page_home_title()}</h1>
23
- <Card shadow='sm' class='bg-base-100'>
24
- <div class='flex items-center gap-3'>
25
- <span class='icon-[tabler--device-mobile] size-8 text-primary'></span>
26
- <p class='text-base-content/70'>{m.page_home_desc()}</p>
27
- </div>
28
- </Card>
29
- {{else}}
30
- <h1 class='text-2xl font-black tracking-tight'>首页</h1>
31
- <Card shadow='sm' class='bg-base-100'>
32
- <div class='flex items-center gap-3'>
33
- <span class='icon-[tabler--device-mobile] size-8 text-primary'></span>
34
- <p class='text-base-content/70'>欢迎使用 Android 应用</p>
35
- </div>
36
- </Card>
37
- {{/if}}
38
- </section>
@@ -1,14 +0,0 @@
1
- <script lang='ts'>
2
- /**
3
- * API 服务根布局
4
- */
5
- import type { Snippet } from 'svelte'
6
-
7
- interface Props {
8
- children: Snippet
9
- }
10
-
11
- const { children }: Props = $props()
12
- </script>
13
-
14
- {@render children()}
@@ -1,11 +0,0 @@
1
- <svelte:head>
2
- <title>API Service</title>
3
- </svelte:head>
4
-
5
- <main class='min-h-screen flex items-center justify-center font-mono'>
6
- <div class='text-center'>
7
- <h1 class='text-3xl font-bold mb-4'>API Service</h1>
8
- <p class='text-gray-600 mb-4'>RESTful API Service</p>
9
- <p class='text-sm text-gray-400'>GET /api/v1/health — 健康检查</p>
10
- </div>
11
- </main>
@@ -1,14 +0,0 @@
1
- /**
2
- * 健康检查端点
3
- */
4
- import type { RequestHandler } from './$types'
5
- import { kit } from '@h-ai/kit'
6
-
7
- export const GET: RequestHandler = async ({ locals }) => {
8
- return kit.response.ok({
9
- status: 'ok',
10
- service: 'api-service',
11
- version: '0.0.1',
12
- timestamp: new Date().toISOString(),
13
- }, locals.requestId)
14
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * Items API — 列表与创建
3
- */
4
- import type { RequestHandler } from './$types'
5
- import { kit } from '@h-ai/kit'
6
-
7
- /**
8
- * GET /api/v1/items — 获取列表
9
- */
10
- export const GET: RequestHandler = async ({ url, locals }) => {
11
- const page = Number(url.searchParams.get('page') || '1')
12
- const pageSize = Number(url.searchParams.get('pageSize') || '20')
13
-
14
- return kit.response.ok({
15
- items: [],
16
- total: 0,
17
- page,
18
- pageSize,
19
- }, locals.requestId)
20
- }
21
-
22
- /**
23
- * POST /api/v1/items — 创建
24
- */
25
- export const POST: RequestHandler = async ({ request, locals }) => {
26
- const body = await request.json()
27
-
28
- if (!body.name) {
29
- return kit.response.badRequest('name is required')
30
- }
31
-
32
- return kit.response.ok({
33
- id: '1',
34
- ...body,
35
- createdAt: new Date().toISOString(),
36
- }, locals.requestId)
37
- }
@@ -1,30 +0,0 @@
1
- /**
2
- * Items API — 单项操作
3
- */
4
- import type { RequestHandler } from './$types'
5
- import { kit } from '@h-ai/kit'
6
-
7
- /**
8
- * GET /api/v1/items/:id — 获取详情
9
- */
10
- export const GET: RequestHandler = async ({ params, locals }) => {
11
- const { id } = params
12
- return kit.response.ok({ id, name: 'Example Item' }, locals.requestId)
13
- }
14
-
15
- /**
16
- * PUT /api/v1/items/:id — 更新
17
- */
18
- export const PUT: RequestHandler = async ({ params, request, locals }) => {
19
- const { id } = params
20
- const body = await request.json()
21
- return kit.response.ok({ id, ...body, updatedAt: new Date().toISOString() }, locals.requestId)
22
- }
23
-
24
- /**
25
- * DELETE /api/v1/items/:id — 删除
26
- */
27
- export const DELETE: RequestHandler = async ({ params, locals }) => {
28
- const { id } = params
29
- return kit.response.ok({ id, deleted: true }, locals.requestId)
30
- }
@@ -1,26 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { GET } from '../src/routes/api/v1/health/+server'
3
-
4
- interface HealthResponseBody {
5
- success: boolean
6
- data?: {
7
- status?: string
8
- service?: string
9
- }
10
- requestId?: string
11
- }
12
-
13
- describe('api health endpoint', () => {
14
- it('returns a successful HaiResult response', async () => {
15
- const response = await GET({
16
- locals: { requestId: 'test-request' },
17
- } as Parameters<typeof GET>[0])
18
- const body = await response.json() as HealthResponseBody
19
-
20
- expect(response.status).toBe(200)
21
- expect(body.success).toBe(true)
22
- expect(body.data?.status).toBe('ok')
23
- expect(body.data?.service).toBe('api-service')
24
- expect(body.requestId).toBe('test-request')
25
- })
26
- })
@@ -1,14 +0,0 @@
1
- {{! @skipIfEmpty }}
2
- {{#if fullstack.frontends.app}}
3
- <!doctype html>
4
- <html lang="%paraglide.lang%">
5
- <head>
6
- <meta charset="utf-8" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1" />
8
- %sveltekit.head%
9
- </head>
10
- <body data-sveltekit-preload-data="hover">
11
- <div style="display: contents">%sveltekit.body%</div>
12
- </body>
13
- </html>
14
- {{/if}}
@@ -1,18 +0,0 @@
1
- {{! @skipIfEmpty }}
2
- {{#if fullstack.frontends.app}}
3
- <script lang="ts">
4
- import { setLocale } from '$lib/paraglide/runtime.js'
5
- import { AppShell } from '{{fullstack.sharedPackageName}}'
6
- import '../app.css'
7
-
8
- const { children } = $props()
9
-
10
- function syncLocale(locale: string) {
11
- setLocale(locale as Parameters<typeof setLocale>[0])
12
- }
13
- </script>
14
-
15
- <AppShell platform="app" onLocaleChange={syncLocale}>
16
- {@render children()}
17
- </AppShell>
18
- {{/if}}