@h-ai/cli 0.1.0-alpha9 → 1.0.0-beta.2
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 +229 -0
- package/README.ja.md +229 -0
- package/README.md +175 -113
- package/dist/chunk-AKV2CQZV.js +1497 -0
- package/dist/chunk-AKV2CQZV.js.map +1 -0
- package/dist/chunk-EF7WOFWZ.js +7557 -0
- package/dist/chunk-EF7WOFWZ.js.map +1 -0
- package/dist/chunk-MUHRBJSW.js +29272 -0
- package/dist/chunk-MUHRBJSW.js.map +1 -0
- package/dist/chunk-ZSDEVXZ7.js +38 -0
- package/dist/{chunk-2H7UOFLK.js.map → chunk-ZSDEVXZ7.js.map} +1 -1
- package/dist/cli-config-templates-HHFHNXBN.js +5 -0
- package/dist/cli-config-templates-HHFHNXBN.js.map +1 -0
- package/dist/cli-skill-templates-PN4FLGBC.js +5 -0
- package/dist/cli-skill-templates-PN4FLGBC.js.map +1 -0
- package/dist/index.js +4444 -554
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -0
- package/dist/src-TEBHR5I5.js +5 -0
- package/dist/src-TEBHR5I5.js.map +1 -0
- package/package.json +35 -15
- package/templates/README.md +56 -114
- package/templates/apps/admin/messages/en-US.json +7 -0
- package/templates/apps/admin/messages/ja-JP.json +40 -0
- package/templates/apps/admin/messages/zh-CN.json +7 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +65 -8
- package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -14
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +54 -22
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
- package/templates/apps/api/.dockerignore.hbs +25 -0
- package/templates/apps/api/.gitignore.hbs +22 -0
- package/templates/apps/api/.npmrc.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +39 -0
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +28 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +5 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +60 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_core.yml.hbs +17 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +54 -0
- package/templates/apps/api/apps/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +66 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +119 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +165 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +57 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +176 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsconfig.json.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +20 -0
- package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/api/e2e/api-serv.spec.ts.hbs +113 -0
- package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
- package/templates/apps/api/eslint.config.js.hbs +30 -0
- package/templates/apps/api/hai.json.hbs +4 -0
- package/templates/apps/api/images/serv.Dockerfile.hbs +37 -0
- package/templates/apps/api/package.json.hbs +53 -0
- package/templates/apps/api/playwright.config.ts.hbs +67 -0
- package/templates/apps/api/pnpm-workspace.yaml.hbs +40 -0
- package/templates/apps/api/tsconfig.base.json +14 -0
- package/templates/apps/fullstack/.dockerignore.hbs +25 -0
- package/templates/apps/fullstack/.gitignore.hbs +38 -0
- package/templates/apps/fullstack/.npmrc.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +67 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +86 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +59 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +19 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +74 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +64 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +66 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +25 -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 +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +33 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +91 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +46 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +89 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +25 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.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 +54 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +53 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/public/runtime-config.js.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +18 -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 +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +76 -0
- package/templates/apps/fullstack/docs/security-configuration.md.hbs +349 -0
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +988 -0
- package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +119 -0
- package/templates/apps/fullstack/eslint.config.js.hbs +41 -0
- package/templates/apps/fullstack/hai.json.hbs +11 -0
- package/templates/apps/fullstack/images/serv.Dockerfile.hbs +38 -0
- package/templates/apps/fullstack/images/web/19-runtime-config.envsh.hbs +5 -0
- package/templates/apps/fullstack/images/web/nginx.conf.hbs +24 -0
- package/templates/apps/fullstack/images/web/runtime-config.js.template.hbs +3 -0
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +37 -0
- package/templates/apps/fullstack/package.json.hbs +61 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +30 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +78 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +134 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +20 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +35 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +23 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +31 -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 +84 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +22 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_feedback.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +60 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +64 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +62 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +115 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +294 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/audit-jobs.ts.hbs +28 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +106 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +34 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +159 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +73 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +505 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +72 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +183 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +18 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +97 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +55 -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 +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +36 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +16 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/session-recovery.svelte.ts.hbs +4 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +122 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +90 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +86 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/configuration.svelte.hbs +25 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +157 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +77 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +44 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +216 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +614 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +23 -0
- 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 +150 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +253 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
- package/templates/apps/fullstack/playwright.config.ts.hbs +114 -0
- package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +18 -0
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +38 -0
- package/templates/apps/fullstack/tsconfig.base.json +14 -0
- package/templates/apps/h5/messages/en-US.json +3 -0
- package/templates/apps/h5/messages/ja-JP.json +40 -0
- package/templates/apps/h5/messages/zh-CN.json +3 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +85 -30
- package/templates/apps/h5/src/routes/+page.svelte.hbs +20 -8
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
- package/templates/apps/mobile-app/.env.hbs +3 -0
- package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
- package/templates/apps/mobile-app/index.html.hbs +14 -0
- package/templates/apps/mobile-app/messages/en-US.json +36 -0
- package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
- package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
- package/templates/apps/mobile-app/public/runtime-config.js +1 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +153 -0
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +213 -0
- package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +14 -0
- package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +58 -0
- package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -0
- package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +16 -0
- package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
- package/templates/apps/website/messages/en-US.json +4 -2
- package/templates/apps/website/messages/ja-JP.json +34 -0
- package/templates/apps/website/messages/zh-CN.json +4 -2
- package/templates/apps/website/scripts/static-website.mjs.hbs +67 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +77 -26
- package/templates/apps/website/src/routes/+layout.ts +3 -0
- package/templates/apps/website/src/routes/+page.svelte.hbs +31 -12
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
- package/templates/apps/website/src/routes/api/health/+server.ts +3 -0
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +44 -34
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
- package/templates/base/.dockerignore.hbs +27 -0
- package/templates/base/.gitignore.hbs +41 -0
- package/templates/base/.npmrc.hbs +1 -0
- package/templates/base/e2e/app.spec.ts.hbs +213 -0
- package/templates/base/e2e/helpers.ts +1 -1
- package/templates/base/eslint-rules.js +45 -0
- package/templates/base/eslint.config.js.hbs +34 -0
- package/templates/base/hai.json.hbs +4 -0
- package/templates/base/images/web/nginx.conf.hbs +24 -0
- package/templates/base/images/web.Dockerfile.hbs +72 -0
- package/templates/base/package.json.hbs +125 -49
- package/templates/base/playwright.config.ts +44 -6
- package/templates/base/pnpm-workspace.yaml.hbs +40 -0
- package/templates/base/src/app.css.hbs +40 -0
- package/templates/base/src/app.d.ts.hbs +14 -1
- package/templates/base/src/app.html.hbs +13 -0
- package/templates/base/src/hooks.server.ts.hbs +115 -43
- package/templates/base/src/lib/build-metadata.ts.hbs +7 -0
- package/templates/base/src/lib/server/init.ts.hbs +125 -152
- package/templates/base/src/lib/server/kit-config.ts.hbs +40 -0
- package/templates/base/src/routes/+layout.server.ts.hbs +35 -0
- package/templates/base/static/favicon.png +0 -0
- package/templates/base/svelte.config.js.hbs +84 -5
- package/templates/base/tests/scaffold.test.ts.hbs +102 -0
- package/templates/base/tsconfig.json.hbs +50 -0
- package/templates/base/vite.config.ts.hbs +117 -12
- package/templates/base/vitest.config.ts.hbs +19 -0
- package/templates/features/ai/routes/api/chat/+server.ts +6 -7
- package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +3 -17
- package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +9 -122
- package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +9 -112
- package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-shared/api/auth/captcha/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-shared/api/auth/config/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/+server.ts +1 -29
- package/templates/features/iam/routes-shared/api/auth/login/ldap/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/otp/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +13 -6
- package/templates/features/iam/routes-shared/api/auth/otp/send/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password/renew/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/confirm/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/request/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/reauthenticate/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/register/+server.ts +1 -23
- package/templates/features/iam/routes-shared/api/auth/session/close/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +25 -23
- package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +5 -2
- package/templates/features/storage/routes/api/upload/+server.ts +10 -8
- package/templates/i18n/project.inlang/settings.json +2 -2
- package/templates/shared/.gitattributes +11 -0
- package/templates/shared/build-metadata.ts +42 -0
- package/templates/shared/container-runtime-config.sh +30 -0
- package/templates/shared/e2e-env.ts +98 -0
- package/templates/shared/hash-router.svelte.ts +83 -0
- package/templates/shared/public-base-path.mjs +19 -0
- package/templates/shared/run-e2e.mjs +104 -0
- package/templates/shared/vite-runtime-config.ts +56 -0
- package/templates/skills/AGENTS.md +75 -16
- package/templates/skills/CLAUDE.md +0 -11
- package/templates/skills/bridges/admin/AGENTS.md +89 -0
- package/templates/skills/bridges/api/AGENTS.md +83 -0
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +102 -0
- package/templates/skills/bridges/h5/AGENTS.md +88 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +100 -0
- package/templates/skills/bridges/website/AGENTS.md +88 -0
- package/templates/skills/copilot-instructions.md +3 -59
- package/templates/skills/hai-ai/SKILL.md +44 -715
- package/templates/skills/hai-ai/guide.md +457 -0
- package/templates/skills/hai-ai/reference.md +292 -0
- package/templates/skills/hai-api-client/SKILL.md +26 -339
- package/templates/skills/hai-api-client/reference.md +180 -0
- package/templates/skills/hai-api-contract/SKILL.md +36 -0
- package/templates/skills/hai-api-contract/reference.md +280 -0
- package/templates/skills/hai-app-create/SKILL.md +38 -351
- package/templates/skills/hai-app-create/collaboration.md +52 -0
- package/templates/skills/hai-app-create/development.md +243 -0
- package/templates/skills/hai-app-create/reference.md +376 -0
- package/templates/skills/hai-app-review/SKILL.md +57 -126
- package/templates/skills/hai-app-review/differential.md +34 -0
- package/templates/skills/hai-app-tests/SKILL.md +34 -454
- package/templates/skills/hai-app-tests/reference.md +462 -0
- package/templates/skills/hai-app-tests/validation.md +42 -0
- package/templates/skills/hai-audit/SKILL.md +37 -122
- package/templates/skills/hai-audit/reference.md +184 -0
- package/templates/skills/hai-build/SKILL.md +62 -315
- package/templates/skills/hai-build/paths.md +30 -0
- package/templates/skills/hai-build/reference.md +353 -0
- package/templates/skills/hai-cache/SKILL.md +26 -175
- package/templates/skills/hai-cache/reference.md +229 -0
- package/templates/skills/hai-capacitor/SKILL.md +24 -364
- package/templates/skills/hai-capacitor/reference.md +358 -0
- package/templates/skills/hai-change-plan/SKILL.md +46 -0
- package/templates/skills/hai-ci/SKILL.md +114 -0
- package/templates/skills/hai-core/SKILL.md +31 -469
- package/templates/skills/hai-core/reference.md +557 -0
- package/templates/skills/hai-core/request-access.md +65 -0
- package/templates/skills/hai-crypto/SKILL.md +29 -180
- package/templates/skills/hai-crypto/reference.md +317 -0
- package/templates/skills/hai-datapipe/SKILL.md +24 -207
- package/templates/skills/hai-datapipe/reference.md +204 -0
- package/templates/skills/hai-deploy/SKILL.md +53 -178
- package/templates/skills/hai-deploy/credentials.md +19 -0
- package/templates/skills/hai-deploy/middleware.md +129 -0
- package/templates/skills/hai-feedback/SKILL.md +85 -0
- package/templates/skills/hai-framework-sync/SKILL.md +105 -0
- package/templates/skills/hai-framework-sync/sync.md +49 -0
- package/templates/skills/hai-iam/SKILL.md +53 -325
- package/templates/skills/hai-iam/reference.md +535 -0
- package/templates/skills/hai-kit/SKILL.md +33 -329
- package/templates/skills/hai-kit/reference.md +202 -0
- package/templates/skills/hai-payment/SKILL.md +28 -262
- package/templates/skills/hai-payment/reference.md +295 -0
- package/templates/skills/hai-pr-review/SKILL.md +41 -0
- package/templates/skills/hai-reach/SKILL.md +28 -300
- package/templates/skills/hai-reach/reference.md +363 -0
- package/templates/skills/hai-reldb/SKILL.md +28 -449
- package/templates/skills/hai-reldb/reference.md +500 -0
- package/templates/skills/hai-scheduler/SKILL.md +26 -174
- package/templates/skills/hai-scheduler/reference.md +216 -0
- package/templates/skills/hai-serv/SKILL.md +60 -0
- package/templates/skills/hai-serv/reference.md +792 -0
- package/templates/skills/hai-spec-implement/SKILL.md +50 -0
- package/templates/skills/hai-spec-implement/changes.md +67 -0
- package/templates/skills/hai-spec-implement/evaluation.md +18 -0
- package/templates/skills/hai-spec-implement/handoff.md +47 -0
- package/templates/skills/hai-spec-implement/templates.md +117 -0
- package/templates/skills/hai-spec-implement/workflow.md +56 -0
- package/templates/skills/hai-spec-review/SKILL.md +57 -0
- package/templates/skills/hai-spec-review/checklist.md +71 -0
- package/templates/skills/hai-storage/SKILL.md +31 -262
- package/templates/skills/hai-storage/reference.md +284 -0
- package/templates/skills/hai-ui/SKILL.md +62 -238
- package/templates/skills/hai-ui/guide.md +81 -0
- package/templates/skills/hai-ui/reference.md +705 -0
- package/templates/skills/hai-ui-design/SKILL.md +31 -0
- package/templates/skills/hai-ui-design/patterns.md +31 -0
- package/templates/skills/hai-ui-review/SKILL.md +32 -0
- package/templates/skills/hai-ui-review/checklist.md +29 -0
- package/templates/skills/hai-vecdb/SKILL.md +25 -267
- package/templates/skills/hai-vecdb/reference.md +325 -0
- package/templates/skills/opencode.json +0 -5
- package/dist/chunk-2H7UOFLK.js +0 -10
- package/dist/chunk-LANIDJC7.js +0 -659
- package/dist/chunk-LANIDJC7.js.map +0 -1
- package/dist/chunk-YV7WPUI6.js +0 -206
- 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-XJ6YXNAF.js +0 -15030
- package/dist/src-XJ6YXNAF.js.map +0 -1
- package/templates/apps/android-app/.env.hbs +0 -3
- package/templates/apps/android-app/messages/en-US.json +0 -24
- package/templates/apps/android-app/messages/zh-CN.json +0 -24
- package/templates/apps/android-app/src/lib/api.ts.hbs +0 -30
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
- package/templates/apps/android-app/src/routes/+layout.ts +0 -7
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
- package/templates/apps/api/src/routes/+layout.svelte +0 -14
- package/templates/apps/api/src/routes/+page.svelte +0 -11
- package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
- package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
- package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
- package/templates/base/src/app.css +0 -2
- package/templates/base/tsconfig.json +0 -8
|
@@ -1,355 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: hai-api-client
|
|
3
|
-
description:
|
|
3
|
+
description: "接入或排查 @h-ai/api-client typed API、登录 Token、自动刷新与加密传输;适用于 Web、SSR 和原生客户端。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# hai-api-client
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## 能力契约
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
| 场景 | 推荐 | 原因 |
|
|
19
|
-
|------|------|------|
|
|
20
|
-
| SSR SvelteKit 应用(同源请求) | `kit.client.create().apiFetch`(见 hai-kit SKILL) | 自动 CSRF、传输加密、同源 Cookie 透传 |
|
|
21
|
-
| SPA / 原生 App(跨域请求) | **本模块** `api.init()` + `api.call()` | 完整 Token 管理、401 自动刷新、独立 baseUrl |
|
|
22
|
-
| 契约调用(类型安全,跨域) | **本模块** `api.call(endpoint, input)` | EndpointDef 双向 Zod 校验 |
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## 适用场景
|
|
27
|
-
|
|
28
|
-
- 浏览器端/App 端统一 API 请求
|
|
29
|
-
- Bearer Token 自动管理(存储、附加、刷新)
|
|
30
|
-
- 基于 EndpointDef 契约的类型安全调用
|
|
31
|
-
- 流式响应(SSE / ReadableStream)
|
|
32
|
-
- 拦截器(请求/响应前后处理)
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 使用步骤
|
|
37
|
-
|
|
38
|
-
### 1. 初始化客户端
|
|
39
|
-
|
|
40
|
-
```typescript
|
|
41
|
-
import { api } from '@h-ai/api-client'
|
|
42
|
-
|
|
43
|
-
// 应用启动时初始化
|
|
44
|
-
await api.init({
|
|
45
|
-
baseUrl: 'http://localhost:3000',
|
|
46
|
-
auth: {
|
|
47
|
-
refreshUrl: '/auth/refresh',
|
|
48
|
-
// Token 刷新失败回调(可选,常用于跳转登录页)
|
|
49
|
-
onRefreshFailed: () => {
|
|
50
|
-
window.location.href = '/login'
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
timeout: 15000,
|
|
54
|
-
})
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
> `auth.storage` 可选:默认使用 `createLocalStorageTokenStorage()`;SSR/测试建议显式传 `createMemoryTokenStorage()`,App 端建议传 `createCapacitorTokenStorage()`。
|
|
58
|
-
|
|
59
|
-
### 2. 普通请求
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// GET 请求
|
|
63
|
-
const users = await api.get<User[]>('/api/v1/users')
|
|
64
|
-
|
|
65
|
-
// POST 请求
|
|
66
|
-
const result = await api.post<CreateResult>('/api/v1/users', {
|
|
67
|
-
username: 'alice',
|
|
68
|
-
email: 'alice@example.com',
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
// 带查询参数(直接传入 Record<string, unknown>)
|
|
72
|
-
const page = await api.get<PageResult>('/api/v1/users', { page: 1, pageSize: 20 })
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
### 3. 契约调用(推荐)
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { iamEndpoints } from '@h-ai/iam/api'
|
|
79
|
-
|
|
80
|
-
// 类型安全:入参和返回值由 EndpointDef 的 Zod schema 推导,入参/出参双向校验
|
|
81
|
-
const loginResult = await api.call(iamEndpoints.login, {
|
|
82
|
-
identifier: 'admin',
|
|
83
|
-
password: 'StrongPassword123',
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
if (loginResult.success) {
|
|
87
|
-
// loginResult.data 类型自动推导为 { user, tokens, agreements? }
|
|
88
|
-
await api.auth.setTokens(loginResult.data.tokens)
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### 4. Token 管理
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
// 手动设置 Token(登录后)
|
|
96
|
-
await api.auth.setTokens({
|
|
97
|
-
accessToken: 'xxx',
|
|
98
|
-
refreshToken: 'yyy',
|
|
99
|
-
expiresIn: 3600,
|
|
100
|
-
tokenType: 'Bearer',
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
// 清除 Token(登出)
|
|
104
|
-
await api.auth.clear()
|
|
105
|
-
|
|
106
|
-
// 监听 Token 刷新
|
|
107
|
-
api.auth.onTokenRefreshed((tokens) => {
|
|
108
|
-
// tokens 包含新的 accessToken / refreshToken
|
|
109
|
-
})
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### 5. 流式响应
|
|
113
|
-
|
|
114
|
-
```typescript
|
|
115
|
-
const controller = new AbortController()
|
|
116
|
-
|
|
117
|
-
// stream(path, body?, options?) — 返回 AsyncIterable<string>,按 SSE data: 行 yield
|
|
118
|
-
for await (const chunk of api.stream('/api/v1/ai/chat', { message: 'Hello' }, { signal: controller.signal })) {
|
|
119
|
-
// 每个 chunk 是 SSE data: 行的内容
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// 主动停止
|
|
123
|
-
controller.abort()
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### 6. 关闭
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
await api.close()
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
## 核心 API
|
|
10
|
+
| 项目 | 契约 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| 能力 | 使用 @h-ai/api-client 调用 typed API,管理 Token、刷新与加密传输 |
|
|
13
|
+
| 适用场景 | 跨端调用共享 HTTP API 或排查认证刷新 |
|
|
14
|
+
| 输入 | baseUrl、共享 contract、TokenStorage、可选 transport.crypto |
|
|
15
|
+
| 输出 | typed client;领域响应为 HaiResult |
|
|
16
|
+
| 限制 | 先 init,结束 close;浏览器 Cookie 与服务端配置匹配,原生端使用安全 TokenStorage。不要在多用户 SSR 中共享带用户 token 的单例。 |
|
|
135
17
|
|
|
136
|
-
|
|
137
|
-
| ---------------------------------- | -------------- | ------------------------------------- |
|
|
138
|
-
| `api.init(config)` | 初始化客户端 | 返回 `HaiResult<void>` |
|
|
139
|
-
| `api.close()` | 关闭并释放资源 | 重复调用安全 |
|
|
140
|
-
| `api.isInitialized` | 初始化状态 | `boolean` |
|
|
141
|
-
| `api.config` | 当前配置 | 未初始化时为 `null` |
|
|
142
|
-
| `api.get<T>(path, params?)` | GET 请求 | params 附加到 URL query string |
|
|
143
|
-
| `api.post<T>(path, body?)` | POST 请求 | body 自动 JSON 序列化 |
|
|
144
|
-
| `api.put<T>(path, body?)` | PUT 请求 | — |
|
|
145
|
-
| `api.patch<T>(path, body?)` | PATCH 请求 | — |
|
|
146
|
-
| `api.delete<T>(path, params?)` | DELETE 请求 | params 附加到 URL query string |
|
|
147
|
-
| `api.call(endpoint, input)` | 契约调用 | 入参/出参 Zod 双向校验,路径/方法由契约决定 |
|
|
148
|
-
| `api.upload(path, file, options?)` | 文件上传 | FormData,支持附加字段 |
|
|
149
|
-
| `api.stream(path, body?)` | 流式请求 | 返回 AsyncIterable<string>(SSE) |
|
|
150
|
-
| `api.auth.setTokens(tokens)` | 设置 Token | 存入 TokenStorage |
|
|
151
|
-
| `api.auth.clear()` | 清空 Token | 清空存储 |
|
|
152
|
-
| `api.auth.onTokenRefreshed(cb)` | 刷新回调 | 返回取消订阅函数,Token 自动刷新成功时通知 |
|
|
18
|
+
## 使用路径
|
|
153
19
|
|
|
154
|
-
|
|
20
|
+
1. 读取服务端 contract、apiPrefix、CORS、Cookie 与 transport 配置,选择默认客户端或 `apiClient.create(contract)`。
|
|
21
|
+
2. 浏览器使用 Cookie/内存;SSR 按请求创建客户端,原生使用安全 TokenStorage,不跨用户复用单例。
|
|
22
|
+
3. 检查 init 与每次业务调用的 `success`。登录成功后设置 tokens;优先使用 `createAuthActions` 连接认证 UI。
|
|
23
|
+
4. 同步服务端与客户端的刷新、加密和错误处理;切换配置前 close,任务结束释放客户端。
|
|
24
|
+
5. 验证登录、刷新重试、失败、退出与会话恢复。
|
|
155
25
|
|
|
156
|
-
|
|
157
|
-
interface EndpointDef<TInput, TOutput> {
|
|
158
|
-
method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
|
159
|
-
path: string
|
|
160
|
-
input: ZodSchema<TInput>
|
|
161
|
-
output: ZodSchema<TOutput>
|
|
162
|
-
requireAuth?: boolean
|
|
163
|
-
meta?: { summary?: string; tags?: string[] }
|
|
164
|
-
}
|
|
165
|
-
```
|
|
26
|
+
错误提示与诊断分离:HTTP/UI 边界用 core.error.toPublic,仅公开 i18n 安全消息及 error.traceId;重新翻译后用 core.error.formatMessage 保留关联。ToastContainer 默认只显示可读说明,自动将编号移入排查信息图标,展开后可查看、复制并提供给客户支持或开发人员。前后端日志传完整 Error 和操作上下文,使用同一 requestId/traceId 并脱敏;禁止只写通用错误标题,也不能把 cause/ext/SQL/绑定值直接返回用户。数据库日志保留安全的驱动错误码、消息和堆栈。
|
|
166
27
|
|
|
167
|
-
|
|
28
|
+
非 2xx HTTP 响应中的合法失败 HaiResult 保留服务端业务码、消息与 traceId,以真实 HTTP 状态执行脱敏。验证 409 冲突、422 输入错误、429 限流和 5xx,不只测试 HTTP 200 业务失败;UI 包装 Error 时通过 cause 保留 HaiError。
|
|
168
29
|
|
|
169
|
-
|
|
170
|
-
interface TokenStorage {
|
|
171
|
-
getAccessToken: () => Promise<string | null>
|
|
172
|
-
setAccessToken: (token: string) => Promise<void>
|
|
173
|
-
getRefreshToken: () => Promise<string | null>
|
|
174
|
-
setRefreshToken: (token: string) => Promise<void>
|
|
175
|
-
clear: () => Promise<void>
|
|
176
|
-
}
|
|
177
|
-
```
|
|
30
|
+
## 按需参考
|
|
178
31
|
|
|
179
|
-
|
|
180
|
-
App 端使用 `@h-ai/capacitor` 的 `createCapacitorTokenStorage()`。
|
|
32
|
+
serv/kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的报文返回加密的 HTTP 400 时间错误;客户端抛 `TransportTimeError`(`hai:crypto:071`),提示同步设备和服务器时间后刷新重试。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 保留该原因。不会自动重放请求或放宽防重放窗口;篡改或未认证报文仍返回通用认证失败。
|
|
181
33
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
## 错误码 — `HaiApiClientError`
|
|
185
|
-
|
|
186
|
-
| 错误码 | code | 说明 |
|
|
187
|
-
|--------|------|------|
|
|
188
|
-
| `HaiApiClientError.NETWORK_ERROR` | `hai:api-client:001` | 网络不可达 |
|
|
189
|
-
| `HaiApiClientError.TIMEOUT` | `hai:api-client:002` | 请求超时 |
|
|
190
|
-
| `HaiApiClientError.SERVER_ERROR` | `hai:api-client:003` | 5xx 服务端错误 |
|
|
191
|
-
| `HaiApiClientError.UNAUTHORIZED` | `hai:api-client:004` | 401 未认证 |
|
|
192
|
-
| `HaiApiClientError.FORBIDDEN` | `hai:api-client:005` | 403 无权限 |
|
|
193
|
-
| `HaiApiClientError.NOT_FOUND` | `hai:api-client:006` | 404 资源不存在 |
|
|
194
|
-
| `HaiApiClientError.VALIDATION_FAILED` | `hai:api-client:007` | 请求参数校验失败 |
|
|
195
|
-
| `HaiApiClientError.TOKEN_REFRESH_FAILED` | `hai:api-client:008` | Token 刷新失败 |
|
|
196
|
-
| `HaiApiClientError.NOT_INITIALIZED` | `hai:api-client:010` | 未初始化 |
|
|
197
|
-
| `HaiApiClientError.CONFIG_ERROR` | `hai:api-client:011` | 配置错误 |
|
|
198
|
-
| `HaiApiClientError.UNKNOWN` | `hai:api-client:099` | 未知错误 |
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
## API 契约范式(端到端类型安全)
|
|
203
|
-
|
|
204
|
-
> `@h-ai/api-client` 和 `@h-ai/kit` 共同消费模块 `api/` 下的 `EndpointDef` 定义,实现客户端↔服务端的全链路类型安全 + 运行时 Zod 校验。
|
|
205
|
-
|
|
206
|
-
### 契约架构
|
|
207
|
-
|
|
208
|
-
```
|
|
209
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
210
|
-
│ @h-ai/xx/api │
|
|
211
|
-
│ xx-api-schemas.ts ← Zod Schema(唯一真相源) │
|
|
212
|
-
│ xx-api-contract.ts ← xxEndpoints(method + path + schema)│
|
|
213
|
-
└─────────────┬──────────────────────────┬────────────────────┘
|
|
214
|
-
│ │
|
|
215
|
-
┌────────▼────────┐ ┌─────────▼─────────┐
|
|
216
|
-
│ 客户端(浏览器)│ │ 服务端(SvelteKit)│
|
|
217
|
-
│ api.call(ep, i) │ │ kit.fromContract │
|
|
218
|
-
│ @h-ai/api-client│ │ @h-ai/kit │
|
|
219
|
-
└────────┬────────┘ └─────────┬─────────┘
|
|
220
|
-
│ HTTP(类型安全) │
|
|
221
|
-
└──────────────────────────┘
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
### 客户端流程(本模块责任)
|
|
225
|
-
|
|
226
|
-
1. 从 `@h-ai/xx/api` 导入 `xxEndpoints`
|
|
227
|
-
2. `api.call(xxEndpoints.xxx, input)` → Zod 校验入参 → 按 method/path 发起 HTTP → Zod 校验出参
|
|
228
|
-
3. 入参或出参校验失败均返回 `VALIDATION_FAILED`(1206)
|
|
229
|
-
4. 返回 `HaiResult<TOutput>`
|
|
230
|
-
|
|
231
|
-
```typescript
|
|
232
|
-
import { storageEndpoints } from '@h-ai/storage/api'
|
|
233
|
-
import { iamEndpoints } from '@h-ai/iam/api'
|
|
234
|
-
import { aiEndpoints } from '@h-ai/ai/api'
|
|
235
|
-
|
|
236
|
-
// 存储:获取上传签名 URL
|
|
237
|
-
const upload = await api.call(storageEndpoints.presignUpload, {
|
|
238
|
-
key: 'avatars/user-1.png',
|
|
239
|
-
contentType: 'image/png',
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
// IAM:登录
|
|
243
|
-
const login = await api.call(iamEndpoints.login, {
|
|
244
|
-
username: 'admin',
|
|
245
|
-
password: 'xxx',
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
// AI:发送消息
|
|
249
|
-
const chat = await api.call(aiEndpoints.sendMessage, {
|
|
250
|
-
conversationId: 'conv-1',
|
|
251
|
-
content: 'Hello',
|
|
252
|
-
})
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### 已有契约模块一览
|
|
256
|
-
|
|
257
|
-
| 模块 | 导入路径 | 端点对象 | 典型端点 |
|
|
258
|
-
| ---------- | -------------------- | -------------------- | ------------------------------- |
|
|
259
|
-
| `storage` | `@h-ai/storage/api` | `storageEndpoints` | presignUpload, listFiles, … |
|
|
260
|
-
| `iam` | `@h-ai/iam/api` | `iamEndpoints` | login, logout, currentUser, … |
|
|
261
|
-
| `ai` | `@h-ai/ai/api` | `aiEndpoints` | chat, chatStream, sendMessage |
|
|
262
|
-
| `payment` | `@h-ai/payment/api` | `paymentEndpoints` | createOrder, queryOrder, … |
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
## 常见模式
|
|
266
|
-
|
|
267
|
-
### 与 @h-ai/iam/api 契约配合
|
|
268
|
-
|
|
269
|
-
```typescript
|
|
270
|
-
import { iamEndpoints } from '@h-ai/iam/api'
|
|
271
|
-
|
|
272
|
-
// 登录(入参字段为 identifier + password)
|
|
273
|
-
const login = await api.call(iamEndpoints.login, { identifier, password })
|
|
274
|
-
if (login.success) {
|
|
275
|
-
// login.data 类型:{ user, tokens, agreements? }
|
|
276
|
-
await api.auth.setTokens(login.data.tokens)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// 获取当前用户(自动携带 Bearer Token)
|
|
280
|
-
const me = await api.call(iamEndpoints.currentUser, {})
|
|
281
|
-
// me.data 类型:{ user, roles, permissions }
|
|
282
|
-
|
|
283
|
-
// 修改密码
|
|
284
|
-
await api.call(iamEndpoints.changePassword, { oldPassword, newPassword })
|
|
285
|
-
|
|
286
|
-
// 登出
|
|
287
|
-
const accessToken = '...' // 从 Token 存储获取
|
|
288
|
-
await api.call(iamEndpoints.logout, { accessToken })
|
|
289
|
-
await api.auth.clear()
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
#### 401 自动刷新机制
|
|
293
|
-
|
|
294
|
-
当请求收到 401 响应时,客户端自动执行:
|
|
295
|
-
|
|
296
|
-
1. 使用存储的 `refreshToken` 调用 `auth.refreshUrl`(POST)
|
|
297
|
-
2. 刷新成功 → 更新存储 → 用新 Token 重试原请求(仅重试一次)
|
|
298
|
-
3. 刷新失败 → 清空 Token → 触发 `onRefreshFailed` 回调
|
|
299
|
-
4. 多个并发 401 → **自动去重**,只发一次刷新请求
|
|
300
|
-
|
|
301
|
-
> 流式请求(`api.stream()`)同样支持 401 自动刷新 + 重试。
|
|
302
|
-
|
|
303
|
-
#### 可用的 IAM 端点
|
|
304
|
-
|
|
305
|
-
| 分类 | 端点 | 方法 | 路径 | 认证 |
|
|
306
|
-
|------|------|------|------|------|
|
|
307
|
-
| 认证 | `iamEndpoints.login` | POST | /auth/login | 否 |
|
|
308
|
-
| | `iamEndpoints.loginWithOtp` | POST | /auth/login/otp | 否 |
|
|
309
|
-
| | `iamEndpoints.logout` | POST | /auth/logout | 是 |
|
|
310
|
-
| | `iamEndpoints.currentUser` | GET | /auth/me | 是 |
|
|
311
|
-
| | `iamEndpoints.refreshToken` | POST | /auth/refresh | 否 |
|
|
312
|
-
| | `iamEndpoints.sendOtp` | POST | /auth/otp/send | 否 |
|
|
313
|
-
| | `iamEndpoints.register` | POST | /auth/register | 否 |
|
|
314
|
-
| | `iamEndpoints.changePassword` | POST | /auth/change-password | 是 |
|
|
315
|
-
| | `iamEndpoints.updateCurrentUser` | PUT | /auth/me | 是 |
|
|
316
|
-
| 用户管理 | `iamEndpoints.listUsers` | GET | /iam/users | 是 |
|
|
317
|
-
| | `iamEndpoints.getUser` | GET | /iam/users/:id | 是 |
|
|
318
|
-
| | `iamEndpoints.createUser` | POST | /iam/users | 是 |
|
|
319
|
-
| | `iamEndpoints.updateUser` | PUT | /iam/users/:id | 是 |
|
|
320
|
-
| | `iamEndpoints.deleteUser` | DELETE | /iam/users/:id | 是 |
|
|
321
|
-
| | `iamEndpoints.adminResetPassword` | POST | /iam/users/:id/reset-password | 是 |
|
|
322
|
-
| 角色管理 | `iamEndpoints.listRoles` | GET | /iam/roles | 是 |
|
|
323
|
-
| | `iamEndpoints.getRole` | GET | /iam/roles/:id | 是 |
|
|
324
|
-
| | `iamEndpoints.createRole` | POST | /iam/roles | 是 |
|
|
325
|
-
| | `iamEndpoints.updateRole` | PUT | /iam/roles/:id | 是 |
|
|
326
|
-
| | `iamEndpoints.deleteRole` | DELETE | /iam/roles/:id | 是 |
|
|
327
|
-
| 权限管理 | `iamEndpoints.listPermissions` | GET | /iam/permissions | 是 |
|
|
328
|
-
| | `iamEndpoints.getPermission` | GET | /iam/permissions/:id | 是 |
|
|
329
|
-
| | `iamEndpoints.createPermission` | POST | /iam/permissions | 是 |
|
|
330
|
-
| | `iamEndpoints.deletePermission` | DELETE | /iam/permissions/:id | 是 |
|
|
331
|
-
|
|
332
|
-
### Android App 中使用
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
import { api } from '@h-ai/api-client'
|
|
336
|
-
import { createCapacitorTokenStorage } from '@h-ai/capacitor'
|
|
337
|
-
|
|
338
|
-
// 应用启动时初始化
|
|
339
|
-
await api.init({
|
|
340
|
-
baseUrl: import.meta.env.PUBLIC_API_BASE,
|
|
341
|
-
auth: {
|
|
342
|
-
storage: createCapacitorTokenStorage(),
|
|
343
|
-
refreshUrl: '/api/v1/auth/refresh',
|
|
344
|
-
},
|
|
345
|
-
})
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
---
|
|
34
|
+
按本次操作读取对应小节;以已安装版本的公开类型核验签名,示例中的业务变量由应用提供。
|
|
349
35
|
|
|
350
|
-
|
|
36
|
+
- [使用步骤](reference.md#使用步骤)
|
|
37
|
+
- [Token Storage 适配器](reference.md#token-storage-适配器)
|
|
38
|
+
- [核心 API](reference.md#核心-api)
|
|
39
|
+
- [常见模式](reference.md#常见模式)
|
|
40
|
+
- [配置驱动认证页面](reference.md#配置驱动认证页面)
|
|
351
41
|
|
|
352
|
-
- `
|
|
353
|
-
- `hai-capacitor`:原生 Token 存储
|
|
354
|
-
- `hai-kit`:服务端契约处理(kit.fromContract)
|
|
355
|
-
- `hai-core`:HaiResult 类型、错误处理基础
|
|
42
|
+
普通请求与 Token 刷新自动将当前 `core.i18n` 语言发送为 `Accept-Language`;切换语言时同步 core。`headers` 中显式配置的同名头优先。
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# hai-api-client 参考
|
|
2
|
+
|
|
3
|
+
> `@h-ai/api-client` 是跨端 typed API client。公共 HTTP API 由 `@h-ai/api-contract` 定义,服务端由 `@h-ai/serv` 挂载,客户端直接调用 `apiClient.<domain>.<group>.<operation>()`。
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
认证协议仅支持 v2:独立随机 SM4-CBC 密钥和 HMAC-SM3 密钥由 SM2 封装,先验签、再验证 MAC,最后解密 CBC。请求由客户端私钥签名,响应由所选服务端版本签名。认证字段包括 version、direction、serverKeyId、clientId、128 位随机 requestId(兼 nonce)、issuedAt、HTTP method、pathname + 原始 search 的 SM3 pathHash,以及响应 status。请求有效期 5 分钟,未来时钟偏差最多 30 秒;共享 registry 原子消费 (clientId, requestId),nonce 至少保留到 issuedAt + 6 分钟以覆盖节点偏差,存储故障拒绝请求。Redis 必须保留有效 nonce,使用 noeviction/可靠持久化策略;各节点时钟须同步。此能力防止同一传输消息重放,业务重试仍需自己的幂等键。
|
|
7
|
+
|
|
8
|
+
空 POST 也发送空明文的认证封装;GET/HEAD 将封装放在 X-Hai-Transport 头,204/304/HEAD 等无正文响应也使用同名头承载认证封装。其它请求/响应在 JSON 正文承载封装并带 X-Encrypted: true。客户端必须关联原请求上下文和 HTTP status,缺标记、旧格式或认证失败一律 reject;明文接口由 Serv/Kit 路径规则 `encryption: disabled` 或宿主 `excludePaths` 显式允许;调用方同步选择普通请求,API Client/Kit 包装器使用自己的 `excludePaths`。CORS 须允许并暴露 X-Hai-Transport。握手公钥的真实性依赖 TLS,不替代 IAM 业务授权。
|
|
9
|
+
|
|
10
|
+
## 使用步骤
|
|
11
|
+
|
|
12
|
+
### 1. 初始化
|
|
13
|
+
|
|
14
|
+
浏览器默认使用 httpOnly cookie 存储(推荐):
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { apiClient } from '@h-ai/api-client'
|
|
18
|
+
|
|
19
|
+
await apiClient.init({
|
|
20
|
+
baseUrl: 'https://api.example.com/api/v1',
|
|
21
|
+
auth: {},
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
启用传输加密时,只传顶层 `crypto` 句柄;api-client 内部自动调用 `crypto.transport.createClient()`:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { apiClient } from '@h-ai/api-client'
|
|
29
|
+
import { crypto } from '@h-ai/crypto'
|
|
30
|
+
|
|
31
|
+
await crypto.init()
|
|
32
|
+
|
|
33
|
+
await apiClient.init({
|
|
34
|
+
baseUrl: 'https://api.example.com/api/v1',
|
|
35
|
+
auth: {},
|
|
36
|
+
transport: { crypto }, // 默认协商路径:/api/v1/_hai/key-exchange
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
App/Capacitor 场景传入自定义 TokenStorage:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { createCapacitorTokenStorage } from '@h-ai/capacitor'
|
|
44
|
+
|
|
45
|
+
await apiClient.init({
|
|
46
|
+
baseUrl: 'https://api.example.com/api/v1',
|
|
47
|
+
auth: { storage: createCapacitorTokenStorage() },
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> `createCapacitorTokenStorage()` 仅在 Android/iOS 原生环境 + `@aparajita/capacitor-secure-storage` 已安装时持久化 token;纯 Web 不会回退到 `localStorage`。
|
|
52
|
+
|
|
53
|
+
SSR / Node.js 测试场景请显式传入内存存储:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { apiClient } from '@h-ai/api-client'
|
|
57
|
+
|
|
58
|
+
await apiClient.init({
|
|
59
|
+
baseUrl: 'https://api.example.com/api/v1',
|
|
60
|
+
auth: { storage: apiClient.tokenStorage.memory() },
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. 调用 typed API
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
const login = await apiClient.iam.auth.login({ identifier: 'alice', password: 'secret' })
|
|
68
|
+
if (login.success) {
|
|
69
|
+
// 默认 httpOnly cookie 模式下,refresh token 由服务端 Set-Cookie 管理。
|
|
70
|
+
await apiClient.auth.setTokens(login.data.tokens)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const me = await apiClient.iam.auth.currentUser()
|
|
74
|
+
if (me.success) {
|
|
75
|
+
// currentUser 返回服务端最新角色/权限;不要把权限快照持久化到 localStorage。
|
|
76
|
+
const { roles, permissions, ...user } = me.data
|
|
77
|
+
}
|
|
78
|
+
const upload = await apiClient.storage.presignedUrls.createUpload({ key: 'avatar.png' })
|
|
79
|
+
const answer = await apiClient.ai.chats.sendMessage({ message: 'hello' })
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
默认 `ai.chats.createCompletion({ messages, tools, tool_choice })` 只返回非流式 HaiResult JSON;不接受 stream 字段。完整 function 参数 JSON Schema、strict 与工具选择直接到模型。先检查 success,再读取助手 tool_calls;业务方授权执行工具后,以对应 tool_call_id 回传工具消息。流式接口须绑定应用自定义流契约。
|
|
83
|
+
|
|
84
|
+
### 3. 自定义 contract
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { apiClient } from '@h-ai/api-client'
|
|
88
|
+
import { apiContract } from '@h-ai/api-contract'
|
|
89
|
+
|
|
90
|
+
const contract = apiContract.create({ iam: apiContract.iam })
|
|
91
|
+
const client = apiClient.create(contract)
|
|
92
|
+
await client.init({ baseUrl: 'https://api.example.com/api/v1' })
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`client.config` / `apiClient.config` 返回的是脱敏后的运行配置快照;`baseUrl` 的内嵌凭证与 `headers.authorization` 等敏感值会自动隐藏。
|
|
96
|
+
|
|
97
|
+
### 4. 关闭
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
await apiClient.close()
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
> 已初始化后再次 `init()` 会返回 `CONFIG_ERROR`,不会覆盖现有 client;切换 `baseUrl` / `fetch` / `transport` 前必须先 `close()`,避免旧 transport 会话泄漏。
|
|
104
|
+
|
|
105
|
+
## Token Storage 适配器
|
|
106
|
+
|
|
107
|
+
| 工厂调用 | 存储位置 | 适用场景 |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `apiClient.tokenStorage.httpOnlyCookie()` | httpOnly cookie(服务端管理) | **默认**;浏览器端推荐,refresh token 不暴露给 JS |
|
|
110
|
+
| `apiClient.tokenStorage.memory()` | 内存 | SSR / Node.js 单元测试(需显式传入) |
|
|
111
|
+
|
|
112
|
+
浏览器只使用内存 access token + 服务端 httpOnly refresh Cookie;原生端注入平台安全 TokenStorage。禁止将认证凭据持久化到 Web Storage。
|
|
113
|
+
|
|
114
|
+
### httpOnly Cookie 模式
|
|
115
|
+
|
|
116
|
+
Access token 存在内存中,refresh token 由服务端通过 `HttpOnly` cookie 管理,浏览器 JS 无法读取,可有效防止 XSS 窃取 token。
|
|
117
|
+
|
|
118
|
+
**前提**:服务端需配置 `serv.createApp({ iam, refreshCookie: {} })`,参见 `hai-serv` skill。
|
|
119
|
+
|
|
120
|
+
启用 `transport` 时,登录、业务请求以及 401 后的自动刷新都会复用同一个加密 fetch 链路;不要在业务代码中手写明文 `/auth/refresh` 请求。
|
|
121
|
+
|
|
122
|
+
自动刷新识别真实 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` 并处理刷新失败后的登录失效。
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { apiClient } from '@h-ai/api-client'
|
|
126
|
+
|
|
127
|
+
// apiClient.tokenStorage.httpOnlyCookie() 是默认存储,无需显式指定
|
|
128
|
+
await apiClient.init({
|
|
129
|
+
baseUrl: 'https://api.example.com/api/v1',
|
|
130
|
+
auth: {},
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// 登录后设置 access token(refresh token 由服务端写入 cookie,前端无需操作)
|
|
134
|
+
const login = await apiClient.iam.auth.login({ identifier: 'alice', password: 'secret' })
|
|
135
|
+
if (login.success) {
|
|
136
|
+
await apiClient.auth.setTokens(login.data.tokens)
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## 核心 API
|
|
141
|
+
|
|
142
|
+
| API | 用途 |
|
|
143
|
+
| --- | --- |
|
|
144
|
+
| `apiClient.init(config)` | 初始化默认 API Service client;重复初始化返回 `CONFIG_ERROR` |
|
|
145
|
+
| `apiClient.close()` | 清理 client 状态 |
|
|
146
|
+
| `apiClient.auth.setTokens(tokens)` | 使旧刷新失效并替换凭据;非 httpOnly 存储保存提供的 refresh token,缺省时清除旧值 |
|
|
147
|
+
| `apiClient.auth.clear()` | 使旧刷新失效并清理本客户端 Token;服务端会话/Cookie 另由退出接口撤销 |
|
|
148
|
+
| `apiClient.auth.onTokenRefreshed(cb)` | 监听刷新结果 |
|
|
149
|
+
| `apiClient.create(contract)` | 创建自定义 typed client |
|
|
150
|
+
| `apiClient.tokenStorage.{memory,httpOnlyCookie}()` | TokenStorage 工厂 |
|
|
151
|
+
|
|
152
|
+
退出/换账号使用 `auth.clear()` / `auth.setTokens()`,不直接写 storage。方法立即取消旧刷新,并按顺序提交异步存储操作;迟到的成功/401 不会恢复旧身份、覆盖新账号或触发旧回调。该保证针对同一个客户端的认证管理器,SSR 仍须按请求隔离实例。
|
|
153
|
+
|
|
154
|
+
### Transport 配置
|
|
155
|
+
|
|
156
|
+
| 字段 | 说明 |
|
|
157
|
+
| --- | --- |
|
|
158
|
+
| `transport.crypto` | 已初始化的 `@h-ai/crypto` 实例 |
|
|
159
|
+
| `transport.keyExchangePath` | 相对于 `baseUrl` 的协商子路径,默认 `/_hai/key-exchange` |
|
|
160
|
+
|
|
161
|
+
服务端必须对应启用 `serv.createApp({ transport: { crypto, serverKeyRing, keyStore } })`。serverKeyRing 与 keyStore 仅服务端注入,生产各节点共用受管版本化 ring 和共享 registry;客户端只接收 serverKeyId/公钥并在请求密文带回版本,不得接收私钥。旧版本撤销后需销毁客户端会话并重协商,不自动重放非幂等请求。
|
|
162
|
+
自动刷新会沿用 `transport.encryptedFetch`,并在 httpOnly cookie 模式下发送空请求体 + `credentials: 'include'`,由服务端从 cookie 读取 refresh token。
|
|
163
|
+
|
|
164
|
+
CLI 独立 mobile 模板在选择 IAM/crypto 时安装前端 crypto 并默认启用该 transport,未选择 crypto 时保留明文 API 模式。`PUBLIC_API_TRANSPORT=off` 仅用于明确匹配的明文服务;`PUBLIC_API_KEY_EXCHANGE_PATH` 可调整公开协商子路径。配置先于 client 初始化,握手失败不会回退明文。关闭顺序为 client → 本客户端初始化的 crypto,不能关闭其他调用方已有的 crypto。
|
|
165
|
+
|
|
166
|
+
## 常见模式
|
|
167
|
+
|
|
168
|
+
- `baseUrl` 通常包含服务端 `apiPrefix`,例如 `/api/v1`。
|
|
169
|
+
- 业务错误不 throw,统一判断 `HaiResult.success`。
|
|
170
|
+
- 客户端不导入服务端 `procedures` 或 `@h-ai/serv`。
|
|
171
|
+
- 客户端不导入 `@h-ai/crypto` 的内部 transport 工厂,只通过 `transport: { crypto }` 装配。
|
|
172
|
+
- 前端只依赖 `@h-ai/api-client` 和 contract 类型,不依赖业务模块实现。
|
|
173
|
+
- httpOnly cookie 模式需服务端与客户端同步配置,跨 Origin 请求需正确设置 CORS 与 credentials;`SameSite=Strict` 限制跨站 Cookie,跨域不等于跨站。
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
## 配置驱动认证页面
|
|
177
|
+
|
|
178
|
+
`apiClient.createAuthActions(client)` 为含标准 iam contract 的客户端提供 publicConfig、login、register、sendOtp、requestPasswordReset、confirmPasswordReset。login 输入使用 identifier/password/method/code,method 为 password、ldap、email、sms。成功认证自动调用既有安全 TokenStorage;应用只需把动作传给 AuthPanel,并在 onauthenticated 中刷新自己的用户状态或导航。
|
|
179
|
+
|
|
180
|
+
传输容量默认从服务端握手获取 `maxPlaintextBytes`;可选客户端 `transport.maxPlaintextBytes` 只收紧上限。容量失败映射为 `HaiApiClientError.PAYLOAD_TOO_LARGE`(`hai:api-client:020`),cause 保留 direction/stage/limitBytes/actualBytes,应用可据此显示本地化提示。
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: hai-api-contract
|
|
3
|
+
description: "新增、组合或修改共享 HTTP 接口的路径与输入输出 Schema,供 serv 与 typed client 共用。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# hai-api-contract
|
|
7
|
+
|
|
8
|
+
## 能力契约
|
|
9
|
+
|
|
10
|
+
| 项目 | 契约 |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| 能力 | 使用 @h-ai/api-contract 定义、组合和扩展共享 HTTP contract 与 Zod 输入输出 |
|
|
13
|
+
| 适用场景 | 新增/修改共享接口定义,不负责实现 handler |
|
|
14
|
+
| 输入 | 领域路径、schema、HTTP 方法、共享错误模型 |
|
|
15
|
+
| 输出 | 供 serv 实现和 api-client 消费的 contract |
|
|
16
|
+
| 限制 | 纯定义,无 init/close;不包含服务端实现或密钥。业务路径属于 contract,公共传输配置属于 transport。 |
|
|
17
|
+
|
|
18
|
+
## 使用路径
|
|
19
|
+
|
|
20
|
+
1. 查当前公开 exports 与已有领域 contract,确认业务路径唯一来源。
|
|
21
|
+
2. 在 contract 中声明 method/path 与输入输出 Schema;只导出真正跨接口或跨层复用的 Schema。
|
|
22
|
+
3. 用 `apiContract.create` 组合领域;不把服务实现、私有配置或传输前缀写进 contract。
|
|
23
|
+
4. 同步 serv procedures、typed client、调用方与失败/校验测试;普通业务输出按当前 HaiResult 契约。
|
|
24
|
+
5. 独立 contract 包实际执行声明构建。推导需要的上游公共类型 `ContractProcedureBuilderWithInputOutput`、`ContractProcedureBuilderWithOutput`、`Schema` 已由本包转出;显式类型从公开入口 `import type`,不引用依赖内部路径。
|
|
25
|
+
|
|
26
|
+
## 按需参考
|
|
27
|
+
|
|
28
|
+
按本次操作读取对应小节;以已安装版本的公开类型核验签名,示例中的业务变量由应用提供。
|
|
29
|
+
|
|
30
|
+
- [运行环境](reference.md#运行环境)
|
|
31
|
+
- [适用场景](reference.md#适用场景)
|
|
32
|
+
- [使用步骤](reference.md#使用步骤)
|
|
33
|
+
- [核心 API](reference.md#核心-api)
|
|
34
|
+
- [Contract 定义规范](reference.md#contract-定义规范)
|
|
35
|
+
- [常见模式](reference.md#常见模式)
|
|
36
|
+
- [测试](reference.md#测试)
|