@h-ai/cli 0.1.0-alpha9 → 1.0.0-beta.2

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 (438) hide show
  1. package/README.en.md +229 -0
  2. package/README.ja.md +229 -0
  3. package/README.md +175 -113
  4. package/dist/chunk-AKV2CQZV.js +1497 -0
  5. package/dist/chunk-AKV2CQZV.js.map +1 -0
  6. package/dist/chunk-EF7WOFWZ.js +7557 -0
  7. package/dist/chunk-EF7WOFWZ.js.map +1 -0
  8. package/dist/chunk-MUHRBJSW.js +29272 -0
  9. package/dist/chunk-MUHRBJSW.js.map +1 -0
  10. package/dist/chunk-ZSDEVXZ7.js +38 -0
  11. package/dist/{chunk-2H7UOFLK.js.map → chunk-ZSDEVXZ7.js.map} +1 -1
  12. package/dist/cli-config-templates-HHFHNXBN.js +5 -0
  13. package/dist/cli-config-templates-HHFHNXBN.js.map +1 -0
  14. package/dist/cli-skill-templates-PN4FLGBC.js +5 -0
  15. package/dist/cli-skill-templates-PN4FLGBC.js.map +1 -0
  16. package/dist/index.js +4444 -554
  17. package/dist/index.js.map +1 -1
  18. package/dist/metafile-esm.json +1 -0
  19. package/dist/src-TEBHR5I5.js +5 -0
  20. package/dist/src-TEBHR5I5.js.map +1 -0
  21. package/package.json +35 -15
  22. package/templates/README.md +56 -114
  23. package/templates/apps/admin/messages/en-US.json +7 -0
  24. package/templates/apps/admin/messages/ja-JP.json +40 -0
  25. package/templates/apps/admin/messages/zh-CN.json +7 -0
  26. package/templates/apps/admin/src/routes/+layout.svelte.hbs +65 -8
  27. package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -14
  28. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +54 -22
  29. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
  30. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
  31. package/templates/apps/api/.dockerignore.hbs +25 -0
  32. package/templates/apps/api/.gitignore.hbs +22 -0
  33. package/templates/apps/api/.npmrc.hbs +1 -0
  34. package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +39 -0
  35. package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +41 -0
  36. package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
  37. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +28 -0
  38. package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +5 -0
  39. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +16 -0
  40. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
  41. package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
  42. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
  43. package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
  44. package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +60 -0
  45. package/templates/apps/api/apps/{{projectName}}-serv/config/_core.yml.hbs +17 -0
  46. package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +54 -0
  47. package/templates/apps/api/apps/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
  48. package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +66 -0
  49. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +119 -0
  50. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
  51. package/templates/apps/api/apps/{{projectName}}-serv/src/index.ts.hbs +41 -0
  52. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +165 -0
  53. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +57 -0
  54. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +41 -0
  55. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +176 -0
  56. package/templates/apps/api/apps/{{projectName}}-serv/tsconfig.json.hbs +16 -0
  57. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +20 -0
  58. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
  59. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +113 -0
  60. package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
  61. package/templates/apps/api/eslint.config.js.hbs +30 -0
  62. package/templates/apps/api/hai.json.hbs +4 -0
  63. package/templates/apps/api/images/serv.Dockerfile.hbs +37 -0
  64. package/templates/apps/api/package.json.hbs +53 -0
  65. package/templates/apps/api/playwright.config.ts.hbs +67 -0
  66. package/templates/apps/api/pnpm-workspace.yaml.hbs +40 -0
  67. package/templates/apps/api/tsconfig.base.json +14 -0
  68. package/templates/apps/fullstack/.dockerignore.hbs +25 -0
  69. package/templates/apps/fullstack/.gitignore.hbs +38 -0
  70. package/templates/apps/fullstack/.npmrc.hbs +1 -0
  71. package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
  72. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +67 -0
  73. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +20 -0
  74. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +20 -0
  75. package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +22 -0
  76. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +7 -0
  77. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
  78. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +7 -0
  79. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +86 -0
  80. package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
  81. package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
  82. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +59 -0
  83. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +20 -0
  84. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +8 -0
  85. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +9 -0
  86. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +19 -0
  87. package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +21 -0
  88. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +16 -0
  89. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +23 -0
  90. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +74 -0
  91. package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
  92. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +64 -0
  93. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +20 -0
  94. package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +20 -0
  95. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +7 -0
  96. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
  97. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +7 -0
  98. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +66 -0
  99. package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
  100. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +25 -0
  101. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
  102. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +8 -0
  103. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +9 -0
  104. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +20 -0
  105. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +33 -0
  106. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
  107. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +16 -0
  108. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
  109. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
  110. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
  111. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
  112. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
  113. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +91 -0
  114. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
  115. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +46 -0
  116. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +14 -0
  117. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +22 -0
  118. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +89 -0
  119. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +25 -0
  120. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
  121. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
  122. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
  123. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
  124. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +54 -0
  125. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +20 -0
  126. package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +21 -0
  127. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +7 -0
  128. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
  129. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +7 -0
  130. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +53 -0
  131. package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
  132. package/templates/apps/fullstack/apps/{{projectName}}-web/public/runtime-config.js.hbs +1 -0
  133. package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +18 -0
  134. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
  135. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +8 -0
  136. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +9 -0
  137. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
  138. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +16 -0
  139. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +23 -0
  140. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +76 -0
  141. package/templates/apps/fullstack/docs/security-configuration.md.hbs +349 -0
  142. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +988 -0
  143. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +119 -0
  144. package/templates/apps/fullstack/eslint.config.js.hbs +41 -0
  145. package/templates/apps/fullstack/hai.json.hbs +11 -0
  146. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +38 -0
  147. package/templates/apps/fullstack/images/web/19-runtime-config.envsh.hbs +5 -0
  148. package/templates/apps/fullstack/images/web/nginx.conf.hbs +24 -0
  149. package/templates/apps/fullstack/images/web/runtime-config.js.template.hbs +3 -0
  150. package/templates/apps/fullstack/images/web.Dockerfile.hbs +37 -0
  151. package/templates/apps/fullstack/package.json.hbs +61 -0
  152. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +40 -0
  153. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +30 -0
  154. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +78 -0
  155. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +134 -0
  156. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +20 -0
  157. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +35 -0
  158. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +7 -0
  159. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +23 -0
  160. package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +31 -0
  161. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
  162. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
  163. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +84 -0
  164. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
  165. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -0
  166. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -0
  167. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +22 -0
  168. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -0
  169. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_feedback.yml.hbs +1 -0
  170. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -0
  171. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
  172. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +60 -0
  173. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
  174. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +64 -0
  175. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -0
  176. package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
  177. package/templates/apps/fullstack/packages/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
  178. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +62 -0
  179. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +115 -0
  180. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
  181. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +40 -0
  182. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +294 -0
  183. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/audit-jobs.ts.hbs +28 -0
  184. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +50 -0
  185. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +50 -0
  186. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +106 -0
  187. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +49 -0
  188. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +34 -0
  189. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +159 -0
  190. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +73 -0
  191. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +505 -0
  192. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +72 -0
  193. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +183 -0
  194. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
  195. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +18 -0
  196. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
  197. package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +10 -0
  198. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +97 -0
  199. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +164 -0
  200. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +164 -0
  201. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +164 -0
  202. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +55 -0
  203. package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
  204. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +7 -0
  205. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +94 -0
  206. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +36 -0
  207. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +16 -0
  208. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/session-recovery.svelte.ts.hbs +4 -0
  209. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +122 -0
  210. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +90 -0
  211. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +86 -0
  212. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +94 -0
  213. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/configuration.svelte.hbs +25 -0
  214. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +157 -0
  215. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +77 -0
  216. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +44 -0
  217. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +216 -0
  218. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +12 -0
  219. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
  220. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +614 -0
  221. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +23 -0
  222. package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
  223. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +150 -0
  224. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +253 -0
  225. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
  226. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
  227. package/templates/apps/fullstack/playwright.config.ts.hbs +114 -0
  228. package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +18 -0
  229. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +38 -0
  230. package/templates/apps/fullstack/tsconfig.base.json +14 -0
  231. package/templates/apps/h5/messages/en-US.json +3 -0
  232. package/templates/apps/h5/messages/ja-JP.json +40 -0
  233. package/templates/apps/h5/messages/zh-CN.json +3 -0
  234. package/templates/apps/h5/src/routes/+layout.svelte.hbs +85 -30
  235. package/templates/apps/h5/src/routes/+page.svelte.hbs +20 -8
  236. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
  237. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
  238. package/templates/apps/mobile-app/.env.hbs +3 -0
  239. package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
  240. package/templates/apps/mobile-app/index.html.hbs +14 -0
  241. package/templates/apps/mobile-app/messages/en-US.json +36 -0
  242. package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
  243. package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
  244. package/templates/apps/mobile-app/public/runtime-config.js +1 -0
  245. package/templates/apps/mobile-app/src/App.svelte.hbs +153 -0
  246. package/templates/apps/mobile-app/src/lib/api.ts.hbs +213 -0
  247. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +14 -0
  248. package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
  249. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +58 -0
  250. package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -0
  251. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +16 -0
  252. package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
  253. package/templates/apps/website/messages/en-US.json +4 -2
  254. package/templates/apps/website/messages/ja-JP.json +34 -0
  255. package/templates/apps/website/messages/zh-CN.json +4 -2
  256. package/templates/apps/website/scripts/static-website.mjs.hbs +67 -0
  257. package/templates/apps/website/src/routes/+layout.svelte.hbs +77 -26
  258. package/templates/apps/website/src/routes/+layout.ts +3 -0
  259. package/templates/apps/website/src/routes/+page.svelte.hbs +31 -12
  260. package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
  261. package/templates/apps/website/src/routes/api/health/+server.ts +3 -0
  262. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +44 -34
  263. package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
  264. package/templates/base/.dockerignore.hbs +27 -0
  265. package/templates/base/.gitignore.hbs +41 -0
  266. package/templates/base/.npmrc.hbs +1 -0
  267. package/templates/base/e2e/app.spec.ts.hbs +213 -0
  268. package/templates/base/e2e/helpers.ts +1 -1
  269. package/templates/base/eslint-rules.js +45 -0
  270. package/templates/base/eslint.config.js.hbs +34 -0
  271. package/templates/base/hai.json.hbs +4 -0
  272. package/templates/base/images/web/nginx.conf.hbs +24 -0
  273. package/templates/base/images/web.Dockerfile.hbs +72 -0
  274. package/templates/base/package.json.hbs +125 -49
  275. package/templates/base/playwright.config.ts +44 -6
  276. package/templates/base/pnpm-workspace.yaml.hbs +40 -0
  277. package/templates/base/src/app.css.hbs +40 -0
  278. package/templates/base/src/app.d.ts.hbs +14 -1
  279. package/templates/base/src/app.html.hbs +13 -0
  280. package/templates/base/src/hooks.server.ts.hbs +115 -43
  281. package/templates/base/src/lib/build-metadata.ts.hbs +7 -0
  282. package/templates/base/src/lib/server/init.ts.hbs +125 -152
  283. package/templates/base/src/lib/server/kit-config.ts.hbs +40 -0
  284. package/templates/base/src/routes/+layout.server.ts.hbs +35 -0
  285. package/templates/base/static/favicon.png +0 -0
  286. package/templates/base/svelte.config.js.hbs +84 -5
  287. package/templates/base/tests/scaffold.test.ts.hbs +102 -0
  288. package/templates/base/tsconfig.json.hbs +50 -0
  289. package/templates/base/vite.config.ts.hbs +117 -12
  290. package/templates/base/vitest.config.ts.hbs +19 -0
  291. package/templates/features/ai/routes/api/chat/+server.ts +6 -7
  292. package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +3 -17
  293. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +10 -0
  294. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +9 -96
  295. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +9 -122
  296. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +10 -0
  297. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +10 -0
  298. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +9 -96
  299. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +9 -112
  300. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +10 -0
  301. package/templates/features/iam/routes-shared/api/auth/captcha/+server.ts.hbs +4 -0
  302. package/templates/features/iam/routes-shared/api/auth/config/+server.ts +4 -0
  303. package/templates/features/iam/routes-shared/api/auth/login/+server.ts +1 -29
  304. package/templates/features/iam/routes-shared/api/auth/login/ldap/+server.ts +4 -0
  305. package/templates/features/iam/routes-shared/api/auth/login/otp/+server.ts +4 -0
  306. package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +13 -6
  307. package/templates/features/iam/routes-shared/api/auth/otp/send/+server.ts +4 -0
  308. package/templates/features/iam/routes-shared/api/auth/password/renew/+server.ts +5 -0
  309. package/templates/features/iam/routes-shared/api/auth/password-reset/confirm/+server.ts +4 -0
  310. package/templates/features/iam/routes-shared/api/auth/password-reset/request/+server.ts +4 -0
  311. package/templates/features/iam/routes-shared/api/auth/reauthenticate/+server.ts +5 -0
  312. package/templates/features/iam/routes-shared/api/auth/register/+server.ts +1 -23
  313. package/templates/features/iam/routes-shared/api/auth/session/close/+server.ts.hbs +4 -0
  314. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +10 -0
  315. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +11 -0
  316. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +11 -0
  317. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +10 -0
  318. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +25 -23
  319. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +5 -2
  320. package/templates/features/storage/routes/api/upload/+server.ts +10 -8
  321. package/templates/i18n/project.inlang/settings.json +2 -2
  322. package/templates/shared/.gitattributes +11 -0
  323. package/templates/shared/build-metadata.ts +42 -0
  324. package/templates/shared/container-runtime-config.sh +30 -0
  325. package/templates/shared/e2e-env.ts +98 -0
  326. package/templates/shared/hash-router.svelte.ts +83 -0
  327. package/templates/shared/public-base-path.mjs +19 -0
  328. package/templates/shared/run-e2e.mjs +104 -0
  329. package/templates/shared/vite-runtime-config.ts +56 -0
  330. package/templates/skills/AGENTS.md +75 -16
  331. package/templates/skills/CLAUDE.md +0 -11
  332. package/templates/skills/bridges/admin/AGENTS.md +89 -0
  333. package/templates/skills/bridges/api/AGENTS.md +83 -0
  334. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +102 -0
  335. package/templates/skills/bridges/h5/AGENTS.md +88 -0
  336. package/templates/skills/bridges/mobile-app/AGENTS.md +100 -0
  337. package/templates/skills/bridges/website/AGENTS.md +88 -0
  338. package/templates/skills/copilot-instructions.md +3 -59
  339. package/templates/skills/hai-ai/SKILL.md +44 -715
  340. package/templates/skills/hai-ai/guide.md +457 -0
  341. package/templates/skills/hai-ai/reference.md +292 -0
  342. package/templates/skills/hai-api-client/SKILL.md +26 -339
  343. package/templates/skills/hai-api-client/reference.md +180 -0
  344. package/templates/skills/hai-api-contract/SKILL.md +36 -0
  345. package/templates/skills/hai-api-contract/reference.md +280 -0
  346. package/templates/skills/hai-app-create/SKILL.md +38 -351
  347. package/templates/skills/hai-app-create/collaboration.md +52 -0
  348. package/templates/skills/hai-app-create/development.md +243 -0
  349. package/templates/skills/hai-app-create/reference.md +376 -0
  350. package/templates/skills/hai-app-review/SKILL.md +57 -126
  351. package/templates/skills/hai-app-review/differential.md +34 -0
  352. package/templates/skills/hai-app-tests/SKILL.md +34 -454
  353. package/templates/skills/hai-app-tests/reference.md +462 -0
  354. package/templates/skills/hai-app-tests/validation.md +42 -0
  355. package/templates/skills/hai-audit/SKILL.md +37 -122
  356. package/templates/skills/hai-audit/reference.md +184 -0
  357. package/templates/skills/hai-build/SKILL.md +62 -315
  358. package/templates/skills/hai-build/paths.md +30 -0
  359. package/templates/skills/hai-build/reference.md +353 -0
  360. package/templates/skills/hai-cache/SKILL.md +26 -175
  361. package/templates/skills/hai-cache/reference.md +229 -0
  362. package/templates/skills/hai-capacitor/SKILL.md +24 -364
  363. package/templates/skills/hai-capacitor/reference.md +358 -0
  364. package/templates/skills/hai-change-plan/SKILL.md +46 -0
  365. package/templates/skills/hai-ci/SKILL.md +114 -0
  366. package/templates/skills/hai-core/SKILL.md +31 -469
  367. package/templates/skills/hai-core/reference.md +557 -0
  368. package/templates/skills/hai-core/request-access.md +65 -0
  369. package/templates/skills/hai-crypto/SKILL.md +29 -180
  370. package/templates/skills/hai-crypto/reference.md +317 -0
  371. package/templates/skills/hai-datapipe/SKILL.md +24 -207
  372. package/templates/skills/hai-datapipe/reference.md +204 -0
  373. package/templates/skills/hai-deploy/SKILL.md +53 -178
  374. package/templates/skills/hai-deploy/credentials.md +19 -0
  375. package/templates/skills/hai-deploy/middleware.md +129 -0
  376. package/templates/skills/hai-feedback/SKILL.md +85 -0
  377. package/templates/skills/hai-framework-sync/SKILL.md +105 -0
  378. package/templates/skills/hai-framework-sync/sync.md +49 -0
  379. package/templates/skills/hai-iam/SKILL.md +53 -325
  380. package/templates/skills/hai-iam/reference.md +535 -0
  381. package/templates/skills/hai-kit/SKILL.md +33 -329
  382. package/templates/skills/hai-kit/reference.md +202 -0
  383. package/templates/skills/hai-payment/SKILL.md +28 -262
  384. package/templates/skills/hai-payment/reference.md +295 -0
  385. package/templates/skills/hai-pr-review/SKILL.md +41 -0
  386. package/templates/skills/hai-reach/SKILL.md +28 -300
  387. package/templates/skills/hai-reach/reference.md +363 -0
  388. package/templates/skills/hai-reldb/SKILL.md +28 -449
  389. package/templates/skills/hai-reldb/reference.md +500 -0
  390. package/templates/skills/hai-scheduler/SKILL.md +26 -174
  391. package/templates/skills/hai-scheduler/reference.md +216 -0
  392. package/templates/skills/hai-serv/SKILL.md +60 -0
  393. package/templates/skills/hai-serv/reference.md +792 -0
  394. package/templates/skills/hai-spec-implement/SKILL.md +50 -0
  395. package/templates/skills/hai-spec-implement/changes.md +67 -0
  396. package/templates/skills/hai-spec-implement/evaluation.md +18 -0
  397. package/templates/skills/hai-spec-implement/handoff.md +47 -0
  398. package/templates/skills/hai-spec-implement/templates.md +117 -0
  399. package/templates/skills/hai-spec-implement/workflow.md +56 -0
  400. package/templates/skills/hai-spec-review/SKILL.md +57 -0
  401. package/templates/skills/hai-spec-review/checklist.md +71 -0
  402. package/templates/skills/hai-storage/SKILL.md +31 -262
  403. package/templates/skills/hai-storage/reference.md +284 -0
  404. package/templates/skills/hai-ui/SKILL.md +62 -238
  405. package/templates/skills/hai-ui/guide.md +81 -0
  406. package/templates/skills/hai-ui/reference.md +705 -0
  407. package/templates/skills/hai-ui-design/SKILL.md +31 -0
  408. package/templates/skills/hai-ui-design/patterns.md +31 -0
  409. package/templates/skills/hai-ui-review/SKILL.md +32 -0
  410. package/templates/skills/hai-ui-review/checklist.md +29 -0
  411. package/templates/skills/hai-vecdb/SKILL.md +25 -267
  412. package/templates/skills/hai-vecdb/reference.md +325 -0
  413. package/templates/skills/opencode.json +0 -5
  414. package/dist/chunk-2H7UOFLK.js +0 -10
  415. package/dist/chunk-LANIDJC7.js +0 -659
  416. package/dist/chunk-LANIDJC7.js.map +0 -1
  417. package/dist/chunk-YV7WPUI6.js +0 -206
  418. package/dist/chunk-YV7WPUI6.js.map +0 -1
  419. package/dist/config-templates-S5RI2MC6.js +0 -5
  420. package/dist/config-templates-S5RI2MC6.js.map +0 -1
  421. package/dist/skill-templates-N5DU5FNX.js +0 -5
  422. package/dist/skill-templates-N5DU5FNX.js.map +0 -1
  423. package/dist/src-XJ6YXNAF.js +0 -15030
  424. package/dist/src-XJ6YXNAF.js.map +0 -1
  425. package/templates/apps/android-app/.env.hbs +0 -3
  426. package/templates/apps/android-app/messages/en-US.json +0 -24
  427. package/templates/apps/android-app/messages/zh-CN.json +0 -24
  428. package/templates/apps/android-app/src/lib/api.ts.hbs +0 -30
  429. package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
  430. package/templates/apps/android-app/src/routes/+layout.ts +0 -7
  431. package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
  432. package/templates/apps/api/src/routes/+layout.svelte +0 -14
  433. package/templates/apps/api/src/routes/+page.svelte +0 -11
  434. package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
  435. package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
  436. package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
  437. package/templates/base/src/app.css +0 -2
  438. package/templates/base/tsconfig.json +0 -8
@@ -0,0 +1,462 @@
1
+ # hai-app-tests — 详细用法
2
+
3
+ 从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
4
+
5
+ 新增/改变业务行为或修复缺陷时先用目标用例定义行为,再实现。按 [development.md](../hai-app-create/development.md) 的需求与安全边界选择测试层;纯文案、格式、文档或无行为变化的可逆低影响修改按影响验证,不补只匹配文本/结构的镜像测试。
6
+
7
+ ## 适用场景
8
+
9
+ - 以 TDD 方式开发新功能(先写测试 → 确认失败 → 再实现 → 确认通过)
10
+ - 为当前架构的公共服务入口编写单元/集成测试
11
+ - 为 API 端点编写 E2E 测试(Playwright)
12
+ - 为页面交互编写 UI E2E 测试(Playwright)
13
+ - 为工具函数、Schema 校验编写单元测试
14
+ - 补齐有具体行为风险的验证缺口;覆盖率是定位线索,不是验收目标
15
+
16
+ ## 行为验证与 TDD 工作流
17
+
18
+ 不要求每个改动同时新增单元与 E2E。先复用现有 fixture 与目标用例,按变化选最小适用层;跨 contract/服务/客户端或 UI 的关键流程仍需相应集成/端到端验证。
19
+
20
+ ### 阶段一:需求分析(Red 前准备)
21
+
22
+ 1. **理解需求**:明确功能的输入、输出、边界条件、错误场景
23
+ 2. **拆分测试点**:将需求转化为可验证的测试用例清单
24
+ 3. **确定测试类型**:
25
+ - **单元测试(Vitest)**:服务层、工具函数、Schema 校验、HaiResult 处理
26
+ - **集成测试**:contract/procedure、事务、持久化、生命周期/失败清理、模块配置的真实组合
27
+ - **E2E 测试(Playwright)**:API 边界、页面交互、认证流程与跨层用户路径
28
+
29
+ ### 阶段二:Red — 编写失败的测试
30
+
31
+ 1. **编写目标用例**:在适用的单元/集成/E2E 层验证目标变化,不重复创建其它层仅为打勾
32
+ 2. 对本次相关的正常、输入边界、越权/跨租户、依赖失败、事务/幂等/清理场景给出可观察断言;纯工具无需添加无关权限路径
33
+ 3. **运行测试确认目标用例因预期行为缺失而失败(仍适用的既有回归保持通过)**;明确新需求替代的模板断言同步更新并记录依据,不能为迁就实现改预期:
34
+ ```bash
35
+ pnpm --filter <app-name> test # 目标位于单元/集成时使用
36
+ pnpm --filter <app-name> test:e2e # 目标位于 E2E 时使用;脚本以实际 package.json 为准
37
+ ```
38
+ 4. 新增用例若已通过,先确认现有实现是否已满足需求;仅在用例没有覆盖目标行为时修正
39
+
40
+ ### 阶段三:Green — 最小实现
41
+
42
+ 1. 参照 `hai-app-create` 技能编写实现代码
43
+ 2. 每实现一个功能点,立即运行对应测试确认通过
44
+ 3. 只写让测试通过的最小代码,不做过度设计
45
+ 4. 运行受影响测试及必要回归确认通过(按影响选择范围):
46
+ ```bash
47
+ pnpm --filter <app-name> test # 单元测试 — 应全部 PASS
48
+ pnpm --filter <app-name> test:e2e # E2E 测试 — 应全部 PASS
49
+ ```
50
+
51
+ ### 阶段四:Refactor — 重构优化
52
+
53
+ 1. 参照 `hai-app-review` 技能审查代码规范
54
+ 2. 重构后执行受影响测试与必要回归,确认已有行为保持通过
55
+ 3. 验证前先分析变更和直接消费者,默认只选相关 test/E2E;全量仅在用户明确要求时执行。多项门禁按 [分轮验证与集中修复](validation.md) 收集一轮结果,汇总后集中修复;先定向确认失败和直接受影响项,再按真实依赖补充受影响流程,不从头重复全量门禁。PowerShell 使用 `pnpm.cmd`
56
+
57
+ ## 测试目录约定
58
+
59
+ 以下是常见组织方式;沿当前应用/workspace 的测试目录、alias 与脚本,不为目录一致性移动已有测试。
60
+
61
+ ```
62
+ tests/ # 单元测试(Vitest)
63
+ services/
64
+ user.test.ts # 服务层测试
65
+ article.test.ts
66
+ schemas/
67
+ user-schema.test.ts # Schema 校验测试
68
+ utils/
69
+ helper.test.ts # 工具函数测试
70
+ e2e/ # E2E 测试(Playwright)
71
+ helpers.ts # E2E 共用工具函数
72
+ health.spec.ts # 健康检查 API
73
+ auth-api.spec.ts # 认证 API 测试
74
+ auth-ui.spec.ts # 认证页面 UI 测试
75
+ users-api.spec.ts # 用户管理 API 测试
76
+ users-ui.spec.ts # 用户管理页面 UI 测试
77
+ ```
78
+
79
+ ## 核心规则
80
+
81
+ 1. **行为测试先行**:新增/改变业务行为和修复缺陷时先定义目标用例;纯文案/格式/文档按影响验证。
82
+ 2. **统一入口**:通过框架模块公共 API 测试(`reldb.sql`、`iam.auth`),不直接调用内部实现。
83
+ 3. **从实际场景出发**:测试用例验证真实业务行为,不做形式覆盖。
84
+ 4. **先审查后修复**:测试不通过时先审查业务逻辑是否有问题,不直接修改测试迎合通过。
85
+ 5. **明确隔离层**:单元测试沿真实注入边界 mock 外部依赖;DB/缓存集成用内存 SQLite 或隔离环境/Testcontainers,不能用 mock 证明真实持久化/事务。
86
+ 6. **区分证据**:端到端运行完整应用;可用受控外部依赖验证确定性错误路径,但报告替身范围。浏览器通过不等于真实 provider 通过;真实数据库/付费 provider/原生平台各自保留实际执行结果,缺环境说明未验证。
87
+
88
+ ## 覆盖范围
89
+
90
+ 按本次改变的行为选择适用路径;下表是设计依据,不要求每个路径在单元与 E2E 重复一遍。纯函数不必虚构权限场景,受保护资源则不能省掉未登录/缺权限与跨用户/租户验收:
91
+
92
+ | 路径 | 说明 | 单元测试示例 | E2E 测试示例 |
93
+ | -------- | ------------------------ | ------------------ | ----------------------- |
94
+ | 正常路径 | 核心功能可用 | 创建用户成功 | POST /api/users → 201 |
95
+ | 边界路径 | 非法输入、空值、格式错误 | 空名称、超长字符串 | 空表单提交 → 校验提示 |
96
+ | 权限路径 | 未认证、无权限 | 未登录调用服务 | 检查真实失败包络/HTTP 状态,kit 页面按实际策略重定向 |
97
+ | 错误路径 | 服务异常、数据库错误 | DB 失败时的 HaiResult | 服务不可用 → 错误提示页 |
98
+
99
+ ## 单元测试(Vitest)
100
+
101
+ ### SQLite 持久化集成示例
102
+
103
+ ```typescript
104
+ import { reldb } from '@h-ai/reldb'
105
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest'
106
+
107
+ // 内存 SQLite 隔离数据;应用服务测试同样从服务的公共入口验证结果。
108
+ beforeAll(async () => {
109
+ const init = await reldb.init({ type: 'sqlite', database: ':memory:' })
110
+ expect(init.success).toBe(true)
111
+ const table = await reldb.ddl.createTable('articles', {
112
+ id: { type: 'TEXT', primaryKey: true },
113
+ title: { type: 'TEXT', notNull: true },
114
+ })
115
+ expect(table.success).toBe(true)
116
+ })
117
+ afterAll(async () => {
118
+ const closed = await reldb.close()
119
+ expect(closed.success).toBe(true)
120
+ })
121
+
122
+ describe('article persistence', () => {
123
+ it('creates and reads the stored article', async () => {
124
+ const articles = reldb.crud.table<{ id: string, title: string }>({ table: 'articles', dbType: 'sqlite' })
125
+ const saved = await articles.create({ id: 'a1', title: 'Test' })
126
+ expect(saved.success).toBe(true)
127
+ const found = await articles.findById('a1')
128
+ expect(found.success).toBe(true)
129
+ if (found.success) expect(found.data).toEqual({ id: 'a1', title: 'Test' })
130
+ })
131
+ })
132
+ ```
133
+
134
+ 本例验证框架真实持久化,不代替应用服务验收。应用另测相关权限、校验和 DB 失败透传;mock 必须沿真实注入边界或 CRUD 仓库实例配置,create 返回 ExecuteResult,不能伪造为实体。
135
+
136
+ ### Schema 校验测试模板
137
+
138
+ ```typescript
139
+ import { CreateUserSchema } from '$lib/server/schemas/user'
140
+ // tests/schemas/user-schema.test.ts
141
+ import { describe, expect, it } from 'vitest'
142
+
143
+ describe('CreateUserSchema', () => {
144
+ it('should accept valid input', () => {
145
+ const result = CreateUserSchema.safeParse({
146
+ username: 'testuser',
147
+ email: 'test@example.com',
148
+ password: '12345678',
149
+ })
150
+ expect(result.success).toBe(true)
151
+ })
152
+
153
+ it('should reject short username', () => {
154
+ const result = CreateUserSchema.safeParse({
155
+ username: 'ab',
156
+ email: 'test@example.com',
157
+ password: '12345678',
158
+ })
159
+ expect(result.success).toBe(false)
160
+ })
161
+
162
+ it('should reject invalid email', () => {
163
+ const result = CreateUserSchema.safeParse({
164
+ username: 'testuser',
165
+ email: 'not-email',
166
+ password: '12345678',
167
+ })
168
+ expect(result.success).toBe(false)
169
+ })
170
+ })
171
+ ```
172
+
173
+ ## E2E 测试(Playwright)
174
+
175
+ ### Playwright 配置
176
+
177
+ 优先复用 CLI 已生成的 `playwright.config.ts`。下列为 SvelteKit preview 示例;API/fullstack/Vite 使用自身已有 webServer/服务组合与 scripts,不照搬 `pnpm preview`:
178
+
179
+ ```typescript
180
+ // playwright.config.ts
181
+ import process from 'node:process'
182
+ import { defineConfig } from '@playwright/test'
183
+
184
+ const DEFAULT_BASE_URL = 'http://localhost:4173'
185
+ const baseURL = process.env.BASE_URL || DEFAULT_BASE_URL
186
+ const previewHost = resolveHostFromBaseUrl(baseURL, 'localhost')
187
+ const previewPort = resolvePortFromBaseUrl(baseURL, '4173')
188
+
189
+ function resolveHostFromBaseUrl(urlString: string, fallbackHost: string): string {
190
+ try {
191
+ const url = new URL(urlString)
192
+ return url.hostname || fallbackHost
193
+ }
194
+ catch {
195
+ return fallbackHost
196
+ }
197
+ }
198
+
199
+ function resolvePortFromBaseUrl(urlString: string, fallbackPort: string): string {
200
+ try {
201
+ const url = new URL(urlString)
202
+ if (url.port)
203
+ return url.port
204
+ return url.protocol === 'https:' ? '443' : '80'
205
+ }
206
+ catch {
207
+ return fallbackPort
208
+ }
209
+ }
210
+
211
+ export default defineConfig({
212
+ testDir: './e2e',
213
+ fullyParallel: true,
214
+ forbidOnly: !!process.env.CI,
215
+ retries: 0,
216
+ workers: 2,
217
+ reporter: 'list',
218
+ timeout: 30_000,
219
+ use: {
220
+ baseURL,
221
+ channel: 'chrome',
222
+ trace: 'retain-on-failure',
223
+ screenshot: 'only-on-failure',
224
+ },
225
+ webServer: {
226
+ command: `pnpm build && pnpm preview --host ${previewHost} --port ${previewPort} --strictPort`,
227
+ env: { HAI_E2E: '1', BASE_URL: baseURL },
228
+ url: baseURL,
229
+ reuseExistingServer: false,
230
+ timeout: 180_000,
231
+ },
232
+ })
233
+ ```
234
+
235
+ ### E2E 工具函数模板
236
+
237
+ 以下登录路径、表单字段与 API 仅作 SvelteKit 示例,必须替换为当前应用路由/认证流程;API service/typed client 测试从现有 contract 读取路径,不维护第二份路由常量。
238
+
239
+ ```typescript
240
+ // e2e/helpers.ts
241
+ import type { APIRequestContext, Page } from '@playwright/test'
242
+
243
+ /** 生成唯一测试用户 */
244
+ export function uniqueUser(prefix = 'e2e') {
245
+ const safePrefix = (prefix.replace(/\W/g, '') || 'e2e').slice(0, 8)
246
+ const entropy = `${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`
247
+ const id = entropy.slice(-10)
248
+ const username = `${safePrefix}_${id}`.slice(0, 20)
249
+ return {
250
+ username,
251
+ email: `${safePrefix}_${id}@test.local`,
252
+ password: 'Test1234!@',
253
+ }
254
+ }
255
+
256
+ /** 通过 API 注册用户 */
257
+ export async function registerViaApi(
258
+ request: APIRequestContext,
259
+ user: ReturnType<typeof uniqueUser>,
260
+ ) {
261
+ return request.post('/api/auth/register', {
262
+ data: {
263
+ username: user.username,
264
+ email: user.email,
265
+ password: user.password,
266
+ confirmPassword: user.password,
267
+ },
268
+ })
269
+ }
270
+
271
+ /** 注册并登录,返回已认证的 Page */
272
+ export async function registerAndLogin(
273
+ page: Page,
274
+ request: APIRequestContext,
275
+ prefix = 'e2e',
276
+ ) {
277
+ const user = uniqueUser(prefix)
278
+ await registerViaApi(request, user)
279
+ await page.goto('/login')
280
+ await page.fill('[name="username"]', user.username)
281
+ await page.fill('[name="password"]', user.password)
282
+ await page.click('button[type="submit"]')
283
+ await page.waitForURL('/')
284
+ return user
285
+ }
286
+ ```
287
+
288
+ ### API 端点 E2E 测试模板
289
+
290
+ 下例是返回 kit Response 的 SvelteKit 端点。serv/oRPC 普通 procedure 可能以 HTTP 200 返回失败 HaiResult,需同时检查 `success/error.code`;不能把 `error.httpStatus` 当作 response.status,也不能统一套用下列 401/201 断言。输入校验与传输错误另按实际状态测试。
291
+
292
+ ```typescript
293
+ // e2e/articles-api.spec.ts
294
+ import { expect, test } from '@playwright/test'
295
+ import { registerAndLogin } from './helpers'
296
+
297
+ test.describe('Articles API', () => {
298
+ test('GET /api/articles 未认证返回 401', async ({ request }) => {
299
+ const response = await request.get('/api/articles')
300
+ expect(response.status()).toBe(401)
301
+ })
302
+
303
+ test('POST /api/articles 创建文章成功', async ({ page, request }) => {
304
+ await registerAndLogin(page, request, 'article')
305
+
306
+ const response = await page.request.post('/api/articles', {
307
+ data: { title: 'E2E Test Article', content: 'Test content' },
308
+ })
309
+ expect(response.status()).toBe(201)
310
+
311
+ const body = await response.json()
312
+ expect(body.success).toBe(true)
313
+ expect(body.data.title).toBe('E2E Test Article')
314
+ })
315
+
316
+ test('POST /api/articles 空标题返回 400', async ({ page, request }) => {
317
+ await registerAndLogin(page, request, 'article')
318
+
319
+ const response = await page.request.post('/api/articles', {
320
+ data: { title: '', content: '' },
321
+ })
322
+ expect(response.status()).toBe(400)
323
+ })
324
+
325
+ test('GET /api/articles 认证后获取列表', async ({ page, request }) => {
326
+ await registerAndLogin(page, request, 'article')
327
+
328
+ const response = await page.request.get('/api/articles')
329
+ expect(response.ok()).toBeTruthy()
330
+
331
+ const body = await response.json()
332
+ expect(body.success).toBe(true)
333
+ expect(Array.isArray(body.data)).toBe(true)
334
+ })
335
+ })
336
+ ```
337
+
338
+ ### 页面 UI E2E 测试模板
339
+
340
+ ```typescript
341
+ // e2e/articles-ui.spec.ts
342
+ import { expect, test } from '@playwright/test'
343
+ import { registerAndLogin } from './helpers'
344
+
345
+ test.describe('Articles Page', () => {
346
+ test('未登录跳转登录页', async ({ page }) => {
347
+ await page.goto('/admin/articles')
348
+ await expect(page).toHaveURL(/login/)
349
+ })
350
+
351
+ test('已登录显示文章列表', async ({ page, request }) => {
352
+ await registerAndLogin(page, request, 'artui')
353
+ await page.goto('/admin/articles')
354
+
355
+ await expect(page.locator('h1, h2').first()).toContainText(/文章|article/i)
356
+ })
357
+
358
+ test('创建文章表单提交', async ({ page, request }) => {
359
+ await registerAndLogin(page, request, 'artui')
360
+ await page.goto('/admin/articles/new')
361
+
362
+ await page.fill('[name="title"]', 'E2E Article')
363
+ await page.fill('[name="content"]', 'E2E content')
364
+ await page.click('button[type="submit"]')
365
+
366
+ // 验证跳转或成功提示
367
+ await expect(page.locator('.hai-toast-item[data-variant="success"]')).toBeVisible({ timeout: 5000 })
368
+ })
369
+ })
370
+ ```
371
+
372
+ ## TDD 用例设计策略
373
+
374
+ 以下展示候选验证点,实际按职责和已有用例选择;不要求将同一输入规则在所有层重复实现和测试。
375
+
376
+ ### 从需求到测试用例的转换
377
+
378
+ ```
379
+ 需求:用户可以创建文章,标题必填且不超过 100 字符,需要登录后才能操作
380
+
381
+ ↓ 拆分测试点
382
+
383
+ 单元测试(Vitest):
384
+ ✅ 创建文章成功返回 ok(data)
385
+ ✅ 空标题被当前边界 Schema 拒绝
386
+ ✅ 超长标题(>100 字符)被拒绝
387
+ ✅ DB 异常时透传错误
388
+
389
+ Schema 测试(Vitest):
390
+ ✅ 合法输入通过校验
391
+ ✅ 空标题被拒绝
392
+ ✅ 超长标题被拒绝
393
+ ✅ 缺少必填字段被拒绝
394
+
395
+ E2E 测试(Playwright):
396
+ ✅ POST /api/articles 未认证 → 401
397
+ ✅ POST /api/articles 合法数据 → 201
398
+ ✅ POST /api/articles 空标题 → 400
399
+ ✅ 页面表单提交成功 → 跳转/提示
400
+ ✅ 未登录访问创建页 → 重定向登录
401
+ ```
402
+
403
+ ## 断言规范
404
+
405
+ - HaiResult 型 API 校验 `result.success`;其它返回、显式抛错与流式 API 按实际签名验证
406
+ - 失败时校验 `error.code`(不只检查 `success === false`)
407
+ - 使用类型缩窄后访问 data 或 error
408
+ - E2E 断言使用 Playwright 内置 expect 匹配器;同时检查用户可见结果和必要持久化状态,不能只断言 HTTP 200、按钮点击或成功提示
409
+ - 失败验收检查错误码/状态与“没有副作用”;事务中途失败、重复回调/写入、取消/关闭等按需求检查一致性与资源退出
410
+
411
+ ```typescript
412
+ // ✅ 单元测试断言
413
+ const result = await service.create(input)
414
+ expect(result.success).toBe(true)
415
+ if (result.success) {
416
+ expect(result.data.id).toBeDefined()
417
+ }
418
+
419
+ // ✅ 单元测试错误断言
420
+ const result = await service.create(invalidInput)
421
+ expect(result.success).toBe(false)
422
+ if (!result.success) {
423
+ expect(result.error.code).toBe('VALIDATION_FAILED')
424
+ }
425
+
426
+ // ✅ E2E API 断言
427
+ const response = await request.post('/api/articles', { data: input })
428
+ expect(response.status()).toBe(201)
429
+ const body = await response.json()
430
+ expect(body.success).toBe(true)
431
+
432
+ // ✅ E2E UI 断言
433
+ await expect(page.locator('.hai-toast-item[data-variant="success"]')).toBeVisible()
434
+ await expect(page).toHaveURL('/admin/articles')
435
+ ```
436
+
437
+ ## 质量门禁
438
+
439
+ 从当前 package.json 确认实际脚本和 workspace 名称,按 [分轮验证与集中修复](validation.md) 组织以下适用检查;不要为格式/文档改动运行无关 provider 或新增镜像测试。逐轮记录范围、状态/退出码、日志、mock/真实环境与未验证原因,完整日志按需读取。
440
+
441
+ ```bash
442
+ # 运行单元测试
443
+ pnpm --filter <app-name> test
444
+
445
+ # 运行 E2E 测试
446
+ pnpm --filter <app-name> test:e2e
447
+
448
+ # 覆盖率
449
+ pnpm --filter <app-name> test:coverage
450
+
451
+ # 仅在用户明确要求全量验收时执行
452
+ pnpm typecheck
453
+ pnpm lint
454
+ pnpm build # 构建/配置/跨包变更
455
+ pnpm test
456
+ ```
457
+
458
+ ## 相关 Skills
459
+
460
+ - `hai-app-create`:应用功能创建规范(TDD Green 阶段参照)
461
+ - `hai-app-review`:应用代码审查规范(TDD Refactor 阶段参照)
462
+ - `hai-build`:项目架构总览与 TDD 工作流导航
@@ -0,0 +1,42 @@
1
+ # 分轮验证与集中修复
2
+
3
+ 网站涉及部署目录时,按[网站挂载目录](../hai-build/paths.md)选择带前缀的真实流程,覆盖资源/运行配置、API地址、认证与匿名拒绝、导航/刷新以及部署健康和增量边界。Playwright页面与新增窗口使用同一完整baseURL;查询当前浏览器会话时使用共享该页面Cookie的page.request,独立request上下文用于匿名边界。保留根路径回归,区分前置失败与业务失败。
4
+
5
+ 适用于开发、审查修复、升级后的质量门禁与整体验收。默认执行“变更影响分析 → 选定相关范围 → 收集一轮 → 归并修复 → 定向确认”,只有用户明确要求全量验收时才启动全仓验证。不要遇到一个普通失败就修改代码并从头重跑。新增行为的目标用例仍可做小范围 TDD Red → Green;它不要求提前运行整套门禁。
6
+
7
+ ## 1. 确定本轮检查
8
+
9
+ - 验证前先由 AI 分析 Git 差异、变更行为、直接调用方和受影响用户流程,再读 `package.json`、任务依赖与环境要求。简述受影响模块/应用、选择哪些 test/E2E 及依据、哪些既有结果可复用,列出命令、工作目录、前置条件和预期证据。
10
+ - 默认只执行变更相关的 test、E2E 及必要静态/构建检查,优先按 workspace、测试文件或用例过滤。跨包变更补充实际受影响的消费者和公开契约检查;影响不明时先补搜索分析,不能据此自动升级全仓验证。只有用户明确要求全量时保留全量范围。纯文案/文档修改只做适用检查,不新增镜像测试。
11
+ - 一轮默认按 typecheck → lint → build(涉及构建/配置/模板/跨包契约)→ test → 相关 E2E 调度;顺序服从真实依赖。同轮收集不等于同时运行:只有输出目录、端口、数据库、容器与 fixture 均隔离的检查才可并行,共用 `dist`、`.svelte-kit` 或预览产物的构建与测试必须串行。
12
+ - 使用现有任务编排或一个临时调度脚本逐项执行、捕获真实退出码并保存日志。不要用跨检查的 `&&`、全局 fail-fast 或 `|| true` 代替结果收集;脚本内部有前置短路时,确认后续检查是否真正执行,必要时分别调度等价子任务,保留原门禁的最终验收。
13
+
14
+ ## 2. 收集全部可执行结果
15
+
16
+ - 本轮开始后保持被测源码、配置、依赖和运行环境稳定;协作 agent 也不得边测边改,不运行自动修复。普通类型错误、lint 错误、测试断言失败只记录,继续其余具备前置条件的检查。
17
+ - 只有真实前置失败才阻塞依赖它的检查,例如依赖无法安装、执行器无法启动、上游构建未产生必要产物、必需服务不可用。标明阻塞原因,继续独立检查;确实无法继续收集时才提前结束本轮、集中修复阻塞。不得使用旧构建、旧镜像或旧截图让下游假通过。
18
+ - 为每轮使用独立且被 Git 忽略的日志目录,例如 `tmp/validation/round-01/`。逐项记录命令/范围、源码版本及未提交改动、环境、状态(通过/失败/阻塞/未执行)、退出码、耗时和日志路径;未执行与不适用须说明原因,不能写成通过。超时、取消和环境失败单列,不能当作断言失败或忽略。
19
+ - 调度脚本等子进程退出后再记录结果;重定向或管道不能覆盖实际退出码。所有必需项均有有效通过结果,整轮才算通过;收集到任何失败或阻塞时,汇总必须保留非成功状态。
20
+ - 完整输出写日志,AI 先读汇总及每类失败的有限上下文,再按需定位原始日志;不反复载入整份成功日志、密集轮询或启动尚未结束的同一检查。长任务期间定期简述进度。
21
+
22
+ ## 3. 集中分析与修复
23
+
24
+ - 本轮可执行检查结束后,把问题按根因去重,记录位置、证据、影响、修复项及关联门禁。上游故障造成的连锁失败合并处理;区分本次引入、原有问题和环境问题。
25
+ - 在已有授权范围内集中修复本次范围的问题,保留仍有效的断言与回归。不能靠删断言、跳过用例、放宽超时或关闭规则换绿灯。环境故障先保存证据、确认恢复条件,再定向重试;不反复重跑到偶然通过。
26
+ - 下载超时先区分 registry、DNS、代理等网络前提与实际编译/业务错误。复用包管理器的有界重试、可信镜像和缓存,保留总时限与每次结果;只对可安全重复的瞬时网络操作重试,不重试断言或掩盖业务失败。超时/取消后确认本轮进程树及已登记资源回收,再重试或启动冲突任务。
27
+ - 新发现的独立问题加入同一清单;修复期间的小范围诊断不触发从头全量重跑,也不能替代下一轮必要验收。
28
+
29
+ ## 4. 先定向回归,再扩大验收
30
+
31
+ - 集中修复后,先用最小适用范围验证原失败、已解除的阻塞及直接受影响的消费者;保留必要构建/服务前置。定向回归仍失败时继续归并和修复,只重跑失败及受新改动影响的项,暂不启动较完整门禁。
32
+ - 相关问题均已验证解决后,仅按实际依赖扩大到受影响工作区或完整用户流程,不自动扩大到全仓。用户先前要求的全量已完成后,后续局部修复也只使相关结果失效;补测相关项,除非用户再次要求全量。扩大验收发现新问题时,仍先收集、集中修复和定向确认,不从头重复整套流程。
33
+ - 只有源码、依赖、配置、工具、环境及所用产物等输入均未改变的已通过项才可复用,并注明来源轮次或缓存;输入变化使相关结果失效。最终所有必需检查必须对最终代码仍有效,缺项不能称为完成。真实部署、Provider、浏览器或原生验收不能只引用静态检查/构建缓存。
34
+ - 保留原有 CI/发布门禁的失败阻断;问题收集时继续运行不代表允许失败提交发布或忽略 required checks。
35
+ - 每轮都在 finally/teardown 停止本轮进程、清理本轮临时工程/容器/镜像/数据;确认退出和资源释放后再运行冲突任务。日志、截图与报告保留到问题分析和交付结束,再按项目约定清理,不覆盖失败证据、不提交验收产物、不删除用户资源。
36
+ - 部署夹具先检查固定公开基础镜像,仅确认缺失才拉取;成功 create 先登记完整 ID,再在私有 PID namespace 内异步准备 APT/pip/sshd。所有准备 exec 转交同一取消信号,等待本地客户端 close 后按该 ID 停止全树并核验消失。总准备 deadline 早于 hook 并预留回收预算;公共缓存不删,私有 tag 回收前复核内容 ID/owner。未取得可信 create 回执或测试进程被强制终止时记录未知,不能按名称或 label 认领资源。
37
+ - 浏览器执行器默认将每轮、每组的证据分别放入忽略的 `test-results/run-*/group-*`;只清理本轮临时数据库/上传数据。显式 `HAI_AUTH_EVIDENCE_DIR`、`--output` 和 Playwright HTML 输出目录会保留,取消也不删除已有报告。不要复制私有环境、密钥或业务数据库到证据目录。
38
+ - 经托管 `test:e2e` 入口为服务子进程提供绝对 `HAI_E2E_DATA_ROOT` 和显式测试后端,隔离继承的 `HAI_*` / `PUBLIC_*` / `VITE_*` 与用户 `.env.local`。仅本轮测试启用 `HAI_E2E=1`;普通开发与生产的 dotenv 加载、共享后端守卫不放宽。启用 transport 的验收使用本轮可信 ring 和 registry,不能关闭加密掩盖客户端契约问题。
39
+ - Fullstack验收已部署服务时,通过 `E2E_ADMIN_PASSWORD`、`E2E_AUDIT_ADMIN_PASSWORD`、`E2E_CONFIG_ADMIN_PASSWORD`、`E2E_BUSINESS_OPERATOR_PASSWORD` 分别提供同环境的初始管理员、审计管理员、配置管理员、业务操作员密码;对应 `HAI_ADMIN_DEFAULT_PASSWORD`、`HAI_AUDIT_ADMIN_PASSWORD`、`HAI_CONFIG_ADMIN_PASSWORD`、`HAI_BUSINESS_OPERATOR_PASSWORD`。测试配置、登录和再次验证共用这些值;固定回退只用于托管测试账号,不能替代随机部署凭据。只核对来源与变量名,不把值写入日志、截图或报告;保留同密码拒绝、初始凭据和再次验证断言。
40
+ - 最终报告各项门禁状态、执行/复用范围、修复结果和未验证原因;mock、容器、真实服务及原生结果分别说明。只陈述实际证据,不以“脚本执行完了”代表验证通过。
41
+
42
+ 公开 API 变更需验证 package.exports 实际入口与配套声明,核对根/子路径真实导入和浏览器打包;不使用 src/dist 深层导入绕过缺失公开产物。Svelte 默认组件、明确 selective/type-only 导出与 client/server 分隔按实际契约验收,不把内部 Provider/Deps 扩成公共 API。