@h-ai/cli 1.0.0-beta.18 → 1.0.0-beta.19

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 (194) hide show
  1. package/README.en.md +4 -0
  2. package/README.ja.md +4 -0
  3. package/README.md +4 -0
  4. package/dist/{chunk-6YZBC5MO.js → chunk-2ZL5ORQ2.js} +85 -25
  5. package/dist/chunk-2ZL5ORQ2.js.map +1 -0
  6. package/dist/{chunk-7NVRYYHN.js → chunk-L53P43B2.js} +129 -31
  7. package/dist/chunk-L53P43B2.js.map +1 -0
  8. package/dist/cli-config-templates-LWMD2I6V.js +5 -0
  9. package/dist/{cli-config-templates-QG5HOYR5.js.map → cli-config-templates-LWMD2I6V.js.map} +1 -1
  10. package/dist/{cli-skill-templates-W4I6ZKYW.js → cli-skill-templates-D6S2OQ6X.js} +3 -3
  11. package/dist/{cli-skill-templates-W4I6ZKYW.js.map → cli-skill-templates-D6S2OQ6X.js.map} +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.js +2747 -671
  14. package/dist/index.js.map +1 -1
  15. package/dist/metafile-esm.json +1 -1
  16. package/package.json +22 -22
  17. package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -10
  18. package/templates/apps/admin/src/routes/+page.svelte.hbs +4 -4
  19. package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +17 -7
  20. package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +26 -6
  21. package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +2 -2
  22. package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +6 -1
  23. package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +13 -5
  24. package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +13 -5
  25. package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  26. package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +71 -32
  27. package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  28. package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +131 -54
  29. package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +39 -13
  30. package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +78 -31
  31. package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +3 -1
  32. package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  33. package/templates/apps/api/e2e/api-serv.spec.ts.hbs +20 -3
  34. package/templates/apps/api/e2e/capture-evidence.ts.hbs +4 -1
  35. package/templates/apps/api/eslint.config.js.hbs +3 -1
  36. package/templates/apps/api/images/serv.Dockerfile.hbs +3 -4
  37. package/templates/apps/api/playwright.config.ts.hbs +23 -19
  38. package/templates/apps/api/pnpm-workspace.yaml.hbs +27 -16
  39. package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +1 -3
  40. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +10 -2
  41. package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +10 -2
  42. package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +0 -1
  43. package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +0 -1
  44. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +4 -1
  45. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +16 -4
  46. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +8 -2
  47. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +0 -1
  48. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +4 -1
  49. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +16 -4
  50. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +10 -2
  51. package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +0 -1
  52. package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +0 -2
  53. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +4 -1
  54. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +19 -5
  55. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +111 -26
  56. package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +19 -5
  57. package/templates/apps/fullstack/eslint.config.js.hbs +3 -1
  58. package/templates/apps/fullstack/images/serv.Dockerfile.hbs +3 -4
  59. package/templates/apps/fullstack/images/web.Dockerfile.hbs +0 -2
  60. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +114 -23
  61. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +57 -11
  62. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +3 -1
  63. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +65 -30
  64. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +0 -1
  65. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +69 -21
  66. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +21 -5
  67. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +63 -11
  68. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -1
  69. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -1
  70. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +139 -49
  71. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +43 -12
  72. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +139 -28
  73. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +33 -10
  74. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +141 -25
  75. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +6 -2
  76. package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +3 -1
  77. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +9 -2
  78. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +0 -3
  79. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +15 -3
  80. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +33 -7
  81. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +16 -2
  82. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +104 -13
  83. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +37 -7
  84. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +9 -3
  85. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +25 -3
  86. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +133 -19
  87. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +14 -2
  88. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +66 -34
  89. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +132 -30
  90. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +8 -2
  91. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +23 -5
  92. package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +143 -21
  93. package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -2
  94. package/templates/apps/fullstack/playwright.config.ts.hbs +9 -3
  95. package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +30 -15
  96. package/templates/apps/h5/src/routes/+layout.svelte.hbs +57 -21
  97. package/templates/apps/h5/src/routes/+page.svelte.hbs +2 -2
  98. package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +2 -2
  99. package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +2 -2
  100. package/templates/apps/mobile-app/src/App.svelte.hbs +17 -5
  101. package/templates/apps/mobile-app/src/lib/api.ts.hbs +14 -3
  102. package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +8 -1
  103. package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +6 -2
  104. package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +5 -1
  105. package/templates/apps/website/scripts/static-website.mjs.hbs +16 -3
  106. package/templates/apps/website/src/routes/+layout.svelte.hbs +44 -23
  107. package/templates/apps/website/src/routes/+page.svelte.hbs +4 -4
  108. package/templates/apps/website/src/routes/about/+page.svelte.hbs +2 -2
  109. package/templates/apps/website/src/routes/contact/+page.svelte.hbs +2 -2
  110. package/templates/apps/website/src/routes/services/+page.svelte.hbs +20 -5
  111. package/templates/base/e2e/app.spec.ts.hbs +49 -16
  112. package/templates/base/eslint-rules.js +44 -25
  113. package/templates/base/eslint.config.js.hbs +3 -1
  114. package/templates/base/images/web.Dockerfile.hbs +3 -4
  115. package/templates/base/package.json.hbs +5 -4
  116. package/templates/base/patches/daisyui-5.7.50.patch +8 -0
  117. package/templates/base/patches/deepmerge-4.3.1.patch +51 -0
  118. package/templates/base/playwright.config.ts +3 -1
  119. package/templates/base/pnpm-workspace.yaml.hbs +33 -16
  120. package/templates/base/src/app.d.ts.hbs +1 -1
  121. package/templates/base/src/hooks.server.ts.hbs +36 -27
  122. package/templates/base/src/lib/build-metadata.ts.hbs +0 -1
  123. package/templates/base/src/lib/server/init.ts.hbs +124 -51
  124. package/templates/base/src/lib/server/kit-config.ts.hbs +7 -4
  125. package/templates/base/src/routes/+layout.server.ts.hbs +2 -2
  126. package/templates/base/svelte.config.js.hbs +10 -100
  127. package/templates/base/tests/scaffold.test.ts.hbs +12 -3
  128. package/templates/base/tsconfig.json.hbs +7 -4
  129. package/templates/base/vite.config.ts.hbs +108 -14
  130. package/templates/base/vitest.config.ts.hbs +6 -2
  131. package/templates/features/ai/routes/api/chat/+server.ts +3 -1
  132. package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +3 -3
  133. package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +3 -3
  134. package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +3 -3
  135. package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +3 -3
  136. package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +3 -3
  137. package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +3 -3
  138. package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +3 -3
  139. package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +3 -3
  140. package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +3 -3
  141. package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +3 -3
  142. package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +3 -3
  143. package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +3 -3
  144. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +11 -2
  145. package/templates/shared/browser-check/startup.js +32 -6
  146. package/templates/shared/browser-startup.spec.ts +3 -1
  147. package/templates/shared/build-metadata.ts +18 -4
  148. package/templates/shared/e2e-env.ts +22 -6
  149. package/templates/shared/native-name.mjs +9 -2
  150. package/templates/shared/public-base-path.mjs +17 -4
  151. package/templates/shared/run-e2e.mjs +40 -9
  152. package/templates/shared/run-node.mjs +15 -4
  153. package/templates/shared/run-tauri.mjs +37 -8
  154. package/templates/shared/vite-runtime-config.ts +9 -3
  155. package/templates/skills/AGENTS.md +10 -73
  156. package/templates/skills/bridges/admin/AGENTS.md +9 -65
  157. package/templates/skills/bridges/api/AGENTS.md +8 -59
  158. package/templates/skills/bridges/fullstack/AGENTS.md.hbs +9 -54
  159. package/templates/skills/bridges/h5/AGENTS.md +8 -63
  160. package/templates/skills/bridges/mobile-app/AGENTS.md +8 -62
  161. package/templates/skills/bridges/website/AGENTS.md +8 -63
  162. package/templates/skills/hai-ai/acp.md +2 -0
  163. package/templates/skills/hai-ai/guide.md +17 -6
  164. package/templates/skills/hai-ai/reference.md +21 -12
  165. package/templates/skills/hai-api-client/reference.md +1 -1
  166. package/templates/skills/hai-app-create/development.md +3 -1
  167. package/templates/skills/hai-app-create/project.md +33 -0
  168. package/templates/skills/hai-app-create/reference.md +8 -8
  169. package/templates/skills/hai-app-tests/reference.md +1 -1
  170. package/templates/skills/hai-build/SKILL.md +2 -2
  171. package/templates/skills/hai-build/paths.md +1 -1
  172. package/templates/skills/hai-build/reference.md +11 -7
  173. package/templates/skills/hai-capacitor/reference.md +2 -0
  174. package/templates/skills/hai-ci/SKILL.md +1 -0
  175. package/templates/skills/hai-core/reference.md +3 -0
  176. package/templates/skills/hai-crypto/reference.md +2 -0
  177. package/templates/skills/hai-deploy/SKILL.md +7 -1
  178. package/templates/skills/hai-deploy/middleware.md +3 -1
  179. package/templates/skills/hai-framework-sync/sync.md +2 -0
  180. package/templates/skills/hai-kit/reference.md +16 -4
  181. package/templates/skills/hai-payment/reference.md +2 -0
  182. package/templates/skills/hai-reach/SKILL.md +2 -1
  183. package/templates/skills/hai-reach/reference.md +1 -1
  184. package/templates/skills/hai-reldb/SKILL.md +1 -1
  185. package/templates/skills/hai-reldb/reference.md +4 -0
  186. package/templates/skills/hai-serv/reference.md +12 -2
  187. package/templates/skills/hai-storage/reference.md +12 -3
  188. package/templates/skills/hai-ui/SKILL.md +3 -2
  189. package/templates/skills/hai-ui/guide.md +1 -1
  190. package/templates/skills/hai-ui/reference.md +23 -35
  191. package/templates/skills/hai-vecdb/reference.md +1 -1
  192. package/dist/chunk-6YZBC5MO.js.map +0 -1
  193. package/dist/chunk-7NVRYYHN.js.map +0 -1
  194. package/dist/cli-config-templates-QG5HOYR5.js +0 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/cli",
3
3
  "type": "module",
4
- "version": "1.0.0-beta.18",
4
+ "version": "1.0.0-beta.19",
5
5
  "description": "Hai Framework CLI for project scaffolding and code generation.",
6
6
  "license": "Apache-2.0",
7
7
  "keywords": [
@@ -30,40 +30,40 @@
30
30
  "node": "^22.23.4 || ^24.22.1 || ^26.12.1"
31
31
  },
32
32
  "dependencies": {
33
- "@h-ai/core": "1.0.0-beta.18",
34
- "cac": "^7.0.1",
33
+ "@h-ai/core": "1.0.0-beta.19",
34
+ "cac": "^7.1.0",
35
35
  "chalk": "^6.0.1",
36
36
  "fast-wrap-ansi": "^0.2.2",
37
37
  "fs-extra": "^11.4.1",
38
38
  "handlebars": "^4.7.10",
39
- "ora": "^9.4.1",
39
+ "ora": "^10.0.0",
40
40
  "prompts": "^2.4.2",
41
41
  "yaml": "^2.9.1"
42
42
  },
43
43
  "devDependencies": {
44
- "@h-ai/api-client": "1.0.0-beta.18",
45
- "@h-ai/cache": "1.0.0-beta.18",
46
- "@h-ai/crypto": "1.0.0-beta.18",
47
- "@h-ai/deploy": "1.0.0-beta.18",
48
- "@h-ai/feedback": "1.0.0-beta.18",
49
- "@h-ai/iam": "1.0.0-beta.18",
50
- "@h-ai/kit": "1.0.0-beta.18",
51
- "@h-ai/payment": "1.0.0-beta.18",
52
- "@h-ai/reach": "1.0.0-beta.18",
53
- "@h-ai/reldb": "1.0.0-beta.18",
54
- "@h-ai/storage": "1.0.0-beta.18",
55
- "@h-ai/vecdb": "1.0.0-beta.18",
44
+ "@h-ai/api-client": "1.0.0-beta.19",
45
+ "@h-ai/cache": "1.0.0-beta.19",
46
+ "@h-ai/crypto": "1.0.0-beta.19",
47
+ "@h-ai/deploy": "1.0.0-beta.19",
48
+ "@h-ai/feedback": "1.0.0-beta.19",
49
+ "@h-ai/iam": "1.0.0-beta.19",
50
+ "@h-ai/kit": "1.0.0-beta.19",
51
+ "@h-ai/payment": "1.0.0-beta.19",
52
+ "@h-ai/reach": "1.0.0-beta.19",
53
+ "@h-ai/reldb": "1.0.0-beta.19",
54
+ "@h-ai/storage": "1.0.0-beta.19",
55
+ "@h-ai/vecdb": "1.0.0-beta.19",
56
56
  "@types/fs-extra": "^11.0.4",
57
- "@types/node": "^26.6.5",
57
+ "@types/node": "^26.6.6",
58
58
  "@types/prompts": "^2.4.9",
59
59
  "altcha": "^3.5.0",
60
60
  "fast-string-width": "^3.0.2",
61
- "rimraf": "^6.1.3",
62
- "testcontainers": "^12.2.0",
63
- "tsup": "^8.5.1",
61
+ "rimraf": "^6.1.4",
62
+ "testcontainers": "^12.2.1",
63
+ "tsup": "^9.0.0",
64
64
  "typescript": "^6.0.3",
65
- "vitest": "^4.1.11",
66
- "zod": "^4.6.5"
65
+ "vitest": "^5.1.0",
66
+ "zod": "^4.6.7"
67
67
  },
68
68
  "scripts": {
69
69
  "build": "tsup",
@@ -4,18 +4,15 @@
4
4
  * 管理后台根布局
5
5
  */
6
6
  import type { Snippet } from 'svelte'
7
- import { browser } from '$app/environment'
7
+ import { browser } from '$app/env'
8
8
  {{#if features.iam}}
9
- import { base } from '$app/paths'
9
+ import { resolve } from '$app/paths'
10
10
  {{else}}
11
11
  {{#if features.crypto}}
12
- import { base } from '$app/paths'
12
+ import { resolve } from '$app/paths'
13
13
  {{/if}}
14
14
  {{/if}}
15
15
  import { page } from '$app/state'
16
- {{#if hasI18n}}
17
- import { getLocale, setLocale } from '$lib/paraglide/runtime.js'
18
- {{/if}}
19
16
  {{#if features.crypto}}
20
17
  import { crypto } from '@h-ai/crypto'
21
18
  import { kit } from '@h-ai/kit'
@@ -31,6 +28,9 @@
31
28
  {{/if}}
32
29
  {{#if features.crypto}}
33
30
  import { untrack } from 'svelte'
31
+ {{/if}}
32
+ {{#if hasI18n}}
33
+ import { getLocale, setLocale } from '#lib/paraglide/runtime.js'
34
34
  {{/if}}
35
35
  import '../app.css'
36
36
 
@@ -40,10 +40,16 @@
40
40
 
41
41
  const { children }: Props = $props()
42
42
  {{#if features.crypto}}
43
- if (browser)
44
- kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), { crypto, basePath: base })
43
+ if (browser) {
44
+ kit.client.installBrowserTransport(untrack(() => page.data.kitConfig), {
45
+ crypto,
46
+ basePath: resolve('/').replace(/\/$/, ''),
47
+ })
48
+ }
45
49
  {{/if}}
46
- const initialTheme = browser ? getSavedTheme() : 'light'
50
+ const initialTheme = browser
51
+ ? getSavedTheme()
52
+ : 'light'
47
53
  let currentTheme = $state(initialTheme)
48
54
  if (browser)
49
55
  applyTheme(initialTheme, false)
@@ -52,7 +58,7 @@
52
58
  applyTheme(theme)
53
59
  }
54
60
  {{#if features.iam}}
55
- const authActions = kit.client.createAuthActions({ basePath: `${base}/api/auth` })
61
+ const authActions = kit.client.createAuthActions({ basePath: `${resolve('/').replace(/\/$/, '')}/api/auth` })
56
62
  $effect(() => authActions.bindPageExit({ enabled: page.data.iamPublicConfig?.session.endOnPageHide }))
57
63
  {{/if}}
58
64
  {{#if hasI18n}}
@@ -5,10 +5,10 @@
5
5
  */
6
6
  import { resolve } from '$app/paths'
7
7
  import { page } from '$app/state'
8
+ import { Badge, Card } from '@h-ai/ui'
8
9
  {{#if hasI18n}}
9
- import * as m from '$lib/paraglide/messages'
10
+ import * as m from '#lib/paraglide/messages.js'
10
11
  {{/if}}
11
- import { Badge, Card } from '@h-ai/ui'
12
12
  </script>
13
13
 
14
14
  <svelte:head>
@@ -31,7 +31,7 @@
31
31
  <h1 class='mt-4 text-4xl font-black tracking-tight'>{page.data.appConfig.name}</h1>
32
32
  <p class='mt-3 text-base-content/60'>{m.page_home_subtitle()}</p>
33
33
  <div class='mt-8 flex flex-wrap gap-3 justify-center'>
34
- <a href={resolve('/admin', {})} class='btn btn-primary'>
34
+ <a href={resolve('admin')} class='btn btn-primary'>
35
35
  <span class='icon-[tabler--layout-dashboard] size-5'></span>
36
36
  {m.nav_admin()}
37
37
  </a>
@@ -46,7 +46,7 @@
46
46
  <h1 class='mt-4 text-4xl font-black tracking-tight'>{page.data.appConfig.name}</h1>
47
47
  <p class='mt-3 text-base-content/60'>基于 hai Agent Framework 构建</p>
48
48
  <div class='mt-8 flex flex-wrap gap-3 justify-center'>
49
- <a href={resolve('/admin', {})} class='btn btn-primary'>
49
+ <a href={resolve('admin')} class='btn btn-primary'>
50
50
  <span class='icon-[tabler--layout-dashboard] size-5'></span>
51
51
  进入后台
52
52
  </a>
@@ -6,10 +6,10 @@
6
6
  import type { Snippet } from 'svelte'
7
7
  import { resolve } from '$app/paths'
8
8
  import { page } from '$app/state'
9
+ import { WorkspaceLayout } from '@h-ai/ui'
9
10
  {{#if hasI18n}}
10
- import * as m from '$lib/paraglide/messages'
11
+ import * as m from '#lib/paraglide/messages.js'
11
12
  {{/if}}
12
- import { WorkspaceLayout } from '@h-ai/ui'
13
13
 
14
14
  interface Props {
15
15
  children: Snippet
@@ -31,11 +31,19 @@
31
31
 
32
32
  const navItems = $derived([
33
33
  {{#if hasI18n}}
34
- { path: '/admin', label: m.nav_dashboard(), icon: 'icon-[tabler--layout-dashboard]' },
35
- { path: '/admin/settings', label: m.nav_settings(), icon: 'icon-[tabler--settings]' },
34
+ {
35
+ path: resolve('admin'),
36
+ label: m.nav_dashboard(),
37
+ icon: 'icon-[tabler--layout-dashboard]',
38
+ },
39
+ {
40
+ path: resolve('admin/settings'),
41
+ label: m.nav_settings(),
42
+ icon: 'icon-[tabler--settings]',
43
+ },
36
44
  {{else}}
37
- { path: '/admin', label: '仪表盘', icon: 'icon-[tabler--layout-dashboard]' },
38
- { path: '/admin/settings', label: '设置', icon: 'icon-[tabler--settings]' },
45
+ { path: resolve('admin'), label: '仪表盘', icon: 'icon-[tabler--layout-dashboard]' },
46
+ { path: resolve('admin/settings'), label: '设置', icon: 'icon-[tabler--settings]' },
39
47
  {{/if}}
40
48
  ] as const)
41
49
  </script>
@@ -64,10 +72,12 @@
64
72
  <ul class='gap-1'>
65
73
  {#each navItems as item (item.path)}
66
74
  <li>
67
- <a href={resolve(item.path, {})} class:menu-active={page.url.pathname === resolve(item.path, {})} onclick={closeDrawer}>
75
+ <!-- eslint-disable svelte/no-navigation-without-resolve -- 菜单字段已由 resolve 生成完整挂载地址;规则无法追踪派生/筛选后的集合,不能二次添加前缀。 -->
76
+ <a href={item.path} class:menu-active={page.url.pathname === item.path} onclick={closeDrawer}>
68
77
  <span class='{item.icon} size-5'></span>
69
78
  {item.label}
70
79
  </a>
80
+ <!-- eslint-enable svelte/no-navigation-without-resolve -->
71
81
  </li>
72
82
  {/each}
73
83
  </ul>
@@ -3,17 +3,37 @@
3
3
  /**
4
4
  * 仪表盘页面
5
5
  */
6
+ import { Card, PageHeader } from '@h-ai/ui'
6
7
  {{#if hasI18n}}
7
- import * as m from '$lib/paraglide/messages'
8
+ import * as m from '#lib/paraglide/messages.js'
8
9
  {{/if}}
9
- import { Card, PageHeader } from '@h-ai/ui'
10
10
  {{#if hasI18n}}
11
11
 
12
12
  const stats = $derived([
13
- { label: m.page_dashboard_total_users(), value: '0', icon: 'icon-[tabler--users]', accent: 'text-primary' },
14
- { label: m.page_dashboard_today_active(), value: '0', icon: 'icon-[tabler--activity]', accent: 'text-success' },
15
- { label: m.page_dashboard_revenue(), value: '¥0', icon: 'icon-[tabler--coin]', accent: 'text-warning' },
16
- { label: m.page_dashboard_orders(), value: '0', icon: 'icon-[tabler--shopping-cart]', accent: 'text-info' },
13
+ {
14
+ label: m.page_dashboard_total_users(),
15
+ value: '0',
16
+ icon: 'icon-[tabler--users]',
17
+ accent: 'text-primary',
18
+ },
19
+ {
20
+ label: m.page_dashboard_today_active(),
21
+ value: '0',
22
+ icon: 'icon-[tabler--activity]',
23
+ accent: 'text-success',
24
+ },
25
+ {
26
+ label: m.page_dashboard_revenue(),
27
+ value: '¥0',
28
+ icon: 'icon-[tabler--coin]',
29
+ accent: 'text-warning',
30
+ },
31
+ {
32
+ label: m.page_dashboard_orders(),
33
+ value: '0',
34
+ icon: 'icon-[tabler--shopping-cart]',
35
+ accent: 'text-info',
36
+ },
17
37
  ])
18
38
  {{else}}
19
39
  const stats = [
@@ -3,10 +3,10 @@
3
3
  /**
4
4
  * 设置页面
5
5
  */
6
+ import { Card, PageHeader } from '@h-ai/ui'
6
7
  {{#if hasI18n}}
7
- import * as m from '$lib/paraglide/messages'
8
+ import * as m from '#lib/paraglide/messages.js'
8
9
  {{/if}}
9
- import { Card, PageHeader } from '@h-ai/ui'
10
10
  </script>
11
11
 
12
12
  <svelte:head>
@@ -4,7 +4,12 @@ import { z } from 'zod'
4
4
  export const AppInfoOutputDataSchema = z.object({
5
5
  name: z.string(),
6
6
  version: z.string(),
7
- env: z.enum(['development', 'production', 'test', 'staging']),
7
+ env: z.enum([
8
+ 'development',
9
+ 'production',
10
+ 'test',
11
+ 'staging',
12
+ ]),
8
13
  defaultLocale: z.string(),
9
14
  uptimeMs: z.number().int().nonnegative(),
10
15
  transportEnabled: z.boolean(),
@@ -5,11 +5,19 @@ import { appContract } from './app-contract.js'
5
5
 
6
6
  /** 工程级应用 contract。 */
7
7
  export const {{api.contractExportName}} = apiContract.create({
8
- {{#if features.iam}} iam: apiContract.iam,
9
- {{/if}}{{#if features.storage}} storage: apiContract.storage,
10
- {{/if}}{{#if features.ai}} ai: apiContract.ai,
11
- {{/if}}{{#if features.feedback}} feedback: apiContract.feedback,
12
- {{/if}} // @hai-generator:contracts:entries
8
+ {{#if features.iam}}
9
+ iam: apiContract.iam,
10
+ {{/if}}
11
+ {{#if features.storage}}
12
+ storage: apiContract.storage,
13
+ {{/if}}
14
+ {{#if features.ai}}
15
+ ai: apiContract.ai,
16
+ {{/if}}
17
+ {{#if features.feedback}}
18
+ feedback: apiContract.feedback,
19
+ {{/if}}
20
+ // @hai-generator:contracts:entries
13
21
  app: appContract,
14
22
  })
15
23
 
@@ -5,14 +5,22 @@ describe('{{api.contractPackageName}}', () => {
5
5
  it('includes generated contract routes', () => {
6
6
  expect({{api.contractExportName}}.app.info).toBeDefined()
7
7
  expect({{api.contractExportName}}.app.echo).toBeDefined()
8
- {{#if features.iam}} expect({{api.contractExportName}}.iam.auth.login).toBeDefined()
9
- {{/if}}{{#if features.storage}} expect({{api.contractExportName}}.storage.presignedUrls.createUpload).toBeDefined()
10
- {{/if}}{{#if features.ai}} expect({{api.contractExportName}}.ai.chats.createCompletion).toBeDefined()
11
- {{/if}} })
8
+ {{#if features.iam}}
9
+ expect({{api.contractExportName}}.iam.auth.login).toBeDefined()
10
+ {{/if}}
11
+ {{#if features.storage}}
12
+ expect({{api.contractExportName}}.storage.presignedUrls.createUpload).toBeDefined()
13
+ {{/if}}
14
+ {{#if features.ai}}
15
+ expect({{api.contractExportName}}.ai.chats.createCompletion).toBeDefined()
16
+ {{/if}}
17
+ })
12
18
 
13
19
  it('validates app.echo input length', () => {
14
20
  expect(AppEchoInputSchema.safeParse({ message: 'hello' }).success).toBe(true)
15
21
  expect(AppEchoInputSchema.safeParse({ message: '' }).success).toBe(false)
16
- expect(AppEchoInputSchema.safeParse({ message: 'x'.repeat(2001) }).success).toBe(false)
22
+ expect(AppEchoInputSchema.safeParse({
23
+ message: 'x'.repeat(2001),
24
+ }).success).toBe(false)
17
25
  })
18
26
  })
@@ -6,6 +6,8 @@ export default defineConfig({
6
6
  target: 'node22',
7
7
  sourcemap: true,
8
8
  clean: true,
9
- dts: { compilerOptions: { ignoreDeprecations: '6.0' } },
9
+ dts: {
10
+ compilerOptions: { ignoreDeprecations: '6.0' },
11
+ },
10
12
  external: ['@h-ai/api-contract', 'zod'],
11
13
  })
@@ -1,14 +1,27 @@
1
1
  import type { CoreConfig } from '@h-ai/core'
2
2
  import type { {{#if features.feedback}}CreateServContext, {{/if}}ServConfig{{#if features.crypto}}, ServTransportConfig{{/if}} } from '@h-ai/serv'
3
- {{#if features.crypto}}import process from 'node:process'
4
- {{/if}}
5
- {{#if features.feedback}}import { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'
6
- {{/if}}import { core } from '@h-ai/core'
7
- {{#if features.crypto}}import { {{#if features.db}}createReldbTransportKeyStore{{else}}createInMemoryKeyStore{{/if}}, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
8
- {{/if}}{{#if features.feedback}}import { FeedbackConfigSchema } from '@h-ai/feedback'
9
- {{/if}}{{#if features.iam}}import { iam } from '@h-ai/iam'
10
- {{/if}}{{#if features.crypto}}{{#if features.db}}import { reldb } from '@h-ai/reldb'
11
- {{/if}}{{/if}}import { serv } from '@h-ai/serv'
3
+ {{#if features.crypto}}
4
+ import process from 'node:process'
5
+ {{/if}}
6
+ {{#if features.feedback}}
7
+ import { resolveFeedbackBudget } from '@h-ai/api-contract/feedback'
8
+ {{/if}}
9
+ import { core } from '@h-ai/core'
10
+ {{#if features.crypto}}
11
+ import { {{#if features.db}}createReldbTransportKeyStore{{else}}createInMemoryKeyStore{{/if}}, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
12
+ {{/if}}
13
+ {{#if features.feedback}}
14
+ import { FeedbackConfigSchema } from '@h-ai/feedback'
15
+ {{/if}}
16
+ {{#if features.iam}}
17
+ import { iam } from '@h-ai/iam'
18
+ {{/if}}
19
+ {{#if features.crypto}}
20
+ {{#if features.db}}
21
+ import { reldb } from '@h-ai/reldb'
22
+ {{/if}}
23
+ {{/if}}
24
+ import { serv } from '@h-ai/serv'
12
25
  import { {{api.contractExportName}} } from '{{api.contractPackageName}}'
13
26
  import { {{api.serviceProceduresFactoryName}} } from './server/procedures/index.js'
14
27
 
@@ -28,56 +41,80 @@ export function {{api.serviceAppFactoryName}}(_options: CreateApiServiceAppOptio
28
41
  corsOrigin: servConfig.cors.origin,
29
42
  nativeOrigins: servConfig.cors.nativeOrigins,
30
43
  })
31
- {{#if features.crypto}} const transportMode = _options.transport ?? 'config'
44
+ {{#if features.crypto}}
45
+ const transportMode = _options.transport ?? 'config'
32
46
  let transport: ServTransportConfig | undefined
33
47
  if (transportMode !== 'disabled' && servConfig.transport !== false) {
34
- {{#unless features.db}} if (coreConfig.env !== 'development' && coreConfig.env !== 'test')
35
- throw new Error('Production transport requires a shared registry; enable the db feature and configure a shared database')
48
+ {{#unless features.db}}
49
+ if (coreConfig.env !== 'development' && coreConfig.env !== 'test')
50
+ throw new Error('Production transport requires a shared registry; enable the db feature and configure a shared database')
36
51
  {{/unless}}
37
52
  const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
38
53
  if (!ring.success)
39
54
  throw new Error(`HAI_CRYPTO_TRANSPORT_SERVERKEYRING: ${ring.error.message} (${ring.error.code})`)
40
- {{#if features.feedback}} // 可选反馈故障重试期间仍使用配置预算,避免缓存默认容量。
55
+ {{#if features.feedback}}
56
+ // 可选反馈故障重试期间仍使用配置预算,避免缓存默认容量。
41
57
  const feedbackSettings = FeedbackConfigSchema.safeParse(core.config.get('feedback'))
42
- const feedbackBudget = resolveFeedbackBudget(feedbackSettings.success ? feedbackSettings.data : {})
43
- {{/if}} transport = {
58
+ const feedbackBudget = resolveFeedbackBudget(feedbackSettings.success
59
+ ? feedbackSettings.data
60
+ : {})
61
+ {{/if}}
62
+ transport = {
44
63
  crypto,
45
64
  serverKeyRing: ring.data,
46
- {{#if features.db}} keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
47
- {{else}} keyStore: createInMemoryKeyStore(), // 无 db 的模板仅在 development/test 使用内存 registry。
65
+ {{#if features.db}}
66
+ keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
67
+ {{else}}
68
+ keyStore: createInMemoryKeyStore(), // 无 db 的模板仅在 development/test 使用内存 registry。
48
69
  {{/if}}
49
70
  keyExchangePath: servConfig.transport.keyExchangePath,
50
71
  maxPlaintextBytes: servConfig.transport.maxPlaintextBytes,
51
72
  maxFutureSkewSeconds: servConfig.transport.maxFutureSkewSeconds,
52
73
  maxRequestAgeSeconds: servConfig.transport.maxRequestAgeSeconds,
53
- {{#if features.feedback}} routePlaintextBytes: {
74
+ {{#if features.feedback}}
75
+ routePlaintextBytes: {
54
76
  [`${servConfig.http.apiPrefix}/feedback/reports`]: feedbackBudget.maxTransportBytes,
55
77
  [`${servConfig.http.apiPrefix}/feedback/reports/*/evidence`]: feedbackBudget.maxTransportBytes,
56
78
  [`${servConfig.http.apiPrefix}/feedback/reports/*/attachments/*`]: feedbackBudget.maxTransportBytes,
57
79
  [`${servConfig.http.apiPrefix}/feedback/reports/*/exports/*`]: feedbackBudget.maxTransportBytes,
58
80
  ...servConfig.transport.routePlaintextBytes,
59
81
  },
60
- {{else}} routePlaintextBytes: servConfig.transport.routePlaintextBytes,
61
- {{/if}}
62
- excludePaths: [...new Set([
63
- ...servConfig.transport.excludePaths,
64
- ...(servConfig.http.health ? [servConfig.http.health.path, servConfig.http.health.readyPath].filter((path): path is `/${string}` => Boolean(path)) : []),
65
- ...(servConfig.http.openapi && security.exposeApiDocs ? [servConfig.http.openapi.path] : []),
66
- ...(servConfig.http.docs && security.exposeApiDocs ? [servConfig.http.docs.path, `${servConfig.http.docs.path.slice(0, servConfig.http.docs.path.lastIndexOf('/') + 1)}_hai/scalar.js`] : []),
67
- ])],
82
+ {{else}}
83
+ routePlaintextBytes: servConfig.transport.routePlaintextBytes,
84
+ {{/if}}
85
+ excludePaths: [
86
+ ...new Set([
87
+ ...servConfig.transport.excludePaths,
88
+ ...(servConfig.http.health
89
+ ? [servConfig.http.health.path, servConfig.http.health.readyPath].filter((path): path is `/${string}` => Boolean(path))
90
+ : []),
91
+ ...(servConfig.http.openapi && security.exposeApiDocs
92
+ ? [servConfig.http.openapi.path]
93
+ : []),
94
+ ...(servConfig.http.docs && security.exposeApiDocs
95
+ ? [servConfig.http.docs.path, `${servConfig.http.docs.path.slice(0, servConfig.http.docs.path.lastIndexOf('/') + 1)}_hai/scalar.js`]
96
+ : []),
97
+ ]),
98
+ ],
68
99
  }
69
100
  }
70
- {{else}} const transport = undefined
101
+ {{else}}
102
+ const transport = undefined
71
103
  {{/if}}
72
104
  {{#if features.iam}}
73
105
  const refreshCookie = _options.refreshCookie === 'disabled'
74
106
  ? undefined
75
- : { secure: security.secureRefreshCookie, nativeTokenTransport: { isRequest: (request: Request) => request.headers.get('x-hai-token-transport') === 'body'
76
- && ['hai-mobile-app', 'hai-desktop-app'].includes(request.headers.get('x-request-client') ?? '')
77
- && security.isNativeOrigin(request.headers.get('origin') ?? '') } }
107
+ : {
108
+ secure: security.secureRefreshCookie,
109
+ nativeTokenTransport: {
110
+ isRequest: (request: Request) => request.headers.get('x-hai-token-transport') === 'body'
111
+ && ['hai-mobile-app', 'hai-desktop-app'].includes(request.headers.get('x-request-client') ?? '')
112
+ && security.isNativeOrigin(request.headers.get('origin') ?? ''),
113
+ },
114
+ }
78
115
  {{/if}}
79
116
  {{#if features.feedback}}
80
- // 普通业务日志与反馈使用同一可信应用范围;身份仍由 IAM 验证。
117
+ // 普通业务日志与反馈使用同一可信应用范围;身份仍由 IAM 验证。
81
118
  const authenticatedContext = serv.buildAuthContextFactory(token => iam.auth.verifyToken(token))
82
119
  const createContext: CreateServContext = async input => ({
83
120
  ...await authenticatedContext(input),
@@ -119,7 +156,9 @@ export function {{api.serviceAppFactoryName}}(_options: CreateApiServiceAppOptio
119
156
  middleware: serv.cors({
120
157
  origin: security.allowOrigin,
121
158
  credentials: servConfig.cors.credentials,
122
- allowedHeaders: [...new Set([...servConfig.cors.allowedHeaders, 'x-request-client', 'x-hai-token-transport'])],
159
+ allowedHeaders: [
160
+ ...new Set([...servConfig.cors.allowedHeaders, 'x-request-client', 'x-hai-token-transport']),
161
+ ],
123
162
  exposedHeaders: [...servConfig.cors.exposedHeaders],
124
163
  }),
125
164
  },
@@ -2,6 +2,5 @@
2
2
  {{#if features.feedback}}
3
3
  /** 当前应用编译时烘焙的产物身份;运行时配置不能覆盖。 */
4
4
  declare const __HAI_BUILD_METADATA__: { appVersion: string, buildId: string, commit: string }
5
-
6
5
  export const buildMetadata = __HAI_BUILD_METADATA__
7
6
  {{/if}}