@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,32 +1,51 @@
|
|
|
1
1
|
{{!-- 官网首页 --}}
|
|
2
|
-
<script lang=
|
|
2
|
+
<script lang='ts'>
|
|
3
3
|
/**
|
|
4
4
|
* 官网首页
|
|
5
5
|
*/
|
|
6
|
+
import { resolve } from '$app/paths'
|
|
7
|
+
import { page } from '$app/state'
|
|
6
8
|
{{#if hasI18n}}
|
|
7
9
|
import * as m from '$lib/paraglide/messages'
|
|
8
10
|
{{/if}}
|
|
11
|
+
import { Badge } from '@h-ai/ui'
|
|
9
12
|
</script>
|
|
10
13
|
|
|
11
14
|
<svelte:head>
|
|
12
15
|
{{#if hasI18n}}
|
|
13
|
-
<title>{
|
|
16
|
+
<title>{page.data.appConfig.name}</title>
|
|
14
17
|
{{else}}
|
|
15
|
-
<title
|
|
18
|
+
<title>{page.data.appConfig.name}</title>
|
|
16
19
|
{{/if}}
|
|
17
20
|
</svelte:head>
|
|
18
21
|
|
|
19
|
-
<section class=
|
|
20
|
-
<div class=
|
|
21
|
-
<div class=
|
|
22
|
+
<section class='hero min-h-[60vh] bg-gradient-to-b from-base-200 to-base-100'>
|
|
23
|
+
<div class='hero-content text-center'>
|
|
24
|
+
<div class='max-w-xl'>
|
|
25
|
+
<div class='flex justify-center'>
|
|
26
|
+
<Badge variant='primary'>
|
|
27
|
+
<span class='icon-[tabler--sparkles] size-4'></span>
|
|
22
28
|
{{#if hasI18n}}
|
|
23
|
-
|
|
24
|
-
<p class="py-6">{m.page_home_subtitle()}</p>
|
|
25
|
-
<a href="/about" class="btn btn-primary">{m.page_home_cta()}</a>
|
|
29
|
+
{page.data.appConfig.name}
|
|
26
30
|
{{else}}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
由 hai 驱动
|
|
32
|
+
{{/if}}
|
|
33
|
+
</Badge>
|
|
34
|
+
</div>
|
|
35
|
+
{{#if hasI18n}}
|
|
36
|
+
<h1 class='mt-5 text-5xl font-black tracking-tight'>{m.page_home_title()}</h1>
|
|
37
|
+
<p class='py-6 text-base-content/60'>{m.page_home_subtitle()}</p>
|
|
38
|
+
<a href={resolve('/about', {})} class='btn btn-primary'>
|
|
39
|
+
<span class='icon-[tabler--arrow-right] size-5'></span>
|
|
40
|
+
{m.page_home_cta()}
|
|
41
|
+
</a>
|
|
42
|
+
{{else}}
|
|
43
|
+
<h1 class='mt-5 text-5xl font-black tracking-tight'>欢迎</h1>
|
|
44
|
+
<p class='py-6 text-base-content/60'>基于 hai Agent Framework 构建</p>
|
|
45
|
+
<a href={resolve('/about', {})} class='btn btn-primary'>
|
|
46
|
+
<span class='icon-[tabler--arrow-right] size-5'></span>
|
|
47
|
+
了解更多
|
|
48
|
+
</a>
|
|
30
49
|
{{/if}}
|
|
31
50
|
</div>
|
|
32
51
|
</div>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{{!-- 关于页面 --}}
|
|
2
|
-
<script lang=
|
|
2
|
+
<script lang='ts'>
|
|
3
3
|
/**
|
|
4
4
|
* 关于页面
|
|
5
5
|
*/
|
|
6
6
|
{{#if hasI18n}}
|
|
7
7
|
import * as m from '$lib/paraglide/messages'
|
|
8
8
|
{{/if}}
|
|
9
|
+
import { Card, PageHeader } from '@h-ai/ui'
|
|
9
10
|
</script>
|
|
10
11
|
|
|
11
12
|
<svelte:head>
|
|
@@ -16,12 +17,16 @@
|
|
|
16
17
|
{{/if}}
|
|
17
18
|
</svelte:head>
|
|
18
19
|
|
|
19
|
-
<section class=
|
|
20
|
+
<section class='py-16 px-4 max-w-4xl mx-auto'>
|
|
20
21
|
{{#if hasI18n}}
|
|
21
|
-
<
|
|
22
|
-
<
|
|
22
|
+
<PageHeader title={m.page_about_title()} />
|
|
23
|
+
<Card shadow='sm' class='bg-base-100'>
|
|
24
|
+
<p class='text-lg text-base-content/70'>{m.page_about_desc()}</p>
|
|
25
|
+
</Card>
|
|
23
26
|
{{else}}
|
|
24
|
-
<
|
|
25
|
-
<
|
|
27
|
+
<PageHeader title='关于我们' />
|
|
28
|
+
<Card shadow='sm' class='bg-base-100'>
|
|
29
|
+
<p class='text-lg text-base-content/70'>了解我们的团队与使命。</p>
|
|
30
|
+
</Card>
|
|
26
31
|
{{/if}}
|
|
27
32
|
</section>
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
{{!-- 联系页面 --}}
|
|
2
|
-
<script lang=
|
|
2
|
+
<script lang='ts'>
|
|
3
3
|
/**
|
|
4
4
|
* 联系我们页面
|
|
5
5
|
*/
|
|
6
6
|
{{#if hasI18n}}
|
|
7
7
|
import * as m from '$lib/paraglide/messages'
|
|
8
8
|
{{/if}}
|
|
9
|
+
import { Button, Card, FormField, FormLayout, Input, notifyWarning, PageHeader, Textarea } from '@h-ai/ui'
|
|
10
|
+
|
|
11
|
+
let name = $state('')
|
|
12
|
+
let email = $state('')
|
|
13
|
+
let message = $state('')
|
|
14
|
+
|
|
15
|
+
function handleSubmit(event: SubmitEvent) {
|
|
16
|
+
event.preventDefault()
|
|
17
|
+
{{#if hasI18n}}
|
|
18
|
+
notifyWarning(m.page_contact_unavailable())
|
|
19
|
+
{{else}}
|
|
20
|
+
notifyWarning('在线留言尚未开通,请使用其他联系方式。您的输入已保留。')
|
|
21
|
+
{{/if}}
|
|
22
|
+
}
|
|
9
23
|
</script>
|
|
10
24
|
|
|
11
25
|
<svelte:head>
|
|
@@ -16,44 +30,40 @@
|
|
|
16
30
|
{{/if}}
|
|
17
31
|
</svelte:head>
|
|
18
32
|
|
|
19
|
-
<section class=
|
|
33
|
+
<section class='py-16 px-4 max-w-2xl mx-auto'>
|
|
20
34
|
{{#if hasI18n}}
|
|
21
|
-
<
|
|
22
|
-
<p class="text-lg text-gray-600 mb-8">{m.page_contact_desc()}</p>
|
|
35
|
+
<PageHeader title={m.page_contact_title()} description={m.page_contact_desc()} />
|
|
23
36
|
{{else}}
|
|
24
|
-
<
|
|
25
|
-
<p class="text-lg text-gray-600 mb-8">有任何疑问?欢迎联系我们。</p>
|
|
37
|
+
<PageHeader title='联系我们' description='有任何疑问?欢迎联系我们。' />
|
|
26
38
|
{{/if}}
|
|
27
39
|
|
|
28
|
-
<
|
|
29
|
-
<
|
|
30
|
-
{
|
|
31
|
-
<label class="label" for="name"><span class="label-text">{m.page_contact_name()}</span></label>
|
|
32
|
-
{{else}}
|
|
33
|
-
<label class="label" for="name"><span class="label-text">姓名</span></label>
|
|
34
|
-
{{/if}}
|
|
35
|
-
<input id="name" type="text" class="input input-bordered w-full" />
|
|
36
|
-
</div>
|
|
37
|
-
<div class="form-control">
|
|
38
|
-
{{#if hasI18n}}
|
|
39
|
-
<label class="label" for="email"><span class="label-text">{m.page_contact_email()}</span></label>
|
|
40
|
-
{{else}}
|
|
41
|
-
<label class="label" for="email"><span class="label-text">邮箱</span></label>
|
|
42
|
-
{{/if}}
|
|
43
|
-
<input id="email" type="email" class="input input-bordered w-full" />
|
|
44
|
-
</div>
|
|
45
|
-
<div class="form-control">
|
|
46
|
-
{{#if hasI18n}}
|
|
47
|
-
<label class="label" for="message"><span class="label-text">{m.page_contact_message()}</span></label>
|
|
48
|
-
{{else}}
|
|
49
|
-
<label class="label" for="message"><span class="label-text">留言</span></label>
|
|
50
|
-
{{/if}}
|
|
51
|
-
<textarea id="message" class="textarea textarea-bordered w-full" rows="4"></textarea>
|
|
52
|
-
</div>
|
|
40
|
+
<Card shadow='sm' class='bg-base-100'>
|
|
41
|
+
<form onsubmit={handleSubmit}>
|
|
42
|
+
<FormLayout columns={2} labelPosition='top'>
|
|
53
43
|
{{#if hasI18n}}
|
|
54
|
-
|
|
44
|
+
<FormField for='name' label={m.page_contact_name()} required>
|
|
45
|
+
<Input id='name' type='text' bind:value={name} required />
|
|
46
|
+
</FormField>
|
|
47
|
+
<FormField for='email' label={m.page_contact_email()} required>
|
|
48
|
+
<Input id='email' type='email' bind:value={email} required />
|
|
49
|
+
</FormField>
|
|
50
|
+
<FormField for='message' label={m.page_contact_message()} required>
|
|
51
|
+
<Textarea id='message' rows={4} bind:value={message} required />
|
|
52
|
+
</FormField>
|
|
53
|
+
<Button type='submit' variant='primary' class='w-full'>{m.page_contact_submit()}</Button>
|
|
55
54
|
{{else}}
|
|
56
|
-
|
|
55
|
+
<FormField for='name' label='姓名' required>
|
|
56
|
+
<Input id='name' type='text' bind:value={name} required />
|
|
57
|
+
</FormField>
|
|
58
|
+
<FormField for='email' label='邮箱' required>
|
|
59
|
+
<Input id='email' type='email' bind:value={email} required />
|
|
60
|
+
</FormField>
|
|
61
|
+
<FormField for='message' label='留言' required>
|
|
62
|
+
<Textarea id='message' rows={4} bind:value={message} required />
|
|
63
|
+
</FormField>
|
|
64
|
+
<Button type='submit' variant='primary' class='w-full'>发送</Button>
|
|
57
65
|
{{/if}}
|
|
58
|
-
|
|
66
|
+
</FormLayout>
|
|
67
|
+
</form>
|
|
68
|
+
</Card>
|
|
59
69
|
</section>
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
{{!-- 服务页面 --}}
|
|
2
|
-
<script lang=
|
|
2
|
+
<script lang='ts'>
|
|
3
3
|
/**
|
|
4
4
|
* 服务页面
|
|
5
5
|
*/
|
|
6
6
|
{{#if hasI18n}}
|
|
7
7
|
import * as m from '$lib/paraglide/messages'
|
|
8
|
+
{{/if}}
|
|
9
|
+
import { Card, PageHeader } from '@h-ai/ui'
|
|
10
|
+
|
|
11
|
+
{{#if hasI18n}}
|
|
12
|
+
const services = $derived([
|
|
13
|
+
{ id: 'consulting', title: m.page_services_item1(), desc: m.page_services_desc(), icon: 'icon-[tabler--message-circle]' },
|
|
14
|
+
{ id: 'development', title: m.page_services_item2(), desc: m.page_services_desc(), icon: 'icon-[tabler--code]' },
|
|
15
|
+
{ id: 'operations', title: m.page_services_item3(), desc: m.page_services_desc(), icon: 'icon-[tabler--server-cog]' },
|
|
16
|
+
])
|
|
17
|
+
{{else}}
|
|
18
|
+
const services = [
|
|
19
|
+
{ id: 'consulting', title: '咨询服务', desc: '提供专业的技术咨询与解决方案。', icon: 'icon-[tabler--message-circle]' },
|
|
20
|
+
{ id: 'development', title: '定制开发', desc: '根据需求定制开发高质量应用。', icon: 'icon-[tabler--code]' },
|
|
21
|
+
{ id: 'operations', title: '运维支持', desc: '提供全方位的系统运维与技术支持。', icon: 'icon-[tabler--server-cog]' },
|
|
22
|
+
]
|
|
8
23
|
{{/if}}
|
|
9
24
|
</script>
|
|
10
25
|
|
|
@@ -16,48 +31,20 @@
|
|
|
16
31
|
{{/if}}
|
|
17
32
|
</svelte:head>
|
|
18
33
|
|
|
19
|
-
<section class=
|
|
34
|
+
<section class='mx-auto w-full max-w-[120rem] px-4 py-16 sm:px-6 lg:px-8'>
|
|
20
35
|
{{#if hasI18n}}
|
|
21
|
-
<
|
|
22
|
-
<p class="text-lg text-gray-600 mb-12">{m.page_services_desc()}</p>
|
|
36
|
+
<PageHeader title={m.page_services_title()} description={m.page_services_desc()} />
|
|
23
37
|
{{else}}
|
|
24
|
-
<
|
|
25
|
-
<p class="text-lg text-gray-600 mb-12">我们提供以下专业服务。</p>
|
|
38
|
+
<PageHeader title='我们的服务' description='我们提供以下专业服务。' />
|
|
26
39
|
{{/if}}
|
|
27
40
|
|
|
28
|
-
<div class=
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
{
|
|
32
|
-
<h2 class=
|
|
33
|
-
<p>{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<p>提供专业的技术咨询与解决方案。</p>
|
|
37
|
-
{{/if}}
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
<div class="card bg-base-100 shadow">
|
|
41
|
-
<div class="card-body">
|
|
42
|
-
{{#if hasI18n}}
|
|
43
|
-
<h2 class="card-title">{m.page_services_item2()}</h2>
|
|
44
|
-
<p>{m.page_services_desc()}</p>
|
|
45
|
-
{{else}}
|
|
46
|
-
<h2 class="card-title">定制开发</h2>
|
|
47
|
-
<p>根据需求定制开发高质量应用。</p>
|
|
48
|
-
{{/if}}
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
<div class="card bg-base-100 shadow">
|
|
52
|
-
<div class="card-body">
|
|
53
|
-
{{#if hasI18n}}
|
|
54
|
-
<h2 class="card-title">{m.page_services_item1()}</h2>
|
|
55
|
-
<p>{m.page_services_desc()}</p>
|
|
56
|
-
{{else}}
|
|
57
|
-
<h2 class="card-title">运维支持</h2>
|
|
58
|
-
<p>提供全方位的系统运维与技术支持。</p>
|
|
59
|
-
{{/if}}
|
|
60
|
-
</div>
|
|
61
|
-
</div>
|
|
41
|
+
<div class='grid grid-cols-1 md:grid-cols-3 gap-6'>
|
|
42
|
+
{#each services as service (service.id)}
|
|
43
|
+
<Card shadow='sm' class='bg-base-100'>
|
|
44
|
+
<span class='{service.icon} size-8 text-primary'></span>
|
|
45
|
+
<h2 class='mt-3 text-lg font-semibold'>{service.title}</h2>
|
|
46
|
+
<p class='mt-1 text-sm text-base-content/60'>{service.desc}</p>
|
|
47
|
+
</Card>
|
|
48
|
+
{/each}
|
|
62
49
|
</div>
|
|
63
50
|
</section>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
**/.git
|
|
2
|
+
**/node_modules
|
|
3
|
+
**/.pnpm-store
|
|
4
|
+
**/.cache
|
|
5
|
+
**/.svelte-kit
|
|
6
|
+
**/.turbo
|
|
7
|
+
**/build
|
|
8
|
+
**/dist
|
|
9
|
+
**/coverage
|
|
10
|
+
**/playwright-report
|
|
11
|
+
**/test-results
|
|
12
|
+
**/src-tauri/target
|
|
13
|
+
**/hash-core/target
|
|
14
|
+
tmp
|
|
15
|
+
**/*.tar
|
|
16
|
+
.github
|
|
17
|
+
.agents
|
|
18
|
+
.claude
|
|
19
|
+
.codex
|
|
20
|
+
.opencode
|
|
21
|
+
android
|
|
22
|
+
ios
|
|
23
|
+
**/data
|
|
24
|
+
*.log
|
|
25
|
+
# 仅保留公共基础 .env;分环境配置、私有覆盖及已有交付包不进入构建上下文。
|
|
26
|
+
**/.env.*
|
|
27
|
+
**/.hai
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 构建产物目录
|
|
2
|
+
node_modules
|
|
3
|
+
{{#unless isSvelteOnlyApp}}
|
|
4
|
+
.svelte-kit
|
|
5
|
+
{{/unless}}
|
|
6
|
+
build
|
|
7
|
+
dist
|
|
8
|
+
.turbo
|
|
9
|
+
android
|
|
10
|
+
ios
|
|
11
|
+
**/src/lib/paraglide
|
|
12
|
+
**/src-tauri/gen/
|
|
13
|
+
**/src-tauri/target/
|
|
14
|
+
**/hash-core/target/
|
|
15
|
+
|
|
16
|
+
# 日志测试目录
|
|
17
|
+
*.log
|
|
18
|
+
test-results/
|
|
19
|
+
playwright-report/
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# 系统文件
|
|
23
|
+
.DS_Store
|
|
24
|
+
|
|
25
|
+
# 本地数据目录
|
|
26
|
+
**/data/
|
|
27
|
+
|
|
28
|
+
# 构建与部署产物(镜像 / Compose tar / 私有运行配置)
|
|
29
|
+
.hai/
|
|
30
|
+
*.tar
|
|
31
|
+
|
|
32
|
+
# 本机私有配置;公共 .env 与 dev/test/prod 环境文件纳入版本控制。
|
|
33
|
+
.env.local
|
|
34
|
+
.env.*.local
|
|
35
|
+
|
|
36
|
+
# 构建器生成的安装输入快照
|
|
37
|
+
**/images/dependencies/
|
|
38
|
+
|
|
39
|
+
# 项目本地缓存
|
|
40
|
+
**/.pnpm-store/
|
|
41
|
+
**/.cache/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# 注册表与认证可配置在此;pnpm 专属设置统一位于 pnpm-workspace.yaml。
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
{{#if features.iam}}
|
|
2
|
+
import { randomUUID } from 'node:crypto'
|
|
3
|
+
{{/if}}
|
|
4
|
+
import { mkdir } from 'node:fs/promises'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
import process from 'node:process'
|
|
7
|
+
import { expect, test } from '@playwright/test'
|
|
8
|
+
|
|
9
|
+
{{#if_eq appType 'admin'}}
|
|
10
|
+
test('high contrast appearance is selectable and survives reload', async ({ page }) => {
|
|
11
|
+
await page.goto('./')
|
|
12
|
+
const header = page.locator('header').first()
|
|
13
|
+
await header.getByRole('button', { name: /选择主题|Select theme|テーマを選択/, exact: true }).click()
|
|
14
|
+
await header.getByRole('button', { name: /高对比|High contrast|ハイコントラスト/, exact: true }).click()
|
|
15
|
+
await expect(page.locator('html')).toHaveAttribute('data-theme', 'high-contrast')
|
|
16
|
+
await page.reload()
|
|
17
|
+
await expect(page.locator('html')).toHaveAttribute('data-theme', 'high-contrast')
|
|
18
|
+
await expect.poll(() => page.evaluate(() => getComputedStyle(document.documentElement).colorScheme)).toBe('dark')
|
|
19
|
+
await header.getByRole('button', { name: /选择主题|Select theme|テーマを選択/, exact: true }).press('Enter')
|
|
20
|
+
await header.getByRole('button', { name: /简洁商务|Formal|ビジネス(角丸なし)/, exact: true }).press('Enter')
|
|
21
|
+
await expect(page.locator('html')).toHaveAttribute('data-theme', 'formal')
|
|
22
|
+
await page.reload()
|
|
23
|
+
await expect(page.locator('html')).toHaveAttribute('data-theme', 'formal')
|
|
24
|
+
expect(await header.locator('button').first().evaluate(element => getComputedStyle(element).borderTopLeftRadius)).toBe('0px')
|
|
25
|
+
})
|
|
26
|
+
{{/if_eq}}
|
|
27
|
+
|
|
28
|
+
{{#if_eq appType 'h5'}}
|
|
29
|
+
test.use({ viewport: { width: 390, height: 844 } })
|
|
30
|
+
{{/if_eq}}
|
|
31
|
+
{{#if isCapacitorApp}}
|
|
32
|
+
test.use({ viewport: { width: 390, height: 844 } })
|
|
33
|
+
{{/if}}
|
|
34
|
+
|
|
35
|
+
/** 首页从真实浏览器页面发起,覆盖基础渲染链路。 */
|
|
36
|
+
test('home page renders from browser', async ({ page }) => {
|
|
37
|
+
{{#if_eq appType 'h5'}}
|
|
38
|
+
await page.setViewportSize({ width: 390, height: 844 })
|
|
39
|
+
{{/if_eq}}
|
|
40
|
+
const pageErrors: string[] = []
|
|
41
|
+
page.on('pageerror', error => pageErrors.push(error.message))
|
|
42
|
+
await page.goto('./')
|
|
43
|
+
await expect(page).toHaveTitle(process.env.HAI_CORE_NAME ?? '{{projectName}}')
|
|
44
|
+
await expect(pageErrors).toEqual([])
|
|
45
|
+
await expect(page.locator('main, section').first()).toBeVisible()
|
|
46
|
+
await expect(page.locator('header').first()).toBeVisible()
|
|
47
|
+
await expect(page.locator('footer').first()).toBeAttached()
|
|
48
|
+
// 大屏使用可用空间,窄屏由组件内部滚动,不能撑宽整个页面。
|
|
49
|
+
for (const width of [390, 1440, 1920, 2560, 3840]) {
|
|
50
|
+
await page.setViewportSize({ width, height: 960 })
|
|
51
|
+
const availableWidth = await page.evaluate(() => document.documentElement.clientWidth)
|
|
52
|
+
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
|
|
53
|
+
const shell = page.locator('.hai-mobile-shell')
|
|
54
|
+
if (await shell.count())
|
|
55
|
+
expect((await shell.boundingBox())!.width).toBeGreaterThan(availableWidth - 2)
|
|
56
|
+
}
|
|
57
|
+
await page.setViewportSize({ width: 390, height: 844 })
|
|
58
|
+
{{#if_eq appType 'h5'}}
|
|
59
|
+
// 在手机宽度验证导航真正切换路由,避免样式失效但首页渲染测试仍通过。
|
|
60
|
+
const nav = page.locator('nav')
|
|
61
|
+
await nav.getByRole('button', { name: /发现|Discover/i, exact: true }).click()
|
|
62
|
+
await expect(page).toHaveURL(/\/discover$/)
|
|
63
|
+
await page.reload()
|
|
64
|
+
await expect(page).toHaveURL(/\/discover$/)
|
|
65
|
+
await expect(page.getByRole('heading', { name: /发现|Discover/i })).toBeVisible()
|
|
66
|
+
await nav.getByRole('button', { name: /首页|Home/i, exact: true }).click()
|
|
67
|
+
await expect(page).toHaveURL(/\/$/)
|
|
68
|
+
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
|
|
69
|
+
{{/if_eq}}
|
|
70
|
+
{{#if_eq appType 'website'}}
|
|
71
|
+
await page.goto('./about')
|
|
72
|
+
await page.reload()
|
|
73
|
+
await expect(page).toHaveURL(/\/about$/)
|
|
74
|
+
await expect(page.locator('header')).toBeVisible()
|
|
75
|
+
await expect(page.locator('footer')).toBeVisible()
|
|
76
|
+
{{/if_eq}}
|
|
77
|
+
const evidence = process.env.HAI_AUTH_EVIDENCE_DIR || path.resolve('test-results/auth-screenshots')
|
|
78
|
+
await mkdir(evidence, { recursive: true })
|
|
79
|
+
await page.evaluate(() => document.fonts.ready)
|
|
80
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-home.png'), fullPage: true, animations: 'disabled' })
|
|
81
|
+
})
|
|
82
|
+
{{#if features.iam}}
|
|
83
|
+
|
|
84
|
+
/** 实际注册和密码登录;截图只保存空白表单。 */
|
|
85
|
+
test('configured IAM registration and password login', async ({ page, context }) => {
|
|
86
|
+
test.setTimeout(90_000)
|
|
87
|
+
{{#if_eq appType 'h5'}}
|
|
88
|
+
await page.setViewportSize({ width: 390, height: 844 })
|
|
89
|
+
{{/if_eq}}
|
|
90
|
+
const evidence = process.env.HAI_AUTH_EVIDENCE_DIR || path.resolve('test-results/auth-screenshots')
|
|
91
|
+
await mkdir(evidence, { recursive: true })
|
|
92
|
+
const username = `scaf${randomUUID().replaceAll('-', '').slice(0, 12)}`
|
|
93
|
+
const password = 'ScaffoldPassword123'
|
|
94
|
+
const authUrl = '{{#if isCapacitorApp}}./{{else}}./auth/login{{/if}}'
|
|
95
|
+
await page.goto(authUrl)
|
|
96
|
+
await expect(page.locator('#login-username')).toBeVisible()
|
|
97
|
+
await expect(page.locator('header').first()).toBeVisible()
|
|
98
|
+
await expect(page.locator('footer')).toBeVisible()
|
|
99
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-login.png'), fullPage: true })
|
|
100
|
+
await page.getByRole('{{#if isCapacitorApp}}button{{else}}link{{/if}}', { name: /立即注册|Register now/i }).click()
|
|
101
|
+
{{#unless isCapacitorApp}}
|
|
102
|
+
await expect(page).toHaveURL(/\/auth\/register(?:\?|$)/)
|
|
103
|
+
{{/unless}}
|
|
104
|
+
const registerForm = page.locator('.register-form')
|
|
105
|
+
await expect(registerForm.locator('#register-username')).toBeVisible()
|
|
106
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-register.png'), fullPage: true })
|
|
107
|
+
if (process.env.IAM_NOTIFICATION_URL) {
|
|
108
|
+
// 协议弹窗留在认证页,关闭后继续填写注册表单。
|
|
109
|
+
await registerForm.getByRole('button', { name: /用户协议|Terms of Service/i, exact: true }).click()
|
|
110
|
+
await expect(page.getByRole('dialog')).toBeVisible()
|
|
111
|
+
await expect(page.getByRole('dialog').getByRole('heading', { name: 'Configured registration agreement' })).toBeVisible()
|
|
112
|
+
await expect(page.locator('iframe')).toHaveCount(0)
|
|
113
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-agreement.png'), fullPage: true })
|
|
114
|
+
await page.keyboard.press('Escape')
|
|
115
|
+
await expect(page.getByRole('dialog')).not.toBeVisible()
|
|
116
|
+
}
|
|
117
|
+
await registerForm.locator('#register-username').fill(username)
|
|
118
|
+
await registerForm.locator('#register-email').fill(`${username}@example.com`)
|
|
119
|
+
await registerForm.locator('#register-password').fill(password)
|
|
120
|
+
await registerForm.locator('#register-confirm-password').fill(password)
|
|
121
|
+
await registerForm.locator('button[type="submit"]').click()
|
|
122
|
+
await expect(page.locator('.register-form')).not.toBeVisible()
|
|
123
|
+
{{#unless isCapacitorApp}}
|
|
124
|
+
// 通过页面 fetch 复用 Cookie 与已安装的传输加密,避免 HTTP 辅助客户端绕过浏览器协议。
|
|
125
|
+
const me = await page.evaluate(async url => (await fetch(url)).status, new URL('./api/auth/me', test.info().project.use.baseURL).href)
|
|
126
|
+
expect(me).toBe(200)
|
|
127
|
+
await context.clearCookies()
|
|
128
|
+
{{/unless}}
|
|
129
|
+
await page.reload()
|
|
130
|
+
await page.goto(authUrl)
|
|
131
|
+
await expect(page.locator('#login-username')).toBeVisible()
|
|
132
|
+
await page.locator('#login-username').fill(username)
|
|
133
|
+
await page.locator('input[type="password"]').fill(password)
|
|
134
|
+
await page.locator('button[type="submit"]').click()
|
|
135
|
+
await expect(page.locator('.login-form')).not.toBeVisible()
|
|
136
|
+
expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true)
|
|
137
|
+
|
|
138
|
+
if (!process.env.IAM_NOTIFICATION_URL)
|
|
139
|
+
return
|
|
140
|
+
await context.clearCookies()
|
|
141
|
+
await page.reload()
|
|
142
|
+
await page.goto(authUrl)
|
|
143
|
+
await page.getByRole('button', { name: /邮件验证码|Email code/i, exact: true }).click()
|
|
144
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-email.png'), fullPage: true })
|
|
145
|
+
const email = `${username}@example.com`
|
|
146
|
+
await page.locator('#login-username').fill(email)
|
|
147
|
+
await page.getByRole('button', { name: /发送验证码|Send code/i, exact: true }).click()
|
|
148
|
+
await expect(page.getByRole('button', { name: /秒后重发|Resend in/ })).toBeDisabled()
|
|
149
|
+
async function received(template: string) {
|
|
150
|
+
const response = await page.request.get(`${process.env.IAM_NOTIFICATION_URL}/messages?to=${encodeURIComponent(email)}`)
|
|
151
|
+
const messages = await response.json() as { template: string, vars: Record<string, string> }[]
|
|
152
|
+
return messages.findLast(item => item.template === template)?.vars
|
|
153
|
+
}
|
|
154
|
+
const otp = await received('otp_email')
|
|
155
|
+
expect(Boolean(otp?.code)).toBe(true)
|
|
156
|
+
await page.locator('#login-code').fill(otp?.code ?? '')
|
|
157
|
+
await page.locator('button[type="submit"]').click()
|
|
158
|
+
await expect(page.locator('.login-form')).not.toBeVisible()
|
|
159
|
+
await context.clearCookies()
|
|
160
|
+
await page.reload()
|
|
161
|
+
await page.goto(authUrl)
|
|
162
|
+
await page.getByRole('button', { name: /忘记密码|Forgot password/i }).click()
|
|
163
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-forgot.png'), fullPage: true })
|
|
164
|
+
await page.locator('input[type="email"]').fill(email)
|
|
165
|
+
await page.locator('button[type="submit"]').click()
|
|
166
|
+
await expect(page.locator('.hai-toast-item[data-variant="success"]')).toBeVisible()
|
|
167
|
+
const reset = await received('password_reset')
|
|
168
|
+
expect(Boolean(reset?.token)).toBe(true)
|
|
169
|
+
await page.getByRole('button', { name: /已有重置令牌|I have a reset token/i }).click()
|
|
170
|
+
await page.screenshot({ path: path.join(evidence, '{{projectName}}-reset.png'), fullPage: true })
|
|
171
|
+
const resetUrl = `{{#if isCapacitorApp}}/{{else}}/auth/reset-password{{/if}}?token=${encodeURIComponent(reset?.token ?? '')}`
|
|
172
|
+
{{#if_eq appType 'h5'}}
|
|
173
|
+
// 延迟客户端脚本,确定性覆盖 SSR 页面已显示、事件绑定尚未完成的窗口。
|
|
174
|
+
let resumeClient = () => {}
|
|
175
|
+
const clientBoot = new Promise<void>((resolve) => {
|
|
176
|
+
resumeClient = resolve
|
|
177
|
+
})
|
|
178
|
+
await page.route('**/*.js', async (route) => {
|
|
179
|
+
await clientBoot
|
|
180
|
+
await route.continue()
|
|
181
|
+
})
|
|
182
|
+
try {
|
|
183
|
+
await page.goto(resetUrl, { waitUntil: 'commit' })
|
|
184
|
+
await expect(page.locator('input[type="password"]').nth(0)).toBeDisabled()
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
resumeClient()
|
|
188
|
+
// 等待正在恢复的路由完成,避免提前移除拦截导致 continue 被重复处理。
|
|
189
|
+
await page.unrouteAll({ behavior: 'wait' })
|
|
190
|
+
}
|
|
191
|
+
{{else}}
|
|
192
|
+
await page.goto(resetUrl)
|
|
193
|
+
{{/if_eq}}
|
|
194
|
+
await expect(page.locator('input[type="password"]').nth(0)).toBeVisible()
|
|
195
|
+
await page.locator('input[type="password"]').nth(0).fill('ScaffoldReset456')
|
|
196
|
+
await page.locator('input[type="password"]').nth(1).fill('ScaffoldReset456')
|
|
197
|
+
await page.locator('button[type="submit"]').click()
|
|
198
|
+
await expect(page.locator('.hai-toast-item[data-variant="success"]')).toBeVisible()
|
|
199
|
+
await page.getByRole('{{#if isCapacitorApp}}button{{else}}link{{/if}}', { name: /^(登录|Sign in|Login)$/i }).click()
|
|
200
|
+
await page.locator('#login-username').fill(username)
|
|
201
|
+
await page.locator('input[type="password"]').fill('ScaffoldReset456')
|
|
202
|
+
await page.locator('button[type="submit"]').click()
|
|
203
|
+
await expect(page.locator('.login-form')).not.toBeVisible()
|
|
204
|
+
expect(new URL(page.url()).searchParams.has('token')).toBe(false)
|
|
205
|
+
await page.reload()
|
|
206
|
+
{{#if isCapacitorApp}}
|
|
207
|
+
// Web 预览采用内存 TokenStore,刷新后应回到登录,而不是已消费令牌的重置页面。
|
|
208
|
+
await expect(page.locator('#login-username')).toBeVisible()
|
|
209
|
+
{{else}}
|
|
210
|
+
expect(await page.evaluate(async url => (await fetch(url)).status, new URL('./api/auth/me', test.info().project.use.baseURL).href)).toBe(200)
|
|
211
|
+
{{/if}}
|
|
212
|
+
})
|
|
213
|
+
{{/if}}
|
|
@@ -40,7 +40,7 @@ export async function registerAndLogin(
|
|
|
40
40
|
) {
|
|
41
41
|
const user = uniqueUser(prefix)
|
|
42
42
|
await registerViaApi(request, user)
|
|
43
|
-
await page.goto('
|
|
43
|
+
await page.goto('./login')
|
|
44
44
|
await page.fill('[name="username"]', user.username)
|
|
45
45
|
await page.fill('[name="password"]', user.password)
|
|
46
46
|
await page.click('button[type="submit"]')
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 应用共享质量门禁。依赖 Antfu 已注册的 TypeScript / ESLint comments 插件。
|
|
3
|
+
* 必要第三方 workaround 使用单行 eslint-disable-next-line <规则> -- 具体原因,
|
|
4
|
+
* 不关闭整个文件的检查。秘密泄漏、输入/权限校验仍需结合业务审查。
|
|
5
|
+
*/
|
|
6
|
+
export const haiQualityConfig = {
|
|
7
|
+
files: ['**/*.{js,mjs,cjs,ts,tsx,svelte}'],
|
|
8
|
+
linterOptions: {
|
|
9
|
+
reportUnusedDisableDirectives: 'error',
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
'no-console': ['error', {}],
|
|
13
|
+
'ts/no-explicit-any': 'error',
|
|
14
|
+
'ts/ban-ts-comment': ['error', {
|
|
15
|
+
'ts-ignore': true,
|
|
16
|
+
'ts-nocheck': true,
|
|
17
|
+
'ts-check': false,
|
|
18
|
+
'ts-expect-error': 'allow-with-description',
|
|
19
|
+
'minimumDescriptionLength': 10,
|
|
20
|
+
}],
|
|
21
|
+
'eslint-comments/no-unlimited-disable': 'error',
|
|
22
|
+
'eslint-comments/require-description': 'error',
|
|
23
|
+
// 只禁内部源码/构建目录,公开的 /client、/adapter 等 exports 子路径可用。
|
|
24
|
+
'no-restricted-imports': ['error', {
|
|
25
|
+
patterns: [{
|
|
26
|
+
group: ['@h-ai/*/src', '@h-ai/*/src/**', '@h-ai/*/dist', '@h-ai/*/dist/**'],
|
|
27
|
+
message: 'Use the public exports of hai packages instead of their src/dist internals.',
|
|
28
|
+
}],
|
|
29
|
+
}],
|
|
30
|
+
'no-restricted-syntax': ['error', {
|
|
31
|
+
selector: ':matches(TSAsExpression, TSTypeAssertion)[expression.typeAnnotation.type="TSUnknownKeyword"]',
|
|
32
|
+
message: 'Use the real upstream type or narrow unknown. Explain necessary third-party workarounds with a scoped lint exception.',
|
|
33
|
+
}, {
|
|
34
|
+
selector: 'ImportExpression[source.value=/^@h-ai\\/[^/]+\\/(src|dist)(\\/|$)/]',
|
|
35
|
+
message: 'Use the public exports of hai packages instead of their src/dist internals.',
|
|
36
|
+
}, {
|
|
37
|
+
// 仅识别明确的静态敏感键;变量键、别名及业务敏感程度仍需审查。
|
|
38
|
+
selector: 'CallExpression[callee.property.name="setItem"][callee.object.name="localStorage"][arguments.0.value=/^(token|password|secret|api[_-]?key|(access|refresh|auth|session)[_-]?token)$/i]',
|
|
39
|
+
message: 'Keep sensitive tokens in memory, httpOnly cookies or a secure native TokenStore instead of localStorage.',
|
|
40
|
+
}, {
|
|
41
|
+
selector: 'CallExpression[callee.property.name="setItem"][callee.object.property.name="localStorage"][arguments.0.value=/^(token|password|secret|api[_-]?key|(access|refresh|auth|session)[_-]?token)$/i]',
|
|
42
|
+
message: 'Keep sensitive tokens in memory, httpOnly cookies or a secure native TokenStore instead of localStorage.',
|
|
43
|
+
}],
|
|
44
|
+
},
|
|
45
|
+
}
|