@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.
- package/dist/{chunk-LANIDJC7.js → chunk-BPO34NRL.js} +3 -3
- package/dist/chunk-BPO34NRL.js.map +1 -0
- package/dist/{chunk-YV7WPUI6.js → chunk-GSMXGUYF.js} +6 -2
- package/dist/chunk-GSMXGUYF.js.map +1 -0
- package/dist/cli-config-templates-JCS7T3NU.js +5 -0
- package/dist/cli-config-templates-JCS7T3NU.js.map +1 -0
- package/dist/cli-skill-templates-IMYZPQRG.js +5 -0
- package/dist/cli-skill-templates-IMYZPQRG.js.map +1 -0
- package/dist/index.js +391 -58
- package/dist/index.js.map +1 -1
- package/dist/{src-RZ4DPYNJ.js → src-N4NPS7AG.js} +1239 -493
- package/dist/src-N4NPS7AG.js.map +1 -0
- package/package.json +8 -7
- package/templates/README.md +10 -3
- package/templates/apps/android-app/src/lib/api.ts.hbs +1 -1
- package/templates/apps/api/tests/health.test.ts.hbs +26 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +50 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.html.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+layout.svelte.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/routes/+page.svelte.hbs +162 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/tests/api.test.ts.hbs +28 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +29 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +50 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.html.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+layout.svelte.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/routes/+page.svelte.hbs +162 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tests/api.test.ts.hbs +28 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +29 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +13 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +34 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +50 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.html.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+layout.svelte.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/routes/+page.svelte.hbs +162 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/tests/api.test.ts.hbs +28 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +29 -0
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +30 -0
- package/templates/apps/fullstack/eslint.config.js +44 -0
- package/templates/apps/fullstack/package.json.hbs +42 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +15 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +27 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +21 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-routes.ts.hbs +27 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +34 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +4 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +48 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +14 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +29 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +15 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +38 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +13 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server-app.ts.hbs +42 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/server-app.test.ts.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +39 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +24 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +24 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +44 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +8 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +60 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/LanguageSwitcher.svelte.hbs +27 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +18 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme.svelte.ts.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/playwright.config.ts.hbs +34 -0
- package/templates/apps/fullstack/pnpm-workspace.yaml +7 -0
- package/templates/apps/fullstack/tsconfig.base.json +15 -0
- package/templates/base/e2e/app.spec.ts.hbs +7 -0
- package/templates/base/eslint.config.js +6 -0
- package/templates/base/package.json.hbs +46 -39
- package/templates/base/src/app.css.hbs +1 -0
- package/templates/base/src/lib/server/init.ts.hbs +3 -3
- package/templates/base/tests/scaffold.test.ts.hbs +27 -0
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +15 -7
- package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +1 -2
- package/templates/skills/hai-ai/SKILL.md +2 -0
- package/templates/skills/hai-api-client/SKILL.md +4 -0
- package/templates/skills/hai-audit/SKILL.md +7 -2
- package/templates/skills/hai-cache/SKILL.md +2 -0
- package/templates/skills/hai-capacitor/SKILL.md +11 -9
- package/templates/skills/hai-core/SKILL.md +4 -1
- package/templates/skills/hai-crypto/SKILL.md +42 -8
- package/templates/skills/hai-iam/SKILL.md +2 -0
- package/templates/skills/hai-kit/SKILL.md +9 -2
- package/templates/skills/hai-payment/SKILL.md +5 -0
- package/templates/skills/hai-reach/SKILL.md +3 -1
- package/templates/skills/hai-reldb/SKILL.md +2 -0
- package/templates/skills/hai-scheduler/SKILL.md +2 -0
- package/templates/skills/hai-serv/SKILL.md +14 -9
- package/templates/skills/hai-storage/SKILL.md +10 -1
- package/templates/skills/hai-vecdb/SKILL.md +8 -1
- package/dist/chunk-LANIDJC7.js.map +0 -1
- package/dist/chunk-YV7WPUI6.js.map +0 -1
- package/dist/config-templates-S5RI2MC6.js +0 -5
- package/dist/config-templates-S5RI2MC6.js.map +0 -1
- package/dist/skill-templates-N5DU5FNX.js +0 -5
- package/dist/skill-templates-N5DU5FNX.js.map +0 -1
- 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>
|
package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme.svelte.ts.hbs
ADDED
|
@@ -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,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
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "{{projectName}}",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
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.
|
|
25
|
-
"@h-ai/kit": "^0.1.0-alpha.
|
|
26
|
-
"@h-ai/ui": "^0.1.0-alpha.
|
|
27
|
-
"@h-ai/reldb": "^0.1.0-alpha.
|
|
28
|
-
"@h-ai/cache": "^0.1.0-alpha.
|
|
29
|
-
"@h-ai/iam": "^0.1.0-alpha.
|
|
30
|
-
"@h-ai/crypto": "^0.1.0-alpha.
|
|
31
|
-
"@h-ai/storage": "^0.1.0-alpha.
|
|
32
|
-
"@h-ai/ai": "^0.1.0-alpha.
|
|
33
|
-
"@h-ai/audit": "^0.1.0-alpha.
|
|
34
|
-
"@h-ai/reach": "^0.1.0-alpha.
|
|
35
|
-
"@h-ai/payment": "^0.1.0-alpha.
|
|
36
|
-
"@h-ai/vecdb": "^0.1.0-alpha.
|
|
37
|
-
"@h-ai/datapipe": "^0.1.0-alpha.
|
|
38
|
-
"@h-ai/scheduler": "^0.1.0-alpha.
|
|
39
|
-
"@h-ai/deploy": "^0.1.0-alpha.
|
|
40
|
-
"@h-ai/api-client": "^0.1.0-alpha.
|
|
41
|
-
"@h-ai/capacitor": "^0.1.0-alpha.
|
|
42
|
-
"@h-ai/api-client": "^0.1.0-alpha.
|
|
43
|
-
"@h-ai/capacitor": "^0.1.0-alpha.
|
|
44
|
-
"zod": "^4.3
|
|
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
|
-
"@
|
|
48
|
+
"@antfu/eslint-config": "^9.0.0",
|
|
49
|
+
"@playwright/test": "^1.60.0",
|
|
48
50
|
{{#if isCapacitorApp}}
|
|
49
|
-
|
|
50
|
-
"@capacitor/
|
|
51
|
-
"@capacitor/
|
|
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.
|
|
62
|
-
"@sveltejs/vite-plugin-svelte": "^7.
|
|
63
|
-
"@types/node": "^25.
|
|
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.
|
|
67
|
-
"svelte-check": "^4.4.
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"tailwindcss": "^4.
|
|
73
|
-
"
|
|
74
|
-
"
|
|
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.
|
|
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": {
|
|
@@ -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
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
|
@@ -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 | 说明 |
|
|
@@ -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`
|
|
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
|
|
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
|
|
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
|
|
67
|
+
`createCapacitorTokenStorage()` 返回 `TokenStorage` 实例(兼容 `@h-ai/api-client`),底层使用 `@aparajita/capacitor-secure-storage`:
|
|
68
68
|
|
|
69
|
-
- Android → SharedPreferences
|
|
70
|
-
- iOS →
|
|
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
|
|
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
|
|
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) | ⚠️
|
|
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]` 前缀) |
|