@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
@@ -52,7 +52,10 @@ function startFeedback(): Promise<void> {
52
52
  feedbackClosing = false
53
53
  feedbackStarting = (async () => {
54
54
  try {
55
- const result = await feedback.init({ ...core.config.getOrThrow<import('@h-ai/feedback').FeedbackConfigInput>('feedback'), ...buildMetadata })
55
+ const result = await feedback.init({
56
+ ...core.config.getOrThrow<import('@h-ai/feedback').FeedbackConfigInput>('feedback'),
57
+ ...buildMetadata,
58
+ })
56
59
  if (!result.success) {
57
60
  if (feedbackFailure !== result.error.code)
58
61
  core.logger.warn('Optional feedback unavailable; business runtime remains ready', { module: 'feedback', code: result.error.code })
@@ -86,104 +89,174 @@ async function closeFeedback() {
86
89
  await feedbackStarting
87
90
  return feedback.close()
88
91
  }
89
-
90
92
  {{/if}}
91
93
 
92
94
  const runtime = core.module.createRuntime([
93
- { name: 'configuration', start: () => {
94
- core.init({
95
- configDir: './config',
96
- configSchemas: {
95
+ {
96
+ name: 'configuration',
97
+ start: () => {
98
+ core.init({
99
+ configDir: './config',
100
+ configSchemas: {
97
101
  {{#if features.ai}}
98
- ai: AIConfigSchema,
102
+ ai: AIConfigSchema,
99
103
  {{/if}}
100
104
  {{#if features.audit}}
101
- audit: AuditInitConfigSchema,
105
+ audit: AuditInitConfigSchema,
102
106
  {{/if}}
103
107
  {{#if features.cache}}
104
- cache: CacheConfigSchema,
108
+ cache: CacheConfigSchema,
105
109
  {{/if}}
106
110
  {{#if features.feedback}}
107
- feedback: FeedbackConfigSchema,
111
+ feedback: FeedbackConfigSchema,
108
112
  {{/if}}
109
113
  {{#if features.iam}}
110
- iam: IamConfigSchema,
114
+ iam: IamConfigSchema,
111
115
  {{/if}}
112
116
  {{#if features.reach}}
113
- reach: ReachConfigSchema,
117
+ reach: ReachConfigSchema,
114
118
  {{/if}}
115
119
  {{#if features.db}}
116
- db: ReldbConfigSchema,
120
+ db: ReldbConfigSchema,
117
121
  {{/if}}
118
122
  {{#if features.audit}}
119
123
  {{#if features.scheduler}}
120
- scheduler: SchedulerConfigSchema,
124
+ scheduler: SchedulerConfigSchema,
121
125
  {{/if}}
122
126
  {{/if}}
123
127
  {{#if features.storage}}
124
- storage: StorageConfigSchema,
128
+ storage: StorageConfigSchema,
125
129
  {{/if}}
126
130
  {{#if features.vecdb}}
127
- vecdb: VecdbConfigSchema,
131
+ vecdb: VecdbConfigSchema,
128
132
  {{/if}}
129
- },
130
- })
131
- }, close: () => {} },
133
+ },
134
+ })
135
+ },
136
+ close: () => { },
137
+ },
132
138
  {{#if features.db}}
133
- { name: 'reldb', start: async () => {
134
- const config = ReldbConfigSchema.parse(core.config.getOrThrow('db'))
135
- if (config.type === 'sqlite' && config.database !== ':memory:') {
136
- const { mkdir } = await import('node:fs/promises')
137
- const { dirname } = await import('node:path')
138
- await mkdir(dirname(config.database), { recursive: true })
139
- }
140
- return reldb.init(config)
141
- }, close: () => reldb.close() },
139
+ {
140
+ name: 'reldb',
141
+ start: async () => {
142
+ const config = ReldbConfigSchema.parse(core.config.getOrThrow('db'))
143
+ if (config.type === 'sqlite' && config.database !== ':memory:') {
144
+ const { mkdir } = await import('node:fs/promises')
145
+ const { dirname } = await import('node:path')
146
+ await mkdir(dirname(config.database), { recursive: true })
147
+ }
148
+ return reldb.init(config)
149
+ },
150
+ close: () => reldb.close(),
151
+ },
142
152
  {{/if}}
143
153
  {{#if features.cache}}
144
- { name: 'cache', start: () => cache.init(CacheConfigSchema.parse(core.config.getOrThrow('cache'))), close: () => cache.close() },
154
+ {
155
+ name: 'cache',
156
+ start: () => cache.init(CacheConfigSchema.parse(core.config.getOrThrow('cache'))),
157
+ close: () => cache.close(),
158
+ },
145
159
  {{/if}}
146
160
  {{#if features.vecdb}}
147
- { name: 'vecdb', start: () => vecdb.init(VecdbConfigSchema.parse(core.config.getOrThrow('vecdb'))), close: () => vecdb.close() },
161
+ {
162
+ name: 'vecdb',
163
+ start: () => vecdb.init(VecdbConfigSchema.parse(core.config.getOrThrow('vecdb'))),
164
+ close: () => vecdb.close(),
165
+ },
148
166
  {{/if}}
149
167
  {{#if features.crypto}}
150
- { name: 'crypto', start: () => crypto.init(), close: () => crypto.close() },
168
+ {
169
+ name: 'crypto',
170
+ start: () => crypto.init(),
171
+ close: () => crypto.close(),
172
+ },
151
173
  {{/if}}
152
174
  {{#if features.storage}}
153
- { name: 'storage', start: () => storage.init(StorageConfigSchema.parse(core.config.getOrThrow('storage'))), close: () => storage.close() },
175
+ {
176
+ name: 'storage',
177
+ start: () => storage.init(StorageConfigSchema.parse(core.config.getOrThrow('storage'))),
178
+ close: () => storage.close(),
179
+ },
154
180
  {{/if}}
155
181
  {{#if features.reach}}
156
- { name: 'reach', enabled: () => Boolean(core.config.get('reach')), start: () => reach.init(ReachConfigSchema.parse(core.config.getOrThrow('reach'))), close: () => reach.close() },
182
+ {
183
+ name: 'reach',
184
+ enabled: () => Boolean(core.config.get('reach')),
185
+ start: () => reach.init(ReachConfigSchema.parse(core.config.getOrThrow('reach'))),
186
+ close: () => reach.close(),
187
+ },
157
188
  {{/if}}
158
189
  {{#if features.audit}}
159
- { name: 'audit', start: () => audit.init({ ...AuditInitConfigSchema.parse(core.config.get('audit') ?? {}){{#if features.storage}}, storage{{/if}}{{#if features.reach}}, reach{{/if}} }), close: () => audit.close() },
190
+ {
191
+ name: 'audit',
192
+ start: () => audit.init({
193
+ ...AuditInitConfigSchema.parse(core.config.get('audit') ?? {}),
194
+ {{#if features.storage}}
195
+ storage,
196
+ {{/if}}
197
+ {{#if features.reach}}
198
+ reach,
199
+ {{/if}}
200
+ }),
201
+ close: () => audit.close(),
202
+ },
160
203
  {{/if}}
161
204
  {{#if features.iam}}
162
- { name: 'iam', start: () => iam.init({ ...IamConfigSchema.parse(core.config.getOrThrow('iam')){{#if features.reach}}, reach{{/if}} }), close: () => iam.close() },
205
+ {
206
+ name: 'iam',
207
+ start: () => iam.init({
208
+ ...IamConfigSchema.parse(core.config.getOrThrow('iam')),
209
+ {{#if features.reach}}
210
+ reach,
211
+ {{/if}}
212
+ }),
213
+ close: () => iam.close(),
214
+ },
163
215
  {{/if}}
164
216
  {{#if features.audit}}
165
217
  {{#if features.scheduler}}
166
- { name: 'audit-jobs', enabled: () => Boolean(audit.schedulerPlan), start: async () => {
167
- const schedule = audit.schedulerPlan
168
- if (!schedule)
169
- return
170
- const initialized = await scheduler.init({ ...SchedulerConfigSchema.parse(core.config.get('scheduler') ?? {}), ...schedule })
171
- if (!initialized.success)
172
- return initialized
173
- const started = scheduler.start()
174
- if (!started.success)
175
- await scheduler.close()
176
- return started
177
- }, close: () => scheduler.close() },
218
+ {
219
+ name: 'audit-jobs',
220
+ enabled: () => Boolean(audit.schedulerPlan),
221
+ start: async () => {
222
+ const schedule = audit.schedulerPlan
223
+ if (!schedule)
224
+ return
225
+ const initialized = await scheduler.init({
226
+ ...SchedulerConfigSchema.parse(core.config.get('scheduler') ?? {}),
227
+ ...schedule,
228
+ })
229
+ if (!initialized.success)
230
+ return initialized
231
+ const started = scheduler.start()
232
+ if (!started.success)
233
+ await scheduler.close()
234
+ return started
235
+ },
236
+ close: () => scheduler.close(),
237
+ },
178
238
  {{/if}}
179
239
  {{/if}}
180
240
  {{#if features.feedback}}
181
- { name: 'feedback', enabled: () => Boolean(core.config.get('feedback')), start: startFeedback, close: closeFeedback },
241
+ {
242
+ name: 'feedback',
243
+ enabled: () => Boolean(core.config.get('feedback')),
244
+ start: startFeedback,
245
+ close: closeFeedback,
246
+ },
182
247
  {{/if}}
183
248
  {{#if features.ai}}
184
- { name: 'ai', start: () => ai.init(AIConfigSchema.parse(core.config.getOrThrow('ai'))), close: () => ai.close() },
185
- {{/if}}
186
- { name: 'bootstrap', start: () => { core.logger.info('Application initialized') }, close: () => {} },
249
+ {
250
+ name: 'ai',
251
+ start: () => ai.init(AIConfigSchema.parse(core.config.getOrThrow('ai'))),
252
+ close: () => ai.close(),
253
+ },
254
+ {{/if}}
255
+ {
256
+ name: 'bootstrap',
257
+ start: () => { core.logger.info('Application initialized') },
258
+ close: () => { },
259
+ },
187
260
  ])
188
261
 
189
262
  /** 启动失败只报告模块、错误码和配置路径,私密值不进入错误上下文。 */
@@ -1,7 +1,7 @@
1
1
  {{! @skipIfEmpty }}
2
2
  {{#unless isSvelteOnlyApp}}
3
3
  import type { KitConfig } from '@h-ai/kit'
4
- import { base } from '$app/paths'
4
+ import { resolve } from '$app/paths'
5
5
  import { core } from '@h-ai/core'
6
6
  import { KitConfigSchema } from '@h-ai/kit'
7
7
 
@@ -9,9 +9,9 @@ let configured: KitConfig | undefined
9
9
 
10
10
  /** 输入已由 Schema 校验为绝对路径;宿主补构建目录并保留绝对路径类型。 */
11
11
  function mounted(path: string): `/${string}` {
12
- if (!base || path === base || path.startsWith(`${base}/`))
12
+ if (!resolve('/').replace(/\/$/, '') || path === resolve('/').replace(/\/$/, '') || path.startsWith(`${resolve('/').replace(/\/$/, '')}/`))
13
13
  return `/${path.slice(1)}`
14
- return `/${base.slice(1)}${path}`
14
+ return `/${resolve('/').replace(/\/$/, '').slice(1)}${path}`
15
15
  }
16
16
 
17
17
  /** 启动时固定服务端配置;浏览器只能接收根 load 明确投影的 transport。 */
@@ -31,7 +31,10 @@ export function getKitConfig(): KitConfig {
31
31
  keyExchangePath: mounted(transport.keyExchangePath),
32
32
  excludePaths: transport.excludePaths.map(mounted),
33
33
  routePlaintextBytes: transport.routePlaintextBytes
34
- ? Object.fromEntries(Object.entries(transport.routePlaintextBytes).map(([path, bytes]) => [mounted(path), bytes]))
34
+ ? Object.fromEntries(Object.entries(transport.routePlaintextBytes).map(([path, bytes]) => [
35
+ mounted(path),
36
+ bytes,
37
+ ]))
35
38
  : undefined,
36
39
  },
37
40
  }
@@ -2,12 +2,12 @@
2
2
  {{#unless isSvelteOnlyApp}}
3
3
  import type { CoreConfig } from '@h-ai/core'
4
4
  import type { KitPublicConfig } from '@h-ai/kit'
5
- import { getKitConfig } from '$lib/server/kit-config.js'
6
5
  import { core } from '@h-ai/core'
7
6
  {{#if features.iam}}
8
7
  import { iam } from '@h-ai/iam'
9
8
  import { error } from '@sveltejs/kit'
10
9
  {{/if}}
10
+ import { getKitConfig } from '#lib/server/kit-config.js'
11
11
 
12
12
  /** 只向浏览器提供公开配置,避免暴露日志上下文、凭证或其它模块配置。 */
13
13
  export async function load() {
@@ -16,7 +16,7 @@ export async function load() {
16
16
  const publicConfig = await iam.getPublicConfig()
17
17
  if (!publicConfig.success) {
18
18
  core.logger.error('Failed to load public authentication configuration', { error: publicConfig.error })
19
- error(503, { message: core.error.toPublic(publicConfig.error).message })
19
+ error(503, core.error.toPublic(publicConfig.error).message)
20
20
  }
21
21
  {{/if}}
22
22
  return {
@@ -1,109 +1,19 @@
1
- /**
2
- * Svelte 配置
3
- */
4
- {{#unless isSvelteOnlyApp}}
5
- import process from 'node:process'
6
- {{/unless}}
1
+ {{! @skipIfEmpty }}
2
+ {{#if isSvelteOnlyApp}}
3
+ /** Svelte + Vite 客户端的预处理配置;SvelteKit 配置统一在 vite.config.ts。 */
7
4
  {{#if hasUi}}
8
5
  import { autoImportHaiUi } from '@h-ai/ui/auto-import'
9
6
  {{/if}}
10
- {{#unless isSvelteOnlyApp}}
11
- import adapter from '@sveltejs/adapter-node'
12
- {{#if_eq appType 'website'}}
13
- import staticAdapter from '@sveltejs/adapter-static'
14
- {{/if_eq}}
15
- {{/unless}}
16
7
  import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
17
- {{#unless isSvelteOnlyApp}}
18
- import { resolvePublicBasePath } from './scripts/public-base-path.mjs'
19
- {{/unless}}
20
- {{#if_eq appType 'website'}}
21
- import { resolveStaticWebsite, validateStaticRoutes } from './scripts/static-website.mjs'
22
-
23
- const website = resolveStaticWebsite()
24
- const staticOutput = staticAdapter({ strict: false })
25
- {{/if_eq}}
26
8
 
27
- {{#if isSvelteOnlyApp}}
28
9
  /** @type {import('@sveltejs/vite-plugin-svelte').SvelteConfig} */
29
- const config = {
30
- preprocess: [{{#if hasUi}}autoImportHaiUi(), {{/if}}vitePreprocess()],
31
- compilerOptions: {
32
- runes: true,
33
- },
34
- }
35
- {{else}}
36
- const DEFAULT_E2E_ORIGINS = ['http://localhost:4173', 'http://127.0.0.1:4173']
37
-
38
- function resolveTrustedOrigins() {
39
- if (process.env.HAI_E2E !== '1')
40
- return []
41
-
42
- const rawBaseUrl = process.env.BASE_URL ?? DEFAULT_E2E_ORIGINS[0]
43
-
44
- try {
45
- const url = new URL(rawBaseUrl)
46
- const origins = new Set([url.origin])
47
-
48
- if (url.hostname === 'localhost') {
49
- url.hostname = '127.0.0.1'
50
- origins.add(url.origin)
51
- }
52
- else if (url.hostname === '127.0.0.1') {
53
- url.hostname = 'localhost'
54
- origins.add(url.origin)
55
- }
56
-
57
- return [...origins]
58
- }
59
- catch {
60
- return DEFAULT_E2E_ORIGINS
61
- }
62
- }
63
-
64
- /** @type {import('@sveltejs/kit').Config} */
65
- const config = {
66
- preprocess: [{{#if hasUi}}autoImportHaiUi(), {{/if}}vitePreprocess()],
67
- compilerOptions: {
68
- runes: true,
69
- },
70
- kit: {
71
- // 环境文件由 Vite 的 core loader 统一加载;Kit 不再二次读取根目录私有配置。
72
- env: { dir: './.svelte-kit' },
73
- paths: { base: resolvePublicBasePath() },
74
- {{#if isCapacitorApp}}
75
- adapter: adapter({
76
- pages: 'build',
77
- assets: 'build',
78
- fallback: 'index.html',
79
- }),
80
- {{else}}
81
- {{#if_eq appType 'website'}}
82
- adapter: website.enabled
83
- ? {
84
- ...staticOutput,
85
- name: 'hai-static-website',
86
- async adapt(builder) {
87
- // 仅省略模板健康端点;自定义API或未预渲染页面明确失败,不用SPA回退掩盖。
88
- validateStaticRoutes(builder.routes)
89
- await staticOutput.adapt(builder)
90
- },
91
- }
92
- : adapter(),
93
- {{else}}
94
- adapter: adapter(),
95
- {{/if_eq}}
10
+ export default {
11
+ preprocess: [
12
+ vitePreprocess(),
13
+ {{#if hasUi}}
14
+ autoImportHaiUi(),
96
15
  {{/if}}
97
- csrf: {
98
- trustedOrigins: resolveTrustedOrigins(),
99
- },
100
- alias: {
101
- $components: './src/lib/components',
102
- $stores: './src/lib/stores',
103
- $utils: './src/lib/utils',
104
- },
105
- },
16
+ ],
17
+ compilerOptions: { runes: true },
106
18
  }
107
19
  {{/if}}
108
-
109
- export default config
@@ -39,7 +39,6 @@ describe('generated scaffold', () => {
39
39
  expect(pkg.scripts.test).toBeDefined()
40
40
  expect(pkg.scripts['test:e2e']).toBeDefined()
41
41
  })
42
-
43
42
  {{#if isSvelteOnlyApp}}
44
43
  it('renders the Vite app shell entry', async () => {
45
44
  const indexHtml = await readFile(join(rootDir, 'index.html'), 'utf-8')
@@ -83,7 +82,12 @@ describe('generated scaffold', () => {
83
82
  expect(await load()).toEqual({
84
83
  kitConfig: { transport: getKitConfig().transport },
85
84
  iamPublicConfig: publicConfig.data,
86
- appConfig: { name: config.name, version: config.version, env: config.env, defaultLocale: config.defaultLocale },
85
+ appConfig: {
86
+ name: config.name,
87
+ version: config.version,
88
+ env: config.env,
89
+ defaultLocale: config.defaultLocale,
90
+ },
87
91
  })
88
92
  }
89
93
  finally {
@@ -94,7 +98,12 @@ describe('generated scaffold', () => {
94
98
  {{else}}
95
99
  expect(await load()).toEqual({
96
100
  kitConfig: { transport: getKitConfig().transport },
97
- appConfig: { name: config.name, version: config.version, env: config.env, defaultLocale: config.defaultLocale },
101
+ appConfig: {
102
+ name: config.name,
103
+ version: config.version,
104
+ env: config.env,
105
+ defaultLocale: config.defaultLocale,
106
+ },
98
107
  })
99
108
  {{/if}}
100
109
  })
@@ -28,7 +28,7 @@
28
28
  }
29
29
  {{else}}
30
30
  {
31
- "extends": "./.svelte-kit/tsconfig.json",
31
+ "extends": "$app/tsconfig",
32
32
  "compilerOptions": {
33
33
  "moduleResolution": "bundler",
34
34
  "allowImportingTsExtensions": true,
@@ -39,12 +39,15 @@
39
39
  "skipLibCheck": true
40
40
  },
41
41
  "include": [
42
- "src/**/*",
43
- "src/**/*.svelte"
42
+ "src",
43
+ "tests",
44
+ "*.ts",
45
+ "*.js"
44
46
  ],
45
47
  "exclude": [
46
48
  "node_modules",
47
- ".svelte-kit"
49
+ "build",
50
+ "src/service-worker"
48
51
  ]
49
52
  }
50
53
  {{/if}}
@@ -10,6 +10,9 @@ import process from 'node:process'
10
10
  import { fileURLToPath } from 'node:url'
11
11
  import { core } from '@h-ai/core'
12
12
  {{#if hasUi}}
13
+ {{#unless isSvelteOnlyApp}}
14
+ import { autoImportHaiUi } from '@h-ai/ui/auto-import'
15
+ {{/unless}}
13
16
  import { haiOptimizeExclude, haiPrebundledDeps } from '@h-ai/ui/vite'
14
17
  {{/if}}
15
18
  {{#if hasI18n}}
@@ -18,26 +21,66 @@ import { paraglideVitePlugin } from '@inlang/paraglide-js'
18
21
  {{#if isSvelteOnlyApp}}
19
22
  import { svelte } from '@sveltejs/vite-plugin-svelte'
20
23
  {{else}}
24
+ import adapter from '@sveltejs/adapter-node'
25
+ {{#if_eq appType 'website'}}
26
+ import staticAdapter from '@sveltejs/adapter-static'
27
+ {{/if_eq}}
21
28
  import { sveltekit } from '@sveltejs/kit/vite'
29
+ import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
22
30
  {{/if}}
23
31
  {{#if hasUi}}
24
32
  import tailwindcss from '@tailwindcss/vite'
25
33
  {{/if}}
26
34
  import { defineConfig } from 'vite'
27
35
  import { resolveBuildMetadata } from './scripts/build-metadata.js'
36
+ import { resolvePublicBasePath } from './scripts/public-base-path.mjs'
28
37
  {{#if_eq appType 'website'}}
29
- import { resolveStaticWebsite } from './scripts/static-website.mjs'
38
+ import { resolveStaticWebsite, validateStaticRoutes } from './scripts/static-website.mjs'
30
39
  {{/if_eq}}
31
40
  {{#if isSvelteOnlyApp}}
32
- import { resolvePublicBasePath } from './scripts/public-base-path.mjs'
33
41
  import { publicRuntimeConfig } from './scripts/vite-runtime-config.js'
34
42
  {{/if}}
35
43
 
44
+ {{#unless isSvelteOnlyApp}}
45
+ const DEFAULT_E2E_ORIGINS = ['http://localhost:4173', 'http://127.0.0.1:4173']
46
+
47
+ function resolveTrustedOrigins() {
48
+ if (process.env.HAI_E2E !== '1')
49
+ return []
50
+
51
+ const rawBaseUrl = process.env.BASE_URL ?? DEFAULT_E2E_ORIGINS[0]
52
+
53
+ try {
54
+ const url = new URL(rawBaseUrl)
55
+ const origins = new Set([url.origin])
56
+
57
+ if (url.hostname === 'localhost') {
58
+ url.hostname = '127.0.0.1'
59
+ origins.add(url.origin)
60
+ }
61
+ else if (url.hostname === '127.0.0.1') {
62
+ url.hostname = 'localhost'
63
+ origins.add(url.origin)
64
+ }
65
+
66
+ return [...origins]
67
+ }
68
+ catch {
69
+ return DEFAULT_E2E_ORIGINS
70
+ }
71
+ }
72
+ {{/unless}}
36
73
  export default defineConfig(({ mode, command }) => {
37
74
  {{#if_eq appType 'website'}}
38
75
  const website = resolveStaticWebsite()
76
+ const staticOutput = staticAdapter({ strict: false })
39
77
  {{/if_eq}}
40
- const envResult = command === 'build' || process.env.HAI_E2E === '1'{{#if_eq appType 'website'}} || website.enabled{{/if_eq}} ? { success: true as const, data: {} as Record<string, string> } : core.config.loadEnvFiles({ mode, envDir: process.cwd() })
78
+ const envResult = command === 'build' || process.env.HAI_E2E === '1'{{#if_eq appType 'website'}} || website.enabled{{/if_eq}}
79
+ ? { success: true as const, data: {} as Record<string, string> }
80
+ : core.config.loadEnvFiles({
81
+ mode,
82
+ envDir: process.cwd(),
83
+ })
41
84
  if (!envResult.success)
42
85
  throw new Error(envResult.error.message)
43
86
  const env = envResult.data
@@ -46,7 +89,11 @@ export default defineConfig(({ mode, command }) => {
46
89
  const metadataAsset: Plugin = {
47
90
  name: 'hai-build-metadata',
48
91
  generateBundle() {
49
- this.emitFile({ type: 'asset', fileName: 'build-metadata.json', source: JSON.stringify(buildMetadata) })
92
+ this.emitFile({
93
+ type: 'asset',
94
+ fileName: 'build-metadata.json',
95
+ source: JSON.stringify(buildMetadata),
96
+ })
50
97
  },
51
98
  }
52
99
  {{#if isSvelteOnlyApp}}
@@ -58,14 +105,18 @@ export default defineConfig(({ mode, command }) => {
58
105
  version: config.version,
59
106
  env: config.env,
60
107
  defaultLocale: config.defaultLocale,
61
- logging: config.logging ? { level: config.logging.level, format: config.logging.format } : undefined,
108
+ logging: config.logging
109
+ ? { level: config.logging.level, format: config.logging.format }
110
+ : undefined,
62
111
  }
63
112
  const publicBase = resolvePublicBasePath()
64
113
  {{/if}}
65
114
 
66
115
  return {
67
116
  {{#if isSvelteOnlyApp}}
68
- base: publicBase ? `${publicBase}/` : './',
117
+ base: publicBase
118
+ ? `${publicBase}/`
119
+ : './',
69
120
  {{/if}}
70
121
  envDir: false,
71
122
  envPrefix: ['VITE_', 'PUBLIC_'],
@@ -90,17 +141,58 @@ export default defineConfig(({ mode, command }) => {
90
141
  },
91
142
  },
92
143
  {{/if_eq}}
93
- {{#if isSvelteOnlyApp}}
94
- publicRuntimeConfig({ apiBase: process.env.PUBLIC_API_BASE, {{#if features.crypto}}apiTransport: process.env.PUBLIC_API_TRANSPORT, apiKeyExchangePath: process.env.PUBLIC_API_KEY_EXCHANGE_PATH, {{/if}}core: appConfig }),
144
+ {{#if isSvelteOnlyApp}}
145
+ publicRuntimeConfig({
146
+ apiBase: process.env.PUBLIC_API_BASE,
147
+ {{#if features.crypto}}
148
+ apiTransport: process.env.PUBLIC_API_TRANSPORT,
149
+ apiKeyExchangePath: process.env.PUBLIC_API_KEY_EXCHANGE_PATH,
150
+ {{/if}}
151
+ core: appConfig,
152
+ }),
95
153
  svelte(),
96
- {{else}}
97
- sveltekit(),
98
- {{/if}}
154
+ {{else}}
155
+ sveltekit({
156
+ preprocess: [
157
+ vitePreprocess(),
158
+ {{#if hasUi}}
159
+ autoImportHaiUi(),
160
+ {{/if}}
161
+ ],
162
+ compilerOptions: { runes: true },
163
+ // Core 统一加载环境文件;SSR 路径固定为绝对前缀供 HTTP/加密管道使用。
164
+ env: { dir: './.svelte-kit' },
165
+ paths: {
166
+ base: resolvePublicBasePath(),
167
+ relative: false,
168
+ },
169
+ {{#if_eq appType 'website'}}
170
+ adapter: website.enabled
171
+ ? {
172
+ ...staticOutput,
173
+ name: 'hai-static-website',
174
+ async adapt(builder) {
175
+ // 仅省略模板健康端点,自定义 API 或未预渲染页面仍须明确失败。
176
+ validateStaticRoutes(builder.routes)
177
+ await staticOutput.adapt(builder)
178
+ },
179
+ }
180
+ : adapter(),
181
+ {{else}}
182
+ adapter: adapter(),
183
+ {{/if_eq}}
184
+ csrf: {
185
+ trustedOrigins: resolveTrustedOrigins(),
186
+ },
187
+ }),
188
+ {{/if}}
99
189
  {{#if hasUi}}
100
190
  tailwindcss(),
101
191
  {{/if}}
102
192
  {{#if hasI18n}}
103
193
  paraglideVitePlugin({
194
+ // 共享物理消息产物供独立 Vitest/Node 工具读取。
195
+ outputStructure: 'message-modules',
104
196
  project: './project.inlang',
105
197
  outdir: './src/lib/paraglide',
106
198
  strategy: ['cookie', 'baseLocale'],
@@ -109,8 +201,8 @@ export default defineConfig(({ mode, command }) => {
109
201
  ],
110
202
  {{#if hasUi}}
111
203
  optimizeDeps: {
112
- // bits-ui 含 .svelte 源码须 exclude;@internationalized/date 须与 bits-ui 同为原始副本,
113
- // 避免日期类型 instanceof 失败("Unknown date type")。
204
+ // bits-ui 含 .svelte 源码须 exclude;@internationalized/date 须与 bits-ui 同为原始副本,
205
+ // 避免日期类型 instanceof 失败("Unknown date type")。
114
206
  exclude: [...haiOptimizeExclude],
115
207
  // 预打包 @h-ai/ui 的重型纯 JS 依赖,避免首次进入业务路由触发依赖再优化与整页刷新
116
208
  include: [...haiPrebundledDeps],
@@ -125,7 +217,9 @@ export default defineConfig(({ mode, command }) => {
125
217
  {{/unless}}
126
218
  server: {
127
219
  fs: {
128
- allow: [path.resolve(process.cwd())],
220
+ allow: [
221
+ path.resolve(process.cwd()),
222
+ ],
129
223
  },
130
224
  },
131
225
  }