@h-ai/cli 0.1.0-alpha.56 → 0.1.0-alpha.58
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/README.en.md +239 -0
- package/README.ja.md +239 -0
- package/README.md +51 -1
- package/dist/chunk-2H7UOFLK.js +0 -0
- package/dist/chunk-F4IBPVZ5.js +355 -0
- package/dist/chunk-F4IBPVZ5.js.map +1 -0
- package/dist/{chunk-O3ANVICQ.js → chunk-WUSFJFW5.js} +13 -7
- package/dist/chunk-WUSFJFW5.js.map +1 -0
- package/dist/cli-config-templates-6XA7V6CC.js +5 -0
- package/dist/{cli-config-templates-OWBEGBZQ.js.map → cli-config-templates-6XA7V6CC.js.map} +1 -1
- package/dist/{cli-skill-templates-ZIWYMS4Y.js → cli-skill-templates-45CK4RQ2.js} +3 -3
- package/dist/{cli-skill-templates-ZIWYMS4Y.js.map → cli-skill-templates-45CK4RQ2.js.map} +1 -1
- package/dist/index.js +134 -125
- package/dist/index.js.map +1 -1
- package/dist/{src-TBIET7YU.js → src-DUGLX4YB.js} +7270 -2119
- package/dist/src-DUGLX4YB.js.map +1 -0
- package/package.json +17 -17
- package/templates/README.md +4 -4
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +7 -0
- package/templates/apps/admin/src/routes/+page.svelte.hbs +5 -4
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +2 -2
- package/templates/apps/api/.gitignore.hbs +13 -0
- package/templates/apps/api/.npmrc.hbs +1 -0
- package/templates/apps/api/Dockerfile.hbs +6 -5
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +1 -1
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +2 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +1 -1
- package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +8 -0
- package/templates/apps/api/apps/{{projectName}}-service/package.json.hbs +1 -1
- package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +7 -8
- package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +4 -3
- package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +0 -1
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/app-procedures.ts.hbs +4 -0
- package/templates/apps/api/apps/{{projectName}}-service/tests/service.test.ts.hbs +3 -1
- package/templates/apps/api/e2e/api-service.spec.ts.hbs +4 -2
- package/templates/apps/api/{eslint.config.js → eslint.config.js.hbs} +6 -8
- package/templates/apps/api/package.json.hbs +3 -3
- package/templates/apps/api/pnpm-workspace.yaml.hbs +26 -0
- package/templates/apps/api/tsconfig.base.json +0 -1
- package/templates/apps/fullstack/.dockerignore.hbs +3 -0
- package/templates/apps/fullstack/.gitignore.hbs +16 -0
- package/templates/apps/fullstack/.npmrc.hbs +1 -0
- package/templates/apps/fullstack/Dockerfile.hbs +6 -5
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +5 -8
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +7 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +1 -34
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +1 -34
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +30 -170
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +6 -5
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +48 -22
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +3 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +5 -8
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +6 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +1 -28
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +1 -28
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +5 -4
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +10 -141
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +5 -5
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +3 -3
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +21 -2
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +5 -8
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +6 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +1 -28
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +1 -28
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +5 -143
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +48 -22
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +207 -17
- package/templates/apps/fullstack/{eslint.config.js → eslint.config.js.hbs} +6 -8
- package/templates/apps/fullstack/package.json.hbs +3 -3
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +2 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +66 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +96 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +3 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +5 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +13 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +2 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +10 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +21 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +10 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +10 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +63 -28
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +26 -11
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +276 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +29 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +6 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +5 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +98 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +446 -33
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +48 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +19 -26
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +78 -15
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +78 -15
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +4 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +3 -4
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +53 -27
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +73 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +55 -45
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AuditManagement.svelte.hbs +61 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ProfileSettings.svelte.hbs +57 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/RoleManagement.svelte.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/UserManagement.svelte.hbs +174 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +399 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +7 -39
- package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +151 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +101 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
- package/templates/apps/fullstack/playwright.config.ts.hbs +6 -0
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +24 -0
- package/templates/apps/fullstack/tsconfig.base.json +0 -1
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +4 -0
- package/templates/apps/h5/src/routes/+page.svelte.hbs +3 -2
- package/templates/apps/mobile-app/index.html.hbs +2 -2
- package/templates/apps/mobile-app/src/App.svelte.hbs +6 -2
- package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +13 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +8 -2
- package/templates/apps/website/src/routes/+page.svelte.hbs +4 -3
- package/templates/base/.npmrc.hbs +1 -0
- package/templates/base/Dockerfile.hbs +9 -8
- package/templates/base/e2e/app.spec.ts.hbs +1 -0
- package/templates/base/eslint-rules.js +45 -0
- package/templates/base/eslint.config.js.hbs +6 -8
- package/templates/base/package.json.hbs +39 -42
- package/templates/base/pnpm-workspace.yaml.hbs +26 -0
- package/templates/base/src/app.d.ts.hbs +4 -0
- package/templates/base/src/hooks.server.ts.hbs +0 -8
- package/templates/base/src/lib/server/init.ts.hbs +26 -5
- package/templates/base/src/routes/+layout.server.ts.hbs +18 -0
- package/templates/base/tests/scaffold.test.ts.hbs +21 -1
- package/templates/base/vite.config.ts.hbs +21 -0
- package/templates/features/ai/routes/api/chat/+server.ts +6 -7
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +1 -1
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +1 -1
- package/templates/features/iam/routes-shared/api/auth/login/+server.ts +14 -10
- package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +6 -4
- package/templates/features/storage/routes/api/upload/+server.ts +10 -8
- package/templates/skills/AGENTS.md +9 -8
- package/templates/skills/CLAUDE.md +0 -10
- package/templates/skills/bridges/admin/AGENTS.md +8 -0
- package/templates/skills/bridges/admin/copilot-instructions.md +2 -0
- package/templates/skills/bridges/api/AGENTS.md +8 -1
- package/templates/skills/bridges/api/copilot-instructions.md +2 -0
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +21 -4
- package/templates/skills/bridges/fullstack/copilot-instructions.md.hbs +5 -0
- package/templates/skills/bridges/h5/AGENTS.md +8 -0
- package/templates/skills/bridges/h5/copilot-instructions.md +2 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +8 -0
- package/templates/skills/bridges/mobile-app/copilot-instructions.md +2 -0
- package/templates/skills/bridges/website/AGENTS.md +8 -0
- package/templates/skills/bridges/website/copilot-instructions.md +2 -0
- package/templates/skills/copilot-instructions.md +2 -0
- package/templates/skills/hai-api-client/SKILL.md +2 -0
- package/templates/skills/hai-app-create/SKILL.md +9 -7
- package/templates/skills/hai-app-create/development.md +72 -0
- package/templates/skills/hai-app-create/reference.md +44 -32
- package/templates/skills/hai-app-review/SKILL.md +50 -144
- package/templates/skills/hai-app-tests/SKILL.md +3 -1
- package/templates/skills/hai-app-tests/reference.md +47 -27
- package/templates/skills/hai-build/SKILL.md +5 -4
- package/templates/skills/hai-build/reference.md +56 -34
- package/templates/skills/hai-ci/SKILL.md +8 -15
- package/templates/skills/hai-core/SKILL.md +2 -0
- package/templates/skills/hai-core/reference.md +6 -4
- package/templates/skills/hai-framework-sync/SKILL.md +8 -2
- package/templates/skills/hai-pr-review/SKILL.md +5 -4
- package/templates/skills/hai-reldb/SKILL.md +1 -0
- package/templates/skills/hai-reldb/reference.md +3 -0
- package/templates/skills/hai-scheduler/SKILL.md +3 -0
- package/templates/skills/hai-serv/SKILL.md +2 -0
- package/templates/skills/hai-serv/reference.md +18 -2
- package/templates/skills/hai-storage/SKILL.md +3 -1
- package/templates/skills/hai-ui/SKILL.md +6 -0
- package/templates/skills/hai-ui/reference.md +7 -4
- package/templates/skills/hai-vecdb/reference.md +53 -49
- package/dist/chunk-O3ANVICQ.js.map +0 -1
- package/dist/chunk-WUYLYCW2.js +0 -237
- package/dist/chunk-WUYLYCW2.js.map +0 -1
- package/dist/cli-config-templates-OWBEGBZQ.js +0 -5
- package/dist/src-TBIET7YU.js.map +0 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/tests/api.test.ts.hbs +0 -28
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tests/api.test.ts.hbs +0 -28
- package/templates/apps/fullstack/apps/{{projectName}}-web/tests/api.test.ts.hbs +0 -55
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/LanguageSwitcher.svelte.hbs +0 -27
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/ThemeSwitcher.svelte.hbs +0 -18
- package/templates/skills/bridges/admin/CLAUDE.md +0 -11
- package/templates/skills/bridges/api/CLAUDE.md +0 -11
- package/templates/skills/bridges/fullstack/CLAUDE.md.hbs +0 -5
- package/templates/skills/bridges/h5/CLAUDE.md +0 -11
- package/templates/skills/bridges/mobile-app/CLAUDE.md +0 -11
- package/templates/skills/bridges/website/CLAUDE.md +0 -11
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
{{#if features.ai}}
|
|
31
31
|
import type { AIConfigInput } from '@h-ai/ai'
|
|
32
32
|
{{/if}}
|
|
33
|
+
{{#if features.audit}}
|
|
34
|
+
import type { AuditInitConfigInput } from '@h-ai/audit'
|
|
35
|
+
{{/if}}
|
|
36
|
+
import type { CoreConfig } from '@h-ai/core'
|
|
33
37
|
{{#if features.iam}}
|
|
34
38
|
import type { IamConfigSettingsInput } from '@h-ai/iam'
|
|
35
39
|
{{/if}}
|
|
@@ -43,12 +47,15 @@ import type { StorageConfigInput } from '@h-ai/storage'
|
|
|
43
47
|
import { ai } from '@h-ai/ai'
|
|
44
48
|
{{/if}}
|
|
45
49
|
{{#if features.audit}}
|
|
46
|
-
import { audit } from '@h-ai/audit'
|
|
50
|
+
import { audit, AuditInitConfigSchema } from '@h-ai/audit'
|
|
47
51
|
{{/if}}
|
|
48
52
|
{{#if features.cache}}
|
|
49
53
|
import { cache, CacheConfigSchema } from '@h-ai/cache'
|
|
50
54
|
{{/if}}
|
|
51
55
|
import { core } from '@h-ai/core'
|
|
56
|
+
{{#if features.crypto}}
|
|
57
|
+
import { crypto } from '@h-ai/crypto'
|
|
58
|
+
{{/if}}
|
|
52
59
|
{{#if features.iam}}
|
|
53
60
|
import { iam } from '@h-ai/iam'
|
|
54
61
|
{{/if}}
|
|
@@ -81,9 +88,15 @@ export async function initApp(): Promise<void> {
|
|
|
81
88
|
// 1. 加载配置
|
|
82
89
|
core.init({
|
|
83
90
|
configDir: './config',
|
|
84
|
-
logging: { level: 'info' },
|
|
85
91
|
})
|
|
86
92
|
|
|
93
|
+
{{#if features.crypto}}
|
|
94
|
+
// 加密模块初始化完成后才继续启动依赖它的 IAM / transport。
|
|
95
|
+
const cryptoResult = await crypto.init()
|
|
96
|
+
if (!cryptoResult.success)
|
|
97
|
+
throw new Error(`Crypto initialization failed: ${cryptoResult.error.message}`)
|
|
98
|
+
{{/if}}
|
|
99
|
+
|
|
87
100
|
{{#if features.db}}
|
|
88
101
|
// ─── 配置校验 ───
|
|
89
102
|
const dbValidation = core.config.validate('db', ReldbConfigSchema)
|
|
@@ -97,6 +110,11 @@ export async function initApp(): Promise<void> {
|
|
|
97
110
|
throw new Error(`Cache config invalid: ${cacheValidation.error.message}`)
|
|
98
111
|
}
|
|
99
112
|
{{/if}}
|
|
113
|
+
{{#if features.audit}}
|
|
114
|
+
const auditValidation = core.config.validate('audit', AuditInitConfigSchema)
|
|
115
|
+
if (!auditValidation.success)
|
|
116
|
+
throw new Error(`Audit config invalid: ${auditValidation.error.message}`)
|
|
117
|
+
{{/if}}
|
|
100
118
|
|
|
101
119
|
{{#if features.db}}
|
|
102
120
|
// ─── 获取配置 ───
|
|
@@ -108,6 +126,9 @@ export async function initApp(): Promise<void> {
|
|
|
108
126
|
{{#if features.iam}}
|
|
109
127
|
const iamConfig = core.config.getOrThrow<IamConfigSettingsInput>('iam')
|
|
110
128
|
{{/if}}
|
|
129
|
+
{{#if features.audit}}
|
|
130
|
+
const auditConfig = core.config.getOrThrow<AuditInitConfigInput>('audit')
|
|
131
|
+
{{/if}}
|
|
111
132
|
{{#if features.storage}}
|
|
112
133
|
const storageConfig = core.config.get<StorageConfigInput>('storage')
|
|
113
134
|
{{/if}}
|
|
@@ -177,9 +198,9 @@ export async function initApp(): Promise<void> {
|
|
|
177
198
|
|
|
178
199
|
{{#if features.audit}}
|
|
179
200
|
// ─── 初始化审计 ───
|
|
180
|
-
const auditResult = await audit.init()
|
|
201
|
+
const auditResult = await audit.init(auditConfig)
|
|
181
202
|
if (!auditResult.success) {
|
|
182
|
-
|
|
203
|
+
throw new Error(`Audit initialization failed: ${auditResult.error.message}`)
|
|
183
204
|
}
|
|
184
205
|
{{/if}}
|
|
185
206
|
|
|
@@ -194,5 +215,5 @@ export async function initApp(): Promise<void> {
|
|
|
194
215
|
{{/if}}
|
|
195
216
|
|
|
196
217
|
initialized = true
|
|
197
|
-
core.logger.info('{
|
|
218
|
+
core.logger.info('Application initialized', { app: core.config.getOrThrow<CoreConfig>('core').name })
|
|
198
219
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#unless isSvelteOnlyApp}}
|
|
3
|
+
import type { CoreConfig } from '@h-ai/core'
|
|
4
|
+
import { core } from '@h-ai/core'
|
|
5
|
+
|
|
6
|
+
/** 只向浏览器提供公开配置,避免暴露日志上下文、凭证或其它模块配置。 */
|
|
7
|
+
export function load() {
|
|
8
|
+
const config = core.config.getOrThrow<CoreConfig>('core')
|
|
9
|
+
return {
|
|
10
|
+
appConfig: {
|
|
11
|
+
name: config.name,
|
|
12
|
+
version: config.version,
|
|
13
|
+
env: config.env,
|
|
14
|
+
defaultLocale: config.defaultLocale,
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
{{/unless}}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
{{#unless isSvelteOnlyApp}}
|
|
2
|
+
import type { CoreConfig } from '@h-ai/core'
|
|
3
|
+
{{/unless}}
|
|
1
4
|
import { readFile } from 'node:fs/promises'
|
|
2
5
|
import { join } from 'node:path'
|
|
3
6
|
import { fileURLToPath } from 'node:url'
|
|
7
|
+
{{#unless isSvelteOnlyApp}}
|
|
8
|
+
import { core } from '@h-ai/core'
|
|
9
|
+
{{/unless}}
|
|
4
10
|
import { describe, expect, it } from 'vitest'
|
|
11
|
+
{{#unless isSvelteOnlyApp}}
|
|
12
|
+
import { load } from '../src/routes/+layout.server'
|
|
13
|
+
{{/unless}}
|
|
5
14
|
|
|
6
15
|
const rootDir = fileURLToPath(new URL('..', import.meta.url))
|
|
7
16
|
|
|
@@ -39,4 +48,15 @@ describe('generated scaffold', () => {
|
|
|
39
48
|
expect(coreConfig).toContain('defaultLocale: {{defaultLocale}}')
|
|
40
49
|
})
|
|
41
50
|
{{/unless}}
|
|
42
|
-
}
|
|
51
|
+
{{#unless isSvelteOnlyApp}}
|
|
52
|
+
|
|
53
|
+
it('publishes only public metadata from parsed core configuration', () => {
|
|
54
|
+
core.init({ configDir: './config' })
|
|
55
|
+
const config = core.config.getOrThrow<CoreConfig>('core')
|
|
56
|
+
expect(core.logger.getLevel()).toBe(config.logging?.level ?? 'info')
|
|
57
|
+
expect(load()).toEqual({
|
|
58
|
+
appConfig: { name: config.name, version: config.version, env: config.env, defaultLocale: config.defaultLocale },
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
{{/unless}}
|
|
62
|
+
})
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* {{projectName}} - Vite 配置
|
|
3
3
|
*/
|
|
4
|
+
{{#if isSvelteOnlyApp}}
|
|
5
|
+
import type { CoreConfig } from '@h-ai/core'
|
|
6
|
+
{{/if}}
|
|
4
7
|
import path from 'node:path'
|
|
5
8
|
import process from 'node:process'
|
|
9
|
+
{{#if isSvelteOnlyApp}}
|
|
10
|
+
import { core } from '@h-ai/core'
|
|
11
|
+
{{/if}}
|
|
6
12
|
{{#if hasUi}}
|
|
7
13
|
import { haiOptimizeExclude, haiPrebundledDeps } from '@h-ai/ui/vite'
|
|
8
14
|
{{/if}}
|
|
@@ -22,8 +28,23 @@ import { defineConfig, loadEnv } from 'vite'
|
|
|
22
28
|
export default defineConfig(({ mode }) => {
|
|
23
29
|
const env = loadEnv(mode, process.cwd(), '')
|
|
24
30
|
Object.assign(process.env, env)
|
|
31
|
+
{{#if isSvelteOnlyApp}}
|
|
32
|
+
// 浏览器无法读取 YAML;构建时通过 core 解析,仅注入明确可公开的字段。
|
|
33
|
+
core.init({ configDir: './config' })
|
|
34
|
+
const config = core.config.getOrThrow<CoreConfig>('core')
|
|
35
|
+
const appConfig = {
|
|
36
|
+
name: config.name,
|
|
37
|
+
version: config.version,
|
|
38
|
+
env: config.env,
|
|
39
|
+
defaultLocale: config.defaultLocale,
|
|
40
|
+
logging: config.logging ? { level: config.logging.level, format: config.logging.format } : undefined,
|
|
41
|
+
}
|
|
42
|
+
{{/if}}
|
|
25
43
|
|
|
26
44
|
return {
|
|
45
|
+
{{#if isSvelteOnlyApp}}
|
|
46
|
+
define: { __APP_CORE_CONFIG__: JSON.stringify(appConfig) },
|
|
47
|
+
{{/if}}
|
|
27
48
|
plugins: [
|
|
28
49
|
{{#if isSvelteOnlyApp}}
|
|
29
50
|
svelte(),
|
|
@@ -4,23 +4,22 @@
|
|
|
4
4
|
import type { RequestHandler } from './$types'
|
|
5
5
|
import { ai } from '@h-ai/ai'
|
|
6
6
|
import { kit } from '@h-ai/kit'
|
|
7
|
+
import { z } from 'zod'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
const { message } = await request.json()
|
|
9
|
+
const ChatInputSchema = z.object({ message: z.string().trim().min(1).max(4000) }).strict()
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
11
|
+
export const POST: RequestHandler = kit.handler(async ({ request, locals }) => {
|
|
12
|
+
const { message } = await kit.validate.body(request, ChatInputSchema)
|
|
14
13
|
|
|
15
14
|
const result = await ai.llm.ask(message, {
|
|
16
15
|
systemPrompt: 'You are a helpful assistant.',
|
|
17
16
|
})
|
|
18
17
|
|
|
19
18
|
if (!result.success) {
|
|
20
|
-
return kit.response.
|
|
19
|
+
return kit.response.fromError(result.error, locals.requestId)
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
return kit.response.ok({
|
|
24
23
|
reply: result.data,
|
|
25
24
|
}, locals.requestId)
|
|
26
|
-
}
|
|
25
|
+
})
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
const res = await fetch('/api/auth/login', {
|
|
23
23
|
method: 'POST',
|
|
24
24
|
headers: { 'Content-Type': 'application/json' },
|
|
25
|
-
body: JSON.stringify({ username, password }),
|
|
25
|
+
body: JSON.stringify({ identifier: username, password }),
|
|
26
26
|
})
|
|
27
27
|
const data = await res.json()
|
|
28
28
|
if (data.success) {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
const res = await fetch('/api/auth/login', {
|
|
23
23
|
method: 'POST',
|
|
24
24
|
headers: { 'Content-Type': 'application/json' },
|
|
25
|
-
body: JSON.stringify({ username, password }),
|
|
25
|
+
body: JSON.stringify({ identifier: username, password }),
|
|
26
26
|
})
|
|
27
27
|
const data = await res.json()
|
|
28
28
|
if (data.success) {
|
|
@@ -1,32 +1,36 @@
|
|
|
1
|
+
import type { CoreConfig } from '@h-ai/core'
|
|
1
2
|
/**
|
|
2
3
|
* 登录 API
|
|
3
4
|
*/
|
|
4
5
|
import type { RequestHandler } from './$types'
|
|
6
|
+
import { core } from '@h-ai/core'
|
|
5
7
|
import { iam } from '@h-ai/iam'
|
|
6
8
|
import { kit } from '@h-ai/kit'
|
|
9
|
+
import { z } from 'zod'
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
const LoginInputSchema = z.object({
|
|
12
|
+
identifier: z.string().trim().min(1).max(254),
|
|
13
|
+
password: z.string().min(1).max(128),
|
|
14
|
+
}).strict()
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
16
|
+
export const POST: RequestHandler = kit.handler(async ({ request, cookies, locals }) => {
|
|
17
|
+
const { identifier, password } = await kit.validate.body(request, LoginInputSchema)
|
|
15
18
|
|
|
16
19
|
const result = await iam.auth.login({ identifier, password })
|
|
17
20
|
if (!result.success) {
|
|
18
|
-
return kit.response.
|
|
21
|
+
return kit.response.fromError(result.error, locals.requestId)
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
const { tokens } = result.data
|
|
25
|
+
const config = core.config.getOrThrow<CoreConfig>('core')
|
|
22
26
|
|
|
23
27
|
cookies.set('session_token', tokens.accessToken, {
|
|
24
28
|
path: '/',
|
|
25
29
|
httpOnly: true,
|
|
26
30
|
sameSite: 'lax',
|
|
27
|
-
secure:
|
|
31
|
+
secure: config.env === 'production' || config.env === 'staging',
|
|
28
32
|
maxAge: tokens.expiresIn,
|
|
29
33
|
})
|
|
30
34
|
|
|
31
|
-
return kit.response.ok({
|
|
32
|
-
}
|
|
35
|
+
return kit.response.ok({ authenticated: true }, locals.requestId)
|
|
36
|
+
})
|
|
@@ -5,11 +5,13 @@ import type { RequestHandler } from './$types'
|
|
|
5
5
|
import { iam } from '@h-ai/iam'
|
|
6
6
|
import { kit } from '@h-ai/kit'
|
|
7
7
|
|
|
8
|
-
export const POST: RequestHandler = async ({ cookies, locals }) => {
|
|
8
|
+
export const POST: RequestHandler = kit.handler(async ({ cookies, locals }) => {
|
|
9
9
|
const token = cookies.get('session_token')
|
|
10
10
|
if (token) {
|
|
11
|
-
await iam.auth.logout(token)
|
|
11
|
+
const result = await iam.auth.logout(token)
|
|
12
|
+
if (!result.success)
|
|
13
|
+
return kit.response.fromError(result.error, locals.requestId)
|
|
12
14
|
}
|
|
13
15
|
cookies.delete('session_token', { path: '/' })
|
|
14
|
-
return kit.response.ok({
|
|
15
|
-
}
|
|
16
|
+
return kit.response.ok({ authenticated: false }, locals.requestId)
|
|
17
|
+
})
|
|
@@ -2,28 +2,30 @@
|
|
|
2
2
|
* 文件上传 API — storage 功能示例
|
|
3
3
|
*/
|
|
4
4
|
import type { RequestHandler } from './$types'
|
|
5
|
+
import { core } from '@h-ai/core'
|
|
5
6
|
import { kit } from '@h-ai/kit'
|
|
6
7
|
import { storage } from '@h-ai/storage'
|
|
7
8
|
|
|
8
|
-
export const POST: RequestHandler = async ({ request, locals }) => {
|
|
9
|
+
export const POST: RequestHandler = kit.handler(async ({ request, locals }) => {
|
|
9
10
|
const formData = await request.formData()
|
|
10
|
-
const file = formData.get('file')
|
|
11
|
+
const file = formData.get('file')
|
|
11
12
|
|
|
12
|
-
if (!file) {
|
|
13
|
-
return kit.response.badRequest('
|
|
13
|
+
if (!(file instanceof File) || file.size === 0 || file.size > 10 * 1024 * 1024) {
|
|
14
|
+
return kit.response.badRequest(core.i18n.coreM('core_errorValidation'), locals.requestId)
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
const { Buffer } = await import('node:buffer')
|
|
17
18
|
const buffer = Buffer.from(await file.arrayBuffer())
|
|
18
|
-
|
|
19
|
+
// 路径由服务端生成,用户文件名仅作为元数据保存。
|
|
20
|
+
const key = `uploads/${core.id.uuid()}`
|
|
19
21
|
|
|
20
|
-
const result = await storage.put(key, buffer, {
|
|
22
|
+
const result = await storage.file.put(key, buffer, {
|
|
21
23
|
contentType: file.type,
|
|
22
24
|
metadata: { originalName: file.name },
|
|
23
25
|
})
|
|
24
26
|
|
|
25
27
|
if (!result.success) {
|
|
26
|
-
return kit.response.
|
|
28
|
+
return kit.response.fromError(result.error, locals.requestId)
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
return kit.response.ok({
|
|
@@ -32,4 +34,4 @@ export const POST: RequestHandler = async ({ request, locals }) => {
|
|
|
32
34
|
size: file.size,
|
|
33
35
|
type: file.type,
|
|
34
36
|
}, locals.requestId)
|
|
35
|
-
}
|
|
37
|
+
})
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:修改 / 新建 / 删除哪些文件;哪些脚本、类型、配置或路由会变。
|
|
@@ -13,14 +21,7 @@
|
|
|
13
21
|
|
|
14
22
|
本项目由 hai-framework CLI 生成。单应用工程通常在 `src/` 下开发;多包工程会同时包含 `packages/*` 与 `apps/*`。实际结构以当前项目目录为准。
|
|
15
23
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
- 先用全局检索确认是否已有实现、测试和文档;优先复用,避免为“未来可能”新增抽象。
|
|
19
|
-
- 生命周期模块按 init → use → close;core/serv/kit/纯函数和流式 API 按实际签名使用。返回 HaiResult 的业务操作先检查 success,不以 try/catch 代替判断。
|
|
20
|
-
- 禁止 `any`、无说明的危险类型断言、`console.log`、硬编码密钥。
|
|
21
|
-
- 用户可见文本必须走 i18n;如果项目启用了 `messages/zh-CN.json` 与 `messages/en-US.json`,修改文案时必须同步更新。
|
|
22
|
-
- 代码注释中文,日志消息英文。
|
|
23
|
-
- 如项目使用 SvelteKit,`+server.ts` 只能导出 HTTP handler 与 SvelteKit 允许的配置项;辅助函数放到 `src/lib/**`。
|
|
24
|
+
如项目使用 SvelteKit,`+server.ts` 只能导出 HTTP handler 与 SvelteKit 允许的配置项;辅助函数放到 `src/lib/**`。
|
|
24
25
|
|
|
25
26
|
## 工作流程
|
|
26
27
|
|
|
@@ -1,11 +1 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
1
|
@AGENTS.md
|
|
4
|
-
|
|
5
|
-
> Claude Code 项目指引。共享规范通过 `@AGENTS.md` 复用;本文件用于 generic fallback 场景,模块和工作流参考资料位于 `.agents/skills/`。
|
|
6
|
-
|
|
7
|
-
共享规则见项目根 [AGENTS.md](AGENTS.md);若未自动加载,先读取该文件。模块/流程按需读取项目根 .agents/skills/<name>/SKILL.md 及其相邻参考文件。
|
|
8
|
-
|
|
9
|
-
## 质量门禁
|
|
10
|
-
|
|
11
|
-
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:哪些 `+page.svelte`、`+layout.svelte`、`+page.server.ts`、`+server.ts`、service、messages、README、测试会变。
|
|
@@ -7,3 +7,5 @@
|
|
|
7
7
|
## 质量门禁
|
|
8
8
|
|
|
9
9
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
10
|
+
|
|
11
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:哪些 `apps/*-contract`、`apps/*-service`、config、README、测试会变。
|
|
@@ -18,7 +26,6 @@
|
|
|
18
26
|
- API 输入输出必须由 `apps/*-contract/src/**` 中的 Zod schema 与 contract 定义统一约束。
|
|
19
27
|
- Service 通过 `@h-ai/serv` + `@h-ai/api-contract` 装配 HTTP App;不要退回到 SvelteKit API routes 架构。
|
|
20
28
|
- Typed client / contract / service 三者保持同一份路径与类型定义,不要复制粘贴接口。
|
|
21
|
-
- 返回 `HaiResult<T>` 的业务 API 先判断 `success`;纯函数、工厂与流按实际签名处理。
|
|
22
29
|
- 不生成用户页面;不要引入 UI 专属依赖或页面文案。
|
|
23
30
|
- 配置和密钥来自 `apps/*-service/config/` 与环境变量,禁止硬编码。
|
|
24
31
|
|
|
@@ -9,3 +9,5 @@
|
|
|
9
9
|
## 质量门禁
|
|
10
10
|
|
|
11
11
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
12
|
+
|
|
13
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -4,9 +4,16 @@ Fullstack 多包工程入口。先读 README、根 workspace 脚本与相关 pac
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
- 修改前检索实现、调用方、测试和文档,优先复用现有 contract、procedure、共享组件与脚本。
|
|
8
16
|
- 跨包变更先明确受影响的 contract、serv、shared、前端及交付流程,再同步调用方;不必输出固定问卷。
|
|
9
|
-
- 禁止 `any`、`console.log`、硬编码密钥。代码注释中文,日志英文;用户文本走 i18n。
|
|
10
17
|
|
|
11
18
|
## 架构边界
|
|
12
19
|
|
|
@@ -21,9 +28,19 @@ Fullstack 多包工程入口。先读 README、根 workspace 脚本与相关 pac
|
|
|
21
28
|
| `apps/{{projectName}}-miniapp` | 选择 miniapp 时生成的预留说明与文案,当前不是可运行应用 |
|
|
22
29
|
|
|
23
30
|
- 前端负责 UI 与请求编排;后端业务放 serv,共享能力放 shared。本样板默认不用 `@h-ai/kit`,不要混入 SvelteKit load / route 结构。
|
|
24
|
-
- 返回 `HaiResult<T>` 的业务 API 先判断 `success`,业务错误直接透传;纯函数、工厂和流按实际签名使用,不能假定都返回 HaiResult。
|
|
25
31
|
- 用户文本按 shared 跨端文案与各 app 专属文案分工,同步现有 locale。
|
|
26
|
-
-
|
|
32
|
+
- 本样板默认启用 IAM、reldb、cache、audit、storage 和 crypto,复用现有初始化与关闭顺序;新增模块前先检查依赖、配置与公开契约。
|
|
33
|
+
- 应用名称、版本、环境、日志与 locale 配置通过 core 统一获取;浏览器显示来自服务端 `app.info`,不另写硬编码副本或将私有配置注入客户端。
|
|
34
|
+
|
|
35
|
+
## 管理与安全边界
|
|
36
|
+
|
|
37
|
+
- `admin` / `user` 是固定角色代码。管理员进入用户、角色和审计管理;普通用户只进入个人设置。服务端为每个管理操作验证角色,个人资料、密码和头像按当前会话绑定用户,不能只靠导航隐藏保护权限。
|
|
38
|
+
- 角色管理更新说明并显示人数,用户管理负责角色分配;保留当前管理员的自删除、自禁用、自降级及最后管理员保护,并验证并发管理请求。
|
|
39
|
+
- JSON 业务请求与响应统一经 typed api-client 和 serv 的 crypto transport 加解密,包含登录与刷新;健康/就绪检查和公开头像二进制资源遵循已有例外,不能为新增业务 API 绕过传输加密。
|
|
40
|
+
- Web 使用内存 access token 和 HttpOnly refresh Cookie;App 原生端装配 `createCapacitorTokenStorage`,浏览器预览沿用 Cookie;Desktop 原生端使用内存 TokenStorage,重启后重新登录。原生 body 刷新通道同时验证 `X-HAI-Token-Transport: body`、端对应的 `x-request-client` 与受信完整 Origin,刷新请求沿用这些头。敏感 token 不写 localStorage,不擅自将其持久化到普通配置文件。
|
|
41
|
+
- 头像接受 PNG/JPEG/WebP,最大 512 KiB;contract、客户端与服务端校验保持一致。服务端验证实际图片数据并生成 storage key;普通用户仅更新自己的头像,管理员可替用户更新。
|
|
42
|
+
- 用户与审计查询按 contract 分页,`page >= 1`、`pageSize` 为 1–100;页面默认每页 20 条。新增筛选同步 schema、procedure、store 和测试,SQL 值参数化。
|
|
43
|
+
- 语言与主题偏好保存到当前用户 metadata,客户端只应用已支持的值。审计仅记录操作字段和资源标识,不记录密码、token、头像内容或联系信息。
|
|
27
44
|
|
|
28
45
|
## 质量门禁
|
|
29
46
|
|
|
@@ -46,4 +63,4 @@ pnpm test:e2e
|
|
|
46
63
|
|
|
47
64
|
## 优先 Skills
|
|
48
65
|
|
|
49
|
-
构建与验收:`hai-build`、`hai-app-review`、`hai-app-tests
|
|
66
|
+
构建与验收:`hai-build`、`hai-app-review`、`hai-app-tests`。管理业务按需读取 `hai-iam`、`hai-reldb`、`hai-cache`、`hai-audit`、`hai-storage`、`hai-crypto`;配置与跨端读取 `hai-core`、`hai-ui`、`hai-serv`、`hai-api-contract`、`hai-api-client`、`hai-capacitor`。
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
- `packages/{{projectName}}-contract` 定义 API;Fullstack 服务端 `packages/{{projectName}}-serv` 实现业务;`packages/{{projectName}}-shared` 共享 UI、i18n 和 typed client。
|
|
6
6
|
- 前端按选择生成;App 使用 Capacitor,Desktop 使用 Tauri v2。miniapp 当前仅预留说明,不是可运行应用。
|
|
7
|
+
- 默认 mini 管理后台复用 IAM/reldb/cache/audit/storage/crypto。管理员管理用户、固定 admin/user 角色及审计;普通用户仅操作个人设置,服务端按角色和当前会话验证权限。
|
|
8
|
+
- typed api-client 与 serv 的 crypto transport 统一加解密 JSON 请求与响应,包含认证与刷新。Web 使用内存 access token + HttpOnly refresh Cookie,App 原生端使用 Capacitor 安全 TokenStorage,Desktop 使用内存 TokenStorage;具体边界与例外见根 AGENTS。
|
|
9
|
+
- 应用名称、版本、环境、日志与 locale 配置通过 core 获取;前端消费 `app.info`。头像、分页、偏好与管理员保护以 contract、服务端实现和根 AGENTS 为准,改动时同步各端。
|
|
7
10
|
|
|
8
11
|
## 质量门禁
|
|
9
12
|
|
|
@@ -12,3 +15,5 @@
|
|
|
12
15
|
## 完成条件
|
|
13
16
|
|
|
14
17
|
同步受影响的 contract、serv、shared、各端调用方及文档与测试,报告门禁结果和未执行原因。
|
|
18
|
+
|
|
19
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:哪些页面、layout、导航、API、messages、README、测试会变。
|
|
@@ -7,3 +7,5 @@
|
|
|
7
7
|
## 质量门禁
|
|
8
8
|
|
|
9
9
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
10
|
+
|
|
11
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:哪些页面、store、原生桥接、messages、README、测试和打包脚本会变。
|
|
@@ -7,3 +7,5 @@
|
|
|
7
7
|
## 质量门禁
|
|
8
8
|
|
|
9
9
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
10
|
+
|
|
11
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## 行为契约
|
|
6
6
|
|
|
7
|
+
普通新增、修改、修复任务开始前,先读 [应用开发 Skill](.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](.agents/skills/hai-app-create/development.md);再按任务读取模块 Skill 及其相邻参考文件。架构/构建、审查、测试分别读取 hai-build、hai-app-review、hai-app-tests,不加载整个 skill 树。
|
|
8
|
+
|
|
9
|
+
- 对当前需求逐项检索 hai-framework 能力和已有实现,确认适用的公开 API 后优先复用;未安装模块先核对依赖与配置,不能因 Skill 已存在就假定已启用。框架不适用时说明具体限制与选用方案,不为覆盖清单引入无关模块。
|
|
10
|
+
- 按已安装版本的公开类型确认模块契约:生命周期模块按 init → use → close;core/serv/kit、纯函数/工厂与流按实际签名处理。返回 HaiResult 的操作先检查 success,不以 try/catch 代替判断;事务失败明确触发回滚。
|
|
11
|
+
- 边界输入做 schema 校验,服务端验证身份、租户与资源权限;SQL 动态值参数化,文件路径防逃逸。密钥不进入 PUBLIC_/VITE_ 变量、客户端代码和日志;敏感 token 不写 localStorage。
|
|
12
|
+
- 禁止 any、无说明的 as unknown as、console.log 和硬编码密钥;从包公开入口导入。注释中文、结构化日志英文并脱敏,用户文本走现有 i18n 并同步所有 locale。
|
|
13
|
+
- 完成时说明实际复用的框架能力、未采用的相关能力及原因、门禁结果;跨边界同步类型、配置、调用方、文档和测试。
|
|
14
|
+
|
|
7
15
|
先读 README、package.json、相关实现/测试和所需 .agents/skills;不要加载整个 skill 树。新增抽象前确认复用路径与真实需求;保留用户改动。跨文件任务简述影响和验证计划,无须固定规模标签或重复问卷。
|
|
8
16
|
|
|
9
17
|
- 直接影响:哪些页面、layout、表单/API、messages、README、测试会变。
|
|
@@ -7,3 +7,5 @@
|
|
|
7
7
|
## 质量门禁
|
|
8
8
|
|
|
9
9
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
10
|
+
|
|
11
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -7,3 +7,5 @@
|
|
|
7
7
|
## 质量门禁
|
|
8
8
|
|
|
9
9
|
按 AGENTS.md 和实际 package.json 选择 typecheck、lint、build、test、test:e2e;最终说明已执行结果、未运行原因及同步文档/依赖方。
|
|
10
|
+
|
|
11
|
+
普通新增、修改、修复任务先读 [应用开发 Skill](../.agents/skills/hai-app-create/SKILL.md) 和 [开发规范与框架能力路由](../.agents/skills/hai-app-create/development.md),依照 AGENTS.md 的默认规则复用框架并完成安全与质量验证。
|
|
@@ -126,6 +126,8 @@ Access token 存在内存中,refresh token 由服务端通过 `HttpOnly` cooki
|
|
|
126
126
|
|
|
127
127
|
启用 `transport` 时,登录、业务请求以及 401 后的自动刷新都会复用同一个加密 fetch 链路;不要在业务代码中手写明文 `/auth/refresh` 请求。
|
|
128
128
|
|
|
129
|
+
自动刷新识别真实 HTTP 401(`Response.status`),以及 HTTP 200 的有效失败 HaiResult(`success=false`、字符串 `error.code/message`、`error.httpStatus=401`),成功后只重试一次原请求。内置登录、注册与配置的 `auth.refreshPath` 排除自动刷新,403/500 等其它失败也不刷新。serv 普通 procedure 的 HTTP 状态仍为 200;调用方须检查最终 `success/error.code` 并处理刷新失败后的登录失效。
|
|
130
|
+
|
|
129
131
|
```ts
|
|
130
132
|
import { apiClient } from '@h-ai/api-client'
|
|
131
133
|
|