@h-ai/cli 0.1.0-alpha.16 → 0.1.0-alpha.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 (134) hide show
  1. package/dist/{chunk-LANIDJC7.js → chunk-BPO34NRL.js} +3 -3
  2. package/dist/chunk-BPO34NRL.js.map +1 -0
  3. package/dist/{chunk-YV7WPUI6.js → chunk-GSMXGUYF.js} +6 -2
  4. package/dist/chunk-GSMXGUYF.js.map +1 -0
  5. package/dist/cli-config-templates-JCS7T3NU.js +5 -0
  6. package/dist/cli-config-templates-JCS7T3NU.js.map +1 -0
  7. package/dist/cli-skill-templates-IMYZPQRG.js +5 -0
  8. package/dist/cli-skill-templates-IMYZPQRG.js.map +1 -0
  9. package/dist/index.js +391 -58
  10. package/dist/index.js.map +1 -1
  11. package/dist/{src-RZ4DPYNJ.js → src-N4NPS7AG.js} +1239 -493
  12. package/dist/src-N4NPS7AG.js.map +1 -0
  13. package/package.json +8 -7
  14. package/templates/README.md +10 -3
  15. package/templates/apps/android-app/src/lib/api.ts.hbs +1 -1
  16. package/templates/apps/api/tests/health.test.ts.hbs +26 -0
  17. package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +21 -0
  18. package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +23 -0
  19. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +34 -0
  20. package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +34 -0
  21. package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +50 -0
  22. package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
  23. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +18 -0
  24. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +9 -0
  25. package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +14 -0
  26. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +18 -0
  27. package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +162 -0
  28. package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +20 -0
  29. package/templates/apps/fullstack/apps/{{projectName}}-app/tests/api.test.ts.hbs +28 -0
  30. package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +17 -0
  31. package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +29 -0
  32. package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +21 -0
  33. package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +23 -0
  34. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +34 -0
  35. package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +34 -0
  36. package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +50 -0
  37. package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
  38. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
  39. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +9 -0
  40. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +14 -0
  41. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +18 -0
  42. package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +162 -0
  43. package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +20 -0
  44. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tests/api.test.ts.hbs +28 -0
  45. package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +17 -0
  46. package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +29 -0
  47. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +13 -0
  48. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
  49. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
  50. package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
  51. package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +21 -0
  52. package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +23 -0
  53. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +34 -0
  54. package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +34 -0
  55. package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +50 -0
  56. package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
  57. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
  58. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +9 -0
  59. package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +14 -0
  60. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +18 -0
  61. package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +162 -0
  62. package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +20 -0
  63. package/templates/apps/fullstack/apps/{{projectName}}-web/tests/api.test.ts.hbs +28 -0
  64. package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +17 -0
  65. package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +29 -0
  66. package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +30 -0
  67. package/templates/apps/fullstack/eslint.config.js +44 -0
  68. package/templates/apps/fullstack/package.json.hbs +42 -0
  69. package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +15 -0
  70. package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +27 -0
  71. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +21 -0
  72. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-routes.ts.hbs +27 -0
  73. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +34 -0
  74. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +4 -0
  75. package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +9 -0
  76. package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +48 -0
  77. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
  78. package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
  79. package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +14 -0
  80. package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +29 -0
  81. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +15 -0
  82. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +38 -0
  83. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +13 -0
  84. package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server-app.ts.hbs +42 -0
  85. package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/server-app.test.ts.hbs +49 -0
  86. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
  87. package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +9 -0
  88. package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +3 -0
  89. package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +39 -0
  90. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +24 -0
  91. package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +24 -0
  92. package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +44 -0
  93. package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
  94. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +8 -0
  95. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +49 -0
  96. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +60 -0
  97. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/LanguageSwitcher.svelte.hbs +27 -0
  98. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +18 -0
  99. package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme.svelte.ts.hbs +55 -0
  100. package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
  101. package/templates/apps/fullstack/playwright.config.ts.hbs +34 -0
  102. package/templates/apps/fullstack/pnpm-workspace.yaml +7 -0
  103. package/templates/apps/fullstack/tsconfig.base.json +15 -0
  104. package/templates/base/e2e/app.spec.ts.hbs +7 -0
  105. package/templates/base/eslint.config.js +6 -0
  106. package/templates/base/package.json.hbs +46 -39
  107. package/templates/base/src/app.css.hbs +1 -0
  108. package/templates/base/src/lib/server/init.ts.hbs +3 -3
  109. package/templates/base/tests/scaffold.test.ts.hbs +27 -0
  110. package/templates/features/payment/routes/api/v1/payment/create/+server.ts +15 -7
  111. package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +1 -2
  112. package/templates/skills/hai-ai/SKILL.md +2 -0
  113. package/templates/skills/hai-api-client/SKILL.md +4 -0
  114. package/templates/skills/hai-audit/SKILL.md +7 -2
  115. package/templates/skills/hai-cache/SKILL.md +2 -0
  116. package/templates/skills/hai-capacitor/SKILL.md +11 -9
  117. package/templates/skills/hai-core/SKILL.md +4 -1
  118. package/templates/skills/hai-crypto/SKILL.md +42 -8
  119. package/templates/skills/hai-iam/SKILL.md +2 -0
  120. package/templates/skills/hai-kit/SKILL.md +9 -2
  121. package/templates/skills/hai-payment/SKILL.md +5 -0
  122. package/templates/skills/hai-reach/SKILL.md +3 -1
  123. package/templates/skills/hai-reldb/SKILL.md +2 -0
  124. package/templates/skills/hai-scheduler/SKILL.md +2 -0
  125. package/templates/skills/hai-serv/SKILL.md +14 -9
  126. package/templates/skills/hai-storage/SKILL.md +10 -1
  127. package/templates/skills/hai-vecdb/SKILL.md +8 -1
  128. package/dist/chunk-LANIDJC7.js.map +0 -1
  129. package/dist/chunk-YV7WPUI6.js.map +0 -1
  130. package/dist/config-templates-S5RI2MC6.js +0 -5
  131. package/dist/config-templates-S5RI2MC6.js.map +0 -1
  132. package/dist/skill-templates-N5DU5FNX.js +0 -5
  133. package/dist/skill-templates-N5DU5FNX.js.map +0 -1
  134. package/dist/src-RZ4DPYNJ.js.map +0 -1
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import * as m from '../paraglide/messages.js'
3
+ import { AVAILABLE_THEMES, themeStore } from '../stores/theme.svelte.js'
4
+
5
+ function handleChange(event: Event) {
6
+ const target = event.target as HTMLSelectElement
7
+ themeStore.set(target.value)
8
+ }
9
+ </script>
10
+
11
+ <label class="form-control w-32 sm:w-40">
12
+ <span class="label-text text-xs">{m.settings_theme()}</span>
13
+ <select class="select select-bordered select-sm bg-base-100/80" value={themeStore.current} onchange={handleChange}>
14
+ {#each AVAILABLE_THEMES as theme (theme)}
15
+ <option value={theme}>{theme}</option>
16
+ {/each}
17
+ </select>
18
+ </label>
@@ -0,0 +1,55 @@
1
+ {{!-- Shared theme store for {{projectName}} fullstack apps. --}}
2
+ const STORAGE_KEY = 'hai-theme'
3
+ const DEFAULT_THEME = '{{fullstack.theme.defaultTheme}}'
4
+ export const AVAILABLE_THEMES: readonly string[] = [{{#each fullstack.theme.themes}}'{{this}}'{{#unless @last}}, {{/unless}}{{/each}}]
5
+
6
+ function isBrowser(): boolean {
7
+ return typeof window !== 'undefined' && typeof document !== 'undefined'
8
+ }
9
+
10
+ function readInitialTheme(): string {
11
+ if (!isBrowser())
12
+ return DEFAULT_THEME
13
+ try {
14
+ const stored = window.localStorage.getItem(STORAGE_KEY)
15
+ if (stored && AVAILABLE_THEMES.includes(stored))
16
+ return stored
17
+ }
18
+ catch {
19
+ // localStorage 不可用时(隐私模式 / SSR),回退到默认主题
20
+ }
21
+ return DEFAULT_THEME
22
+ }
23
+
24
+ class ThemeState {
25
+ current = $state<string>(DEFAULT_THEME)
26
+
27
+ constructor() {
28
+ this.current = readInitialTheme()
29
+ if (isBrowser())
30
+ this.apply(this.current)
31
+ }
32
+
33
+ set(value: string): void {
34
+ if (!AVAILABLE_THEMES.includes(value))
35
+ return
36
+ this.current = value
37
+ this.apply(value)
38
+ if (isBrowser()) {
39
+ try {
40
+ window.localStorage.setItem(STORAGE_KEY, value)
41
+ }
42
+ catch {
43
+ // 忽略 localStorage 写入失败
44
+ }
45
+ }
46
+ }
47
+
48
+ private apply(value: string): void {
49
+ if (!isBrowser())
50
+ return
51
+ document.documentElement.dataset.theme = value
52
+ }
53
+ }
54
+
55
+ export const themeStore = new ThemeState()
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "allowImportingTsExtensions": true,
5
+ "allowJs": true,
6
+ "checkJs": false,
7
+ "module": "ESNext",
8
+ "moduleResolution": "bundler",
9
+ "noEmit": true,
10
+ "skipLibCheck": true,
11
+ "strict": true,
12
+ "types": ["svelte"],
13
+ "verbatimModuleSyntax": true
14
+ },
15
+ "include": ["src/**/*", "src/**/*.svelte"],
16
+ "exclude": ["node_modules", "src/lib/paraglide"]
17
+ }
@@ -0,0 +1,34 @@
1
+ import process from 'node:process'
2
+ import { defineConfig } from '@playwright/test'
3
+
4
+ export default defineConfig({
5
+ testDir: './e2e',
6
+ fullyParallel: false,
7
+ forbidOnly: !!process.env.CI,
8
+ retries: process.env.CI ? 2 : 0,
9
+ workers: 1,
10
+ reporter: 'list',
11
+ timeout: 30_000,
12
+ use: {
13
+ baseURL: '{{#if fullstack.e2eFrontend}}http://127.0.0.1:{{fullstack.e2eFrontend.port}}{{else}}http://127.0.0.1:3000{{/if}}',
14
+ channel: 'chrome',
15
+ trace: 'on-first-retry',
16
+ screenshot: 'only-on-failure',
17
+ },
18
+ webServer: [
19
+ {
20
+ name: '{{fullstack.servPackageName}}',
21
+ command: 'pnpm --filter {{fullstack.servPackageName}} start',
22
+ url: 'http://127.0.0.1:3000/health',
23
+ reuseExistingServer: false,
24
+ timeout: 120_000,
25
+ }{{#if fullstack.e2eFrontend}},
26
+ {
27
+ name: '{{fullstack.e2eFrontend.packageName}}',
28
+ command: 'pnpm --filter {{fullstack.e2eFrontend.packageName}} preview',
29
+ url: 'http://127.0.0.1:{{fullstack.e2eFrontend.port}}',
30
+ reuseExistingServer: false,
31
+ timeout: 120_000,
32
+ }{{/if}},
33
+ ],
34
+ })
@@ -0,0 +1,7 @@
1
+ shellEmulator: true
2
+
3
+ trustPolicy: no-downgrade
4
+
5
+ packages:
6
+ - 'packages/*'
7
+ - 'apps/*'
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "ignoreDeprecations": "6.0",
7
+ "resolveJsonModule": true,
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "isolatedModules": true,
12
+ "verbatimModuleSyntax": true,
13
+ "skipLibCheck": true
14
+ }
15
+ }
@@ -0,0 +1,7 @@
1
+ import { expect, test } from '@playwright/test'
2
+
3
+ /** 首页从真实浏览器页面发起,覆盖基础渲染链路。 */
4
+ test('home page renders from browser', async ({ page }) => {
5
+ await page.goto('/')
6
+ await expect(page.locator('main, section').first()).toBeVisible()
7
+ })
@@ -15,6 +15,12 @@ export default antfu({
15
15
  '**/project.inlang/**',
16
16
  '**/paraglide/**',
17
17
  '**/.agents/**',
18
+ '**/.github/**',
19
+ '**/AGENTS.md',
20
+ '**/CLAUDE.md',
21
+ '**/README.md',
22
+ '**/opencode.json',
23
+ '**/package.json',
18
24
  ],
19
25
  svelte: true,
20
26
  }, {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "{{projectName}}",
3
- "version": "0.1.0-alpha.16",
3
+ "version": "0.1.0-alpha.19",
4
4
  "private": true,
5
5
  "description": "{{#if_eq appType 'admin'}}Enterprise management system built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'website'}}Enterprise website built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'h5'}}Mobile H5 app built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'api'}}REST API service built with hai Agent Framework{{/if_eq}}{{#if_eq appType 'android-app'}}Android app built with hai Agent Framework{{/if_eq}}",
6
6
  "keywords": ["hai", "sveltekit", "svelte5", "{{appType}}"],
@@ -14,6 +14,7 @@
14
14
  "build": "vite build",
15
15
  "preview": "vite preview",
16
16
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
17
+ "typecheck": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
17
18
  "lint": "eslint .",
18
19
  "test": "vitest run",
19
20
  "test:watch": "vitest",
@@ -21,34 +22,36 @@
21
22
  "clean": "rimraf .svelte-kit build .turbo"
22
23
  },
23
24
  "dependencies": {
24
- "@h-ai/core": "^0.1.0-alpha.16",
25
- "@h-ai/kit": "^0.1.0-alpha.16"{{#if hasUi}},
26
- "@h-ai/ui": "^0.1.0-alpha.16"{{/if}}{{#if features.db}},
27
- "@h-ai/reldb": "^0.1.0-alpha.16"{{/if}}{{#if features.cache}},
28
- "@h-ai/cache": "^0.1.0-alpha.16"{{/if}}{{#if features.iam}},
29
- "@h-ai/iam": "^0.1.0-alpha.16"{{/if}}{{#if features.crypto}},
30
- "@h-ai/crypto": "^0.1.0-alpha.16"{{/if}}{{#if features.storage}},
31
- "@h-ai/storage": "^0.1.0-alpha.16"{{/if}}{{#if features.ai}},
32
- "@h-ai/ai": "^0.1.0-alpha.16"{{/if}}{{#if features.audit}},
33
- "@h-ai/audit": "^0.1.0-alpha.16"{{/if}}{{#if features.reach}},
34
- "@h-ai/reach": "^0.1.0-alpha.16"{{/if}}{{#if features.payment}},
35
- "@h-ai/payment": "^0.1.0-alpha.16"{{/if}}{{#if features.vecdb}},
36
- "@h-ai/vecdb": "^0.1.0-alpha.16"{{/if}}{{#if features.datapipe}},
37
- "@h-ai/datapipe": "^0.1.0-alpha.16"{{/if}}{{#if features.scheduler}},
38
- "@h-ai/scheduler": "^0.1.0-alpha.16"{{/if}}{{#if features.deploy}},
39
- "@h-ai/deploy": "^0.1.0-alpha.16"{{/if}}{{#if features.api-client}},
40
- "@h-ai/api-client": "^0.1.0-alpha.16"{{/if}}{{#if features.capacitor}},
41
- "@h-ai/capacitor": "^0.1.0-alpha.16"{{/if}}{{#if isCapacitorApp}}{{#unless features.api-client}},
42
- "@h-ai/api-client": "^0.1.0-alpha.16"{{/unless}}{{#unless features.capacitor}},
43
- "@h-ai/capacitor": "^0.1.0-alpha.16"{{/unless}}{{/if}},
44
- "zod": "^4.3.6"
25
+ "@h-ai/core": "^0.1.0-alpha.19",
26
+ "@h-ai/kit": "^0.1.0-alpha.19"{{#if hasUi}},
27
+ "@h-ai/ui": "^0.1.0-alpha.19"{{/if}}{{#if features.db}},
28
+ "@h-ai/reldb": "^0.1.0-alpha.19"{{/if}}{{#if features.cache}},
29
+ "@h-ai/cache": "^0.1.0-alpha.19"{{/if}}{{#if features.iam}},
30
+ "@h-ai/iam": "^0.1.0-alpha.19"{{/if}}{{#if features.crypto}},
31
+ "@h-ai/crypto": "^0.1.0-alpha.19"{{/if}}{{#if features.storage}},
32
+ "@h-ai/storage": "^0.1.0-alpha.19"{{/if}}{{#if features.ai}},
33
+ "@h-ai/ai": "^0.1.0-alpha.19"{{/if}}{{#if features.audit}},
34
+ "@h-ai/audit": "^0.1.0-alpha.19"{{/if}}{{#if features.reach}},
35
+ "@h-ai/reach": "^0.1.0-alpha.19"{{/if}}{{#if features.payment}},
36
+ "@h-ai/payment": "^0.1.0-alpha.19"{{/if}}{{#if features.vecdb}},
37
+ "@h-ai/vecdb": "^0.1.0-alpha.19"{{/if}}{{#if features.datapipe}},
38
+ "@h-ai/datapipe": "^0.1.0-alpha.19"{{/if}}{{#if features.scheduler}},
39
+ "@h-ai/scheduler": "^0.1.0-alpha.19"{{/if}}{{#if features.deploy}},
40
+ "@h-ai/deploy": "^0.1.0-alpha.19"{{/if}}{{#if features.api-client}},
41
+ "@h-ai/api-client": "^0.1.0-alpha.19"{{/if}}{{#if features.capacitor}},
42
+ "@h-ai/capacitor": "^0.1.0-alpha.19"{{/if}}{{#if isCapacitorApp}}{{#unless features.api-client}},
43
+ "@h-ai/api-client": "^0.1.0-alpha.19"{{/unless}}{{#unless features.capacitor}},
44
+ "@h-ai/capacitor": "^0.1.0-alpha.19"{{/unless}}{{/if}},
45
+ "zod": "^4.4.3"
45
46
  },
46
47
  "devDependencies": {
47
- "@playwright/test": "^1.59.1",
48
+ "@antfu/eslint-config": "^9.0.0",
49
+ "@playwright/test": "^1.60.0",
48
50
  {{#if isCapacitorApp}}
49
- "@capacitor/cli": "^8.2.0",
50
- "@capacitor/core": "^8.2.0",
51
- "@capacitor/android": "^8.2.0",
51
+ "@aparajita/capacitor-secure-storage": "^8.0.0",
52
+ "@capacitor/cli": "^8.3.4",
53
+ "@capacitor/core": "^8.3.4",
54
+ "@capacitor/android": "^8.3.4",
52
55
  "@capacitor/preferences": "^8.0.1",
53
56
  "@sveltejs/adapter-static": "^3.0.10",
54
57
  {{else}}
@@ -58,22 +61,26 @@
58
61
  "@sveltejs/adapter-auto": "^7.0.1",
59
62
  {{/if_eq}}
60
63
  {{/if}}
61
- "@sveltejs/kit": "^2.57.1",
62
- "@sveltejs/vite-plugin-svelte": "^7.0.0",
63
- "@types/node": "^25.6.0",
64
+ "@sveltejs/kit": "^2.61.1",
65
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
66
+ "@types/node": "^25.9.1",
67
+ "eslint": "^10.4.0",
68
+ "eslint-plugin-format": "^2.0.1",
69
+ "eslint-plugin-svelte": "^3.17.1",
64
70
  "pino-pretty": "^13.1.3",
65
71
  "rimraf": "^6.1.3",
66
- "svelte": "^5.55.3",
67
- "svelte-check": "^4.4.6",
68
- "typescript": "^6.0.2",
69
- "vite": "^8.0.8",
70
- "vitest": "^4.1.4"{{#if hasUi}},
71
- "@tailwindcss/vite": "^4.2.2",
72
- "tailwindcss": "^4.2.2",
73
- "daisyui": "^5.5.19",
74
- "@iconify-json/tabler": "^1.2.33",
72
+ "svelte": "^5.55.9",
73
+ "svelte-check": "^4.4.8",
74
+ "svelte-eslint-parser": "^1.6.1",
75
+ "typescript": "^6.0.3",
76
+ "vite": "^8.0.14",
77
+ "vitest": "^4.1.7"{{#if hasUi}},
78
+ "@tailwindcss/vite": "^4.3.0",
79
+ "tailwindcss": "^4.3.0",
80
+ "daisyui": "^5.5.20",
81
+ "@iconify-json/tabler": "^1.2.35",
75
82
  "@iconify/tailwind4": "^1.2.3"{{/if}}{{#if hasI18n}},
76
- "@inlang/paraglide-js": "^2.15.3",
83
+ "@inlang/paraglide-js": "^2.18.1",
77
84
  "@inlang/plugin-message-format": "^4.4.0"{{/if}}
78
85
  }{{#if features.db}},
79
86
  "pnpm": {
@@ -1,3 +1,4 @@
1
+ {{! @skipIfEmpty }}
1
2
  {{#if hasUi}}
2
3
  /* ─── Tailwind CSS v4 ─── */
3
4
  @import 'tailwindcss';
@@ -27,13 +27,13 @@
27
27
  {{/if}}
28
28
  */
29
29
 
30
+ {{#if features.cache}}
31
+ import { cache, CacheConfigSchema } from '@h-ai/cache'
32
+ {{/if}}
30
33
  import { core } from '@h-ai/core'
31
34
  {{#if features.db}}
32
35
  import { reldb, ReldbConfigSchema } from '@h-ai/reldb'
33
36
  {{/if}}
34
- {{#if features.cache}}
35
- import { cache, CacheConfigSchema } from '@h-ai/cache'
36
- {{/if}}
37
37
  {{#if features.iam}}
38
38
  import type { IamConfigSettingsInput } from '@h-ai/iam'
39
39
  import { iam } from '@h-ai/iam'
@@ -0,0 +1,27 @@
1
+ import { readFile } from 'node:fs/promises'
2
+ import { join } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { describe, expect, it } from 'vitest'
5
+
6
+ const rootDir = fileURLToPath(new URL('..', import.meta.url))
7
+
8
+ describe('generated scaffold', () => {
9
+ it('declares project metadata and quality gate scripts', async () => {
10
+ const packageJsonPath = join(rootDir, 'package.json')
11
+ const pkg = JSON.parse(await readFile(packageJsonPath, 'utf-8')) as {
12
+ name: string
13
+ scripts: Record<string, string>
14
+ }
15
+
16
+ expect(pkg.name).toBe('{{projectName}}')
17
+ expect(pkg.scripts.typecheck).toBeDefined()
18
+ expect(pkg.scripts.lint).toBeDefined()
19
+ expect(pkg.scripts.test).toBeDefined()
20
+ expect(pkg.scripts['test:e2e']).toBeDefined()
21
+ })
22
+
23
+ it('renders the app shell locale marker', async () => {
24
+ const appHtml = await readFile(join(rootDir, 'src/app.html'), 'utf-8')
25
+ expect(appHtml).toContain('lang="{{#if hasI18n}}%lang%{{else}}{{defaultLocale}}{{/if}}"')
26
+ })
27
+ })
@@ -7,18 +7,26 @@ import { payment } from '@h-ai/payment'
7
7
 
8
8
  export const POST: RequestHandler = async ({ request, locals }) => {
9
9
  const body = await request.json()
10
- const { provider, tradeType, outTradeNo, totalAmount, subject, notifyUrl } = body
10
+ const { provider, tradeType, outTradeNo, totalAmount, subject, notifyUrl, userId, metadata } = body
11
11
 
12
12
  if (!provider || !outTradeNo || !totalAmount || !subject) {
13
13
  return kit.response.badRequest('Missing required fields: provider, outTradeNo, totalAmount, subject')
14
14
  }
15
15
 
16
- const result = await payment.createOrder({
17
- provider,
18
- tradeType: tradeType ?? 'JSAPI',
19
- outTradeNo,
20
- totalAmount,
21
- subject,
16
+ const normalizedTradeType = tradeType === 'h5'
17
+ || tradeType === 'app'
18
+ || tradeType === 'native'
19
+ || tradeType === 'mini_program'
20
+ ? tradeType
21
+ : 'jsapi'
22
+
23
+ const result = await payment.createOrder(provider, {
24
+ orderNo: outTradeNo,
25
+ amount: Number(totalAmount),
26
+ description: subject,
27
+ tradeType: normalizedTradeType,
28
+ userId,
29
+ metadata,
22
30
  notifyUrl: notifyUrl ?? `${new URL(request.url).origin}/api/v1/payment/notify/${provider}`,
23
31
  })
24
32
 
@@ -21,8 +21,7 @@ export const POST: RequestHandler = async ({ request, params }) => {
21
21
  headers[key] = value
22
22
  })
23
23
 
24
- const result = await payment.handleNotify({
25
- provider,
24
+ const result = await payment.handleNotify(provider, {
26
25
  headers,
27
26
  body,
28
27
  })
@@ -122,6 +122,8 @@ ai.init(core.config.get('ai'))
122
122
  ai.close()
123
123
  ```
124
124
 
125
+ `ai.config` 返回的是脱敏后的配置快照;`apiKey`、`privateKey`、`baseUrl` 等敏感字段会自动隐藏,URL 类字段只掩码内嵌凭证。
126
+
125
127
  **特殊说明**:`ai.tools` 和 `ai.stream` 无需 init 即可使用;`ai.llm` 和 `ai.mcp` 操作需要先 init。
126
128
 
127
129
  ---
@@ -48,6 +48,8 @@ await apiClient.init({
48
48
  })
49
49
  ```
50
50
 
51
+ > `createCapacitorTokenStorage()` 仅在 Android/iOS 原生环境 + `@aparajita/capacitor-secure-storage` 已安装时持久化 token;纯 Web 不会回退到 `localStorage`。
52
+
51
53
  SSR / Node.js 测试场景请显式传入内存存储:
52
54
 
53
55
  ```ts
@@ -84,6 +86,8 @@ const client = apiClient.create(contract)
84
86
  await client.init({ baseUrl: 'https://api.example.com/api/v1' })
85
87
  ```
86
88
 
89
+ `client.config` / `apiClient.config` 返回的是脱敏后的运行配置快照;`baseUrl` 的内嵌凭证与 `headers.authorization` 等敏感值会自动隐藏。
90
+
87
91
  ### 4. 关闭
88
92
 
89
93
  ```ts
@@ -52,7 +52,10 @@ await audit.init({
52
52
  ### 3. 关闭
53
53
 
54
54
  ```ts
55
- await audit.close()
55
+ const closeResult = await audit.close()
56
+ if (!closeResult.success) {
57
+ throw new Error(closeResult.error.message)
58
+ }
56
59
  ```
57
60
 
58
61
  ## 核心 API
@@ -62,7 +65,7 @@ await audit.close()
62
65
  | 方法 | 签名 | 说明 |
63
66
  | --------------------- | ---------------------------------------------------------------- | ---------- |
64
67
  | `audit.init` | `(config: AuditInitConfig) => Promise<HaiResult<void>>` | 初始化模块 |
65
- | `audit.close` | `() => Promise<void>` | 关闭模块 |
68
+ | `audit.close` | `() => Promise<HaiResult<void>>` | 关闭模块 |
66
69
  | `audit.isInitialized` | `boolean` | 初始化状态 |
67
70
 
68
71
  ### 日志操作
@@ -86,6 +89,8 @@ await audit.close()
86
89
  | `audit.helper.passwordResetComplete(userId, ip?, ua?)` | 密码重置完成 |
87
90
  | `audit.helper.crud(input)` | CRUD 操作 |
88
91
 
92
+ > `audit.log()` / `audit.helper.*()` 中的 `details` 仅会自动脱敏凭证类字段(如 `password` / `token` / `secret`);邮箱、手机号默认保留原值。
93
+
89
94
  ## 错误码
90
95
 
91
96
  | 错误码 | code | 说明 |
@@ -51,6 +51,8 @@ await cache.init(core.config.get('cache'))
51
51
  await cache.close()
52
52
  ```
53
53
 
54
+ `cache.config` 返回的是脱敏后的配置快照;Redis `password` / `url` 等敏感值不会原样暴露给日志或调试输出。
55
+
54
56
  ---
55
57
 
56
58
  ## 核心 API
@@ -5,20 +5,20 @@ description: 使用 @h-ai/capacitor 桥接 Capacitor 原生能力(Token 安全
5
5
 
6
6
  # hai-capacitor
7
7
 
8
- > `@h-ai/capacitor` 是 hai-framework 的 Capacitor 原生桥接模块,封装常用原生能力为统一 API,返回 `HaiResult<T>`。与 `@h-ai/api-client` 配合实现 App 端 Token 安全存储。
8
+ > `@h-ai/capacitor` 是 hai-framework 的 Capacitor 原生桥接模块,封装常用原生能力为统一 API,返回 `HaiResult<T>`。与 `@h-ai/api-client` 配合时,Token 仅存于原生安全存储,不回退到 Web `localStorage`。
9
9
 
10
10
  ---
11
11
 
12
12
  ## 运行环境
13
13
 
14
- > **浏览器端 / 原生 App 专用。** 在 Capacitor 原生环境(Android/iOS)中提供完整能力,纯 Web 环境下部分功能退化(如 Preferences 退化为 localStorage)。
14
+ > **浏览器端 / 原生 App 专用。** 在 Capacitor 原生环境(Android/iOS)中提供完整能力;`createCapacitorTokenStorage()` 仅在原生环境持久化 token,纯 Web 不做不安全回退。`capacitor.preferences` 仍可用于普通偏好数据。
15
15
 
16
16
  ---
17
17
 
18
18
  ## 适用场景
19
19
 
20
20
  - Android/iOS 原生应用开发(SvelteKit + Capacitor)
21
- - Token 安全存储(Capacitor Preferences → SharedPreferences / UserDefaults)
21
+ - Token 安全存储(`@aparajita/capacitor-secure-storage`)
22
22
  - 设备信息获取(平台、型号、版本)
23
23
  - 推送通知注册与监听(FCM / APNs)
24
24
  - 原生相机拍照 / 相册选取
@@ -64,13 +64,13 @@ await apiClient.init({
64
64
  })
65
65
  ```
66
66
 
67
- `createCapacitorTokenStorage()` 返回 `TokenStorage` 实例(兼容 `@h-ai/api-client`),底层使用 `@capacitor/preferences`:
67
+ `createCapacitorTokenStorage()` 返回 `TokenStorage` 实例(兼容 `@h-ai/api-client`),底层使用 `@aparajita/capacitor-secure-storage`:
68
68
 
69
- - Android → SharedPreferences(应用沙盒)
70
- - iOS → UserDefaults
71
- - Web → localStorage(退化,建议仅原生端使用)
69
+ - Android → Android KeyStore + 加密 SharedPreferences
70
+ - iOS → Keychain
71
+ - Web → **不回退到 localStorage**;`get*()` 返回 `null`,`set*()` / `clear()` 为 no-op
72
72
 
73
- 所有方法内置 try-catch,Preferences 异常时 get 返回 `null`、set/clear 静默失败并记录日志。
73
+ 所有方法内置 try-catch;原生安全存储异常时 get 返回 `null`、set/clear 静默失败并记录日志。
74
74
 
75
75
  #### Preferences 子操作
76
76
 
@@ -208,6 +208,7 @@ await capacitor.statusBar.show()
208
208
  | `HaiCapacitorError.PREFERENCES_SET_FAILED` | `hai:capacitor:012` | Preferences 写入失败 |
209
209
  | `HaiCapacitorError.PREFERENCES_REMOVE_FAILED`| `hai:capacitor:013` | Preferences 删除失败 |
210
210
  | `HaiCapacitorError.DEVICE_INFO_FAILED` | `hai:capacitor:020` | 获取设备信息失败 |
211
+ | `HaiCapacitorError.APP_VERSION_FAILED` | `hai:capacitor:021` | 获取应用版本失败 |
211
212
  | `HaiCapacitorError.PUSH_REGISTER_FAILED` | `hai:capacitor:030` | 推送注册失败 |
212
213
  | `HaiCapacitorError.PUSH_LISTEN_FAILED` | `hai:capacitor:031` | 推送监听失败 |
213
214
  | `HaiCapacitorError.CAMERA_FAILED` | `hai:capacitor:040` | 拍照/相册失败 |
@@ -359,7 +360,8 @@ async function captureAndUpload() {
359
360
  | 插件 | 类型 | 用于 |
360
361
  | --- | --- | --- |
361
362
  | `@capacitor/core` | peerDependency(必需) | 核心运行时 |
362
- | `@capacitor/preferences` | peerDependency(必需) | Token 存储 |
363
+ | `@aparajita/capacitor-secure-storage` | 可选 peerDependency(原生 token 存储必需) | `createCapacitorTokenStorage()` |
364
+ | `@capacitor/preferences` | peerDependency(必需) | `capacitor.preferences.*` 普通偏好数据 |
363
365
  | `@capacitor/device` | 可选 | `getDeviceInfo()` |
364
366
  | `@capacitor/app` | 可选 | `getAppVersion()` |
365
367
  | `@capacitor/push-notifications` | 可选 | `registerPush()` / `listenPush()` |
@@ -16,7 +16,7 @@ description: 使用 @h-ai/core 进行配置加载、日志记录、i18n 国际
16
16
  | 能力 | Node.js | 浏览器 |
17
17
  |------|---------|--------|
18
18
  | `core.logger` | ✅ pino(结构化 JSON / pretty) | ✅ loglevel(DevTools console) |
19
- | `core.config` | ✅ 完整(YAML 加载、watch、validate) | ⚠️ 仅支持 `core.init({ ... })` 传入配置 |
19
+ | `core.config` | ✅ 完整(YAML 加载、watch、validate) | ⚠️ 占位 API;文件配置方法返回 `SERVICE_UNAVAILABLE` |
20
20
  | `core.i18n` | ✅ | ✅ |
21
21
  | `core.zodValidation` | ✅ | ✅ |
22
22
  | `core.id` | ✅ | ✅ |
@@ -79,6 +79,8 @@ const formErrors = core.zodValidation.mapZodErrorToFormErrors(zodError, getMessa
79
79
 
80
80
  ### 配置管理 — `core.config`
81
81
 
82
+ > 浏览器端保留 `core.config` 对象用于类型/runtime 对齐,但没有文件系统:`get()` 返回 `undefined`,`has()` 返回 `false`,`keys()` 返回 `[]`;`load()` / `validate()` / `reload()` 返回 `HaiCommonError.SERVICE_UNAVAILABLE`;`watch()` 会立即回调该错误并返回 no-op 取消函数。
83
+
82
84
  | 方法 | 签名 | 说明 |
83
85
  | ------------ | -------------------------------------------------------------- | ------------------------------ |
84
86
  | `get` | `<T>(name: string) => T \| undefined` | 获取模块配置段 |
@@ -541,6 +543,7 @@ logger.debug('Data fetched', { count: items.length })
541
543
 
542
544
  | 功能 | 行为 |
543
545
  |------|------|
546
+ | `core.config` 文件配置 | 不支持;文件相关方法返回 `SERVICE_UNAVAILABLE`,配置应由服务端读取后下发 |
544
547
  | `format: 'json' \| 'pretty'` | 被忽略(始终输出到 DevTools console) |
545
548
  | `redact` 字段脱敏 | 不生效(需手动脱敏) |
546
549
  | `fatal` 级别 | 映射为 `console.error`(带 `[FATAL]` 前缀) |