@h-ai/cli 0.1.0-alpha.67 → 0.1.0-alpha.68
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 +40 -4
- package/README.ja.md +40 -4
- package/README.md +40 -4
- package/dist/{src-2V6VP4I5.js → chunk-FI56GONY.js} +32 -3103
- package/dist/chunk-FI56GONY.js.map +1 -0
- package/dist/chunk-MBPB37FR.js +1348 -0
- package/dist/chunk-MBPB37FR.js.map +1 -0
- package/dist/{chunk-7DSURTJ4.js → chunk-ZFNBUF77.js} +327 -199
- package/dist/chunk-ZFNBUF77.js.map +1 -0
- package/dist/cli-config-templates-W2LLPMB6.js +5 -0
- package/dist/{cli-config-templates-6AHNUGBN.js.map → cli-config-templates-W2LLPMB6.js.map} +1 -1
- package/dist/{cli-skill-templates-FC3QRKDO.js → cli-skill-templates-US5CCAJ4.js} +3 -3
- package/dist/{cli-skill-templates-FC3QRKDO.js.map → cli-skill-templates-US5CCAJ4.js.map} +1 -1
- package/dist/index.js +920 -336
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -0
- package/dist/src-DSJJXM2F.js +3849 -0
- package/dist/src-DSJJXM2F.js.map +1 -0
- package/package.json +9 -8
- package/templates/apps/admin/messages/ja-JP.json +38 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +16 -6
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +3 -3
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +2 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +4 -1
- package/templates/apps/api/apps/{{projectName}}-service/README.md.hbs +5 -1
- package/templates/apps/api/apps/{{projectName}}-service/config/_core.yml.hbs +0 -10
- package/templates/apps/api/apps/{{projectName}}-service/config/_serv.yml.hbs +2 -1
- package/templates/apps/api/apps/{{projectName}}-service/src/app.ts.hbs +24 -11
- package/templates/apps/api/apps/{{projectName}}-service/src/index.ts.hbs +8 -1
- package/templates/apps/api/apps/{{projectName}}-service/src/lib/server/init.ts.hbs +68 -11
- package/templates/apps/api/apps/{{projectName}}-service/src/server/procedures/index.ts.hbs +10 -2
- package/templates/apps/api/e2e/api-service.spec.ts.hbs +2 -2
- package/templates/apps/api/package.json.hbs +1 -1
- package/templates/apps/api/playwright.config.ts.hbs +15 -7
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +7 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +1 -1
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +1 -1
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +19 -8
- package/templates/apps/fullstack/package.json.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +2 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +5 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +0 -6
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +8 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +2 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +6 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +9 -5
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +3 -2
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +16 -1
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +7 -3
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +3 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +58 -7
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +13 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +9 -4
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +105 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +3 -3
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +5 -5
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +7 -7
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +1 -1
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +8 -8
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +11 -12
- package/templates/apps/fullstack/playwright.config.ts.hbs +15 -6
- package/templates/apps/h5/messages/ja-JP.json +40 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +14 -3
- package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +13 -3
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +173 -14
- package/templates/apps/website/messages/ja-JP.json +32 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +10 -2
- package/templates/base/e2e/app.spec.ts.hbs +13 -8
- package/templates/base/package.json.hbs +4 -1
- package/templates/base/playwright.config.ts +15 -4
- package/templates/base/src/hooks.server.ts.hbs +15 -6
- package/templates/base/src/lib/server/init.ts.hbs +139 -30
- package/templates/base/vite.config.ts.hbs +2 -2
- package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +11 -6
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +18 -25
- package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +4 -0
- package/templates/i18n/project.inlang/settings.json +1 -1
- package/templates/shared/e2e-env.ts +98 -0
- package/templates/shared/run-e2e.mjs +51 -12
- package/templates/skills/AGENTS.md +4 -0
- package/templates/skills/bridges/admin/AGENTS.md +5 -1
- package/templates/skills/bridges/api/AGENTS.md +2 -0
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +4 -0
- package/templates/skills/bridges/h5/AGENTS.md +5 -1
- package/templates/skills/bridges/mobile-app/AGENTS.md +5 -1
- package/templates/skills/bridges/website/AGENTS.md +5 -1
- package/templates/skills/hai-ai/SKILL.md +8 -2
- package/templates/skills/hai-ai/guide.md +134 -60
- package/templates/skills/hai-ai/reference.md +51 -11
- package/templates/skills/hai-api-client/SKILL.md +2 -0
- package/templates/skills/hai-api-client/reference.md +17 -5
- package/templates/skills/hai-api-contract/SKILL.md +1 -0
- package/templates/skills/hai-api-contract/reference.md +4 -2
- package/templates/skills/hai-app-create/SKILL.md +4 -0
- package/templates/skills/hai-app-create/development.md +20 -4
- package/templates/skills/hai-app-create/reference.md +2 -1
- package/templates/skills/hai-app-review/SKILL.md +6 -2
- package/templates/skills/hai-app-review/differential.md +34 -0
- package/templates/skills/hai-app-tests/SKILL.md +3 -1
- package/templates/skills/hai-app-tests/reference.md +4 -4
- package/templates/skills/hai-app-tests/validation.md +10 -3
- package/templates/skills/hai-audit/SKILL.md +10 -8
- package/templates/skills/hai-audit/reference.md +3 -0
- package/templates/skills/hai-build/reference.md +6 -4
- package/templates/skills/hai-cache/SKILL.md +9 -3
- package/templates/skills/hai-cache/reference.md +53 -11
- package/templates/skills/hai-capacitor/SKILL.md +3 -1
- package/templates/skills/hai-capacitor/reference.md +9 -5
- package/templates/skills/hai-core/SKILL.md +4 -0
- package/templates/skills/hai-core/reference.md +25 -5
- package/templates/skills/hai-crypto/SKILL.md +10 -2
- package/templates/skills/hai-crypto/reference.md +64 -10
- package/templates/skills/hai-datapipe/SKILL.md +2 -0
- package/templates/skills/hai-datapipe/reference.md +3 -1
- package/templates/skills/hai-deploy/SKILL.md +9 -4
- package/templates/skills/hai-deploy/middleware.md +51 -37
- package/templates/skills/hai-iam/SKILL.md +24 -8
- package/templates/skills/hai-iam/reference.md +181 -154
- package/templates/skills/hai-kit/SKILL.md +23 -7
- package/templates/skills/hai-kit/reference.md +42 -24
- package/templates/skills/hai-payment/SKILL.md +13 -11
- package/templates/skills/hai-payment/reference.md +80 -41
- package/templates/skills/hai-pr-review/SKILL.md +21 -88
- package/templates/skills/hai-reach/SKILL.md +5 -2
- package/templates/skills/hai-reach/reference.md +83 -22
- package/templates/skills/hai-reldb/SKILL.md +5 -2
- package/templates/skills/hai-reldb/reference.md +68 -25
- package/templates/skills/hai-scheduler/SKILL.md +8 -5
- package/templates/skills/hai-scheduler/reference.md +38 -24
- package/templates/skills/hai-serv/SKILL.md +23 -8
- package/templates/skills/hai-serv/reference.md +123 -87
- package/templates/skills/hai-spec-implement/SKILL.md +4 -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 +5 -0
- package/templates/skills/hai-spec-implement/workflow.md +2 -0
- package/templates/skills/hai-spec-review/SKILL.md +4 -0
- package/templates/skills/hai-storage/SKILL.md +8 -2
- package/templates/skills/hai-storage/reference.md +64 -25
- package/templates/skills/hai-ui/SKILL.md +16 -2
- package/templates/skills/hai-ui/guide.md +3 -3
- package/templates/skills/hai-ui/reference.md +17 -6
- package/templates/skills/hai-ui-design/SKILL.md +31 -0
- package/templates/skills/hai-ui-design/patterns.md +26 -0
- package/templates/skills/hai-ui-review/SKILL.md +30 -0
- package/templates/skills/hai-ui-review/checklist.md +22 -0
- package/templates/skills/hai-vecdb/SKILL.md +12 -8
- package/templates/skills/hai-vecdb/reference.md +33 -3
- package/dist/chunk-7DSURTJ4.js.map +0 -1
- package/dist/chunk-AOQ4N657.js +0 -640
- package/dist/chunk-AOQ4N657.js.map +0 -1
- package/dist/cli-config-templates-6AHNUGBN.js +0 -5
- package/dist/src-2V6VP4I5.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@h-ai/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.0-alpha.
|
|
4
|
+
"version": "0.1.0-alpha.68",
|
|
5
5
|
"description": "Hai Framework CLI for project scaffolding and code generation.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"keywords": [
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@h-ai/core": "0.1.0-alpha.
|
|
33
|
+
"@h-ai/core": "0.1.0-alpha.68",
|
|
34
34
|
"cac": "^7.0.1",
|
|
35
35
|
"chalk": "^6.0.1",
|
|
36
36
|
"fast-wrap-ansi": "^0.2.2",
|
|
@@ -41,12 +41,13 @@
|
|
|
41
41
|
"yaml": "^2.9.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@h-ai/
|
|
45
|
-
"@h-ai/
|
|
46
|
-
"@h-ai/
|
|
47
|
-
"@h-ai/
|
|
48
|
-
"@h-ai/
|
|
49
|
-
"@h-ai/
|
|
44
|
+
"@h-ai/api-client": "0.1.0-alpha.68",
|
|
45
|
+
"@h-ai/cache": "0.1.0-alpha.68",
|
|
46
|
+
"@h-ai/crypto": "0.1.0-alpha.68",
|
|
47
|
+
"@h-ai/deploy": "0.1.0-alpha.68",
|
|
48
|
+
"@h-ai/reach": "0.1.0-alpha.68",
|
|
49
|
+
"@h-ai/reldb": "0.1.0-alpha.68",
|
|
50
|
+
"@h-ai/storage": "0.1.0-alpha.68",
|
|
50
51
|
"@types/fs-extra": "^11.0.4",
|
|
51
52
|
"@types/node": "^26.6.5",
|
|
52
53
|
"@types/prompts": "^2.4.9",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"app_title": "管理コンソール",
|
|
3
|
+
"app_description": "hai Agent Frameworkで構築した管理コンソール",
|
|
4
|
+
"meta_description": "管理コンソール — 企業管理システム",
|
|
5
|
+
"nav_home": "ホーム",
|
|
6
|
+
"nav_dashboard": "ダッシュボード",
|
|
7
|
+
"nav_settings": "設定",
|
|
8
|
+
"nav_admin": "管理画面へ",
|
|
9
|
+
"page_home_title": "管理コンソール",
|
|
10
|
+
"page_home_subtitle": "hai Agent Frameworkで構築",
|
|
11
|
+
"page_home_badge": "Powered by hai",
|
|
12
|
+
"page_dashboard_title": "ダッシュボード",
|
|
13
|
+
"page_dashboard_subtitle": "システム稼働状況の概要",
|
|
14
|
+
"page_dashboard_total_users": "総ユーザー数",
|
|
15
|
+
"page_dashboard_today_active": "本日のアクティブユーザー",
|
|
16
|
+
"page_dashboard_revenue": "月間売上",
|
|
17
|
+
"page_dashboard_orders": "未処理の注文",
|
|
18
|
+
"page_settings_title": "システム設定",
|
|
19
|
+
"page_settings_subtitle": "システム設定を管理",
|
|
20
|
+
"page_settings_basic": "基本設定",
|
|
21
|
+
"page_settings_desc": "ここでシステムの設定を管理します。",
|
|
22
|
+
"auth_login_title": "ログイン",
|
|
23
|
+
"auth_login_submit": "ログイン",
|
|
24
|
+
"auth_login_loading": "ログイン中...",
|
|
25
|
+
"auth_login_failed": "ログインに失敗しました",
|
|
26
|
+
"auth_login_to_register": "アカウントをお持ちでない方は新規登録",
|
|
27
|
+
"auth_register_title": "登録",
|
|
28
|
+
"auth_register_submit": "登録",
|
|
29
|
+
"auth_register_loading": "登録中...",
|
|
30
|
+
"auth_register_failed": "登録に失敗しました",
|
|
31
|
+
"auth_register_to_login": "既にアカウントをお持ちの方はログイン",
|
|
32
|
+
"auth_label_username": "ユーザー名",
|
|
33
|
+
"auth_label_email": "メールアドレス",
|
|
34
|
+
"auth_label_password": "パスワード",
|
|
35
|
+
"auth_label_confirm_password": "パスワードの確認",
|
|
36
|
+
"auth_error_network": "ネットワークエラー",
|
|
37
|
+
"auth_error_password_mismatch": "パスワードが一致しません"
|
|
38
|
+
}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
{{/if}}
|
|
10
10
|
import { page } from '$app/state'
|
|
11
11
|
{{#if hasI18n}}
|
|
12
|
-
import { getLocale } from '$lib/paraglide/runtime.js'
|
|
13
|
-
import { setGlobalLocale } from '@h-ai/ui'
|
|
12
|
+
import { getLocale, setLocale } from '$lib/paraglide/runtime.js'
|
|
13
|
+
import { LanguageSwitch, setGlobalLocale } from '@h-ai/ui'
|
|
14
14
|
{{/if}}
|
|
15
15
|
import '../app.css'
|
|
16
16
|
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
const { children }: Props = $props()
|
|
22
22
|
{{#if hasI18n}}
|
|
23
23
|
|
|
24
|
+
function handleLanguageChange(language: string) {
|
|
25
|
+
setGlobalLocale(language)
|
|
26
|
+
setLocale(language as Parameters<typeof setLocale>[0])
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
if (browser) {
|
|
25
30
|
const paraglideLocale = getLocale()
|
|
26
31
|
setGlobalLocale(paraglideLocale)
|
|
@@ -32,8 +37,13 @@
|
|
|
32
37
|
<title>{page.data.appConfig.name}</title>
|
|
33
38
|
</svelte:head>
|
|
34
39
|
|
|
35
|
-
<div class='
|
|
36
|
-
<header class='navbar border-b border-base-300 bg-base-100 px-6'
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
<div class='h-dvh flex flex-col overflow-hidden bg-base-200'>
|
|
41
|
+
<header class='navbar shrink-0 border-b border-base-300 bg-base-100 px-6'>
|
|
42
|
+
<span class='flex-1 text-lg font-semibold'>{page.data.appConfig.name}</span>
|
|
43
|
+
{{#if hasI18n}}
|
|
44
|
+
<LanguageSwitch currentLanguage={getLocale()} onchange={handleLanguageChange} />
|
|
45
|
+
{{/if}}
|
|
46
|
+
</header>
|
|
47
|
+
<div class='flex min-h-0 flex-1 flex-col overflow-auto'>{@render children()}</div>
|
|
48
|
+
<footer class='shrink-0 border-t border-base-300 bg-base-100 p-3 text-center text-xs text-base-content/60'>{page.data.appConfig.name} · {page.data.appConfig.version} · {page.data.appConfig.env}</footer>
|
|
39
49
|
</div>
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
] as const)
|
|
28
28
|
</script>
|
|
29
29
|
|
|
30
|
-
<div class='drawer lg:drawer-open'>
|
|
30
|
+
<div class='drawer min-h-0 flex-1 lg:drawer-open'>
|
|
31
31
|
<input id='admin-drawer' type='checkbox' class='drawer-toggle' />
|
|
32
|
-
<div class='drawer-content min-w-0 p-4 sm:p-6'>
|
|
33
|
-
<label for='admin-drawer' class='btn btn-ghost btn-sm drawer-button lg:hidden mb-4'>
|
|
32
|
+
<div class='drawer-content flex min-h-0 min-w-0 flex-col overflow-auto p-4 sm:p-6'>
|
|
33
|
+
<label for='admin-drawer' class='btn btn-ghost btn-sm drawer-button shrink-0 self-start lg:hidden mb-4'>
|
|
34
34
|
<span class='icon-[tabler--menu-2] size-5'></span>
|
|
35
35
|
</label>
|
|
36
36
|
{@render children()}
|
package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { apiContract } from '@h-ai/api-contract'
|
|
2
2
|
import { appContract } from './app-contract.js'
|
|
3
3
|
|
|
4
|
+
// @hai-generator:contracts:imports
|
|
5
|
+
|
|
4
6
|
/** 工程级应用 contract。 */
|
|
5
7
|
export const {{api.contractExportName}} = apiContract.create({
|
|
6
8
|
{{#if features.iam}} iam: apiContract.iam,
|
|
7
9
|
{{/if}}{{#if features.storage}} storage: apiContract.storage,
|
|
8
10
|
{{/if}}{{#if features.ai}} ai: apiContract.ai,
|
|
9
|
-
{{/if}}
|
|
11
|
+
{{/if}} // @hai-generator:contracts:entries
|
|
12
|
+
app: appContract,
|
|
10
13
|
})
|
|
11
14
|
|
|
12
15
|
export type ApiWorkspaceContract = typeof {{api.contractExportName}}
|
|
@@ -27,6 +27,10 @@ pnpm --filter {{api.servicePackageName}} test
|
|
|
27
27
|
|
|
28
28
|
### 关键目录
|
|
29
29
|
|
|
30
|
+
{{#if features.crypto}}启用 transport 时,`serverKeyRing` 与客户端 `keyStore` 都必须显式提供。CLI 在本服务被忽略的 `.env.local` 中一次性生成独立开发 ring,变量为 `HAI_CRYPTO_TRANSPORT_SERVERKEYRING`;运行时不生成密钥。部署使用 Secret Manager 向所有节点分发相同受管 ring,配合共享数据库 registry。公钥/版本参与协商,私钥不进入普通 YAML、PUBLIC_/VITE_、日志或公开响应。轮换先分发新旧版本再切 activeKeyId,过渡期后撤销旧 ID;无需会话粘性。
|
|
31
|
+
{{#unless features.db}}本模板未选择 db,registry 仅在 development/test 显式使用内存;production/staging 会拒绝启动 transport。选择 db 并配置共享数据库后再部署,或显式关闭 transport。
|
|
32
|
+
{{/unless}}{{/if}}
|
|
33
|
+
|
|
30
34
|
- `config/`:service 配置
|
|
31
35
|
- `src/app.ts`:HTTP App 装配
|
|
32
36
|
- `src/lib/server/init.ts`:模块初始化与关闭
|
|
@@ -37,7 +41,7 @@ pnpm --filter {{api.servicePackageName}} test
|
|
|
37
41
|
|
|
38
42
|
服务端 `config/_iam.yml` 统一控制登录、注册、重置、协议与 `ui` 品牌。邮件/短信可用 `_reach.yml` 中的 Provider/标准模板或自定义发送回调。客户端可通过安全公开配置和框架认证动作接入 `AuthPanel`。单实例可使用 Memory;多实例需共享数据库与 Redis,并按工程根 README 配置写入路由和传输会话。
|
|
39
43
|
|
|
40
|
-
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise
|
|
44
|
+
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise;回调第三参数 context 提供 expiresAt/idempotencyKey,发送服务按稳定键持久化去重,异常/超时为结果未知且不自动重发。协议在 Modal 显示;LoginForm/RegisterForm 提供 header/extraFields/footer,AuthPanel 透传 loginHeader/loginFields/loginFooter 和 registerHeader/registerFields/registerFooter。配置及例子见生成项目的 hai-iam/hai-ui skills。
|
|
41
45
|
|
|
42
46
|
协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
|
|
43
47
|
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
name: {{projectName}} API Service
|
|
6
6
|
version: 0.1.0
|
|
7
7
|
env: ${HAI_CORE_ENV:development}
|
|
8
|
-
debug: ${HAI_CORE_DEBUG:false}
|
|
9
8
|
|
|
10
9
|
logging:
|
|
11
10
|
level: info
|
|
@@ -16,12 +15,3 @@ logging:
|
|
|
16
15
|
- secret
|
|
17
16
|
|
|
18
17
|
defaultLocale: {{defaultLocale}}
|
|
19
|
-
supportedLocales:
|
|
20
|
-
{{#if_eq defaultLocale 'en-US'}} - en-US
|
|
21
|
-
- zh-CN
|
|
22
|
-
{{else}} - zh-CN
|
|
23
|
-
- en-US
|
|
24
|
-
{{/if_eq}}
|
|
25
|
-
|
|
26
|
-
features:
|
|
27
|
-
apiAccess: true
|
|
@@ -27,11 +27,13 @@ cors:
|
|
|
27
27
|
- Content-Type
|
|
28
28
|
{{#if features.crypto}} - X-Client-Id
|
|
29
29
|
- X-Encrypted
|
|
30
|
+
- X-Hai-Transport
|
|
30
31
|
{{/if}} - X-Hai-Locale
|
|
31
32
|
- X-Request-Id
|
|
32
33
|
- X-Requested-With
|
|
33
34
|
exposedHeaders:
|
|
34
35
|
{{#if features.crypto}} - X-Encrypted
|
|
36
|
+
- X-Hai-Transport
|
|
35
37
|
{{/if}} - X-Request-Id
|
|
36
38
|
|
|
37
39
|
{{#if features.crypto}}transport:
|
|
@@ -42,6 +44,5 @@ cors:
|
|
|
42
44
|
- /openapi.json
|
|
43
45
|
- /docs
|
|
44
46
|
- /_hai/scalar.js
|
|
45
|
-
maxClients: 10000
|
|
46
47
|
{{else}}transport: false
|
|
47
48
|
{{/if}}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import type { CoreConfig } from '@h-ai/core'
|
|
2
|
-
import type { ServConfig } from '@h-ai/serv'
|
|
2
|
+
import type { ServConfig{{#if features.crypto}}, ServTransportConfig{{/if}} } from '@h-ai/serv'
|
|
3
|
+
{{#if features.crypto}}import process from 'node:process'
|
|
4
|
+
{{/if}}
|
|
3
5
|
import { core } from '@h-ai/core'
|
|
4
|
-
{{#if features.crypto}}import { crypto } from '@h-ai/crypto'
|
|
6
|
+
{{#if features.crypto}}import { {{#if features.db}}createReldbTransportKeyStore{{else}}createInMemoryKeyStore{{/if}}, crypto, parseTransportServerKeyRing } from '@h-ai/crypto'
|
|
5
7
|
{{/if}}{{#if features.iam}}import { iam } from '@h-ai/iam'
|
|
6
|
-
{{/if}}import {
|
|
8
|
+
{{/if}}{{#if features.crypto}}{{#if features.db}}import { reldb } from '@h-ai/reldb'
|
|
9
|
+
{{/if}}{{/if}}import { serv } from '@h-ai/serv'
|
|
7
10
|
import { {{api.contractExportName}} } from '{{api.contractPackageName}}'
|
|
8
11
|
import { {{api.serviceProceduresFactoryName}} } from './server/procedures/index.js'
|
|
9
12
|
|
|
@@ -24,14 +27,24 @@ export function {{api.serviceAppFactoryName}}(_options: CreateApiServiceAppOptio
|
|
|
24
27
|
nativeOrigins: servConfig.cors.nativeOrigins,
|
|
25
28
|
})
|
|
26
29
|
{{#if features.crypto}} const transportMode = _options.transport ?? 'config'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
let transport: ServTransportConfig | undefined
|
|
31
|
+
if (transportMode !== 'disabled' && servConfig.transport !== false) {
|
|
32
|
+
{{#unless features.db}} if (coreConfig.env !== 'development' && coreConfig.env !== 'test')
|
|
33
|
+
throw new Error('Production transport requires a shared registry; enable the db feature and configure a shared database')
|
|
34
|
+
{{/unless}}
|
|
35
|
+
const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
|
|
36
|
+
if (!ring.success)
|
|
37
|
+
throw new Error(ring.error.message)
|
|
38
|
+
transport = {
|
|
39
|
+
crypto,
|
|
40
|
+
serverKeyRing: ring.data,
|
|
41
|
+
{{#if features.db}} keyStore: createReldbTransportKeyStore({ reldb, ttlSeconds: 3600 }),
|
|
42
|
+
{{else}} keyStore: createInMemoryKeyStore(), // 无 db 的模板仅在 development/test 使用内存 registry。
|
|
43
|
+
{{/if}}
|
|
44
|
+
keyExchangePath: servConfig.transport.keyExchangePath,
|
|
45
|
+
excludePaths: [...servConfig.transport.excludePaths],
|
|
46
|
+
}
|
|
47
|
+
}
|
|
35
48
|
{{else}} const transport = undefined
|
|
36
49
|
{{/if}}
|
|
37
50
|
{{#if features.iam}}
|
|
@@ -21,7 +21,14 @@ async function main(): Promise<void> {
|
|
|
21
21
|
})
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
main().catch((error: unknown) => {
|
|
24
|
+
main().catch(async (error: unknown) => {
|
|
25
25
|
core.logger.error('API service failed to start', { error })
|
|
26
26
|
process.exitCode = 1
|
|
27
|
+
try {
|
|
28
|
+
// 包括初始化后的 app/transport 创建失败,均须释放已建立的连接。
|
|
29
|
+
await closeApp()
|
|
30
|
+
}
|
|
31
|
+
catch (cleanupError) {
|
|
32
|
+
core.logger.error('API service startup cleanup failed', { error: cleanupError })
|
|
33
|
+
}
|
|
27
34
|
})
|
|
@@ -21,23 +21,47 @@
|
|
|
21
21
|
|
|
22
22
|
let initialized = false
|
|
23
23
|
let initPromise: Promise<void> | null = null
|
|
24
|
+
/** 记录启动/关闭后未确认释放的资源,使失败清理可以重试。 */
|
|
25
|
+
let cleanupPending = false
|
|
26
|
+
let closePromise: Promise<void> | null = null
|
|
24
27
|
{{#if features.crypto}}let cryptoInitialized = false
|
|
25
28
|
{{/if}}
|
|
26
29
|
|
|
30
|
+
/**
|
|
31
|
+
* 合并并发启动;任一步失败先逆序清理,未释放的资源会在下次启动前重试。
|
|
32
|
+
* @throws Error | AggregateError - 启动失败,或启动与资源清理同时失败。
|
|
33
|
+
* @example
|
|
34
|
+
* await initApp()
|
|
35
|
+
*/
|
|
27
36
|
export async function initApp(): Promise<void> {
|
|
37
|
+
if (closePromise)
|
|
38
|
+
await closePromise
|
|
28
39
|
if (initialized)
|
|
29
40
|
return
|
|
30
41
|
if (initPromise)
|
|
31
42
|
return initPromise
|
|
43
|
+
if (cleanupPending) {
|
|
44
|
+
await closeApp()
|
|
45
|
+
return await initApp()
|
|
46
|
+
}
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await initPromise
|
|
48
|
+
cleanupPending = true
|
|
49
|
+
initPromise = doInit().then(() => {
|
|
36
50
|
initialized = true
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
cleanupPending = false
|
|
52
|
+
}).catch(async (error: unknown) => {
|
|
53
|
+
// 私有清理不等待 initPromise,避免启动失败时等待自身。
|
|
54
|
+
try {
|
|
55
|
+
await cleanupModules()
|
|
56
|
+
}
|
|
57
|
+
catch (cleanupError) {
|
|
58
|
+
throw new AggregateError([error, cleanupError], 'Application startup and cleanup failed')
|
|
59
|
+
}
|
|
60
|
+
throw error
|
|
61
|
+
}).finally(() => {
|
|
39
62
|
initPromise = null
|
|
40
|
-
}
|
|
63
|
+
})
|
|
64
|
+
return await initPromise
|
|
41
65
|
}
|
|
42
66
|
|
|
43
67
|
async function doInit(): Promise<void> {
|
|
@@ -160,16 +184,38 @@ async function doInit(): Promise<void> {
|
|
|
160
184
|
core.logger.info('API service initialized')
|
|
161
185
|
}
|
|
162
186
|
|
|
187
|
+
/**
|
|
188
|
+
* 等待启动并关闭所有模块;失败时保留重试入口。
|
|
189
|
+
* @throws AggregateError - 任一资源未确认释放。
|
|
190
|
+
* @example
|
|
191
|
+
* await closeApp()
|
|
192
|
+
*/
|
|
163
193
|
export async function closeApp(): Promise<void> {
|
|
164
|
-
|
|
194
|
+
closePromise ??= doCloseApp().finally(() => {
|
|
195
|
+
closePromise = null
|
|
196
|
+
})
|
|
197
|
+
return await closePromise
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** 等待启动结束后逐一释放;HaiResult 失败与异常都会聚合报告并保留重试入口。 */
|
|
201
|
+
async function doCloseApp(): Promise<void> {
|
|
202
|
+
if (!initialized && !initPromise && !cleanupPending)
|
|
165
203
|
return
|
|
166
204
|
|
|
205
|
+
if (initPromise)
|
|
206
|
+
await initPromise.catch(() => undefined)
|
|
207
|
+
await cleanupModules()
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** 不等待启动屏障,供启动失败与显式关闭共用的逆序清理。 */
|
|
211
|
+
async function cleanupModules(): Promise<void> {
|
|
212
|
+
const failures: unknown[] = []
|
|
167
213
|
const closers: Array<readonly [string, () => unknown]> = [
|
|
168
214
|
{{#if features.ai}} ['ai', () => ai.close()],
|
|
169
215
|
{{/if}}{{#if features.storage}} ['storage', () => storage.close()],
|
|
170
216
|
{{/if}}{{#if features.iam}} ['iam', () => iam.close()],
|
|
171
|
-
{{/if}}{{#if features.reach}} ['reach', () => reach.close()],
|
|
172
217
|
{{/if}}{{#if features.vecdb}} ['vecdb', () => vecdb.close()],
|
|
218
|
+
{{/if}}{{#if features.reach}} ['reach', () => reach.close()],
|
|
173
219
|
{{/if}}{{#if features.cache}} ['cache', () => cache.close()],
|
|
174
220
|
{{/if}}{{#if features.db}} ['reldb', () => reldb.close()],
|
|
175
221
|
{{/if}} ]
|
|
@@ -180,14 +226,25 @@ export async function closeApp(): Promise<void> {
|
|
|
180
226
|
|
|
181
227
|
for (const [name, close] of closers) {
|
|
182
228
|
try {
|
|
183
|
-
await close()
|
|
229
|
+
const result = await close()
|
|
230
|
+
if (result && typeof result === 'object' && 'success' in result && result.success === false) {
|
|
231
|
+
failures.push('error' in result ? result.error : new Error('Module close failed'))
|
|
232
|
+
core.logger.warn(`Module close failed: ${name}`)
|
|
233
|
+
continue
|
|
234
|
+
}
|
|
235
|
+
{{#if features.crypto}} if (name === 'crypto')
|
|
236
|
+
cryptoInitialized = false
|
|
237
|
+
{{/if}}
|
|
184
238
|
}
|
|
185
239
|
catch (error) {
|
|
240
|
+
failures.push(error)
|
|
186
241
|
core.logger.warn(`Module close failed: ${name}`, { error })
|
|
187
242
|
}
|
|
188
243
|
}
|
|
189
244
|
|
|
190
245
|
initialized = false
|
|
191
|
-
|
|
192
|
-
|
|
246
|
+
cleanupPending = failures.length > 0
|
|
247
|
+
if (cleanupPending)
|
|
248
|
+
throw new AggregateError(failures, 'Application resource cleanup failed; retry closeApp()')
|
|
249
|
+
core.logger.info('API service closed')
|
|
193
250
|
}
|
|
@@ -7,12 +7,20 @@ import type { AppProcedureDeps } from './app-procedures.js'
|
|
|
7
7
|
import { storage } from '@h-ai/storage'
|
|
8
8
|
{{/if}}import { createAppProcedures } from './app-procedures.js'
|
|
9
9
|
|
|
10
|
+
// @hai-generator:procedures:imports
|
|
11
|
+
|
|
10
12
|
/** 创建应用级 procedures 聚合。 */
|
|
11
13
|
export function {{api.serviceProceduresFactoryName}}(deps: { app: AppProcedureDeps }) {
|
|
12
14
|
return {
|
|
15
|
+
// @hai-generator:procedures:entries
|
|
13
16
|
{{#if features.iam}} iam: createIamProcedures({ iam }),
|
|
14
|
-
{{/if}}{{#if features.storage}} storage: createStorageProcedures({
|
|
15
|
-
|
|
17
|
+
{{/if}}{{#if features.storage}} storage: createStorageProcedures({
|
|
18
|
+
storage,
|
|
19
|
+
authorize: ({ context, keys }) => keys.every(key =>
|
|
20
|
+
key.startsWith(`users/${encodeURIComponent(context.session.userId)}/`)),
|
|
21
|
+
}),
|
|
22
|
+
{{/if}}{{#if features.ai}} // AI 默认绑定可信 session.userId,跨主体访问需另行提供 authorizeObject 策略。
|
|
23
|
+
ai: createAiProcedures({ ai }),
|
|
16
24
|
{{/if}} app: createAppProcedures(deps.app),
|
|
17
25
|
}
|
|
18
26
|
}
|
|
@@ -19,7 +19,7 @@ test.beforeAll(async () => {
|
|
|
19
19
|
auth: { storage: apiClient.tokenStorage.memory() },
|
|
20
20
|
{{/if}}
|
|
21
21
|
{{#if features.crypto}}
|
|
22
|
-
transport:
|
|
22
|
+
transport: { crypto },
|
|
23
23
|
{{/if}}
|
|
24
24
|
})
|
|
25
25
|
expect(result.success).toBe(true)
|
|
@@ -46,7 +46,7 @@ test('service app.info endpoint returns HaiResult', async () => {
|
|
|
46
46
|
return
|
|
47
47
|
expect(body.data.name).toBe(process.env.HAI_CORE_NAME ?? '{{projectName}} API Service')
|
|
48
48
|
expect(body.data.version).toBe(process.env.HAI_CORE_VERSION ?? '0.1.0')
|
|
49
|
-
expect(body.data.env).toBe(
|
|
49
|
+
expect(body.data.env).toBe('test')
|
|
50
50
|
expect(typeof body.data.transportEnabled).toBe('boolean')
|
|
51
51
|
})
|
|
52
52
|
{{#if features.iam}}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"start:prod": "pnpm --filter {{api.servicePackageName}} start:prod",
|
|
14
14
|
"dev:test": "pnpm --filter {{api.servicePackageName}} dev:test",
|
|
15
15
|
"dev:prod": "pnpm --filter {{api.servicePackageName}} dev:prod",
|
|
16
|
-
"compile": "pnpm
|
|
16
|
+
"compile": "pnpm -r --if-present build",
|
|
17
17
|
"build": "hai build",
|
|
18
18
|
{{#if features.deploy}}
|
|
19
19
|
"deploy": "hai deploy apps/{{projectName}}-service",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import process from 'node:process'
|
|
2
2
|
import { defineConfig } from '@playwright/test'
|
|
3
|
+
import { createE2eNotificationEnv, createE2eServerEnv, createE2eTransportRing } from './scripts/e2e-env.js'
|
|
3
4
|
|
|
4
5
|
const defaultBaseURL = 'http://127.0.0.1:3000'
|
|
5
6
|
const baseURL = process.env.BASE_URL || defaultBaseURL
|
|
@@ -33,25 +34,32 @@ function resolvePortFromBaseUrl(urlString: string, fallbackPort: string): string
|
|
|
33
34
|
export default defineConfig({
|
|
34
35
|
testDir: './e2e',
|
|
35
36
|
globalSetup: './e2e/capture-evidence.ts',
|
|
36
|
-
fullyParallel:
|
|
37
|
+
fullyParallel: true,
|
|
37
38
|
forbidOnly: !!process.env.CI,
|
|
38
|
-
retries:
|
|
39
|
-
workers:
|
|
39
|
+
retries: 0,
|
|
40
|
+
workers: 2,
|
|
40
41
|
reporter: 'list',
|
|
41
42
|
timeout: 30_000,
|
|
42
43
|
use: {
|
|
43
44
|
baseURL,
|
|
44
45
|
channel: 'chrome',
|
|
45
|
-
trace: 'on-
|
|
46
|
+
trace: 'retain-on-failure',
|
|
46
47
|
screenshot: 'only-on-failure',
|
|
47
48
|
},
|
|
48
49
|
webServer: [{
|
|
49
50
|
name: '{{api.servicePackageName}}',
|
|
50
|
-
command: 'pnpm --filter {{api.servicePackageName}}
|
|
51
|
-
env: {
|
|
51
|
+
command: 'pnpm --filter {{api.servicePackageName}} exec node dist/index.js',
|
|
52
|
+
env: createE2eServerEnv({
|
|
53
|
+
...createE2eNotificationEnv(),
|
|
54
|
+
HAI_CORE_ENV: 'test',
|
|
55
|
+
HAI_DB: JSON.stringify({ type: 'sqlite', database: `${process.env.HAI_E2E_DATA_ROOT}/api.db` }),
|
|
56
|
+
HAI_CACHE: JSON.stringify({ type: 'memory' }),
|
|
57
|
+
HAI_STORAGE: JSON.stringify({ type: 'local', root: `${process.env.HAI_E2E_DATA_ROOT}/uploads` }),
|
|
58
|
+
HAI_VECDB: JSON.stringify({ type: 'lancedb', path: `${process.env.HAI_E2E_DATA_ROOT}/vecdb` }),
|
|
59
|
+
HAI_CRYPTO_TRANSPORT_SERVERKEYRING: createE2eTransportRing(),
|
|
52
60
|
HOST: serviceHost,
|
|
53
61
|
PORT: servicePort,
|
|
54
|
-
},
|
|
62
|
+
}),
|
|
55
63
|
url: `${baseURL}/health`,
|
|
56
64
|
reuseExistingServer: false,
|
|
57
65
|
timeout: 120_000,
|
|
@@ -47,7 +47,7 @@ pnpm --filter {{projectName}}-app cap:build:ios
|
|
|
47
47
|
|
|
48
48
|
服务端 `config/_iam.yml` 统一控制登录、注册、重置、协议与 `ui` 品牌。邮件/短信可用 `_reach.yml` 中的 Provider/标准模板或自定义发送回调。`AuthPanel` 使用安全公开配置及框架认证动作;无需在页面适配 Token、验证码倒计时和错误提示。单实例可使用 Memory;多实例需共享数据库与 Redis,并按工程根 README 配置写入路由和传输会话。
|
|
49
49
|
|
|
50
|
-
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise
|
|
50
|
+
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise;回调第三参数 context 提供 expiresAt/idempotencyKey,发送服务按稳定键持久化去重,异常/超时为结果未知且不自动重发。协议在 Modal 显示;LoginForm/RegisterForm 提供 header/extraFields/footer,AuthPanel 透传 loginHeader/loginFields/loginFooter 和 registerHeader/registerFields/registerFooter。配置及例子见生成项目的 hai-iam/hai-ui skills。
|
|
51
51
|
|
|
52
52
|
协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
|
|
53
53
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<script lang="ts">
|
|
4
4
|
import type { ManagementApiOptions } from '{{fullstack.sharedPackageName}}'
|
|
5
5
|
import { capacitor, createCapacitorTokenStorage } from '@h-ai/capacitor'
|
|
6
|
+
import { core } from '@h-ai/core'
|
|
6
7
|
import { Alert } from '@h-ai/ui/components/compounds/index'
|
|
7
8
|
import { Button, Spinner } from '@h-ai/ui/components/primitives/index'
|
|
8
9
|
import { onMount } from 'svelte'
|
|
@@ -29,7 +30,12 @@
|
|
|
29
30
|
}
|
|
30
31
|
onMount(() => {
|
|
31
32
|
void initialize()
|
|
32
|
-
return () =>
|
|
33
|
+
return () => {
|
|
34
|
+
void capacitor.close().then((closed) => {
|
|
35
|
+
if (!closed.success)
|
|
36
|
+
core.logger.warn('Native listener cleanup failed; retry on next initialization')
|
|
37
|
+
})
|
|
38
|
+
}
|
|
33
39
|
})
|
|
34
40
|
</script>
|
|
35
41
|
|
|
@@ -12,7 +12,7 @@ import { defineConfig } from 'vitest/config'
|
|
|
12
12
|
const envDir = fileURLToPath(new URL('../../', import.meta.url))
|
|
13
13
|
|
|
14
14
|
export default defineConfig(({ mode, command }) => {
|
|
15
|
-
const envResult = command === 'build' ? { success: true as const, data: {} as Record<string, string> } : core.config.loadEnvFiles({ mode, envDir })
|
|
15
|
+
const envResult = command === 'build' || process.env.HAI_E2E === '1' ? { success: true as const, data: {} as Record<string, string> } : core.config.loadEnvFiles({ mode, envDir })
|
|
16
16
|
if (!envResult.success)
|
|
17
17
|
throw new Error(envResult.error.message)
|
|
18
18
|
const env = envResult.data
|
|
@@ -46,7 +46,7 @@ pnpm build --target desktop --platform windows --arch x64
|
|
|
46
46
|
|
|
47
47
|
服务端 `config/_iam.yml` 统一控制登录、注册、重置、协议与 `ui` 品牌。邮件/短信可用 `_reach.yml` 中的 Provider/标准模板或自定义发送回调。`AuthPanel` 使用安全公开配置及框架认证动作;无需在页面适配 Token、验证码倒计时和错误提示。单实例可使用 Memory;多实例需共享数据库与 Redis,并按工程根 README 配置写入路由和传输会话。
|
|
48
48
|
|
|
49
|
-
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise
|
|
49
|
+
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise;回调第三参数 context 提供 expiresAt/idempotencyKey,发送服务按稳定键持久化去重,异常/超时为结果未知且不自动重发。协议在 Modal 显示;LoginForm/RegisterForm 提供 header/extraFields/footer,AuthPanel 透传 loginHeader/loginFields/loginFooter 和 registerHeader/registerFields/registerFooter。配置及例子见生成项目的 hai-iam/hai-ui skills。
|
|
50
50
|
|
|
51
51
|
协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
|
|
52
52
|
|
|
@@ -13,7 +13,7 @@ const host = process.env.TAURI_DEV_HOST
|
|
|
13
13
|
const envDir = fileURLToPath(new URL('../../', import.meta.url))
|
|
14
14
|
|
|
15
15
|
export default defineConfig(({ mode, command }) => {
|
|
16
|
-
const envResult = command === 'build' ? { success: true as const, data: {} as Record<string, string> } : core.config.loadEnvFiles({ mode, envDir })
|
|
16
|
+
const envResult = command === 'build' || process.env.HAI_E2E === '1' ? { success: true as const, data: {} as Record<string, string> } : core.config.loadEnvFiles({ mode, envDir })
|
|
17
17
|
if (!envResult.success)
|
|
18
18
|
throw new Error(envResult.error.message)
|
|
19
19
|
const env = envResult.data
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{{! @skipIfEmpty }}
|
|
2
|
+
{{#if fullstack.hasMiniapp}}
|
|
3
|
+
{
|
|
4
|
+
"$schema": "https://inlang.com/schema/inlang-message-format",
|
|
5
|
+
"mini_title": "{{projectName}} ミニアプリ",
|
|
6
|
+
"mini_status": "予約済みのプレースホルダー",
|
|
7
|
+
"mini_description": "ミニアプリの対象では、まだビルド可能なパッケージは生成しません。標準のinlang project.inlangとmessagesを用意しているため、後でミニアプリ用フレームワークに組み込めます。",
|
|
8
|
+
"mini_shared_contract": "packages/{{fullstack.contractPackageName}}のスキーマとルート定数を再利用してください。",
|
|
9
|
+
"mini_own_messages": "ミニアプリ固有の文案はapps/{{projectName}}-miniapp/messagesに配置します。",
|
|
10
|
+
"mini_customize": "端末間の言語切り替えを揃えるため、言語一覧をsharedと一致させてください。"
|
|
11
|
+
}
|
|
12
|
+
{{/if}}
|
|
@@ -38,7 +38,7 @@ pnpm --filter {{projectName}}-web build
|
|
|
38
38
|
|
|
39
39
|
服务端 `config/_iam.yml` 统一控制登录、注册、重置、协议与 `ui` 品牌。邮件/短信可用 `_reach.yml` 中的 Provider/标准模板或自定义发送回调。`AuthPanel` 使用安全公开配置及框架认证动作;无需在页面适配 Token、验证码倒计时和错误提示。单实例可使用 Memory;多实例需共享数据库与 Redis,并按工程根 README 配置写入路由和传输会话。
|
|
40
40
|
|
|
41
|
-
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise
|
|
41
|
+
LDAP/Reach 均可选:基础认证无需安装。默认 LDAP 客户端需在 IAM 服务端 workspace 安装 ldapts,再配置 login.ldap 与连接信息。自定义 onOtpSendEmail/onOtpSendSms/onPasswordResetRequest 回调可独立于 Reach 使用,投递失败须拒绝 Promise;回调第三参数 context 提供 expiresAt/idempotencyKey,发送服务按稳定键持久化去重,异常/超时为结果未知且不自动重发。协议在 Modal 显示;LoginForm/RegisterForm 提供 header/extraFields/footer,AuthPanel 透传 loginHeader/loginFields/loginFooter 和 registerHeader/registerFields/registerFooter。配置及例子见生成项目的 hai-iam/hai-ui skills。
|
|
42
42
|
|
|
43
43
|
协议支持配置中的 userAgreementMarkdown/privacyPolicyMarkdown 正文及 URL;同主题优先 Markdown,由安全渲染器在弹窗显示。
|
|
44
44
|
|