@h-ai/cli 0.1.0-alpha.66 → 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 +86 -241
- package/README.ja.md +86 -241
- package/README.md +86 -241
- package/dist/{src-RDQ2EIBT.js → chunk-FI56GONY.js} +32 -2669
- 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-QYX6V7H2.js → chunk-ZFNBUF77.js} +347 -276
- package/dist/chunk-ZFNBUF77.js.map +1 -0
- package/dist/cli-config-templates-W2LLPMB6.js +5 -0
- package/dist/{cli-config-templates-3XSFIXBP.js.map → cli-config-templates-W2LLPMB6.js.map} +1 -1
- package/dist/{cli-skill-templates-TSYEQTCY.js → cli-skill-templates-US5CCAJ4.js} +3 -3
- package/dist/{cli-skill-templates-TSYEQTCY.js.map → cli-skill-templates-US5CCAJ4.js.map} +1 -1
- package/dist/index.js +1304 -532
- 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/README.md +48 -145
- 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/.dockerignore.hbs +14 -7
- package/templates/apps/api/.gitignore.hbs +7 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +23 -2
- 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 +33 -8
- 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/package.json.hbs +1 -2
- 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/hai.build.json.hbs +1 -1
- package/templates/apps/api/images/app.Dockerfile.hbs +35 -0
- package/templates/apps/api/package.json.hbs +6 -1
- package/templates/apps/api/playwright.config.ts.hbs +15 -7
- package/templates/apps/fullstack/.dockerignore.hbs +14 -9
- package/templates/apps/fullstack/.gitignore.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +24 -6
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -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 +7 -1
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +2 -2
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +23 -5
- 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/README.md.hbs +16 -6
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +24 -6
- 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 +2 -2
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +30 -9
- package/templates/apps/fullstack/hai.build.json.hbs +2 -2
- package/templates/apps/fullstack/images/app.Dockerfile.hbs +36 -0
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +34 -0
- package/templates/apps/fullstack/package.json.hbs +3 -1
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +23 -2
- 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 +32 -8
- 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/.gitignore.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +40 -14
- 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 +6 -6
- 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 +4 -4
- 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 +13 -14
- 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 +16 -5
- package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +15 -5
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +173 -14
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +2 -2
- package/templates/apps/website/messages/ja-JP.json +32 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +13 -5
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +1 -1
- package/templates/base/.dockerignore.hbs +14 -8
- package/templates/base/.gitignore.hbs +7 -0
- package/templates/base/e2e/app.spec.ts.hbs +23 -8
- package/templates/base/hai.build.json.hbs +1 -1
- package/templates/base/{Dockerfile.hbs → images/app.Dockerfile.hbs} +19 -17
- package/templates/base/package.json.hbs +11 -3
- 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 +5 -3
- 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/.gitattributes +6 -0
- package/templates/shared/e2e-env.ts +98 -0
- package/templates/shared/run-e2e.mjs +51 -12
- package/templates/skills/AGENTS.md +7 -3
- package/templates/skills/bridges/admin/AGENTS.md +6 -2
- package/templates/skills/bridges/api/AGENTS.md +3 -1
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +5 -1
- package/templates/skills/bridges/h5/AGENTS.md +6 -2
- package/templates/skills/bridges/mobile-app/AGENTS.md +6 -2
- package/templates/skills/bridges/website/AGENTS.md +6 -2
- 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 +15 -160
- package/templates/skills/hai-api-client/reference.md +178 -0
- package/templates/skills/hai-api-contract/SKILL.md +16 -273
- package/templates/skills/hai-api-contract/reference.md +280 -0
- package/templates/skills/hai-app-create/SKILL.md +6 -2
- package/templates/skills/hai-app-create/development.md +24 -8
- package/templates/skills/hai-app-create/reference.md +7 -5
- package/templates/skills/hai-app-review/SKILL.md +7 -3
- package/templates/skills/hai-app-review/differential.md +34 -0
- package/templates/skills/hai-app-tests/SKILL.md +6 -3
- package/templates/skills/hai-app-tests/reference.md +5 -5
- package/templates/skills/hai-app-tests/validation.md +38 -0
- package/templates/skills/hai-audit/SKILL.md +24 -147
- package/templates/skills/hai-audit/reference.md +148 -0
- package/templates/skills/hai-build/SKILL.md +14 -8
- package/templates/skills/hai-build/reference.md +16 -13
- package/templates/skills/hai-cache/SKILL.md +20 -181
- package/templates/skills/hai-cache/reference.md +229 -0
- package/templates/skills/hai-capacitor/SKILL.md +7 -4
- package/templates/skills/hai-capacitor/reference.md +15 -9
- package/templates/skills/hai-ci/SKILL.md +2 -0
- package/templates/skills/hai-core/SKILL.md +7 -3
- package/templates/skills/hai-core/reference.md +25 -5
- package/templates/skills/hai-crypto/SKILL.md +22 -250
- package/templates/skills/hai-crypto/reference.md +310 -0
- package/templates/skills/hai-datapipe/SKILL.md +16 -195
- package/templates/skills/hai-datapipe/reference.md +204 -0
- package/templates/skills/hai-deploy/SKILL.md +24 -54
- package/templates/skills/hai-deploy/middleware.md +51 -43
- package/templates/skills/hai-framework-sync/SKILL.md +2 -2
- package/templates/skills/hai-framework-sync/sync.md +1 -1
- package/templates/skills/hai-iam/SKILL.md +25 -11
- package/templates/skills/hai-iam/reference.md +181 -154
- package/templates/skills/hai-kit/SKILL.md +35 -174
- package/templates/skills/hai-kit/reference.md +190 -0
- package/templates/skills/hai-payment/SKILL.md +33 -263
- package/templates/skills/hai-payment/reference.md +295 -0
- package/templates/skills/hai-pr-review/SKILL.md +21 -88
- package/templates/skills/hai-reach/SKILL.md +6 -3
- package/templates/skills/hai-reach/reference.md +83 -22
- package/templates/skills/hai-reldb/SKILL.md +6 -3
- package/templates/skills/hai-reldb/reference.md +68 -25
- package/templates/skills/hai-scheduler/SKILL.md +18 -195
- package/templates/skills/hai-scheduler/reference.md +216 -0
- package/templates/skills/hai-serv/SKILL.md +25 -10
- package/templates/skills/hai-serv/reference.md +123 -87
- package/templates/skills/hai-spec-implement/SKILL.md +5 -1
- 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 +5 -3
- package/templates/skills/hai-spec-review/SKILL.md +4 -0
- package/templates/skills/hai-storage/SKILL.md +23 -238
- package/templates/skills/hai-storage/reference.md +282 -0
- package/templates/skills/hai-ui/SKILL.md +17 -3
- package/templates/skills/hai-ui/guide.md +3 -3
- package/templates/skills/hai-ui/reference.md +26 -11
- 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 +14 -10
- package/templates/skills/hai-vecdb/reference.md +33 -3
- package/dist/chunk-FWN5B54L.js +0 -468
- package/dist/chunk-FWN5B54L.js.map +0 -1
- package/dist/chunk-QYX6V7H2.js.map +0 -1
- package/dist/cli-config-templates-3XSFIXBP.js +0 -5
- package/dist/src-RDQ2EIBT.js.map +0 -1
- package/templates/apps/api/Dockerfile.hbs +0 -35
- package/templates/apps/fullstack/Dockerfile.hbs +0 -57
- /package/templates/apps/fullstack/{docker → images/web}/19-runtime-config.envsh.hbs +0 -0
- /package/templates/apps/fullstack/{docker → images/web}/nginx.conf.hbs +0 -0
- /package/templates/apps/fullstack/{docker → images/web}/runtime-config.js.template.hbs +0 -0
- /package/templates/base/{docker → images/web}/nginx.conf.hbs +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../deploy/src/deploy-artifact.ts","../../deploy/messages/en-US.json","../../deploy/messages/ja-JP.json","../../deploy/messages/zh-CN.json","../../deploy/src/deploy-i18n.ts","../../deploy/src/deploy-config.ts","../../deploy/src/deploy-types.ts","../../deploy/src/deploy-environment.ts","../../deploy/src/deploy-credentials.ts","../../deploy/src/deploy-functions.ts","../../deploy/src/deploy-recovery.ts","../../deploy/src/deploy-scanner.ts","../../deploy/src/container/deploy-command-windows.ts","../../deploy/src/container/deploy-command-process.ts","../../deploy/src/container/deploy-secret-masker.ts","../../deploy/src/container/deploy-command.ts","../../deploy/src/container/deploy-target.ts","../../deploy/src/container/deploy-scripts.ts","../../deploy/src/container/deploy-bundle.ts","../../deploy/src/container/deploy-container-compose.ts","../../deploy/src/container/deploy-ssh.ts","../../deploy/src/providers/deploy-provider-docker-ssh.ts","../../deploy/src/providers/deploy-provider-vercel.ts","../../deploy/src/provisioners/deploy-provisioner-aliyun.ts","../../deploy/src/provisioners/deploy-provisioner-neon.ts","../../deploy/src/provisioners/deploy-provisioner-r2.ts","../../deploy/src/provisioners/deploy-provisioner-resend.ts","../../deploy/src/provisioners/deploy-provisioner-upstash.ts","../../deploy/src/deploy-main.ts","../../deploy/src/deploy-middleware.ts"],"names":["core","readFileSync","resolve","existsSync","process","join","parse","writeFileSync","ok","err","dirname","logger","setTimeout","basename","mkdirSync","chmodSync","stringify","randomBytes","deploy","relative","createHash","connectionUri","Buffer"],"mappings":"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","file":"src-DSJJXM2F.js","sourcesContent":["/** 已构建镜像的交付契约;构建器写入,部署器只校验和消费。 */\nimport { createHash } from 'node:crypto'\nimport { createReadStream, existsSync, lstatSync, readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { z } from 'zod'\n\n/**\n * 镜像制品清单,例如 `{ version: 3, appVersion: '1.2.3', buildId: '1.2.3-build1', partial: false, hasWeb: false, images: [...] }`。\n * 清单格式版本为 3;完整产物必须包含 app,声明 hasWeb 时还须包含 web。结构验证不能代替真实归档校验。\n * @example\n * ```ts\n * import { readFile } from 'node:fs/promises'\n * import { DeploymentArtifactSchema } from '@h-ai/deploy'\n * const content = await readFile('.hai/build/docker/build-id/manifest.json', 'utf8')\n * const parsed = DeploymentArtifactSchema.safeParse(JSON.parse(content))\n * if (!parsed.success) throw new Error('Invalid artifact manifest')\n * // Schema 只验证结构;文件路径与 SHA-256 核验使用 readDeploymentArtifact。\n * ```\n */\nexport const DeploymentArtifactSchema = z.object({\n /** 清单格式版本,与应用版本和部署环境无关。 */\n version: z.literal(3),\n /** 应用根 package.json 的版本,用于归档、Compose 与桌面交付;最长 80 字符。 */\n appVersion: z.string().max(80).regex(/^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?(?:\\+[0-9a-z-]+(?:\\.[0-9a-z-]+)*)?$/i),\n /** 本次构建标识;同一应用版本允许重复构建。 */\n buildId: z.string().regex(/^[a-z0-9][\\w.+-]*$/i),\n /** 只包含所选镜像的构建不能用于首次安装。 */\n partial: z.boolean().default(false),\n /** API 单独构建时仍保留工程的 Web 拓扑。 */\n hasWeb: z.boolean().default(false),\n /** 工程显式配置的应用端口,部分构建未包含 app 镜像时仍保留;缺省由部署配置决定。 */\n appContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 工程显式配置的 Web 端口,部分构建未包含 web 镜像时仍保留;缺省使用部署默认值。 */\n webContainerPort: z.number().int().min(1).max(65535).optional(),\n /** 本次构建选择的镜像归档。 */\n images: z.array(z.object({\n /** app 为服务或独立应用,web 为同源 API 代理的静态前端。 */\n name: z.enum(['app', 'web']),\n /** 相对于清单目录的 tar 文件名。 */\n file: z.string().regex(/^[\\w.+-]+\\.tar$/),\n /** 归档导入后可直接使用的不可变镜像引用。 */\n imageRef: z.string().regex(/^[a-z0-9][a-z0-9./:_-]*:[a-z0-9_][a-z0-9_.-]*$/).refine(value => !value.endsWith(':latest')),\n /** tar 内容的 SHA-256,用于部署前校验。 */\n sha256: z.string().regex(/^[a-f0-9]{64}$/),\n /** 容器内部监听端口;服务器公开端口由部署选择。 */\n containerPort: z.number().int().min(1).max(65535).optional(),\n })).min(1).max(2).refine(images => new Set(images.map(image => image.name)).size === images.length),\n}).refine(artifact => artifact.images.every(image => image.file === `${image.name}-${artifact.appVersion}.tar`)).refine(artifact => artifact.partial || artifact.images.some(image => image.name === 'app')).refine(artifact => artifact.partial || !artifact.hasWeb || artifact.images.some(image => image.name === 'web'))\n\n/**\n * 构建器与部署器共享的镜像交付结构;参见 DeploymentArtifactSchema 示例。\n * @example\n * ```ts\n * import type { DeploymentArtifact } from '@h-ai/deploy'\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const verified: DeploymentArtifact = artifact\n * const references = verified.images.map(image => image.imageRef)\n * ```\n */\nexport type DeploymentArtifact = z.infer<typeof DeploymentArtifactSchema>\n\n/**\n * 流式计算制品校验和,避免将大镜像一次性读入内存。\n * @throws Error - 文件读取失败;返回真实 tar 内容的 SHA-256,不校验清单其它字段。\n * @param file - 真实镜像归档文件路径。\n * @returns 文件内容的 SHA-256 十六进制摘要。\n * @example\n * ```ts\n * import { artifactChecksum } from '@h-ai/deploy'\n * const digest = await artifactChecksum('.hai/build/docker/build-id/app-1.0.0.tar')\n * ```\n */\nexport async function artifactChecksum(file: string): Promise<string> {\n const hash = createHash('sha256')\n for await (const chunk of createReadStream(file))\n hash.update(chunk)\n return hash.digest('hex')\n}\n\n/**\n * 校验完整构建产物;缺失、损坏或非法清单均抛错,由部署边界转换为 HaiResult。\n * @throws Error - 清单、路径、镜像 tar 或摘要校验失败;不能用未验证的清单绕过本函数。\n * @param directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @returns 已经验证的构建制品清单。\n * @example\n * ```ts\n * import { readDeploymentArtifact } from '@h-ai/deploy'\n * const directory = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(directory)\n * const images = artifact.images.map(image => ({ name: image.name, imageRef: image.imageRef }))\n * ```\n */\nexport async function readDeploymentArtifact(directory: string): Promise<DeploymentArtifact> {\n const artifact = DeploymentArtifactSchema.parse(JSON.parse(readFileSync(resolve(directory, 'manifest.json'), 'utf8')))\n for (const image of artifact.images) {\n const file = resolve(directory, image.file)\n if (!existsSync(file) || !lstatSync(file).isFile() || lstatSync(file).isSymbolicLink() || await artifactChecksum(file) !== image.sha256)\n throw new Error(`Invalid artifact: ${image.file}`)\n }\n return artifact\n}\n","{\n \"deploy_notInitialized\": \"Deploy module not initialized, call deploy.init() first\",\n \"deploy_initFailed\": \"Deploy module initialization failed: {error}\",\n \"deploy_unsupportedProviderType\": \"Unsupported deploy provider type: {type}\",\n \"deploy_unsupportedProvisionerType\": \"Unsupported service provisioner type: {type}\",\n \"deploy_configTokenRequired\": \"Deploy provider token is required\",\n \"deploy_authRequired\": \"Authentication required\",\n \"deploy_authFailed\": \"Authentication failed: {error}\",\n \"deploy_projectCreateFailed\": \"Project creation failed: {error}\",\n \"deploy_uploadFailed\": \"Build output upload failed: {error}\",\n \"deploy_deployFailed\": \"Deployment failed: {error}\",\n \"deploy_provisionFailed\": \"Service provisioning failed: {service} - {error}\",\n \"deploy_adapterMissing\": \"Target platform adapter not found, please install {adapter}\",\n \"deploy_scanFailed\": \"Application scan failed: {error}\",\n \"deploy_envVarFailed\": \"Environment variable setup failed: {error}\",\n \"deploy_credentialError\": \"Credential read/write failed: {error}\",\n \"deploy_credentialInvalidKey\": \"Unsupported credential key: {key}. Only HAI_DEPLOY_* keys are allowed\",\n \"deploy_credentialSaved\": \"Credentials saved\",\n \"deploy_credentialLoaded\": \"Credentials loaded\",\n \"deploy_configError\": \"Deploy config error: {error}\",\n \"deploy_credentialMissing\": \"Missing credential fields: {fields}\",\n \"deploy_apiError\": \"{service} API error ({status})\",\n \"deploy_fileUploadFailed\": \"File upload failed ({status})\",\n \"deploy_provisionNoResult\": \"No connection info returned from {service}\",\n \"deploy_recoveryFailure\": \"Deployment stopped at {stage}; inspect the recovery details.\",\n \"deploy_recoverySuggestion\": \"Inspect listed resources in the provider console before retrying with the same project name. Unknown means the request may have created a resource. Reused resources are never deleted automatically; remove newly created resources manually only after checking their use.\",\n \"deploy_commandTimeout\": \"Command timed out: {command}\",\n \"deploy_commandFailed\": \"Command failed ({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"Cannot connect to remote host {host}: {error}\",\n \"deploy_remoteRuntimeMissing\": \"Remote host missing container runtime or compose: {runtime}\",\n \"deploy_imageTransferFailed\": \"Image transfer failed: {error}\",\n \"deploy_healthCheckFailed\": \"Health check failed, app not ready at {url}\",\n \"deploy_invalidEnvironment\": \"Use letters, numbers, underscores or hyphens for the environment; local/example are reserved.\",\n \"deploy_environmentMissing\": \"Environment file missing: {path}. Create and configure it before deploying.\",\n \"deploy_environmentReadFailed\": \"Cannot read deployment environment files; check syntax and permissions.\",\n \"deploy_environmentWriteFailed\": \"Cannot save deployment configuration; check file syntax and permissions.\",\n \"deploy_multipleApplications\": \"Multiple service packages found; specify the application directory.\",\n \"deploy_purposeSqlite\": \"Local relational database persisted in a volume\",\n \"deploy_purposeDatabase\": \"Relational database service for business data\",\n \"deploy_purposeMemory\": \"Per-process memory cache; cleared on restart, no external service\",\n \"deploy_purposeLocal\": \"Local filesystem storage persisted in a volume\",\n \"deploy_purposeCache\": \"Shared cache, sessions and distributed locks\",\n \"deploy_purposeStorage\": \"S3-compatible object storage for uploaded files\",\n \"deploy_purposeVector\": \"Vector indexing and similarity search\",\n \"deploy_purposeDisabled\": \"LDAP login is disabled; no directory service is created\",\n \"deploy_purposeLdap\": \"Directory account authentication; the default directory has no business users\",\n \"deploy_purposeConsole\": \"Messages go to application logs without delivery\",\n \"deploy_purposeEmail\": \"Email/HTTP delivery; the default SMTP container only captures test messages\",\n \"deploy_purposeSms\": \"SMS through Aliyun credentials; requires an existing signature and quota\",\n \"deploy_webProxyInvalid\": \"The API prefix must be an absolute path containing only letters, numbers, underscores, hyphens and slashes.\",\n \"deploy_artifactInvalid\": \"Image artifacts are missing or invalid. Run pnpm build --target docker, select valid --artifact-dir, or use pnpm run deploy --build.\",\n \"deploy_sshRequired\": \"Automatic deployment requires SSH settings. Use --bundle-only for manual transfer when the server is unreachable.\",\n \"deploy_bundleInstructions\": \"Bundle: {file}\\nIncludes all images needed by selected services, including self-hosted middleware.\\nWith SSH access, first edit deploy-target.json in the adjacent deployment directory using its _comments, then run deploy.ps1 (Windows) or deploy.sh (Linux/macOS) there. Both read this JSON; the sh entry also requires local awk.\\nFor isolated servers, copy and extract the tar into a separate directory, then run sh apply.sh (uses the configured target directory).\\nLinux requires Docker/Podman, Compose, sh, tar, sha256sum, awk, curl, util-linux flock and filesystem/container permissions on a filesystem supporting flock.\\nNever delete or replace .deploy.lock; its lock releases after every holder exits or the server restarts. Inspect execution and recovery state after forced termination.\\nPartial updates require a successful full installation with matching ports/layout. Steps return nonzero on failure; result-DEPLOYMENT_ID.json records the outcome.\\nThe bundle contains private runtime configuration; transfer it securely.\\nIncluded images:\\n{images}\",\n \"deploy_bundleMetadata\": \"Application version: {version}\\nBuild ID: {buildId}\\nCompose file: {compose}\",\n \"deploy_targetHost\": \"Required: Linux server address or SSH alias. Replace SERVER_HOST before running either upload script.\",\n \"deploy_targetPort\": \"SSH port, integer 1-65535; default 22.\",\n \"deploy_targetUsername\": \"SSH login username; default deploy. Requires write access to directory and container runtime permissions.\",\n \"deploy_targetIdentityFile\": \"Optional private key path on the computer running the upload script. Prefer an absolute path; empty uses ssh-agent/default keys. HAI_DEPLOY_IDENTITY_FILE overrides it.\",\n \"deploy_targetKnownHostsFile\": \"Optional known_hosts path on the computer running the upload script. Prefer an absolute path; empty uses OpenSSH defaults. HAI_DEPLOY_KNOWN_HOSTS_FILE overrides it.\",\n \"deploy_targetStrictHostKeyChecking\": \"Boolean, default true: trust new host keys and reject changed keys. false disables host key checking.\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH connection timeout in seconds, integer 1-2147483647; default 10.\",\n \"deploy_targetDirectory\": \"Required absolute application directory on the Linux server; contains incoming packages, releases and successful current state. Parent-directory traversal is forbidden.\",\n \"deploy_targetBundle\": \"Required tar filename in the parent of this deployment directory. Keep the tar and this entire directory together when moving them.\",\n \"deploy_bundleOnlyContainer\": \"Compose bundle generation is supported only by docker-ssh.\",\n \"deploy_selectedContainerOnly\": \"Selected-service deployment requires a docker-ssh Compose destination.\",\n \"deploy_selectionInvalid\": \"Cannot deploy {service}: check the service name and build its image first.\",\n \"deploy_imageVersionRequired\": \"Specify an image version; latest is not allowed: {image}\",\n \"deploy_bundleRuntimeRequired\": \"Start local Podman/Docker to export middleware images, or prepare this complete offline bundle on the build machine.\",\n \"deploy_bundleFailed\": \"Package preparation or deployment failed: {reason}\",\n \"deploy_configFileInvalid\": \"Invalid YAML in {path}, line {line}. Check indentation, colons and quotes.\",\n \"deploy_configFileUnreadable\": \"Cannot read configuration file {path}. Check its path and permissions.\",\n \"deploy_bundleNameInvalid\": \"Bundle filenames may contain letters, numbers, dots, plus signs, hyphens and underscores; parent directories may contain spaces.\",\n \"deploy_secretsInvalid\": \"Middleware credentials are damaged or incomplete: {path}. Restore a backup; passwords are not regenerated because existing data may become inaccessible.\",\n \"deploy_storageArtifactRequired\": \"Storage initialization requires the application image. Select a complete artifact containing app with --artifact-dir, or run pnpm build --target docker --images app first.\",\n \"deploy_localStopped\": \"The local command process tree has been confirmed exited.\",\n \"deploy_localUnknown\": \"Local process tree termination is unconfirmed; inspect local execution state.\",\n \"deploy_localNotStarted\": \"The local command was not started.\",\n \"deploy_commandOutputFailed\": \"Command output or callback failed\",\n \"deploy_commandInputFailed\": \"Command input failed\",\n \"deploy_commandTreeActive\": \"Child processes remain active after the main command exited\",\n \"deploy_commandExecutionFailed\": \"Command execution failed\",\n \"deploy_remoteUnknown\": \"Remote execution is unknown. Local SSH termination does not prove remote deployment stopped; inspect the server result and actual containers.\",\n \"deploy_remoteFinished\": \"A matching server result confirms the deployment script and recovery finished: stage {stage}, exit {code}. Verify actual service health.\"\n}\n","{\n \"deploy_notInitialized\": \"デプロイモジュールが初期化されていません。先にdeploy.init()を呼び出してください\",\n \"deploy_initFailed\": \"デプロイモジュールの初期化に失敗しました: {error}\",\n \"deploy_unsupportedProviderType\": \"未対応のデプロイプロバイダーの種類です: {type}\",\n \"deploy_unsupportedProvisionerType\": \"未対応のサービスプロビジョナーの種類です: {type}\",\n \"deploy_configTokenRequired\": \"デプロイプロバイダーのトークンは必須です\",\n \"deploy_authRequired\": \"認証が必要です\",\n \"deploy_authFailed\": \"認証に失敗しました: {error}\",\n \"deploy_projectCreateFailed\": \"プロジェクトの作成に失敗しました: {error}\",\n \"deploy_uploadFailed\": \"ビルド成果物のアップロードに失敗しました: {error}\",\n \"deploy_deployFailed\": \"デプロイに失敗しました: {error}\",\n \"deploy_provisionFailed\": \"サービスの準備に失敗しました: {service} - {error}\",\n \"deploy_adapterMissing\": \"対象プラットフォームのアダプターが見つかりません。{adapter}をインストールしてください\",\n \"deploy_scanFailed\": \"アプリケーションのスキャンに失敗しました: {error}\",\n \"deploy_envVarFailed\": \"環境変数の設定に失敗しました: {error}\",\n \"deploy_credentialError\": \"認証情報の読み書きに失敗しました: {error}\",\n \"deploy_credentialInvalidKey\": \"未対応の認証情報キーです: {key}。HAI_DEPLOY_*キーのみ使用できます\",\n \"deploy_credentialSaved\": \"認証情報を保存しました\",\n \"deploy_credentialLoaded\": \"認証情報を読み込みました\",\n \"deploy_configError\": \"デプロイ設定エラー: {error}\",\n \"deploy_credentialMissing\": \"認証情報の項目が不足しています: {fields}\",\n \"deploy_apiError\": \"{service} APIエラー({status})\",\n \"deploy_fileUploadFailed\": \"ファイルのアップロードに失敗しました({status})\",\n \"deploy_provisionNoResult\": \"{service}から接続情報が返されませんでした\",\n \"deploy_recoveryFailure\": \"{stage}でデプロイを停止しました。復旧情報を確認してください。\",\n \"deploy_recoverySuggestion\": \"同じプロジェクト名で再試行する前に、プロバイダーのコンソールで記載されたリソースを確認してください。「不明」は、リクエストによってリソースが作成された可能性を示します。再利用したリソースは自動削除されません。新規リソースは使用状況を確認してから手動で削除してください。\",\n \"deploy_commandTimeout\": \"コマンドがタイムアウトしました: {command}\",\n \"deploy_commandFailed\": \"コマンドに失敗しました({command}): {error}\",\n \"deploy_remoteConnectFailed\": \"リモートホスト{host}に接続できません: {error}\",\n \"deploy_remoteRuntimeMissing\": \"リモートホストにコンテナーランタイムまたはcomposeがありません: {runtime}\",\n \"deploy_imageTransferFailed\": \"イメージの転送に失敗しました: {error}\",\n \"deploy_healthCheckFailed\": \"ヘルスチェックに失敗しました。{url}でアプリの準備が完了していません\",\n \"deploy_invalidEnvironment\": \"環境名には英数字、アンダースコア、ハイフンを使用してください。local/exampleは予約されています。\",\n \"deploy_environmentMissing\": \"環境ファイルがありません: {path}。デプロイ前に作成して設定してください。\",\n \"deploy_environmentReadFailed\": \"デプロイ用の環境ファイルを読み取れません。構文と権限を確認してください。\",\n \"deploy_environmentWriteFailed\": \"デプロイ設定を保存できません。ファイルの構文と権限を確認してください。\",\n \"deploy_multipleApplications\": \"サービスパッケージが複数見つかりました。アプリケーションのディレクトリを指定してください。\",\n \"deploy_purposeSqlite\": \"ボリュームに永続化するローカルリレーショナルデータベース\",\n \"deploy_purposeDatabase\": \"業務データ用のリレーショナルデータベースサービス\",\n \"deploy_purposeMemory\": \"プロセス単位のメモリーキャッシュ。再起動時に消去され、外部サービスは使用しません\",\n \"deploy_purposeLocal\": \"ボリュームに永続化するローカルファイルストレージ\",\n \"deploy_purposeCache\": \"共有キャッシュ、セッション、分散ロック\",\n \"deploy_purposeStorage\": \"アップロードファイル用のS3互換オブジェクトストレージ\",\n \"deploy_purposeVector\": \"ベクトルのインデックス作成と類似検索\",\n \"deploy_purposeDisabled\": \"LDAPログインは無効です。ディレクトリサービスは作成しません\",\n \"deploy_purposeLdap\": \"ディレクトリアカウント認証。既定のディレクトリには業務ユーザーはいません\",\n \"deploy_purposeConsole\": \"配信せず、アプリケーションログにメッセージを出力します\",\n \"deploy_purposeEmail\": \"メール/HTTP配信。既定のSMTPコンテナーはテストメッセージのみ受信します\",\n \"deploy_purposeSms\": \"Aliyunの認証情報によるSMS。既存の署名と利用枠が必要です\",\n \"deploy_webProxyInvalid\": \"APIプレフィックスは、英数字、アンダースコア、ハイフン、スラッシュのみを含む絶対パスで指定してください。\",\n \"deploy_artifactInvalid\": \"イメージ成果物が存在しないか、無効です。pnpm build --target docker を実行するか、--artifact-dir で有効な成果物を選択するか、pnpm run deploy --build を使用してください。\",\n \"deploy_sshRequired\": \"自動デプロイにはSSH設定が必要です。サーバーに接続できない場合は--bundle-onlyで手動転送用のバンドルを生成してください。\",\n \"deploy_bundleInstructions\": \"バンドル:{file}\\n選択したサービスに必要なすべてのイメージを含みます(セルフホストのミドルウェアを含む)。\\nSSH を使用する場合、隣接するデプロイディレクトリの deploy-target.json を _comments に従って編集し、同じ場所で deploy.ps1(Windows)または deploy.sh(Linux/macOS)を実行してください。両方ともこの JSON を読み込みます。sh の実行にはローカルの awk も必要です。\\n隔離されたサーバーでは、tar を別のディレクトリへコピーして展開し、sh apply.sh を実行してください(設定された対象ディレクトリを使用します)。\\nLinux には Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux の flock が必要です。flock に対応したファイルシステム上で、ファイルシステムとコンテナーの操作権限も必要です。\\n.deploy.lock は削除も置換もしないでください。すべての保持プロセスが終了するか、サーバーが再起動するとロックが解放されます。強制終了後は実行状態と復旧状態を確認してください。\\n部分更新にはポートと構成が一致する正常な完全インストールが必要です。各手順は失敗時に非ゼロで終了し、result-DEPLOYMENT_ID.json に結果を記録します。\\nバンドルには非公開の実行時設定が含まれます。安全に転送してください。\\n同梱イメージ:\\n{images}\",\n \"deploy_bundleMetadata\": \"アプリのバージョン: {version}\\nビルドID: {buildId}\\nComposeファイル: {compose}\",\n \"deploy_targetHost\": \"必須:Linux サーバーのアドレスまたは SSH エイリアス。アップロードスクリプトを実行する前に SERVER_HOST を置き換えてください。\",\n \"deploy_targetPort\": \"SSH ポート。1〜65535の整数。既定値は22です。\",\n \"deploy_targetUsername\": \"SSH ログインユーザー名。既定値は deploy です。対象ディレクトリへの書き込み権限とコンテナーランタイムの操作権限が必要です。\",\n \"deploy_targetIdentityFile\": \"アップロードスクリプトを実行する端末上の秘密鍵パス(省略可)。絶対パスを推奨します。空欄では ssh-agent または既定の鍵を使用します。HAI_DEPLOY_IDENTITY_FILE で上書きできます。\",\n \"deploy_targetKnownHostsFile\": \"アップロードスクリプトを実行する端末上の known_hosts パス(省略可)。絶対パスを推奨します。空欄では OpenSSH の既定値を使用します。HAI_DEPLOY_KNOWN_HOSTS_FILE で上書きできます。\",\n \"deploy_targetStrictHostKeyChecking\": \"真偽値。既定値の true は新しいホスト鍵を信頼し、変更された鍵を拒否します。false はホスト鍵の検証を無効にします。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 接続タイムアウト(秒)。1〜2147483647の整数。既定値は10です。\",\n \"deploy_targetDirectory\": \"必須:Linux サーバー上のアプリケーションの絶対ディレクトリ。受信パッケージ、リリース、成功時の current 状態を保存します。親ディレクトリへの移動は許可されません。\",\n \"deploy_targetBundle\": \"必須:このデプロイディレクトリの親にある tar ファイル名。移動時は tar とこのディレクトリ全体を一緒に移動してください。\",\n \"deploy_bundleOnlyContainer\": \"Composeバンドルの生成はdocker-sshのみでサポートされます。\",\n \"deploy_selectedContainerOnly\": \"サービスを選択したデプロイには docker-ssh Compose のデプロイ先が必要です。\",\n \"deploy_selectionInvalid\": \"{service} をデプロイできません。サービス名を確認し、先にイメージをビルドしてください。\",\n \"deploy_imageVersionRequired\": \"イメージのバージョンを指定してください。latest は使用できません:{image}\",\n \"deploy_bundleRuntimeRequired\": \"ミドルウェアイメージをエクスポートするにはローカルの Podman/Docker を起動するか、ビルド端末で完全なオフラインバンドルを作成してください。\",\n \"deploy_bundleFailed\": \"パッケージの準備またはデプロイに失敗しました:{reason}\",\n \"deploy_configFileInvalid\": \"{path} の {line} 行目の YAML が無効です。インデント、コロン、引用符を確認してください。\",\n \"deploy_configFileUnreadable\": \"設定ファイル {path} を読み込めません。パスと権限を確認してください。\",\n \"deploy_bundleNameInvalid\": \"バンドルのファイル名には英数字、ドット、プラス、ハイフン、アンダースコアを使用できます。親ディレクトリには空白を使用できます。\",\n \"deploy_secretsInvalid\": \"ミドルウェアの認証情報が破損しているか、不完全です:{path}。バックアップを復元してください。既存データにアクセスできなくなる可能性があるため、パスワードは再生成しません。\",\n \"deploy_storageArtifactRequired\": \"ストレージの初期化にはアプリケーションイメージが必要です。--artifact-dir で app を含む完全な成果物を選択するか、先に pnpm build --target docker --images app を実行してください。\",\n \"deploy_localStopped\": \"ローカルコマンドのプロセスツリーの終了を確認しました。\",\n \"deploy_localUnknown\": \"ローカルプロセスツリーの終了は未確認です。ローカルの実行状態を確認してください。\",\n \"deploy_localNotStarted\": \"ローカルコマンドは起動していません。\",\n \"deploy_commandOutputFailed\": \"コマンド出力またはコールバックに失敗しました\",\n \"deploy_commandInputFailed\": \"コマンド入力に失敗しました\",\n \"deploy_commandTreeActive\": \"メインコマンド終了後も子プロセスが動作しています\",\n \"deploy_commandExecutionFailed\": \"コマンドの実行に失敗しました\",\n \"deploy_remoteUnknown\": \"リモートの実行状態は不明です。ローカル SSH の終了はリモートデプロイの停止を意味しません。サーバーの結果と実際のコンテナーを確認してください。\",\n \"deploy_remoteFinished\": \"対応するサーバーの結果により、デプロイスクリプトと復旧処理の終了を確認しました:段階 {stage}、終了コード {code}。実際のサービスの稼働状態を確認してください。\"\n}\n","{\n \"deploy_notInitialized\": \"Deploy 模块尚未初始化,请先调用 deploy.init()\",\n \"deploy_initFailed\": \"Deploy 模块初始化失败:{error}\",\n \"deploy_unsupportedProviderType\": \"不支持的部署平台类型:{type}\",\n \"deploy_unsupportedProvisionerType\": \"不支持的服务 Provisioner 类型:{type}\",\n \"deploy_configTokenRequired\": \"部署平台 Token 不能为空\",\n \"deploy_authRequired\": \"请先完成认证\",\n \"deploy_authFailed\": \"认证失败:{error}\",\n \"deploy_projectCreateFailed\": \"项目创建失败:{error}\",\n \"deploy_uploadFailed\": \"构建产物上传失败:{error}\",\n \"deploy_deployFailed\": \"部署失败:{error}\",\n \"deploy_provisionFailed\": \"基础设施开通失败:{service} - {error}\",\n \"deploy_adapterMissing\": \"未检测到目标平台 adapter,请安装 {adapter}\",\n \"deploy_scanFailed\": \"应用扫描失败:{error}\",\n \"deploy_envVarFailed\": \"环境变量设置失败:{error}\",\n \"deploy_credentialError\": \"凭证读写失败:{error}\",\n \"deploy_credentialInvalidKey\": \"不支持的凭证键名:{key}。仅允许 HAI_DEPLOY_*\",\n \"deploy_credentialSaved\": \"凭证已保存\",\n \"deploy_credentialLoaded\": \"凭证已加载\",\n \"deploy_configError\": \"部署配置错误:{error}\",\n \"deploy_credentialMissing\": \"缺少凭证字段:{fields}\",\n \"deploy_apiError\": \"{service} API 请求失败({status})\",\n \"deploy_fileUploadFailed\": \"文件上传失败({status})\",\n \"deploy_provisionNoResult\": \"{service} 未返回连接信息\",\n \"deploy_recoveryFailure\": \"部署在 {stage} 阶段停止,请查看恢复清单。\",\n \"deploy_recoverySuggestion\": \"重试前在服务商控制台核对清单,并使用相同项目名。unknown 表示请求可能已创建资源。复用资源不会自动删除;新建资源仅在确认未被使用后人工清理。\",\n \"deploy_commandTimeout\": \"命令执行超时:{command}\",\n \"deploy_commandFailed\": \"命令执行失败({command}):{error}\",\n \"deploy_remoteConnectFailed\": \"无法连接远程主机 {host}:{error}\",\n \"deploy_remoteRuntimeMissing\": \"远程主机缺少容器运行时或 compose:{runtime}\",\n \"deploy_imageTransferFailed\": \"镜像传输失败:{error}\",\n \"deploy_healthCheckFailed\": \"健康检查失败,应用未在 {url} 就绪\",\n \"deploy_invalidEnvironment\": \"环境名称仅允许字母、数字、下划线和连字符,且不能使用 local/example。\",\n \"deploy_environmentMissing\": \"缺少环境配置 {path};请先创建该文件并完成配置,再重新部署。\",\n \"deploy_environmentReadFailed\": \"部署环境文件读取失败,请检查文件格式与权限。\",\n \"deploy_environmentWriteFailed\": \"部署配置写入失败,请检查文件格式与权限。\",\n \"deploy_multipleApplications\": \"发现多个服务包,请指定要部署的应用目录。\",\n \"deploy_purposeSqlite\": \"本地文件关系数据库,使用持久化卷\",\n \"deploy_purposeDatabase\": \"独立关系数据库服务,保存业务数据\",\n \"deploy_purposeMemory\": \"单进程内存缓存,重启后清空,不创建外部服务\",\n \"deploy_purposeLocal\": \"本地文件存储,使用持久化卷\",\n \"deploy_purposeCache\": \"共享缓存、会话与分布式锁\",\n \"deploy_purposeStorage\": \"S3 兼容对象存储,保存上传文件\",\n \"deploy_purposeVector\": \"向量索引与相似度搜索\",\n \"deploy_purposeDisabled\": \"LDAP 登录未启用,不创建目录服务\",\n \"deploy_purposeLdap\": \"企业目录账号认证;默认目录不包含业务用户\",\n \"deploy_purposeConsole\": \"消息输出到应用日志,不实际投递\",\n \"deploy_purposeEmail\": \"邮件或 HTTP 通知投递;默认 SMTP 容器仅用于测试接收\",\n \"deploy_purposeSms\": \"通过阿里云凭证接入短信服务,需已有签名与额度\",\n \"deploy_webProxyInvalid\": \"API 前缀必须是仅含字母、数字、下划线、连字符和斜杠的绝对路径。\",\n \"deploy_artifactInvalid\": \"镜像产物缺失或校验失败。请先执行 pnpm build --target docker,或用 --artifact-dir 指定有效产物;也可用 pnpm run deploy --build 一次完成。\",\n \"deploy_sshRequired\": \"自动部署需要 SSH 配置;无网络连接时使用 --bundle-only 生成部署包并手工搬运。\",\n \"deploy_bundleInstructions\": \"部署包:{file}\\n包中已包含本次选择服务需要的镜像,包括自建中间件。\\n有 SSH 连接时,先按 _comments 说明修改旁边部署目录中的 deploy-target.json,再运行同目录的 deploy.ps1(Windows)或 deploy.sh(Linux/macOS);两者均读取此 JSON,sh 入口还需本机安装 awk。\\n完全隔离时,复制 tar 到 Linux 服务器,在独立目录解包,再执行 sh apply.sh(使用包中配置的目标目录)。\\n服务器需要 Docker/Podman、Compose、sh、tar、sha256sum、awk、curl、util-linux flock,以及支持 flock 的文件系统和目录、容器运行权限。\\n固定锁文件 .deploy.lock 禁止删除或替换;全部持有进程退出或重启后自动释放。强杀后的执行与恢复状态须人工核对。\\n部分更新要求服务器已有成功的完整部署,端口及应用布局保持一致。每步失败会返回非零退出码;结果记录在部署目录 result-部署ID.json。\\n包包含私有运行配置,请安全传输。\\n所含镜像:\\n{images}\",\n \"deploy_bundleMetadata\": \"应用版本:{version}\\n构建编号:{buildId}\\nCompose 文件:{compose}\",\n \"deploy_targetHost\": \"必填:Linux 服务器地址或 SSH 别名。执行任一上传脚本前,将 SERVER_HOST 改为实际地址。\",\n \"deploy_targetPort\": \"SSH 端口,1-65535 的整数,默认 22。\",\n \"deploy_targetUsername\": \"SSH 登录用户名,默认 deploy;需要目标目录写入权限及容器运行权限。\",\n \"deploy_targetIdentityFile\": \"可选:运行上传脚本的电脑上的私钥路径,建议绝对路径;留空使用 ssh-agent 或默认密钥。HAI_DEPLOY_IDENTITY_FILE 可覆盖。\",\n \"deploy_targetKnownHostsFile\": \"可选:运行上传脚本的电脑上的 known_hosts 路径,建议绝对路径;留空使用 OpenSSH 默认文件。HAI_DEPLOY_KNOWN_HOSTS_FILE 可覆盖。\",\n \"deploy_targetStrictHostKeyChecking\": \"布尔值,默认 true:首次信任新主机密钥,拒绝已变更密钥;false 关闭主机密钥检查。\",\n \"deploy_targetConnectTimeoutSeconds\": \"SSH 连接超时秒数,1-2147483647 的整数,默认 10。\",\n \"deploy_targetDirectory\": \"必填:Linux 服务器上的应用绝对目录,保存 incoming 部署包、releases 及成功状态 current;禁止 .. 父目录跳转。\",\n \"deploy_targetBundle\": \"必填:本部署操作目录上一级的 tar 文件名;搬运时请将 tar 和本目录完整放在一起。\",\n \"deploy_bundleOnlyContainer\": \"仅生成 Compose tar 只支持 docker-ssh。\",\n \"deploy_selectedContainerOnly\": \"按服务局部部署仅适用于 docker-ssh Compose 目标。\",\n \"deploy_selectionInvalid\": \"无法部署服务 {service}:请检查服务名称,并先构建对应镜像。\",\n \"deploy_storageArtifactRequired\": \"存储初始化需要应用镜像。请用 --artifact-dir 选择含 app 镜像的完整制品,或先执行 pnpm build --target docker --images app。\",\n \"deploy_imageVersionRequired\": \"镜像必须指定版本,不能使用 latest:{image}\",\n \"deploy_bundleRuntimeRequired\": \"完整离线包需要导出中间件镜像。请启动本地 Podman/Docker,或在构建机打包。\",\n \"deploy_bundleFailed\": \"交付准备或部署失败:{reason}\",\n \"deploy_configFileInvalid\": \"配置文件 {path} 第 {line} 行格式有误。请检查缩进、冒号和引号后重试。\",\n \"deploy_configFileUnreadable\": \"无法读取配置文件 {path},请检查文件路径与读取权限。\",\n \"deploy_bundleNameInvalid\": \"部署包文件名只支持字母、数字、点、加号、短横线和下划线;所在目录可以包含空格。\",\n \"deploy_secretsInvalid\": \"中间件凭据文件损坏或缺少字段:{path}。请从备份恢复;不会自动更换密码,以免已有数据无法访问。\",\n \"deploy_localStopped\": \"已确认本地命令进程树全部退出。\",\n \"deploy_localUnknown\": \"无法确认本地命令进程树已全部退出;请检查本机执行状态。\",\n \"deploy_localNotStarted\": \"本地命令尚未启动。\",\n \"deploy_commandOutputFailed\": \"命令输出或回调失败\",\n \"deploy_commandInputFailed\": \"命令输入失败\",\n \"deploy_commandTreeActive\": \"主命令退出后仍有活跃的子进程\",\n \"deploy_commandExecutionFailed\": \"命令执行失败\",\n \"deploy_remoteUnknown\": \"远端执行状态未知;本地 SSH 结束不证明远端部署已停止,请核对服务器结果与实际容器状态。\",\n \"deploy_remoteFinished\": \"匹配的服务器结果确认部署脚本及恢复已结束:阶段 {stage},退出码 {code}。请核对实际服务健康状态。\"\n}\n","/**\n * @h-ai/deploy — i18n\n *\n * 本文件提供部署模块的 i18n 文案访问入口。\n * @module deploy-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesJaJP from '../messages/ja-JP.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n// ─── i18n ───\n\n/**\n * 部署模块文案 Key 类型\n * 从现有中文字典推导消息键,避免内部实现使用未注册的翻译。\n * @example 模块内部上下文\n * ```ts\n * const key: DeployMessageKey = 'deploy_notInitialized'\n * const message = deployM(key)\n * ```\n */\ntype DeployMessageKey = keyof typeof messagesZhCN\n\n/**\n * 获取部署模块文案\n * 使用 core 请求/全局 locale 的现有中英字典;不自行缓存调用时的语言。\n * @param key - 文案 Key\n * @param options - 插值参数与格式化选项\n * @returns 本地化后的文案字符串\n * @example 模块内部上下文\n * ```ts\n * const message = deployM('deploy_sshRequired')\n * ```\n */\nexport const deployM = core.i18n.createMessageGetter<DeployMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n 'ja-JP': messagesJaJP,\n})\n","/**\n * @h-ai/deploy — 部署配置 Schema\n *\n * 本文件定义部署模块的 Zod Schema 和配置类型;错误定义位于 deploy-types.ts。\n * @module deploy-config\n */\n\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\n// ─── Provider 配置 Schema ───\n\n/** Vercel 部署平台配置 */\nconst VercelProviderConfigSchema = z.object({\n type: z.literal('vercel'),\n token: z.string().min(1, deployM('deploy_configTokenRequired')),\n})\n\n/** SSH 连接配置(docker-ssh Provider 使用 OpenSSH 客户端连接远程主机) */\nconst SshConfigSchema = z.object({\n /** 远程主机地址或 ~/.ssh/config 中的 Host 别名 */\n host: z.string().regex(/^[a-z0-9][a-z0-9.:-]*$/i),\n /** SSH 端口 */\n port: z.number().int().min(1).max(65535).default(22),\n /** SSH 用户名 */\n username: z.string().regex(/^[a-z_][\\w-]*$/i),\n /** 私钥文件路径(省略时使用 ssh-agent 或 ~/.ssh 默认密钥) */\n identityFile: z.string().min(1).optional(),\n /** known_hosts 文件路径(省略时使用默认;配合 CI/临时环境隔离主机指纹) */\n knownHostsFile: z.string().min(1).optional(),\n /** 严格主机密钥校验,默认开启(true→accept-new 首次信任并拒绝变更;false→关闭校验) */\n strictHostKeyChecking: z.boolean().default(true),\n /** 连接超时(秒) */\n connectTimeoutSeconds: z.number().int().positive().default(10),\n})\n\n/** 端口直出暴露配置 */\nconst PortExposeSchema = z.object({\n type: z.literal('port').default('port'),\n /** 容器内监听端口(adapter-node 默认 3000) */\n containerPort: z.number().int().min(1).max(65535).default(3000),\n /** 宿主机映射端口 */\n hostPort: z.number().int().min(1).max(65535),\n})\n\n/** 应用暴露配置(MVP 仅支持端口直出,域名网关为后续能力) */\nconst ExposeSchema = PortExposeSchema\n\n/** docker-ssh 部署平台配置 */\nconst DockerSshProviderConfigSchema = z.object({\n type: z.literal('docker-ssh'),\n /** SSH 连接参数 */\n ssh: SshConfigSchema.optional(),\n /** 远程主机运行参数 */\n remote: z.object({\n /** 远程应用根目录 */\n baseDir: z.string().regex(/^\\/[\\w/. -]+$/).refine(value => !value.split('/').includes('..')).default('/opt/hai/apps'),\n /** 远程容器运行时(auto 优先 podman) */\n runtime: z.enum(['auto', 'docker', 'podman']).default('auto'),\n }).default({ baseDir: '/opt/hai/apps', runtime: 'auto' }),\n /** 应用暴露方式 */\n expose: ExposeSchema,\n})\n\n/**\n * 部署平台配置联合类型(后续可扩展更多平台)\n * 按 type 区分 Vercel 与 docker-ssh;仅校验配置形状,不验证远端连通性或云凭据。\n * @example\n * ```ts\n * import { ProviderConfigSchema } from '@h-ai/deploy'\n * const result = ProviderConfigSchema.safeParse({ type: 'docker-ssh', expose: { hostPort: 8080 } })\n * if (!result.success) throw new Error('Invalid deployment provider')\n * const provider = result.data\n * ```\n */\nexport const ProviderConfigSchema = z.discriminatedUnion('type', [\n VercelProviderConfigSchema,\n DockerSshProviderConfigSchema,\n])\n\n/**\n * SSH 连接配置(parse 后)\n * 这是 Schema 解析后的类型,默认字段已必填;私钥路径可省略以使用 ssh-agent/默认密钥。\n * @example\n * ```ts\n * import type { SshConfig } from '@h-ai/deploy'\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * ```\n */\nexport type SshConfig = z.infer<typeof SshConfigSchema>\n\n/**\n * 端口暴露配置(parse 后)\n * @example\n * ```ts\n * import type { PortExposeConfig } from '@h-ai/deploy'\n * const ports: PortExposeConfig = { type: 'port', hostPort: 8080, containerPort: 3000 }\n * ```\n */\nexport type PortExposeConfig = z.infer<typeof PortExposeSchema>\n\n/**\n * docker-ssh 部署平台配置(parse 后)\n * SSH 可省略用于离线打包;真正在线发布必须提供 SSH 配置。\n * @example\n * ```ts\n * import type { DockerSshProviderConfig } from '@h-ai/deploy'\n * const provider: DockerSshProviderConfig = { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }\n * ```\n */\nexport type DockerSshProviderConfig = z.infer<typeof DockerSshProviderConfigSchema>\n\n// ─── Provisioner 配置 Schema ───\n\n/** Neon PostgreSQL 服务配置 */\nconst NeonServiceSchema = z.object({\n provisioner: z.literal('neon'),\n apiKey: z.string().min(1),\n})\n\n/** Upstash Redis 服务配置 */\nconst UpstashServiceSchema = z.object({\n provisioner: z.literal('upstash'),\n email: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** Cloudflare R2 存储服务配置 */\nconst R2ServiceSchema = z.object({\n provisioner: z.literal('cloudflare-r2'),\n accessKeyId: z.string().min(1),\n secretAccessKey: z.string().min(1),\n accountId: z.string().min(1),\n apiToken: z.string().min(1),\n})\n\n/** Resend 邮件服务配置 */\nconst ResendServiceSchema = z.object({\n provisioner: z.literal('resend'),\n from: z.string().email(),\n apiKey: z.string().min(1),\n})\n\n/** 阿里云短信服务配置 */\nconst AliyunSmsServiceSchema = z.object({\n provisioner: z.literal('aliyun'),\n signName: z.string().min(1),\n accessKeyId: z.string().min(1),\n accessKeySecret: z.string().min(1),\n})\n\n/** 基础设施服务配置 */\nconst ServicesConfigSchema = z.object({\n db: z.discriminatedUnion('provisioner', [NeonServiceSchema]).optional(),\n cache: z.discriminatedUnion('provisioner', [UpstashServiceSchema]).optional(),\n storage: z.discriminatedUnion('provisioner', [R2ServiceSchema]).optional(),\n email: z.discriminatedUnion('provisioner', [ResendServiceSchema]).optional(),\n sms: z.discriminatedUnion('provisioner', [AliyunSmsServiceSchema]).optional(),\n}).optional()\n\n// ─── 完整配置 Schema ───\n\n/**\n * 部署模块完整配置 Schema\n * @example\n * ```ts\n * import { DeployConfigSchema } from '@h-ai/deploy'\n * const parsed = DeployConfigSchema.safeParse({ environment: 'prod', provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!parsed.success) throw new Error('Invalid deployment configuration')\n * const baseDir = parsed.data.provider.type === 'docker-ssh' ? parsed.data.provider.remote.baseDir : undefined\n * ```\n */\nexport const DeployConfigSchema = z.object({\n /** 部署环境文件模式;dev/test/prod 或自定义模式,禁止 local/example。 */\n environment: z.string().regex(/^[a-z0-9][\\w-]*$/i).refine(value => !['local', 'example'].includes(value.toLowerCase())).optional(),\n provider: ProviderConfigSchema,\n services: ServicesConfigSchema,\n /** Docker Compose 部署参数;构建配置位于项目 hai.build.json。 */\n container: z.object({\n /** 自建 S3 服务实现;协议仍为 storage.type=s3。 */\n s3Engine: z.enum(['rustfs', 'minio']).default('rustfs'),\n }).optional(),\n})\n\n/**\n * 部署配置类型(parse 后)\n * @example\n * ```ts\n * import type { DeployConfig } from '@h-ai/deploy'\n * const config: DeployConfig = { environment: 'prod', provider: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } } }\n * ```\n */\nexport type DeployConfig = z.infer<typeof DeployConfigSchema>\n\n/**\n * 部署配置输入类型(用户输入)\n * @example\n * ```ts\n * import type { DeployConfigInput } from '@h-ai/deploy'\n * const input: DeployConfigInput = { provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } } // 由 init 应用 remote 等默认值。\n * ```\n */\nexport type DeployConfigInput = z.input<typeof DeployConfigSchema>\n","/**\n * @h-ai/deploy — 类型定义\n *\n * 本文件定义部署模块的核心接口和类型(非配置相关)。 配置相关类型请从 deploy-config.ts 导入。\n * @module deploy-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst DeployErrorInfo = {\n DEPLOY_FAILED: '001:500',\n PROJECT_CREATE_FAILED: '002:500',\n UPLOAD_FAILED: '004:500',\n AUTH_REQUIRED: '005:401',\n AUTH_FAILED: '006:401',\n PROVISION_FAILED: '007:500',\n ADAPTER_MISSING: '008:500',\n SCAN_FAILED: '009:500',\n NOT_INITIALIZED: '010:500',\n ENV_VAR_FAILED: '011:500',\n UNSUPPORTED_TYPE: '012:400',\n CONFIG_ERROR: '013:500',\n CREDENTIAL_ERROR: '014:500',\n REMOTE_CONNECT_FAILED: '017:500',\n REMOTE_COMMAND_FAILED: '018:500',\n IMAGE_TRANSFER_FAILED: '019:500',\n HEALTH_CHECK_FAILED: '020:500',\n} as const satisfies ErrorInfo\n\n/**\n *\n * @example\n * ```ts\n * import { err } from '@h-ai/core'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const result = err(HaiDeployError.CONFIG_ERROR, 'Invalid deployment configuration')\n * if (!result.success && result.error.code === HaiDeployError.CONFIG_ERROR.code) {\n * process.stderr.write(result.error.message + '\\n')\n * }\n * ```\n */\nexport const HaiDeployError = core.error.buildHaiErrorsDef('deploy', DeployErrorInfo)\n\n/**\n * 部署错误接口\n *\n * 用于组合错误定义、消息与可选 cause 的描述对象;业务操作返回的 error 遵循 core.HaiError,请按 success 分支读取 code/message。\n * @example\n * ```ts\n * import type { DeployError } from '@h-ai/deploy'\n * import { HaiDeployError } from '@h-ai/deploy'\n * const detail: DeployError = { def: HaiDeployError.DEPLOY_FAILED, message: 'Deployment failed' }\n * ```\n */\nexport interface DeployError {\n /** 错误定义 */\n def: (typeof HaiDeployError)[keyof typeof HaiDeployError]\n /** 错误消息 */\n message: string\n /** 原始错误(可选) */\n cause?: unknown\n}\n\n// ─── 服务类型 ───\n\n/**\n * 基础设施服务类型\n * @example\n * ```ts\n * import type { ServiceType } from '@h-ai/deploy'\n * const service: ServiceType = 'db'\n * ```\n */\nexport type ServiceType = 'db' | 'cache' | 'storage' | 'email' | 'sms' | 'vecdb' | 'ldap'\n\n/**\n * 每项中间件的处理方式;keep 不修改配置,也不开通服务。\n * @example\n * ```ts\n * import type { MiddlewareMode } from '@h-ai/deploy'\n * const mode: MiddlewareMode = 'keep' // 复用已有服务,不修改连接配置或自动开通。\n * ```\n */\nexport type MiddlewareMode = 'default' | 'custom' | 'keep'\n\n/**\n * 扫描环境;例如 `{ environment: 'test', envDir: '/workspace/app' }`。\n * @example\n * ```ts\n * import type { DeployScanOptions } from '@h-ai/deploy'\n * const options: DeployScanOptions = { environment: 'prod', envDir: '/workspace/shop' }\n * ```\n */\nexport interface DeployScanOptions {\n /** 环境文件模式。 */\n environment?: string\n /** 环境文件目录;默认自动定位到应用或 workspace 根。 */\n envDir?: string\n}\n\n/**\n * 依赖对应的中间件;例如 IAM 的 LDAP 位于 `iam.ldap`,可处于 disabled 状态。\n * @example\n * ```ts\n * import type { MiddlewareRequirement } from '@h-ai/deploy'\n * const requirement: MiddlewareRequirement = { service: 'db', backend: 'postgresql', source: '@h-ai/reldb', configName: 'db', configPath: [], envPrefix: 'HAI_DB', config: { host: 'db', database: 'shop' } }\n * // config 可能含私有值;展示时只选择安全字段。\n * ```\n */\nexport interface MiddlewareRequirement {\n /** 中间件类别。 */\n service: ServiceType\n /** 生效后端标识。 */\n backend: string\n /** 检测来源(依赖包或配置名),用于解释为何需要此项。 */\n source: string\n /** 模块配置名。 */\n configName: string\n /** 模块配置内的路径;例如 LDAP 为 ['ldap']。 */\n configPath: string[]\n /** 约定变量前缀。 */\n envPrefix: string\n /** 生效连接配置,可能含凭据,仅用于输入默认值,不得原样输出日志。 */\n config: Record<string, unknown>\n}\n\n// ─── 扫描结果 ───\n\n/**\n * 应用扫描结果\n *\n * 由 scanner 分析应用目录后返回,描述应用的框架类型、依赖和部署需求。\n * 扫描是文件系统能力,不依赖 init,也不代表远程服务已经连通。\n * @example\n * ```ts\n * import type { ScanResult } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const result = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const scan: ScanResult = result.data\n * const services = scan.requiredServices\n * ```\n */\nexport interface ScanResult {\n /** 调用者指定的部署目录,对应 lockfile 中的一个 importer。 */\n appDir?: string\n /** 公共环境文件目录。 */\n envDir?: string\n /** 依赖与配置共同确定的中间件详情。 */\n middlewares?: MiddlewareRequirement[]\n /** 从运行依赖图识别的 Hai 模块;peer 和开发依赖不启用模块。 */\n haiModules?: string[]\n /** 应用名称(目录名称;可用 projectName 显式覆盖部署资源名)。 */\n appName: string\n /** 是否为 SvelteKit 项目 */\n isSvelteKit: boolean\n /** 目标平台 adapter 是否已安装(如 @sveltejs/adapter-vercel) */\n adapterInstalled: boolean\n /** 容器部署所需的 @sveltejs/adapter-node 是否已安装 */\n nodeAdapterInstalled: boolean\n /** 检测到的模块依赖需要的服务列表 */\n requiredServices: ServiceType[]\n /** 各服务检测到的后端类型(如 db→postgresql/mysql,vecdb→qdrant),用于生成匹配的 sidecar */\n serviceBackends: Partial<Record<ServiceType, string>>\n}\n\n// ─── 部署结果 ───\n\n/**\n * 部署结果\n *\n * 包含部署后的访问 URL、状态和已设置的环境变量。\n * @example\n * ```ts\n * import type { DeployResult } from '@h-ai/deploy'\n * const packaged: DeployResult = { url: '', deploymentId: 'deploy-shop-001', status: 'packaged', bundlePath: '/workspace/shop/.hai/deploy/shop-1.0.0.tar', envVarsSet: [], provider: 'docker-ssh', healthCheck: 'skipped' }\n * // packaged 只代表交付包生成;不将其展示为服务已上线。\n * ```\n */\nexport interface DeployResult {\n /** 部署后的访问 URL */\n url: string\n /** 部署 ID */\n deploymentId: string\n /** 部署状态 */\n status: 'ready' | 'packaged' | 'building' | 'error'\n /** Compose 部署 tar 的绝对路径;包含私有配置,应安全传输。 */\n bundlePath?: string\n /** 手工搬运和启动说明;仅打包不代表服务器已运行。 */\n instructions?: string\n /** 已设置的环境变量名列表 */\n envVarsSet: string[]\n /** 部署 Provider 名称(如 vercel / docker-ssh),容器部署时返回 */\n provider?: string\n /** 健康检查结果:passed 表示 HTTP 探测成功,container-only 表示仅确认容器运行 */\n healthCheck?: 'passed' | 'container-only' | 'skipped'\n}\n\n// ─── 开通结果 ───\n\n/**\n * 基础设施开通结果\n *\n * 由 Provisioner 开通服务后返回,包含要注入到部署平台的环境变量。\n * @example\n * ```ts\n * import type { ProvisionResult } from '@h-ai/deploy'\n * const reused: ProvisionResult = { resourceStatus: 'reused', serviceType: 'db', provisionerName: 'neon', envVars: { HAI_DB_TYPE: 'postgresql' }, resourceInfo: 'Existing shop database' }\n * // envVars 可能含密码;不能直接输出。\n * ```\n */\nexport interface ProvisionResult {\n /** 本次新建或复用;凭证型服务始终为 reused */\n resourceStatus: 'created' | 'reused'\n /** 服务类型 */\n serviceType: ServiceType\n /** Provisioner 名称 */\n provisionerName: string\n /** 要注入到部署平台的环境变量 */\n envVars: Record<string, string>\n /** 资源标识信息(如项目名、数据库名等),用于日志和展示 */\n resourceInfo: string\n}\n\n/**\n * 部署失败后的安全恢复信息,不含环境变量值或原始异常。\n * @example\n * ```ts\n * import type { DeployRecoveryInfo } from '@h-ai/deploy'\n * const recovery: DeployRecoveryInfo = { projectName: 'shop', stage: 'provision', resources: [{ serviceType: 'db', provisionerName: 'neon', resourceInfo: 'shop', resourceStatus: 'unknown' }] }\n * // 先在供应商控制台核对 unknown 资源;避免重复创建计费资源。\n * ```\n */\nexport interface DeployRecoveryInfo {\n projectName: string\n stage: string\n platformProjectId?: string\n resources: Array<{\n serviceType: ServiceType\n provisionerName: string\n resourceInfo: string\n resourceStatus: 'created' | 'reused' | 'unknown'\n }>\n}\n\n/**\n * 命令失败后的已核验执行状态;远端 finished 仅指部署脚本及恢复已完成,不代表容器停止。\n * @example\n * ```ts\n * import type { DeployCommandState } from '@h-ai/deploy'\n * const state: DeployCommandState = { reason: 'timeout', localTermination: 'confirmed', remoteExecution: 'unknown', deploymentId: 'deploy-shop-001', resultFile: '/opt/hai/apps/shop/results/deploy-shop-001' }\n * if (state.remoteExecution === 'unknown') process.stderr.write('Verify the matching remote deployment result before retrying\\n')\n * ```\n */\nexport interface DeployCommandState {\n /** 失败触发原因。 */\n reason: 'timeout' | 'output' | 'input' | 'spawn' | 'exit' | 'configuration'\n /** 本地受管理树已全部退出、无法证明,或尚未启动。 */\n localTermination: 'confirmed' | 'unknown' | 'not-started'\n /** SSH 失败默认 unknown;读取匹配部署 ID 的完整终态结果后才为 finished。 */\n remoteExecution?: 'unknown' | 'finished'\n /** 本次不可变部署 ID,可与服务器结果核对。 */\n deploymentId?: string\n /** 服务器端结果文件;无凭据。 */\n resultFile?: string\n /** 匹配终态结果中的真实脚本退出码。 */\n remoteExitCode?: number\n /** 匹配终态结果中的最后阶段。 */\n remoteStage?: string\n}\n\n// ─── 部署选项 ───\n\n/**\n * 部署选项\n * 仅更新指定服务时仍受完整/部分制品与首次部署约束;bundleOnly 不触发 SSH。\n * @example\n * ```ts\n * import type { DeployAppOptions } from '@h-ai/deploy'\n * const options: DeployAppOptions = { environment: 'prod', bundleOnly: true, artifactDir: '.hai/build/docker/build-id', selectedServices: ['app'], output: '.hai/deploy/shop.tar' }\n * ```\n */\nexport interface DeployAppOptions {\n /** 接收实际执行阶段,用于终端进度显示;不包含凭据或配置原文。 */\n onProgress?: (stage: 'packaging' | 'preflight' | 'images' | 'dependencies' | 'start' | 'health' | 'complete') => void\n /** 只更新指定的 Compose 服务;省略时完整制品部署全部,部分制品只部署其镜像。 */\n selectedServices?: string[]\n /** 打包中间件镜像所用的本地引擎,auto 优先 Podman。 */\n runtime?: 'auto' | 'podman' | 'docker'\n /** 部署环境标识;显式指定时必须存在 .env.<environment>。 */\n environment?: string\n /** 环境文件所在目录,默认自动定位。 */\n envDir?: string\n /** 按服务或变量前缀选择处理方式;如 HAI_REACH_PROVIDERS_1 可独立于另一邮件连接。 */\n serviceModes?: Partial<Record<string, MiddlewareMode>>\n /** 项目名称(默认使用明确指定的部署目录名称)。 */\n projectName?: string\n /** 是否跳过全部中间件配置与开通,默认 false;例如配置完备时设为 true。 */\n skipMiddleware?: boolean\n /** 已构建镜像目录;默认最近构建入口/锁文件目录下的 .hai/build/docker。 */\n artifactDir?: string\n /** 只生成部署 tar,不连接 SSH;仅 docker-ssh 支持。 */\n bundleOnly?: boolean\n /** 部署 tar 输出路径;默认 .hai/deploy/<环境>/bundle-<项目>-<部署ID>-<版本>.tar,自定义文件名自动补 -<版本>。 */\n output?: string\n}\n\n// ─── 凭证子功能 ───\n\n/**\n * Deploy 凭证文件操作。\n *\n * 这些方法仅操作 `~/.hai/credentials.yml`,不依赖 `deploy.init()`。\n * @example\n * ```ts\n * import type { DeployCredentialOperations } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const credentials: DeployCredentialOperations = deploy.credentials\n * const path = credentials.getPath() // 无需先 init。\n * ```\n */\nexport interface DeployCredentialOperations {\n /**\n * 获取凭证文件绝对路径。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const path = deploy.credentials.getPath() // 当前用户的全局凭证文件。\n * ```\n */\n getPath: () => string\n /**\n * 加载凭证文件并注入 `process.env`。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const loaded = deploy.credentials.load()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const names = loaded.data // 不输出被注入的值。\n * ```\n */\n load: () => HaiResult<string[]>\n /**\n * 保存单个凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.save('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n save: (key: string, value: string) => HaiResult<void>\n /**\n * 批量保存凭证。\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = deploy.credentials.saveAll({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\n saveAll: (entries: Record<string, string>) => HaiResult<void>\n}\n\n// ─── 模块功能接口 ───\n\n/**\n * Deploy 模块功能接口\n *\n * 提供自动化部署的完整 API:\n * - `deploy.credentials.*()` — 凭证文件读写(不依赖 init)\n * - `deploy.init()` — 初始化(加载配置、创建 Provider 和 Provisioner)\n * - `deploy.scan()` — 扫描应用依赖(纯文件系统能力,不依赖 init)\n * - `deploy.provisionAll()` — 开通所有已配置的基础设施\n * - `deploy.deployApp()` — 完整部署流程\n * - `deploy.close()` — 关闭模块\n * scan 与 credentials 不需要 init;部署与开通遵循 init → 检查结果 → use → finally close。close 返回 Promise<void>,不伪造 HaiResult。\n * @example\n * ```ts\n * import type { DeployFunctions } from '@h-ai/deploy'\n * import { deploy } from '@h-ai/deploy'\n * const operations: DeployFunctions = deploy\n * const scan = await operations.scan(process.cwd())\n * if (!scan.success) throw new Error(scan.error.message)\n * const required = scan.data.requiredServices\n * ```\n */\nexport interface DeployFunctions {\n /** 全局部署凭证文件操作。 */\n readonly credentials: DeployCredentialOperations\n /**\n * 初始化模块(加载配置、创建 Provider 和 Provisioner 实例)\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const ready = deploy.isInitialized\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n init: (config: DeployConfigInput) => Promise<HaiResult<void>>\n /**\n * 关闭模块\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * const provider = deploy.config?.provider.type\n * }\n * finally {\n * await deploy.close() // Promise<void>;不检查不存在的 success 字段。\n * }\n * ```\n */\n close: () => Promise<void>\n /** 当前配置 */\n readonly config: DeployConfig | null\n /** 是否已初始化 */\n readonly isInitialized: boolean\n\n /**\n * 扫描应用目录,检测依赖和所需服务。\n *\n * 这是纯文件系统分析能力,不依赖云端认证状态,可在 `deploy.init()` 之前调用。\n *\n * @param appDir - 应用根目录路径\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const scanned = await deploy.scan(process.cwd(), { environment: 'prod' })\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const services = scanned.data.requiredServices // 无需 init。\n * ```\n */\n scan: (appDir: string, options?: DeployScanOptions) => Promise<HaiResult<ScanResult>>\n\n /**\n * 对所有已配置的 Provisioner 执行基础设施开通\n *\n * @param projectName - 用于资源命名的项目名\n * @returns 所有 Provisioner 的结果列表\n * @example\n * ```ts\n * import { deploy, getDeployRecovery } from '@h-ai/deploy'\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } }, services: { db: { provisioner: 'neon', apiKey } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 会访问真实云服务并可能新建资源。\n * const result = await deploy.provisionAll('shop', ['db'])\n * if (!result.success) {\n * const recovery = getDeployRecovery(result.error)\n * if (recovery?.resources.some(resource => resource.resourceStatus === 'unknown')) {\n * process.stderr.write('Verify unknown resources at the provider before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n provisionAll: (projectName: string, services?: ServiceType[]) => Promise<HaiResult<ProvisionResult[]>>\n\n /**\n * 部署已有构建产物(环境和中间件 → 打包 → 上传/启动);不会调用构建命令。\n *\n * @param appDir - 应用根目录路径\n * @param options - 部署选项\n * @example\n * ```ts\n * import { deploy } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目必须已有构建镜像清单与生产环境配置。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.status // packaged 不代表线上运行。\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\n deployApp: (appDir: string, options?: DeployAppOptions) => Promise<HaiResult<DeployResult>>\n}\n","/** 部署环境的加载和持久化;公开环境文件不保存真实凭据。 */\nimport type { HaiResult } from '@h-ai/core'\nimport { chmodSync, existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join, resolve } from 'node:path'\nimport process from 'node:process'\nimport { parseEnv } from 'node:util'\nimport { core, err, ok } from '@h-ai/core'\nimport { LineCounter, parse, parseDocument } from 'yaml'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\n/**\n * 部署环境快照;例如 prod 的 targetValues 只来自 `.env.prod`,不包含基础/私有覆盖。\n * @example\n * ```ts\n * import type { DeploymentEnvironment } from '@h-ai/deploy'\n * const environment: DeploymentEnvironment = { environment: 'prod', envDir: '/workspace/shop', values: { HAI_DB_TYPE: 'postgresql' }, targetValues: { HAI_DB_TYPE: 'postgresql' } }\n * // values 可能还含私有凭据,不能整体写入日志。\n * ```\n */\nexport interface DeploymentEnvironment {\n /** 文件模式(dev/test/prod 或其他合法模式名)。 */\n environment: string\n /** 环境文件的绝对目录。 */\n envDir: string\n /** 合并后的部署变量,可能含私有值,不得直接记录日志。 */\n values: Record<string, string>\n /** 仅目标环境文件显式声明的变量,用于判断能否“保持不变”。 */\n targetValues: Record<string, string>\n}\n\n/** 与 Core 一致,普通字符串如 CORS 的 `*` 不能因 YAML 标量解析失败而使配置加载失败。 */\nfunction environmentValue(value: string): unknown {\n try {\n return parse(value) ?? value\n }\n catch {\n return value\n }\n}\n\n/** 在已解析的 YAML 结构上处理覆盖,避免密码中的冒号、引号、井号变成 YAML 语法。 */\nfunction resolveConfig(value: unknown, prefix: string, env: Record<string, string | undefined>): unknown {\n if (env[prefix] !== undefined)\n return environmentValue(env[prefix])\n if (Array.isArray(value))\n return value.map((item, index) => resolveConfig(item, `${prefix}_${index}`, env))\n if (value && typeof value === 'object')\n return Object.fromEntries(Object.entries(value).map(([key, nested]) => [key, resolveConfig(nested, `${prefix}_${key.toUpperCase()}`, env)]))\n if (typeof value !== 'string')\n return value\n const resolved = value.replace(/\\$\\{([^:}]+)(?::([^}]*))?\\}/g, (_match, name: string, fallback?: string) => env[name] ?? fallback ?? '')\n return /^\\$\\{[^}]+\\}$/.test(value) ? environmentValue(resolved) : resolved\n}\n\n/**\n * 按部署环境解析配置;未选择的可选 Provisioner 缺少凭据时保留空值,选择完成后由 Schema 校验。\n * 不修改 core 缓存或进程变量,不在 YAML 文本上拼接凭据。\n * @param name - 模块配置名,例如 deploy/db/iam\n * @param path - YAML 文件绝对路径\n * @param values - 已加载的目标环境变量\n * @returns 配置对象;解析错误已脱敏\n * @example\n * ```ts\n * import { loadDeploymentConfig, loadDeploymentEnvironment } from '@h-ai/deploy'\n * const environment = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!environment.success) throw new Error(environment.error.message)\n * const config = loadDeploymentConfig('deploy', `${process.cwd()}/config/_deploy.yml`, environment.data.values)\n * if (!config.success) throw new Error(config.error.message)\n * // 返回对象仍需经 DeployConfigSchema 或 deploy.init 验证。\n * ```\n */\nexport function loadDeploymentConfig(name: string, path: string, values: Record<string, string | undefined>): HaiResult<Record<string, unknown>> {\n try {\n const lineCounter = new LineCounter()\n const document = parseDocument(readFileSync(path, 'utf8'), { lineCounter, prettyErrors: false })\n if (document.errors.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: String(lineCounter.linePos(document.errors[0]!.pos[0]).line) } }))\n const config = resolveConfig(document.toJS(), `HAI_${name.toUpperCase()}`, values)\n if (config !== null && (typeof config !== 'object' || Array.isArray(config)))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileInvalid', { params: { path, line: '1' } }))\n return ok(config && typeof config === 'object' && !Array.isArray(config) ? config as Record<string, unknown> : {})\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_configFileUnreadable', { params: { path } }))\n }\n}\n\n/**\n * 加载部署环境;指定环境文件缺失时返回错误并要求用户创建。\n * 进程环境优先于 .env.local、目标环境文件、基础文件;targetValues 只记录目标文件显式项,不包含其它覆盖。\n * @param options - 模式、环境目录与是否强制存在目标文件\n * @param options.environment - dev/test/prod 或自定义模式\n * @param options.envDir - 环境文件所在目录\n * @param options.requireFile - 默认 true;扫描无显式环境时可只读取已有基础文件\n * @returns 环境快照,可能包含私有值,不得直接输出\n * @example\n * ```ts\n * import { loadDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const explicitlyConfigured = loaded.data.targetValues.HAI_DB_TYPE\n * ```\n */\nexport function loadDeploymentEnvironment(options: { environment: string, envDir: string, requireFile?: boolean }): HaiResult<DeploymentEnvironment> {\n const environment = options.environment === 'production' ? 'prod' : options.environment === 'development' ? 'dev' : options.environment\n if (!/^[a-z0-9][\\w-]*$/i.test(environment) || ['local', 'example'].includes(environment.toLowerCase()))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_invalidEnvironment'))\n const envDir = resolve(options.envDir)\n const target = join(envDir, `.env.${environment}`)\n if (options.requireFile !== false && !existsSync(target))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentMissing', { params: { path: target } }))\n const loaded = core.config.loadEnvFiles({ mode: environment, envDir })\n if (!loaded.success)\n return loaded\n try {\n const values = { ...loaded.data }\n // 只传递应用配置和显式声明的运行变量,不上传整个调用者进程环境。\n for (const [name, value] of Object.entries(process.env)) {\n if (/^(?:HAI_|PUBLIC_|VITE_)/.test(name) && value !== undefined)\n values[name] = value\n }\n values.HAI_DEPLOY_ENVIRONMENT = environment\n values.HAI_CORE_ENV ??= environment === 'prod' ? 'production' : environment === 'dev' ? 'development' : environment === 'test' ? 'test' : 'staging'\n const targetValues: Record<string, string> = {}\n if (existsSync(target)) {\n for (const [name, value] of Object.entries(parseEnv(readFileSync(target, 'utf8')))) {\n if (value !== undefined)\n targetValues[name] = value\n }\n }\n return ok({ environment, envDir, values, targetValues })\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_environmentReadFailed'))\n }\n}\n\n/** 判断值是否包含凭据;连接 URL 和 JSON 配置需要递归检查。 */\nfunction isSecret(name: string, value: string): boolean {\n if (/PASSWORD|SECRET|TOKEN|APIKEY|PRIVATEKEY|ACCESSKEY|AUTHORIZATION/i.test(name.replace(/[^a-z0-9]/gi, '')) || /(?:^|_)PASS$/i.test(name) || value.includes('PRIVATE KEY'))\n return true\n try {\n const url = new URL(value)\n if (url.username || url.password || [...url.searchParams.keys()].some(key => /password|secret|token|key|authorization/i.test(key)))\n return true\n }\n catch { /* 非 URL 配置继续按结构检查。 */ }\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return Object.entries(parsed).some(([key, nested]) => isSecret(key, typeof nested === 'string' ? nested : JSON.stringify(nested)))\n }\n catch { /* 普通字符串无需 JSON 处理。 */ }\n return false\n}\n\n/** 将 JSON 中的凭据剥离,公共文件仍保留可审查的后端/连接结构。 */\nfunction publicConfig(value: unknown): unknown {\n if (Array.isArray(value))\n return value.map(publicConfig)\n if (value && typeof value === 'object')\n return Object.fromEntries(Object.entries(value).filter(([name, item]) => !isSecret(name, typeof item === 'string' ? item : '')).map(([name, item]) => [name, publicConfig(item)]))\n return value\n}\n\n/** dotenv 引号保留空格、注释符、美元符号和 JSON;非法换行键由调用边界拒绝。 */\nfunction quoteEnv(value: string): string {\n // JSON 内用 Unicode 转义表示单引号,dotenv 单引号即可无损保存复杂密码。\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n return `'${JSON.stringify(parsed).replaceAll('\\'', '\\\\u0027')}'`\n }\n catch { /* 标量按 dotenv 原生引号规则处理。 */ }\n if (!value.includes('\\''))\n return `'${value}'`\n if (!value.includes('\"'))\n return `\"${value}\"`\n if (!value.includes('`'))\n return `\\`${value}\\``\n if (!/[\\r\\n#]/.test(value))\n return value\n throw new Error('Unsupported dotenv value')\n}\n\n/** 按原有行更新键,保留注释与其他配置;更新私有文件时要求权限 600。 */\nfunction updateFile(path: string, values: Record<string, string>, privateFile: boolean): void {\n let content = existsSync(path) ? readFileSync(path, 'utf8') : '# Local private deployment configuration; do not commit.\\n'\n for (const [name, value] of Object.entries(values)) {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name))\n throw new Error('Invalid environment variable name')\n const line = `${name}=${quoteEnv(value)}`\n // parseEnv 支持多行引号;替换时一起消费原值,避免遗留秘密片段。\n const pattern = new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*`, 'gm')\n if (pattern.test(content))\n content = content.replace(pattern, () => line)\n else\n content = `${content.trimEnd()}\\n${line}\\n`\n }\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n if (privateFile)\n chmodSync(path, 0o600)\n}\n\n/** 明确修改的公共项必须清掉同名旧私有覆盖,避免重新加载后仍用旧后端。 */\nfunction removeOverrides(path: string, names: string[], privateFile = true): void {\n if (!existsSync(path) || names.length === 0)\n return\n let content = readFileSync(path, 'utf8')\n for (const name of names)\n content = content.replace(new RegExp(`^(?:export\\\\s+)?${name}\\\\s*=\\\\s*(?:'[^']*'|\"[^\"]*\"|\\`[^\\`]*\\`|[^\\\\r\\\\n]*)[^\\\\r\\\\n]*(?:\\\\r?\\\\n|$)`, 'gm'), '')\n writeFileSync(path, content, { mode: privateFile ? 0o600 : 0o644 })\n chmodSync(path, privateFile ? 0o600 : 0o644)\n}\n\n/**\n * 保存部署产生的变量:公共值写目标环境文件,凭据写 `.env.local`。\n * 返回实际写入的变量名,调用者只展示名称或脱敏值。\n * @param environment - 已加载的目标环境快照\n * @param values - 需要更新的变量;未提供的项保持原状\n * @param options - private 为 true 时所有值只保存在本机;适用于 SSH 地址、端口及密钥路径\n * @param options.private - 是否将全部值仅保存到 .env.local\n * @returns 已保存的变量名或脱敏错误\n * @example\n * ```ts\n * import { loadDeploymentEnvironment, saveDeploymentEnvironment } from '@h-ai/deploy'\n * const loaded = loadDeploymentEnvironment({ environment: 'prod', envDir: process.cwd() })\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const saved = saveDeploymentEnvironment(loaded.data, { HAI_DB_HOST: 'db' })\n * if (!saved.success) throw new Error(saved.error.message)\n * // 密钥应以 { private: true } 写入被忽略的 .env.local,不能放公共环境文件。\n * ```\n */\nexport function saveDeploymentEnvironment(environment: DeploymentEnvironment, values: Record<string, string>, options: { private?: boolean } = {}): HaiResult<string[]> {\n try {\n const shared: Record<string, string> = {}\n const privateValues: Record<string, string> = {}\n for (const [name, value] of Object.entries(values)) {\n if (options.private) {\n privateValues[name] = value\n }\n else if (isSecret(name, value)) {\n privateValues[name] = value\n try {\n const parsed: unknown = JSON.parse(value)\n if (parsed && typeof parsed === 'object')\n shared[name] = JSON.stringify(publicConfig(parsed))\n }\n catch { /* 标量秘密仅写私有文件。 */ }\n }\n else {\n shared[name] = value\n }\n }\n if (Object.keys(shared).length)\n updateFile(join(environment.envDir, `.env.${environment.environment}`), shared, false)\n if (Object.keys(privateValues).length)\n updateFile(join(environment.envDir, '.env.local'), privateValues, true)\n removeOverrides(join(environment.envDir, `.env.${environment.environment}`), Object.keys(privateValues).filter(name => !(name in shared)), false)\n removeOverrides(join(environment.envDir, '.env.local'), Object.keys(shared).filter(name => !(name in privateValues)))\n if (Object.keys(privateValues).length) {\n const ignorePath = join(environment.envDir, '.gitignore')\n const ignore = existsSync(ignorePath) ? readFileSync(ignorePath, 'utf8') : ''\n if (!ignore.split(/\\r?\\n/).includes('.env.local'))\n writeFileSync(ignorePath, `${ignore.trimEnd()}\\n.env.local\\n.hai/deploy/\\n`)\n }\n return ok(Object.keys(values))\n }\n catch {\n return err(HaiDeployError.ENV_VAR_FAILED, deployM('deploy_environmentWriteFailed'))\n }\n}\n","/**\n * @h-ai/deploy — 凭证管理\n *\n * 管理全局凭证文件 `~/.hai/credentials.yml`。\n * 这些 helper 由 `deploy.credentials.*` 对外暴露,供 CLI 在加载 `_deploy.yml`\n * 之前注入 `HAI_DEPLOY_*` 环境变量。\n * @module deploy-credentials\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { parse, stringify } from 'yaml'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'credentials' })\n\n/** 仅允许写入 deploy 模块自有的环境变量前缀,避免把任意 YAML key 注入 process.env。 */\nconst DEPLOY_CREDENTIAL_KEY_PATTERN = /^HAI_DEPLOY_[A-Z0-9_]+$/\n\n// ─── 内部工具 ───\n\n/** 校验凭证键名是否属于 deploy 模块。 */\nfunction isAllowedCredentialKey(key: string): boolean {\n return DEPLOY_CREDENTIAL_KEY_PATTERN.test(key)\n}\n\n/**\n * 标准化凭证键值对。\n *\n * 仅保留 `HAI_DEPLOY_*` 键,且值必须是可安全序列化为字符串的标量。\n */\nfunction normalizeCredentialEntries(entries: Record<string, unknown>): Record<string, string> {\n const normalized: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(entries)) {\n if (!isAllowedCredentialKey(key)) {\n logger.warn('Ignoring unsupported deploy credential key', { key })\n continue\n }\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n normalized[key] = String(value)\n continue\n }\n\n logger.warn('Ignoring deploy credential with non-scalar value', { key })\n }\n\n return normalized\n}\n\n/** 在写入前校验单个凭证键名。 */\nfunction assertAllowedCredentialKey(key: string): void {\n if (!isAllowedCredentialKey(key)) {\n throw new Error(deployM('deploy_credentialInvalidKey', { params: { key } }))\n }\n}\n\n/** 在写入前校验批量凭证键名。 */\nfunction assertAllowedCredentialEntries(entries: Record<string, string>): void {\n for (const key of Object.keys(entries)) {\n assertAllowedCredentialKey(key)\n }\n}\n\n/**\n * 获取凭证文件路径\n * @returns `~/.hai/credentials.yml` 的绝对路径\n * @example 模块内部上下文\n * ```ts\n * const path = getCredentialsPath() // 当前用户 ~/.hai/credentials.yml,不含凭据内容。\n * ```\n */\nexport function getCredentialsPath(): string {\n return join(homedir(), '.hai', 'credentials.yml')\n}\n\n/**\n * 确保凭证目录存在\n *\n * @param filePath - 凭证文件路径\n */\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n}\n\n/**\n * 读取凭证文件内容\n *\n * @returns 解析后的键值对,文件不存在时返回空对象\n */\nfunction readCredentialsFile(): Record<string, string> {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) {\n return {}\n }\n const content = readFileSync(filePath, 'utf-8')\n const parsed = parse(content)\n if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {}\n }\n return normalizeCredentialEntries(parsed as Record<string, unknown>)\n}\n\n/**\n * 写入凭证文件\n *\n * @param data - 凭证键值对\n */\nfunction writeCredentialsFile(data: Record<string, string>): void {\n const filePath = getCredentialsPath()\n ensureDir(filePath)\n const header = '# Managed by hai cli - do not edit manually\\n'\n const content = header + stringify(data)\n writeFileSync(filePath, content, { encoding: 'utf-8', mode: 0o600 })\n}\n\n// ─── 公共 API ───\n\n/**\n * 加载全局凭证文件并注入到 process.env\n *\n * 读取 `~/.hai/credentials.yml` 中的所有键值对,\n * 将每个 key-value 设置到 `process.env` 中,\n * 使后续 core 配置加载时自动解析 `${HAI_DEPLOY_*}` 变量。\n * @returns 成功返回加载的凭证键名列表\n * @example 模块内部上下文\n * ```ts\n * const loaded = loadCredentials()\n * if (!loaded.success) throw new Error(loaded.error.message)\n * const injectedNames = loaded.data // 仅键名;已有 process.env 值优先。\n * ```\n */\nexport function loadCredentials(): HaiResult<string[]> {\n try {\n const data = readCredentialsFile()\n const keys = Object.keys(data)\n for (const key of keys) {\n process.env[key] = String(data[key])\n }\n logger.debug('Credentials loaded', { count: keys.length })\n return ok(keys)\n }\n catch (error) {\n logger.error('Failed to load credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 保存单个凭证到全局凭证文件\n *\n * 读取已有凭证 → 合并新凭证 → 写回文件。已有同名 key 会被覆盖。\n * 会写入当前用户的全局凭证文件;仅允许 HAI_DEPLOY_ 前缀。\n * @param key - 环境变量名(如 HAI_DEPLOY_PROVIDER_TOKEN)\n * @param value - 凭证值\n * @returns 已保存时成功;键名、文件或权限处理失败时为错误结果。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredential('HAI_DEPLOY_PROVIDER_TOKEN', token)\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredential(key: string, value: string): HaiResult<void> {\n try {\n assertAllowedCredentialKey(key)\n const data = readCredentialsFile()\n data[key] = value\n writeCredentialsFile(data)\n process.env[key] = value\n logger.debug('Credential saved', { key })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credential', { key, error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n\n/**\n * 批量保存凭证到全局凭证文件\n * @param entries - 凭证键值对\n * @returns 已保存时成功;校验失败不会注入任意键名。\n * @example 模块内部上下文\n * ```ts\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const saved = saveCredentials({ HAI_DEPLOY_PROVIDER_TOKEN: token })\n * if (!saved.success) throw new Error(saved.error.message)\n * ```\n */\nexport function saveCredentials(entries: Record<string, string>): HaiResult<void> {\n try {\n assertAllowedCredentialEntries(entries)\n const data = readCredentialsFile()\n for (const [key, value] of Object.entries(entries)) {\n data[key] = value\n process.env[key] = value\n }\n writeCredentialsFile(data)\n logger.debug('Credentials saved', { count: Object.keys(entries).length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Failed to save credentials', { error })\n return err(\n HaiDeployError.CREDENTIAL_ERROR,\n deployM('deploy_credentialError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n}\n","/**\n * @h-ai/deploy — 部署辅助函数\n *\n * 包含已有产物目录解析等与部署流程相关的辅助操作。 从 deploy-main.ts 中提取,遵循 main 仅做生命周期管理的规范。\n * @module deploy-functions\n */\n\nimport type { DeployAppOptions, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\n\n/**\n * 定位工程根;API workspace 的环境文件可在服务包,构建与部署缓存仍位于工程根。\n * 只定位已约定的构建入口/锁文件,不从目录布局推断应用或中间件依赖。\n * 从目标包向上查找构建入口或锁文件;返回目录不表示清单已存在或通过校验。\n * @param appDir - 部署目标应用目录。\n * @returns 最近的工程入口目录;未找到入口时返回应用目录的绝对路径。\n * @example 模块内部上下文\n * ```ts\n * const project = resolveProjectDirectory('/workspace/shop/apps/shop-service')\n * ```\n */\nexport function resolveProjectDirectory(appDir: string): string {\n let directory = resolve(appDir)\n while (true) {\n if (existsSync(join(directory, 'hai.build.json')) || existsSync(join(directory, 'pnpm-lock.yaml')))\n return directory\n const parent = dirname(directory)\n if (parent === directory)\n return resolve(appDir)\n directory = parent\n }\n}\n\n/**\n * 定位工程根的构建缓存目录;环境文件留在服务包时也沿用同一工程根。\n * @param appDir - 部署目标应用目录。\n * @returns 约定的 .hai/build/docker 目录;不保证其中制品存在或通过校验。\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveArtifactDirectory('/workspace/shop/apps/shop-service')\n * ```\n */\nexport function resolveArtifactDirectory(appDir: string): string {\n return join(resolveProjectDirectory(appDir), '.hai/build/docker')\n}\n\n/**\n * 判断同类连接中是否有默认配置项;具体变量前缀优先于服务类别,未指定时默认处理。\n * @param scan - 依据实际依赖图及环境得到的扫描结果。\n * @param service - 待判断的中间件类别。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 同类连接中存在采用 default 策略的项时为 true。\n * @example 模块内部上下文\n * ```ts\n * const scan: ScanResult = { appName: 'shop', isSvelteKit: false, adapterInstalled: false, nodeAdapterInstalled: false, requiredServices: [], serviceBackends: {} }\n * const enabled = usesDefaultMiddleware(scan, 'db', { serviceModes: { db: 'keep' } }) // false\n * ```\n */\nexport function usesDefaultMiddleware(scan: ScanResult, service: ServiceType, options?: DeployAppOptions): boolean {\n const requirements = scan.middlewares?.filter(item => item.service === service) ?? []\n return requirements.length\n ? requirements.some(item => (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[service] ?? 'default') === 'default')\n : (options?.serviceModes?.[service] ?? 'default') === 'default'\n}\n\n/**\n * 解析构建产物目录\n * @param appDir - 应用根目录\n * @param providerType - Provider 类型\n * @returns 产物目录路径\n * @example 模块内部上下文\n * ```ts\n * const directory = resolveOutputDir('/workspace/shop', 'vercel') // /workspace/shop/.vercel/output\n * ```\n */\nexport function resolveOutputDir(appDir: string, providerType: string): string {\n switch (providerType) {\n case 'vercel':\n return join(appDir, '.vercel', 'output')\n default:\n return join(appDir, 'build')\n }\n}\n","import type { HaiError, HaiResult } from '@h-ai/core'\nimport type { DeployCommandState, DeployRecoveryInfo } from './deploy-types.js'\nimport { err } from '@h-ai/core'\nimport { z } from 'zod'\nimport { deployM } from './deploy-i18n.js'\n\nconst RecoverySchema = z.object({\n projectName: z.string(),\n stage: z.string(),\n platformProjectId: z.string().optional(),\n resources: z.array(z.object({\n serviceType: z.enum(['db', 'cache', 'storage', 'email', 'sms']),\n provisionerName: z.string(),\n resourceInfo: z.string(),\n resourceStatus: z.enum(['created', 'reused', 'unknown']),\n })),\n})\n\nconst CommandStateSchema = z.object({\n reason: z.enum(['timeout', 'output', 'input', 'spawn', 'exit', 'configuration']),\n localTermination: z.enum(['confirmed', 'unknown', 'not-started']),\n remoteExecution: z.enum(['unknown', 'finished']).optional(),\n deploymentId: z.string().optional(),\n resultFile: z.string().optional(),\n remoteExitCode: z.number().int().optional(),\n remoteStage: z.string().optional(),\n})\n\n/**\n * 读取命令失败的安全状态;不把本地 SSH 退出解释为远端停止。\n * @param error - 部署错误\n * @returns 通过结构校验的命令状态,或 undefined\n * @example\n * ```ts\n * import { getDeployCommandState, HaiDeployError } from '@h-ai/deploy'\n * const state = getDeployCommandState({ ...HaiDeployError.REMOTE_COMMAND_FAILED, message: 'SSH connection interrupted', ext: { commandExecution: { reason: 'exit', localTermination: 'confirmed', remoteExecution: 'unknown' } } })\n * if (state?.remoteExecution === 'unknown') process.stderr.write('Remote execution is unknown\\n')\n * ```\n */\nexport function getDeployCommandState(error: HaiError): DeployCommandState | undefined {\n const parsed = CommandStateSchema.safeParse(error.ext?.commandExecution)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 读取错误中的恢复清单;仅返回明确允许展示的字段。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @returns 安全恢复清单;结构不满足约定时为 undefined。\n * @example\n * ```ts\n * import { getDeployRecovery, HaiDeployError } from '@h-ai/deploy'\n * const recovery = getDeployRecovery({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed', ext: { recovery: { projectName: 'shop', stage: 'provision', resources: [] } } })\n * if (recovery) {\n * const stage = recovery.stage\n * }\n * ```\n */\nexport function getDeployRecovery(error: HaiError): DeployRecoveryInfo | undefined {\n const parsed = RecoverySchema.safeParse(error.ext?.recovery)\n return parsed.success ? parsed.data : undefined\n}\n\n/**\n * 在错误中保留可展示的恢复信息,避免异常 cause/命令/URL 泄漏凭证。\n * @param error - 上层捕获的部署 HaiError;不直接展示其 cause。\n * @param recovery - 允许展示的恢复阶段与资源清单。\n * @returns 仅含安全恢复字段的失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const { HaiDeployError } = await import('./deploy-types.js')\n * const failure = recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: 'Provisioning failed' }, { projectName: 'shop', stage: 'provision', resources: [] })\n * if (!failure.success) {\n * const safeMessage = failure.error.message\n * }\n * ```\n */\nexport function recoveryFailure(error: HaiError, recovery: DeployRecoveryInfo): HaiResult<never> {\n return err({\n code: error.code,\n httpStatus: error.httpStatus,\n system: error.system,\n module: error.module,\n message: deployM('deploy_recoveryFailure', { params: { stage: recovery.stage } }),\n suggestion: deployM('deploy_recoverySuggestion'),\n ext: { recovery },\n })\n}\n","/** 应用、环境文件与中间件依赖扫描;不依赖 deploy.init(),不修改进程环境。 */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployScanOptions, MiddlewareRequirement, ScanResult, ServiceType } from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { basename, dirname, join, relative, resolve } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { parseAllDocuments } from 'yaml'\nimport { loadDeploymentConfig, loadDeploymentEnvironment } from './deploy-environment.js'\nimport { deployM } from './deploy-i18n.js'\nimport { HaiDeployError } from './deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'scanner' })\n\n/** 安全缩窄 YAML/JSON 对象;数组与 null 不作为配置对象。 */\nfunction record(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {}\n}\n\n/**\n * 从当前 workspace 的 lockfile 导入项遍历运行依赖,排除 dev 和 peer 边。\n * pnpm 12 的工具链和应用分别存于多个 YAML 文档,只选择含目标 importer 的应用文档。\n * 缺少 lockfile 或目标 importer 时要求先安装,不读取 package.json 或推测应用布局。\n */\nfunction runtimeDependencies(appDir: string): { runtime: Set<string>, build: Set<string>, root: string } {\n let root = appDir\n while (!existsSync(join(root, 'pnpm-lock.yaml'))) {\n const parent = dirname(root)\n if (parent === root)\n throw new Error('Missing pnpm lockfile; run pnpm install')\n root = parent\n }\n const importerKey = relative(root, appDir).replaceAll('\\\\', '/') || '.'\n const documents = parseAllDocuments(readFileSync(join(root, 'pnpm-lock.yaml'), 'utf8'))\n if (documents.some(document => document.errors.length))\n throw new Error('Invalid pnpm lockfile')\n const lock = documents.map(document => record(document.toJS())).reverse().find(document => importerKey in record(document.importers))\n if (!lock)\n throw new Error('Application is missing from pnpm lockfile; run pnpm install')\n const importers = record(lock.importers)\n const packages = record(lock.packages)\n const snapshots = record(lock.snapshots)\n const names = new Set<string>()\n const visited = new Set<string>()\n const visit = (id: string, node: Record<string, unknown>, importer?: string): void => {\n if (visited.has(id))\n return\n visited.add(id)\n const metadata = importer === undefined ? record(packages[id.split('(')[0]]) : {}\n const peers = record(metadata.peerDependencies)\n for (const [name, reference] of Object.entries({ ...record(node.dependencies), ...record(node.optionalDependencies) })) {\n if (name in peers)\n continue\n const version = typeof reference === 'string' ? reference : record(reference).version\n if (typeof version !== 'string')\n throw new Error('Invalid pnpm dependency reference')\n if (version.startsWith('link:')) {\n if (importer === undefined)\n throw new Error('Invalid workspace dependency')\n const target = relative(root, resolve(root, importer, version.slice(5))).replaceAll('\\\\', '/') || '.'\n const linked = record(importers[target])\n if (!Object.keys(linked).length)\n throw new Error('Missing linked workspace importer')\n names.add(name)\n visit(`workspace:${target}`, linked, target)\n continue\n }\n // npm alias 的引用已包含真实包名,不能再拼接别名。\n const key = version in snapshots || version in packages ? version : `${name}@${version}`\n names.add(key.match(/^(@[^/]+\\/[^@]+|[^@]+)@/)?.[1] ?? name)\n const snapshot = record(snapshots[key] ?? packages[key])\n if (!Object.keys(snapshot).length && !(key in snapshots) && !(key in packages))\n throw new Error('Missing pnpm dependency snapshot')\n visit(key, snapshot)\n }\n }\n visit(`workspace:${importerKey}`, record(importers[importerKey]), importerKey)\n return { runtime: names, build: new Set([...names, ...Object.keys(record(record(importers[importerKey]).devDependencies))]), root }\n}\n\n/**\n * 扫描依赖和实际环境下的后端,不把 memory/local/console 强制改为外部服务。\n * 沿目标 importer 的运行依赖识别模块;LDAP 等可选能力再按实际配置识别。\n * 以真实运行依赖图和显式配置识别模块;缺少或不一致锁文件不能静默降级为猜测。\n * @param inputDir - 待扫描的真实应用包目录。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 实际应用、依赖与中间件需求,或失败 HaiResult。\n * @example 模块内部上下文\n * ```ts\n * const result = await scanApp(process.cwd(), { environment: 'prod' })\n * if (!result.success) throw new Error(result.error.message)\n * const enabled = result.data.haiModules\n * ```\n */\nexport async function scanApp(inputDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n try {\n const appDir = resolve(inputDir)\n const graph = runtimeDependencies(appDir)\n const envDir = options?.envDir ? resolve(options.envDir) : existsSync(join(appDir, '.env')) ? appDir : graph.root\n const loaded = loadDeploymentEnvironment({ environment: options?.environment ?? 'prod', envDir, requireFile: options?.environment !== undefined })\n if (!loaded.success)\n return loaded\n const env = loaded.data.values\n const deps = graph.runtime\n const configs: Record<string, Record<string, unknown>> = {}\n for (const [name, owner] of Object.entries({ db: 'reldb', cache: 'cache', storage: 'storage', vecdb: 'vecdb', iam: 'iam', reach: 'reach' })) {\n configs[name] = {}\n if (!deps.has(`@h-ai/${owner}`))\n continue\n const configFile = ['yml', 'yaml'].map(ext => join(appDir, 'config', `_${name}.${ext}`)).find(existsSync)\n const config = configFile ? loadDeploymentConfig(name, configFile, env) : undefined\n if (config && !config.success)\n return config\n configs[name] = config?.data ?? {}\n }\n const middlewares: MiddlewareRequirement[] = []\n const add = (service: ServiceType, backend: string, configName = service as string, configPath: string[] = [], config = configs[configName] ?? {}, source = `_${configName}.yml`) => {\n middlewares.push({ service, backend, source, configName, configPath, envPrefix: ['HAI', configName, ...configPath].map(part => part.toUpperCase()).join('_'), config })\n }\n const iam = deps.has('@h-ai/iam')\n if (deps.has('@h-ai/reldb'))\n add('db', String(configs.db.type ?? 'sqlite'), 'db', [], configs.db, '@h-ai/reldb / _db.yml')\n if (deps.has('@h-ai/cache'))\n add('cache', String(configs.cache.type ?? 'memory'), 'cache', [], configs.cache, '@h-ai/cache / _cache.yml')\n if (deps.has('@h-ai/storage'))\n add('storage', String(configs.storage.type ?? 'local'))\n if (deps.has('@h-ai/vecdb'))\n add('vecdb', String(configs.vecdb.type ?? 'lancedb'))\n if (iam) {\n const ldap = record(configs.iam.ldap)\n add('ldap', record(configs.iam.login).ldap === true ? 'ldap' : 'disabled', 'iam', ['ldap'], ldap, '@h-ai/iam (LDAP)')\n }\n const providers = configs.reach.providers\n if (deps.has('@h-ai/reach') && Array.isArray(providers)) {\n for (const [index, item] of providers.entries()) {\n const provider = record(item)\n const type = String(provider.type ?? '')\n // Console/API 没有渠道字段,沿用生成应用的 sms Provider 名称识别短信。\n const service = type === 'aliyun-sms' || (['console', 'api'].includes(type) && provider.name === 'sms') ? 'sms' : ['smtp', 'api', 'console'].includes(type) ? 'email' : undefined\n if (service)\n add(service, type, 'reach', ['providers', String(index)], provider, '@h-ai/reach')\n }\n }\n if (deps.has('@h-ai/reach') && !middlewares.some(item => item.configName === 'reach'))\n add('email', 'console', 'reach', ['providers', '0'], { name: 'email', type: 'console' }, '@h-ai/reach')\n const isSvelteKit = graph.build.has('@sveltejs/kit')\n const scan: ScanResult = {\n appDir,\n envDir,\n middlewares,\n haiModules: [...deps].filter(name => name.startsWith('@h-ai/')).sort(),\n appName: basename(appDir),\n isSvelteKit,\n adapterInstalled: graph.build.has('@sveltejs/adapter-vercel'),\n nodeAdapterInstalled: graph.build.has('@sveltejs/adapter-node'),\n requiredServices: [...new Set(middlewares.map(item => item.service))],\n serviceBackends: Object.fromEntries(middlewares.map(item => [item.service, item.backend])),\n }\n logger.info('Application scanned', { appName: scan.appName, haiModules: scan.haiModules, requiredServices: scan.requiredServices, serviceBackends: scan.serviceBackends })\n return ok(scan)\n }\n catch {\n // JSON/YAML 异常可能带有凭据行,不把原异常暴露到日志或用户错误。\n return err(HaiDeployError.SCAN_FAILED, deployM('deploy_scanFailed', { params: { error: 'Invalid or ambiguous application/configuration/lockfile; specify the application directory and run pnpm install' } }))\n }\n}\n","/** Windows Job Object 桥接:静态代码内嵌在包中,参数只通过私有环境入口传递。 */\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n// Native 结构与语义按 Windows SDK;创建时挂起,分配成功后才恢复,避免子进程逃离 Job。\n// https://learn.microsoft.com/windows/win32/procthread/job-objects\nconst nativeJob = String.raw`\nusing System;\nusing System.ComponentModel;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Threading;\n\npublic static class HaiCommandJob {\n [StructLayout(LayoutKind.Sequential)] struct BasicLimits {\n public long ProcessTime, JobTime;\n public uint Flags;\n public UIntPtr MinimumWorkingSet, MaximumWorkingSet;\n public uint ActiveProcessLimit;\n public UIntPtr Affinity;\n public uint PriorityClass, SchedulingClass;\n }\n [StructLayout(LayoutKind.Sequential)] struct IoCounters {\n public ulong ReadOperations, WriteOperations, OtherOperations, ReadBytes, WriteBytes, OtherBytes;\n }\n [StructLayout(LayoutKind.Sequential)] struct ExtendedLimits {\n public BasicLimits Basic;\n public IoCounters Io;\n public UIntPtr ProcessMemory, JobMemory, PeakProcessMemory, PeakJobMemory;\n }\n [StructLayout(LayoutKind.Sequential)] struct Accounting {\n public long UserTime, KernelTime, PeriodUserTime, PeriodKernelTime;\n public uint Faults, Total, Active, Terminated;\n }\n [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct Startup {\n public uint Size;\n public string Reserved, Desktop, Title;\n public uint X, Y, Width, Height, XChars, YChars, Fill, Flags;\n public ushort Show, ReservedSize;\n public IntPtr ReservedData, Input, Output, Error;\n }\n [StructLayout(LayoutKind.Sequential)] struct ProcessInfo {\n public IntPtr Process, Thread;\n public uint ProcessId, ThreadId;\n }\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr CreateJobObject(IntPtr attributes, string name);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern IntPtr OpenJobObject(uint access, bool inherit, string name);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetInformationJobObject(IntPtr job, int kind, ref ExtendedLimits information, uint size);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool QueryInformationJobObject(IntPtr job, int kind, out Accounting information, uint size, IntPtr length);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);\n [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode, SetLastError = true)] static extern bool CreateProcess(string application, StringBuilder command, IntPtr processAttributes, IntPtr threadAttributes, bool inherit, uint flags, IntPtr environment, string directory, ref Startup startup, out ProcessInfo information);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint ResumeThread(IntPtr thread);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateProcess(IntPtr process, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool TerminateJobObject(IntPtr job, uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern uint WaitForSingleObject(IntPtr handle, uint milliseconds);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool GetExitCodeProcess(IntPtr process, out uint code);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool CloseHandle(IntPtr handle);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern IntPtr GetStdHandle(int kind);\n [DllImport(\"kernel32.dll\", SetLastError = true)] static extern bool SetHandleInformation(IntPtr handle, uint mask, uint flags);\n\n static void Check(bool success) { if (!success) throw new Win32Exception(Marshal.GetLastWin32Error()); }\n static uint Active(IntPtr job) {\n Accounting information;\n Check(QueryInformationJobObject(job, 1, out information, (uint)Marshal.SizeOf(typeof(Accounting)), IntPtr.Zero));\n return information.Active;\n }\n // Windows argv 编码:引号前与结尾的反斜杠加倍,其余字符原样传递,不经过命令 shell。\n static string Quote(string value) {\n StringBuilder result = new StringBuilder(\"\\\"\");\n int slashes = 0;\n foreach (char current in value) {\n if (current == '\\\\') { slashes++; continue; }\n if (current == '\"') result.Append('\\\\', slashes * 2 + 1);\n else result.Append('\\\\', slashes);\n result.Append(current);\n slashes = 0;\n }\n result.Append('\\\\', slashes * 2).Append('\"');\n return result.ToString();\n }\n public static int Run(string name, string command, string[] arguments) {\n IntPtr job = CreateJobObject(IntPtr.Zero, name);\n if (job == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());\n ProcessInfo process = new ProcessInfo();\n bool assigned = false;\n try {\n ExtendedLimits limits = new ExtendedLimits();\n limits.Basic.Flags = 0x2000; // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;不允许 breakaway。\n Check(SetInformationJobObject(job, 9, ref limits, (uint)Marshal.SizeOf(typeof(ExtendedLimits))));\n StringBuilder line = new StringBuilder(Quote(command));\n foreach (string argument in arguments) line.Append(' ').Append(Quote(argument));\n Startup startup = new Startup();\n startup.Size = (uint)Marshal.SizeOf(typeof(Startup));\n startup.Flags = 0x100;\n startup.Input = GetStdHandle(-10); startup.Output = GetStdHandle(-11); startup.Error = GetStdHandle(-12);\n Check(SetHandleInformation(startup.Input, 1, 1));\n Check(SetHandleInformation(startup.Output, 1, 1));\n Check(SetHandleInformation(startup.Error, 1, 1));\n Check(CreateProcess(null, line, IntPtr.Zero, IntPtr.Zero, true, 0x08000004, IntPtr.Zero, null, ref startup, out process));\n Check(AssignProcessToJobObject(job, process.Process));\n assigned = true;\n if (ResumeThread(process.Thread) == 0xFFFFFFFF) throw new Win32Exception(Marshal.GetLastWin32Error());\n if (WaitForSingleObject(process.Process, 0xFFFFFFFF) != 0) throw new Win32Exception(Marshal.GetLastWin32Error());\n uint code;\n Check(GetExitCodeProcess(process.Process, out code));\n while (Active(job) != 0) Thread.Sleep(20);\n return unchecked((int)code);\n }\n finally {\n if (process.Process != IntPtr.Zero) {\n // 分配失败时进程仍挂起,直接终止,不允许裸进程恢复;Job 在其他异常时同样清空。\n if (!assigned) TerminateProcess(process.Process, 125);\n else TerminateJobObject(job, 125);\n WaitForSingleObject(process.Process, 5000);\n }\n if (process.Thread != IntPtr.Zero) CloseHandle(process.Thread);\n if (process.Process != IntPtr.Zero) CloseHandle(process.Process);\n CloseHandle(job);\n }\n }\n public static bool Empty(string name) {\n IntPtr job = OpenJobObject(4, false, name); // JOB_OBJECT_QUERY\n if (job == IntPtr.Zero) {\n if (Marshal.GetLastWin32Error() == 2) return true;\n throw new Win32Exception(Marshal.GetLastWin32Error());\n }\n try { return Active(job) == 0; }\n finally { CloseHandle(job); }\n }\n}\n`\n\n/** 生成隐藏 PowerShell 的静态脚本;执行策略不影响内联命令,不加载用户 profile。 */\nfunction powershell(script: string): string[] {\n return ['-NoLogo', '-NoProfile', '-NonInteractive', '-EncodedCommand', Buffer.from(script, 'utf16le').toString('base64')]\n}\n\n/**\n * 创建命令 Job;参数不插入代码,启动失败直接拒绝,不能降级为无 Job 的裸进程。\n * 只生成 Job helper 的参数和私有环境载荷;调用者必须按约定启动 helper,不能直接恢复裸子进程。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @returns Job 名、隐藏 PowerShell 参数与私有环境载荷。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probe = windowsJobProbe(job.name)\n * // job.args/env 供隐藏 powershell.exe 使用;不要记录其中的私有参数。\n * ```\n */\nexport function windowsCommand(command: string, args: string[]): { name: string, args: string[], env: Record<string, string> } {\n const name = `Local\\\\hai-deploy-${randomUUID()}`\n const key = `__HAI_DEPLOY_JOB_${randomUUID().replaceAll('-', '')}`\n const script = `$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n $inputConfig = [Environment]::GetEnvironmentVariable('${key}') | ConvertFrom-Json\n [Environment]::SetEnvironmentVariable('${key}', $null)\n exit ([HaiCommandJob]::Run([string]$inputConfig.name, [string]$inputConfig.command, [string[]]$inputConfig.args))\n} catch { [Console]::Error.WriteLine('Windows command job failed'); exit 125 }`\n return { name, args: powershell(script), env: { [key]: JSON.stringify({ name, command, args }) } }\n}\n\n/**\n * 查询 Job 的真实成员数;不存在表示全部退出,任何检查故障均不能声称终止确认。\n * 名称必须来自 windowsCommand,不能把外部任意文本插入 PowerShell 探测脚本。\n * @param name - 由 windowsCommand 生成的内部 Job 名称。\n * @returns 探测静态脚本的 PowerShell 参数;探测返回码另行检查。\n * @example 模块内部上下文\n * ```ts\n * const job = windowsCommand(process.execPath, ['--version'])\n * const probeArgs = windowsJobProbe(job.name)\n * // 仅对本函数配套创建的 Job 名执行探测;0为空、1仍有成员、2为探测故障。\n * ```\n */\nexport function windowsJobProbe(name: string): string[] {\n return powershell(`$ErrorActionPreference='Stop'; $ProgressPreference='SilentlyContinue'; $InformationPreference='SilentlyContinue'\ntry {\n Add-Type -TypeDefinition @'\n${nativeJob}\n'@\n if ([HaiCommandJob]::Empty('${name}')) { exit 0 } else { exit 1 }\n} catch { exit 2 }`)\n}\n","/** 管理命令的真实本地进程树;POSIX 使用独立进程组,Windows 使用不可 breakaway 的 Job。 */\nimport type { ChildProcessWithoutNullStreams, SpawnOptionsWithoutStdio } from 'node:child_process'\nimport { spawn } from 'node:child_process'\nimport { readdir, readFile } from 'node:fs/promises'\nimport process from 'node:process'\nimport { setTimeout } from 'node:timers/promises'\nimport { windowsCommand, windowsJobProbe } from './deploy-command-windows.js'\n\n/** Linux 的孤儿 zombie 已退出,不能把未回收的 PID 当作仍执行的进程。 */\nasync function groupExited(pid: number): Promise<boolean> {\n try {\n process.kill(-pid, 0)\n }\n catch (error) {\n return error instanceof Error && 'code' in error && error.code === 'ESRCH'\n }\n if (process.platform !== 'linux')\n return false\n try {\n for (const entry of await readdir('/proc')) {\n if (!/^\\d+$/.test(entry))\n continue\n let stat: string\n try {\n stat = await readFile(`/proc/${entry}/stat`, 'utf8')\n }\n catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT')\n continue\n return false\n }\n // comm 可包含空格/括号,取最后一个右括号之后的固定字段。\n const fields = stat.slice(stat.lastIndexOf(')') + 2).split(' ')\n if (Number(fields[2]) === pid && fields[0] !== 'Z' && fields[0] !== 'X')\n return false\n }\n return true\n }\n catch {\n return false\n }\n}\n\n/** 辅助工具只返回退出码,既不捕获参数/输出,也不把原始错误传播到用户结果。 */\nasync function helper(command: string, args: string[], timeoutMs: number): Promise<boolean> {\n if (timeoutMs <= 0)\n return false\n return new Promise((resolve) => {\n const child = spawn(command, args, { windowsHide: true, shell: false, stdio: 'ignore' })\n let settled = false\n let timer: NodeJS.Timeout | undefined\n const finish = (success: boolean): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(success)\n }\n timer = globalThis.setTimeout(() => {\n child.kill('SIGKILL')\n child.unref()\n finish(false)\n }, timeoutMs)\n child.once('error', () => finish(false))\n child.once('close', code => finish(code === 0))\n })\n}\n\n/**\n * 只向命令执行器暴露必要控制,不把平台句柄或 Job 名称作为用户配置。\n * 控制句柄只管理本地进程树;调用 treeExited/terminate 后仍要按 boolean/状态判断,不推断远端副作用。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport interface CommandProcess {\n child: ChildProcessWithoutNullStreams\n treeExited: () => Promise<boolean>\n terminate: (timeoutMs: number) => Promise<'confirmed' | 'unknown'>\n}\n\n/**\n * 启动受管理进程;Windows helper/Job 失败时没有裸进程降级路径。\n * 由 runCommand 负责输出、异常与超时编排;此低层入口本身不提供 HaiResult 或脱敏。\n * @param command - 本地可执行文件名或绝对路径,不是 shell 命令串。\n * @param args - 逐项传入的参数数组,不再自行拼接 shell。\n * @param options - 本次操作选项;字段含义见各子项。\n * @returns 受管理子进程及本地进程树检查/终止句柄。\n * @example 模块内部上下文\n * ```ts\n * const controlled = spawnCommand(process.execPath, ['--version'], { cwd: process.cwd(), env: process.env })\n * const exited = await controlled.treeExited()\n * if (!exited) {\n * const termination = await controlled.terminate(10000)\n * if (termination === 'unknown') process.stderr.write('Termination unconfirmed\\n')\n * }\n * ```\n */\nexport function spawnCommand(command: string, args: string[], options: Pick<SpawnOptionsWithoutStdio, 'cwd' | 'env'>): CommandProcess {\n const job = process.platform === 'win32' ? windowsCommand(command, args) : undefined\n const child = spawn(job ? 'powershell.exe' : command, job?.args ?? args, {\n ...options,\n env: job ? { ...options.env, ...job.env } : options.env,\n windowsHide: true,\n shell: false,\n detached: !job,\n })\n let exited = false\n child.once('exit', () => {\n exited = true\n })\n child.once('close', () => {\n exited = true\n })\n let termination: Promise<'confirmed' | 'unknown'> | undefined\n const treeExited = async (): Promise<boolean> => {\n if (!child.pid)\n return true\n if (job)\n return exited && helper('powershell.exe', windowsJobProbe(job.name), 5000)\n return groupExited(child.pid)\n }\n const terminate = (timeoutMs: number): Promise<'confirmed' | 'unknown'> => {\n termination ??= (async () => {\n const deadline = performance.now() + timeoutMs\n let windowsKillConfirmed = !job || exited\n if (child.pid) {\n if (job) {\n if (!exited) {\n // /T 也覆盖 Add-Type 的编译器;payload 的断链后代由 Job 的 close-kill 保证收回。\n windowsKillConfirmed = await helper('taskkill', ['/pid', String(child.pid), '/t', '/f'], Math.max(1, deadline - performance.now()))\n child.kill('SIGKILL')\n }\n }\n else {\n try {\n process.kill(-child.pid, 'SIGKILL')\n }\n catch {\n // 退出 race 或权限失败都必须由下方状态核验决定,不能把 kill 请求当确认。\n }\n }\n }\n while (performance.now() < deadline) {\n if (exited)\n break\n await setTimeout(20)\n }\n let verified = false\n if (exited && job) {\n // 原生命令已自然返回时,helper 已等待所有 Job 成员;被强杀则仍查询 Job 实际归零。\n verified = await helper('powershell.exe', windowsJobProbe(job.name), deadline - performance.now())\n verified &&= windowsKillConfirmed || child.exitCode !== null\n }\n else if (exited) {\n while (performance.now() < deadline) {\n if (await treeExited()) {\n verified = true\n break\n }\n await setTimeout(20)\n }\n }\n // exit 与管道 close 分开:消费者可仍等待回调,但不能据此误判进程仍运行。\n // 异常后丢弃未完成秘密尾部并关闭管道,不等待无法取消的已进入回调。\n child.stdin.destroy()\n child.stdout.destroy()\n child.stderr.destroy()\n if (!verified)\n child.unref()\n return verified ? 'confirmed' : 'unknown'\n })()\n return termination\n }\n return { child, treeExited, terminate }\n}\n","/** 已知秘密的跨块字面量脱敏;不会把秘密当成正则语法。 */\n\n/**\n * 单个逻辑文本流的脱敏器;UTF-8解码由调用方的StringDecoder完成。\n * @example 模块内部上下文\n * ```ts\n * const masker: SecretMasker = createSecretMasker(['example-token'])\n * const text = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport interface SecretMasker {\n /** 接收已正确解码的下一块,仅释放不可能与后续块组成秘密的前缀。 */\n write: (text: string) => string\n /** 正常流结束时释放最后一块;重复调用为空,异常终止可丢弃未释放尾部。 */\n end: () => string\n}\n\n/**\n * 创建精确字面量流式脱敏器;最多保留最长秘密长度减一的尾部。\n * 每个逻辑流使用独立实例;write 可能延迟尾部,正常结束须 end,不能提前把缓冲原文输出。\n * @param secrets - 已知敏感值;忽略空值、去重,优先匹配同位置的较长值,总长度上限1Mi UTF-16单元\n * @returns 每次write/end的安全输出按顺序拼接得到完整脱敏文本\n * @throws 秘密总长度超限或底层表达式不能编译时抛错,调用方必须失败关闭\n * @example 模块内部上下文\n * ```ts\n * const masker = createSecretMasker(['example-token'])\n * const output = masker.write('example-') + masker.write('token public') + masker.end() // *** public\n * ```\n */\nexport function createSecretMasker(secrets: readonly string[] = []): SecretMasker {\n const values = [...new Set(secrets.filter(Boolean))].sort((a, b) => b.length - a.length)\n if (values.reduce((total, value) => total + value.length, 0) > 1048576)\n throw new RangeError('Secret redaction input is too large')\n const pattern = values.length ? new RegExp(values.map(value => value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')).join('|'), 'g') : undefined\n const tailLength = Math.max(0, (values[0]?.length ?? 1) - 1)\n let pending = ''\n let ended = false\n\n /** 在原文边界上计算释放位置;不能从掩码中间切分后再释放其原文尾部。 */\n function drain(final: boolean): string {\n let end = final ? pending.length : Math.max(0, pending.length - tailLength)\n // 避免向分别编码/显示回调片段的消费者交付半个Unicode代理对。\n if (end > 0 && end < pending.length && /[\\uD800-\\uDBFF]/.test(pending[end - 1]!) && /[\\uDC00-\\uDFFF]/.test(pending[end]!))\n end--\n if (end === 0)\n return ''\n let cursor = 0\n let output = ''\n if (pattern) {\n pattern.lastIndex = 0\n let match = pattern.exec(pending)\n while (match && match.index < end) {\n output += `${pending.slice(cursor, match.index)}***`\n cursor = pattern.lastIndex\n // 跨释放边界的完整匹配整体消费,不能在后续write重新暴露其后半段。\n end = Math.max(end, cursor)\n match = pattern.exec(pending)\n }\n }\n output += pending.slice(cursor, end)\n pending = pending.slice(end)\n return output\n }\n\n return {\n write(text) {\n if (ended)\n throw new Error('Secret masker has ended')\n pending += text\n return drain(false)\n },\n end() {\n if (ended)\n return ''\n ended = true\n return drain(true)\n },\n }\n}\n","/**\n * @h-ai/deploy — 命令执行器。\n * command与args分离,不经过shell;流式回调、捕获结果和错误使用相同秘密脱敏边界。\n * @module deploy-command\n */\nimport type { HaiResult } from '@h-ai/core'\nimport type { DeployCommandState } from '../deploy-types.js'\nimport process from 'node:process'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { spawnCommand } from './deploy-command-process.js'\nimport { createSecretMasker } from './deploy-secret-masker.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'command' })\n\n/**\n * 命令执行选项;secrets必须列出可能输出的已知敏感值。\n * @example 模块内部上下文\n * ```ts\n * const options: CommandOptions = { cwd: process.cwd(), timeoutMs: 5000, terminationTimeoutMs: 10000, maxCaptureChars: 4096 }\n * const result = await runCommand(process.execPath, ['--version'], options)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport interface CommandOptions {\n /** 正确UTF-8解码且跨块脱敏的stdout片段;顺序完整,末尾可能延迟至close。 */\n onOutput?: (output: string) => void | Promise<void>\n /** 工作目录。 */\n cwd?: string\n /** 追加环境;不会自动将全部环境值视为秘密。 */\n env?: Record<string, string>\n /** 超时毫秒,须为 1..2147483647 的整数;超时不代表远程进程已终止。 */\n timeoutMs?: number\n /** 超时/异常后核验本地树退出的最长等待,默认 10 秒,最大 60 秒;未确认时返回 unknown。 */\n terminationTimeoutMs?: number\n /** 通过stdin传入的内容。 */\n input?: string\n /** 已知敏感字面量;总长度最多1Mi UTF-16单元,超限失败关闭。 */\n secrets?: string[]\n /** 每条捕获流保留的尾部字符上限,默认1Mi,最大16Mi;回调仍接收全部安全stdout。 */\n maxCaptureChars?: number\n}\n\n/**\n * 已脱敏的有界命令结果;解析结构化输出前必须拒绝截断结果。\n * 仅保存脱敏流的有界尾部;不把尾部捕获当作完整日志。\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { maxCaptureChars: 4096 })\n * if (!result.success) throw new Error(result.error.message)\n * const output: CommandResult = result.data\n * const truncated = output.stdoutTruncated\n * ```\n */\nexport interface CommandResult {\n /** 实际退出码。 */\n code: number\n /** 已脱敏stdout尾部。 */\n stdout: string\n /** 已脱敏stderr尾部。 */\n stderr: string\n /** stdout是否超过捕获上限。 */\n stdoutTruncated: boolean\n /** stderr是否超过捕获上限。 */\n stderrTruncated: boolean\n}\n\n/**\n * 对完整文本进行同样的精确字面量脱敏。\n * @param text - 完整文本\n * @param secrets - 已知秘密\n * @returns 脱敏文本\n * @example 模块内部上下文\n * ```ts\n * const text = maskSecrets('example-token public', ['example-token']) // *** public;合成字符串只用于演示。\n * ```\n */\nexport function maskSecrets(text: string, secrets: string[] = []): string {\n const masker = createSecretMasker(secrets)\n return masker.write(text) + masker.end()\n}\n\n/**\n * 执行外部命令,捕获与回调在UTF-8解码后以逻辑流为单位脱敏。\n * 无 shell 启动命令;stdout 回调接收按顺序脱敏的完整流,捕获结果仅保留有界尾部。超时后核验本地树退出;SSH 的远端状态由上层单独核对。\n * @param command - 可执行文件名或路径,不使用shell\n * @param args - 独立参数\n * @param options - 超时、输入、已知秘密及安全输出选项\n * @returns 失败返回REMOTE_COMMAND_FAILED;ext.commandExecution 记录终止核验,不暴露原始异常cause\n * @example 模块内部上下文\n * ```ts\n * const result = await runCommand(process.execPath, ['--version'], { timeoutMs: 5000, maxCaptureChars: 4096 })\n * if (!result.success) {\n * const { getDeployCommandState } = await import('../deploy-recovery.js')\n * const state = getDeployCommandState(result.error)\n * if (state?.localTermination === 'unknown') process.stderr.write('Local process-tree exit was not confirmed\\n')\n * }\n * else {\n * const output = result.data.stdout\n * }\n * ```\n */\nexport async function runCommand(command: string, args: string[], options: CommandOptions = {}): Promise<HaiResult<CommandResult>> {\n /** 失败状态只包含核验结论,不附加原始异常或可能携密的命令参数。 */\n const failure = (message: string, state: DeployCommandState): HaiResult<never> => err({\n ...HaiDeployError.REMOTE_COMMAND_FAILED,\n message: `${message}\\n${deployM(state.localTermination === 'confirmed' ? 'deploy_localStopped' : state.localTermination === 'not-started' ? 'deploy_localNotStarted' : 'deploy_localUnknown')}`,\n ext: { commandExecution: state },\n })\n try {\n return await new Promise((resolve) => {\n if (typeof command !== 'string' || !command || command.includes('\\0') || args.some(argument => typeof argument !== 'string' || argument.includes('\\0')))\n throw new TypeError('Invalid command arguments')\n if (options.input !== undefined && typeof options.input !== 'string')\n throw new TypeError('Invalid command input')\n const maxCapture = options.maxCaptureChars ?? 1048576\n if (!Number.isSafeInteger(maxCapture) || maxCapture <= 0 || maxCapture > 16777216)\n throw new RangeError('Invalid command capture limit')\n const terminationTimeout = options.terminationTimeoutMs ?? 10_000\n if (!Number.isSafeInteger(terminationTimeout) || terminationTimeout <= 0 || terminationTimeout > 60_000)\n throw new RangeError('Invalid command termination timeout')\n if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0 || options.timeoutMs > 2147483647))\n throw new RangeError('Invalid command timeout')\n const secrets = [...(options.secrets ?? [])]\n const safeCommand = maskSecrets(command, secrets)\n const outputMasker = createSecretMasker(secrets)\n const errorMasker = createSecretMasker(secrets)\n const control = spawnCommand(command, args, { cwd: options.cwd, env: options.env ? { ...process.env, ...options.env } : process.env })\n const child = control.child\n child.stdout.setEncoding('utf8')\n child.stderr.setEncoding('utf8')\n let stdout = ''\n let stderr = ''\n let stdoutTruncated = false\n let stderrTruncated = false\n let settled = false\n let interrupted = false\n let interruption: Promise<void> | undefined\n let timer: NodeJS.Timeout | undefined\n const finish = (result: HaiResult<CommandResult>): void => {\n if (settled)\n return\n settled = true\n if (timer)\n clearTimeout(timer)\n resolve(result)\n }\n /** 先停止输出交付,再终止并等待整棵树;同一失败/close race 只结束一次。 */\n const interrupt = (reason: DeployCommandState['reason'], message: string): Promise<void> => {\n interrupted = true\n interruption ??= (async () => {\n if (timer)\n clearTimeout(timer)\n const localTermination = child.pid ? await control.terminate(terminationTimeout) : 'not-started'\n logger.error('Command termination checked', { command: safeCommand, reason, localTermination })\n finish(failure(message, { reason, localTermination }))\n })()\n return interruption\n }\n /** 所有捕获发生在脱敏后;流尾部状态和捕获长度均有上限。 */\n const publish = async (text: string): Promise<void> => {\n if (!text || settled || interrupted)\n return\n stdoutTruncated ||= stdout.length + text.length > maxCapture\n stdout = (stdout + text).slice(-maxCapture)\n try {\n await options.onOutput?.(text)\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n }\n const captureError = (text: string): void => {\n stderrTruncated ||= stderr.length + text.length > maxCapture\n stderr = (stderr + text).slice(-maxCapture)\n }\n if (options.timeoutMs && options.timeoutMs > 0) {\n timer = setTimeout(() => {\n logger.error('Command timed out', { command: safeCommand, timeoutMs: options.timeoutMs })\n // 异常结束不释放可能尚未完整的秘密尾部,也不再调用onOutput。\n void interrupt('timeout', deployM('deploy_commandTimeout', { params: { command: safeCommand } }))\n }, options.timeoutMs)\n }\n // 异步迭代器在等待回调期间保留pipe背压,不创建无限增长的Promise/输出队列。\n const outputTask = (async () => {\n try {\n for await (const chunk of child.stdout as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command output must be UTF-8 decoded')\n await publish(outputMasker.write(chunk))\n }\n if (!settled && !interrupted)\n await publish(outputMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n const errorTask = (async () => {\n try {\n for await (const chunk of child.stderr as AsyncIterable<unknown>) {\n if (settled || interrupted)\n return\n if (typeof chunk !== 'string')\n throw new TypeError('Command error output must be UTF-8 decoded')\n captureError(errorMasker.write(chunk))\n }\n if (!settled && !interrupted)\n captureError(errorMasker.end())\n }\n catch {\n await interrupt('output', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandOutputFailed') } }))\n }\n })()\n child.stdin.on('error', () => {\n void interrupt('input', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandInputFailed') } }))\n })\n child.on('error', (error) => {\n const safeError = maskSecrets(error.message, secrets)\n logger.error('Command failed to start', { command: safeCommand, error: safeError })\n void interrupt('spawn', deployM('deploy_commandFailed', { params: { command: safeCommand, error: safeError } }))\n })\n child.on('close', async (code) => {\n await Promise.all([outputTask, errorTask])\n if (settled || interrupted)\n return\n if (timer)\n clearTimeout(timer)\n if (!(await control.treeExited())) {\n await interrupt('exit', deployM('deploy_commandFailed', { params: { command: safeCommand, error: deployM('deploy_commandTreeActive') } }))\n return\n }\n const exitCode = code ?? -1\n if (exitCode === 0) {\n finish(ok({ code: exitCode, stdout, stderr, stdoutTruncated, stderrTruncated }))\n return\n }\n logger.error('Command exited with non-zero code', { command: safeCommand, code: exitCode, stderr: maskSecrets(stderr, secrets).slice(-500), stdout: maskSecrets(stdout, secrets).slice(-3000), stdoutTruncated, stderrTruncated })\n finish(failure(deployM('deploy_commandFailed', { params: { command: safeCommand, error: maskSecrets(`${stdout.slice(-2500)}\\n${stderr || `exit ${exitCode}`}`, secrets).slice(-3000) } }), { reason: 'exit', localTermination: 'confirmed' }))\n })\n if (options.input !== undefined)\n child.stdin.write(options.input)\n child.stdin.end()\n })\n }\n catch {\n // 参数/正则编译/spawn同步错误可能携带原秘密,使用无cause的固定诊断失败关闭。\n return failure(deployM('deploy_commandFailed', { params: { command: '<command>', error: deployM('deploy_commandExecutionFailed') } }), { reason: 'configuration', localTermination: 'not-started' })\n }\n}\n","/**\n * 生成独立 JSON 读取器;上传脚本仅需 POSIX awk,无 Node 或 jq 依赖。\n * @returns 可作为部署包 read-target.awk 文件内容的 POSIX awk 程序。\n * @example 模块内部上下文\n * ```ts\n * const reader: string = createTargetReader()\n * // 将 reader 写入部署包,由上传脚本读取 deploy-target.json 中的目标配置。\n * ```\n */\nexport function createTargetReader(): string {\n return String.raw`function fail(message) {\n print \"Invalid deploy-target.json: \" message > \"/dev/stderr\"\n exit 2\n}\nfunction whitespace() {\n while (substr(input, position, 1) ~ /^[ \\t\\r\\n]$/) position++\n}\nfunction hexadecimal(text, result, offset, digit) {\n result = 0\n if (length(text) != 4) fail(\"invalid Unicode escape\")\n for (offset = 1; offset <= 4; offset++) {\n digit = index(\"0123456789abcdef\", tolower(substr(text, offset, 1))) - 1\n if (digit < 0) fail(\"invalid Unicode escape\")\n result = result * 16 + digit\n }\n return result\n}\nfunction utf8(code) {\n if (code < 128) return sprintf(\"%c\", code)\n if (code < 2048) return sprintf(\"%c%c\", 192 + int(code / 64), 128 + code % 64)\n if (code < 65536) return sprintf(\"%c%c%c\", 224 + int(code / 4096), 128 + int(code / 64) % 64, 128 + code % 64)\n return sprintf(\"%c%c%c%c\", 240 + int(code / 262144), 128 + int(code / 4096) % 64, 128 + int(code / 64) % 64, 128 + code % 64)\n}\nfunction string_value( result, character, escaped, code, low) {\n if (substr(input, position++, 1) != \"\\\"\") fail(\"expected string\")\n result = \"\"\n while (position <= length(input)) {\n character = substr(input, position++, 1)\n if (character == \"\\\"\") return result\n if (character ~ /[[:cntrl:]]/) fail(\"control character in string\")\n if (character != \"\\\\\") { result = result character; continue }\n escaped = substr(input, position++, 1)\n if (escaped == \"\\\"\" || escaped == \"\\\\\" || escaped == \"/\") result = result escaped\n else if (escaped == \"b\") result = result sprintf(\"%c\", 8)\n else if (escaped == \"f\") result = result sprintf(\"%c\", 12)\n else if (escaped == \"n\") result = result \"\\n\"\n else if (escaped == \"r\") result = result \"\\r\"\n else if (escaped == \"t\") result = result \"\\t\"\n else if (escaped == \"u\") {\n code = hexadecimal(substr(input, position, 4)); position += 4\n if (code >= 55296 && code <= 56319) {\n if (substr(input, position, 2) != \"\\\\u\") fail(\"missing low surrogate\")\n position += 2\n low = hexadecimal(substr(input, position, 4)); position += 4\n if (low < 56320 || low > 57343) fail(\"invalid low surrogate\")\n code = 65536 + (code - 55296) * 1024 + low - 56320\n } else if (code >= 56320 && code <= 57343) fail(\"unexpected low surrogate\")\n if (code == 0) fail(\"NUL is not allowed\")\n result = result utf8(code)\n } else fail(\"invalid escape\")\n }\n fail(\"unterminated string\")\n}\nfunction object_value(depth, key, character, value, kind) {\n if (depth > 16) fail(\"nesting is too deep\")\n position++\n whitespace()\n if (substr(input, position, 1) == \"}\") { position++; return }\n while (position <= length(input)) {\n whitespace(); key = string_value(); whitespace()\n if (substr(input, position++, 1) != \":\") fail(\"expected colon\")\n whitespace(); character = substr(input, position, 1)\n if (character == \"{\") { object_value(depth + 1); value = \"\"; kind = \"object\" }\n else if (character == \"\\\"\") { value = string_value(); kind = \"string\" }\n else if (substr(input, position, 4) == \"true\") { value = \"true\"; kind = \"boolean\"; position += 4 }\n else if (substr(input, position, 5) == \"false\") { value = \"false\"; kind = \"boolean\"; position += 5 }\n else if (substr(input, position, 4) == \"null\") { value = \"\"; kind = \"null\"; position += 4 }\n else if (match(substr(input, position), /^-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?/)) {\n value = substr(input, position, RLENGTH); position += RLENGTH; kind = \"number\"\n } else fail(\"unsupported value\")\n if (depth == 1) {\n if (key in values) fail(\"duplicate field: \" key)\n values[key] = value; kinds[key] = kind\n }\n whitespace(); character = substr(input, position++, 1)\n if (character == \"}\") return\n if (character != \",\") fail(\"expected comma or closing brace\")\n }\n fail(\"unterminated object\")\n}\n{ input = input $0 \"\\n\" }\nEND {\n position = 1\n if (substr(input, 1, 3) == sprintf(\"%c%c%c\", 239, 187, 191)) position = 4\n whitespace()\n if (substr(input, position, 1) != \"{\") fail(\"expected object\")\n object_value(1); whitespace()\n if (position <= length(input)) fail(\"trailing content\")\n if (!(field in values) || kinds[field] == \"null\") { print fallback; exit }\n if (kinds[field] != expected) fail(\"wrong type for \" field)\n if (values[field] ~ /[[:cntrl:]]/) fail(\"control character in \" field)\n print values[field]\n}\n`\n}\n","/** 在线发布与手工交付共用的服务器执行脚本。远程依赖 Linux flock、基础工具及 Compose。 */\nimport { createTargetReader } from './deploy-target.js'\n\n/**\n * 将可信配置编码为一个 shell 参数。\n * @param value - 受信值,编码为一个远端 shell 参数。\n * @returns 可作为一个远端 shell 参数的编码文本。\n * @example 模块内部上下文\n * ```ts\n * const encoded = shellArgument(\"Shop's app\") // 整体作为一个远端 shell 参数。\n * ```\n */\nexport function shellArgument(value: string): string {\n return `'${value.replaceAll('\\'', '\\'\"\\'\"\\'')}'`\n}\n\n/**\n * 生成分步执行、增量合并和失败恢复脚本;密钥始终从环境文件读取。\n * 仅生成 Linux 脚本;正常收尾显式释放 FD9 flock,中断时由仍持有描述符的进程树维持。未知旧锁目录不删除,结果仅由取得锁的 owner 发布。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.hostPort - 宿主公开端口。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @returns 待在 Linux 远端运行的 apply 脚本文本。\n * @example 模块内部上下文\n * ```ts\n * const script = createApplyScript({ deploymentId: 'shop-prod-001', projectName: 'shop-prod', environment: 'prod', directory: '/opt/hai/apps/shop-prod', runtime: 'auto', partial: false, selected: ['app'], hostPort: 8080, healthPaths: ['/health'] })\n * ```\n */\nexport function createApplyScript(options: {\n deploymentId: string\n projectName: string\n environment: string\n directory: string\n runtime: 'auto' | 'docker' | 'podman'\n partial: boolean\n selected: string[]\n hostPort: number\n healthPaths: string[]\n}): string {\n const values: Record<string, string> = {\n ID: shellArgument(options.deploymentId),\n PROJECT: shellArgument(`hai-${options.projectName}`),\n ENV: shellArgument(options.environment),\n RUNTIME: shellArgument(options.runtime),\n PARTIAL: options.partial ? 'true' : 'false',\n SELECTED: shellArgument(options.selected.join(' ')),\n ROOT: shellArgument(options.directory),\n PORT: String(options.hostPort),\n HEALTH: options.healthPaths.map(shellArgument).join(' '),\n }\n return String.raw`#!/bin/sh\nset -eu\numask 077\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ndestination=@@ROOT@@\nif [ \"$#\" -gt 0 ]; then destination=$1; fi\nroot=$(mkdir -p -- \"$destination\" && CDPATH= cd -- \"$destination\" && pwd)\nid=@@ID@@\nproject=@@PROJECT@@\nexport HAI_DEPLOY_ENVIRONMENT=@@ENV@@\nruntime=@@RUNTIME@@\npartial=@@PARTIAL@@\norphan_option=''\nif [ \"$partial\" = false ]; then orphan_option=--remove-orphans; fi\nrecreate_option=--force-recreate\nif [ \"$partial\" = true ]; then recreate_option=--no-recreate; fi\nselected=@@SELECTED@@\nrelease=\"$root/releases/$id\"\ncase \"$release/\" in \"$source_dir/\"*) printf 'Extract the package outside the deployment directory before applying it.\\n' >&2; exit 1;; esac\nstage=''\nprevious=''\nrestore=''\nchanged=false\nlocked=false\ninterrupted=false\nstarted=$(date +%s)\nstep_started=$started\nstep() {\n if [ -n \"$stage\" ]; then\n duration=$(( $(date +%s) - step_started ))\n printf '[PASS] %s (%ss)\\n' \"$stage\" \"$duration\"\n printf '{\"stage\":\"%s\",\"status\":\"passed\",\"durationSeconds\":%s}\\n' \"$stage\" \"$duration\" >> \"$root/steps-$id.jsonl\"\n fi\n stage=\"$1\"\n step_started=$(date +%s)\n printf '\\n[%s] %s\\n' \"$stage\" \"$2\"\n}\ncompose() {\n arguments_file=\"$release/compose-files\"\n if [ -n \"$restore\" ]; then arguments_file=\"$root/releases/$restore/compose-files\"; fi\n # -f 按顺序合并,由 Compose 保留未选服务、卷和环境文件,不自行拼装配置。\n command_args=\"$release/.compose-command\"\n # 文件列表先反向读取,再向参数头部加入,保留原始合并顺序。\n awk '{lines[NR]=$0} END {for(i=NR;i>0;i--) print lines[i]}' \"$arguments_file\" > \"$command_args\"\n while IFS= read -r file; do set -- -f \"$file\" \"$@\"; done < \"$command_args\"\n \"$runtime\" compose -p \"$project\" \"$@\"\n}\nremove_selected() {\n test \"$partial\" = true || return 0\n # 直接替换选中容器,避免 Compose Provider 连带重建依赖它的未选服务;不删除卷。\n for service in \"$@\"; do\n containers=$(\"$runtime\" ps -aq --filter \"label=com.docker.compose.project=$project\" --filter \"label=com.docker.compose.service=$service\") || return 1\n for container in $containers; do\n \"$runtime\" rm -f \"$container\" || return 1\n done\n done\n}\nfinish() {\n code=$?\n trap - EXIT HUP INT TERM\n if [ \"$code\" -ne 0 ]; then\n printf '[FAIL] %s (exit %s)\\n' \"$stage\" \"$code\" >&2\n if [ \"$changed\" = true ]; then\n diagnostics=\"$root/diagnostics-$id.log\"\n : > \"$diagnostics\"\n for service in $selected; do\n containers=$(\"$runtime\" ps -aq --filter \"label=com.docker.compose.project=$project\" --filter \"label=com.docker.compose.service=$service\" || true)\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Name}} {{.State.Status}} exit={{.State.ExitCode}}' \"$container\" >> \"$diagnostics\" 2>&1 || true\n \"$runtime\" logs --tail 80 \"$container\" >> \"$diagnostics\" 2>&1 || true\n done\n done\n printf 'Startup diagnostics saved to %s (private server file).\\n' \"$diagnostics\" >&2\n fi\n if [ -f \"$release/rollback-images\" ]; then\n while IFS=' ' read -r image reference; do\n test -n \"$reference\" || continue\n \"$runtime\" tag \"$image\" \"$reference\" || printf '[FAIL] Cannot restore image %s\\n' \"$reference\" >&2\n done < \"$release/rollback-images\"\n fi\n if [ \"$changed\" = true ] && [ -n \"$previous\" ]; then\n printf '[RECOVER] Restoring previous selected services\\n' >&2\n recover_selected=$selected\n if [ \"$partial\" = false ]; then recover_selected=$(grep -v -- '-init$' \"$root/releases/$previous/services\"); fi\n restore=\"$previous\"\n if remove_selected $recover_selected && compose up -d --no-deps --no-build --pull never \"$recreate_option\" $orphan_option $recover_selected; then\n case \" $selected \" in *' app '*)\n if grep -qx web \"$root/releases/$previous/services\"; then compose exec -T web nginx -s reload || true; fi\n ;;\n esac\n printf '[RECOVER] Previous containers restored; verify application health\\n' >&2\n else\n printf '[FAIL] Recovery failed. Use the previous release and inspect container logs.\\n' >&2\n fi\n elif [ \"$changed\" = true ]; then\n compose stop $selected || true\n printf '[RECOVER] Failed first installation stopped; data volumes retained\\n' >&2\n fi\n fi\n if [ \"$locked\" = true ]; then\n elapsed=$(( $(date +%s) - started ))\n outcome=passed\n if [ \"$code\" -ne 0 ]; then outcome=failed; fi\n printf '{\"stage\":\"%s\",\"status\":\"%s\",\"durationSeconds\":%s}\\n' \"$stage\" \"$outcome\" \"$(( $(date +%s) - step_started ))\" >> \"$root/steps-$id.jsonl\"\n # 先完整写入再同目录原子发布,SSH 重连核对不能读取到半份终态结果。\n printf '{\"deploymentId\":\"%s\",\"stage\":\"%s\",\"exitCode\":%s,\"durationSeconds\":%s}\\n' \"$id\" \"$stage\" \"$code\" \"$elapsed\" > \"$root/result-$id.json.next\"\n mv \"$root/result-$id.json.next\" \"$root/result-$id.json\"\n # 前台命令及同步恢复已结束;后台服务可继续运行,但不能使成功终态永久占锁。\n # 中断时仍可能有活跃子命令,必须由全部描述符持有者退出后释放。\n if [ \"$interrupted\" = false ]; then\n flock -u 9\n exec 9>&-\n fi\n fi\n exit \"$code\"\n}\ntrap finish EXIT\ntrap 'interrupted=true; exit 130' HUP INT TERM\nstep preflight 'Checking deployment tools and package'\nfor tool in sha256sum tar awk curl flock; do command -v \"$tool\" >/dev/null || { printf 'Required command missing: %s\\n' \"$tool\" >&2; exit 1; }; done\nif [ \"$runtime\" = auto ]; then\n if command -v podman >/dev/null 2>&1 && podman version >/dev/null 2>&1; then runtime=podman; else runtime=docker; fi\nfi\ncase \"$runtime\" in docker|podman) ;; *) printf 'Runtime must be docker or podman\\n' >&2; exit 1;; esac\n\"$runtime\" version >/dev/null\n\"$runtime\" compose version >/dev/null\n\"$runtime\" compose up --help | grep -q never || { printf 'Compose is too old. Install Docker Compose v2 or podman-compose 1.6.0 or newer (supports --pull never).\\n' >&2; exit 1; }\n# 内核锁绑定同一文件描述符;绝不删除/替换锁文件,避免新 inode 绕过活跃部署。\n# 子命令继承 FD 9:即使父 shell 被强杀,仍执行的命令继续持锁;全部退出或重启后自动释放。\nexec 9>\"$root/.deploy.lock\"\nif flock -n 9; then\n :\nelse\n lock_code=$?\n if [ \"$lock_code\" -eq 1 ]; then\n printf 'Another deployment is running. Wait for its commands to finish; do not remove %s/.deploy.lock.\\n' \"$root\" >&2\n else\n printf 'Cannot acquire deployment lock (exit %s). Check filesystem flock support and permissions.\\n' \"$lock_code\" >&2\n fi\n exit \"$lock_code\"\nfi\nlocked=true\ncd \"$source_dir\"\nsha256sum -c SHA256SUMS\nif [ -f \"$root/current\" ]; then\n previous=$(cat \"$root/current\")\n case \"$previous\" in ''|*[!a-zA-Z0-9._-]*) printf 'Invalid deployment state\\n' >&2; exit 1;; esac\n test -f \"$root/releases/$previous/compose-files\"\nfi\nif [ \"$partial\" = true ]; then\n test -n \"$previous\" || { printf 'Partial deployment requires a successful full installation. Deploy a complete bundle first.\\n' >&2; exit 1; }\n cmp -s layout \"$root/releases/$previous/layout\" || { printf 'Ports, API routes or application layout changed. Create a full deployment bundle.\\n' >&2; exit 1; }\nfi\ntest ! -e \"$release\" || { printf 'This deployment ID was already used. Create a new deployment bundle.\\n' >&2; exit 1; }\nmkdir -p \"$release\"\ncp -R \"$source_dir/.\" \"$release/\"\n# Nginx 以非 root 用户运行;只开放不含凭据的代理配置读取权限。\nif [ -f \"$release/web.conf\" ]; then chmod 644 \"$release/web.conf\"; fi\n: > \"$release/compose-files\"\nif [ \"$partial\" = true ]; then\n cp \"$root/releases/$previous/compose-files\" \"$release/compose-files\"\n cp \"$root/releases/$previous/middleware.env\" \"$release/middleware.env\"\n for service in $selected; do\n grep -qx \"$service\" \"$root/releases/$previous/services\" || { printf 'Service %s has no installed baseline. Use a full deployment.\\n' \"$service\" >&2; exit 1; }\n done\nfi\nprintf '%s\\n' \"$release/compose-entry.json\" >> \"$release/compose-files\"\ncompose config >/dev/null\ncompose config --services > \"$release/services\"\n: > \"$release/rollback-images\"\nif [ -n \"$previous\" ]; then\n for service in $selected; do\n containers=$(\"$runtime\" ps -aq --filter \"label=com.docker.compose.project=$project\" --filter \"label=com.docker.compose.service=$service\")\n for container in $containers; do\n \"$runtime\" inspect --format '{{.Image}} {{.Config.Image}}' \"$container\" >> \"$release/rollback-images\"\n done\n done\nfi\nstep images 'Loading packaged images (no registry access)'\nwhile IFS=' ' read -r archive reference; do\n test -n \"$archive\" || continue\n \"$runtime\" load -i \"$release/images/$archive\"\n \"$runtime\" image inspect \"$reference\" >/dev/null\n architecture=$(\"$runtime\" image inspect --format '{{.Architecture}}' \"$reference\")\n host_arch=$(uname -m)\n case \"$host_arch:$architecture\" in x86_64:amd64|aarch64:arm64) ;; *) printf 'Image architecture %s does not match server %s\\n' \"$architecture\" \"$host_arch\" >&2; exit 1;; esac\ndone < \"$release/image-list\"\nstep dependencies 'Checking dependencies of selected services'\nif [ \"$partial\" = true ]; then cat \"$release/services\" >> \"$release/dependencies\"; fi\nwhile IFS= read -r dependency; do\n test -n \"$dependency\" || continue\n case \"$dependency\" in *-init) continue;; esac\n case \" $selected \" in *\" $dependency \"*) continue;; esac\n running=$(\"$runtime\" ps -q --filter \"label=com.docker.compose.project=$project\" --filter \"label=com.docker.compose.service=$dependency\")\n test -n \"$running\" || { printf 'Dependency %s is not running. Include it in a full deployment.\\n' \"$dependency\" >&2; exit 1; }\n for container in $running; do\n test \"$(\"$runtime\" inspect --format '{{.State.Running}}' \"$container\")\" = true || { printf 'Dependency %s is stopped. Start it before retrying.\\n' \"$dependency\" >&2; exit 1; }\n done\ndone < \"$release/dependencies\"\nstep start 'Updating selected services'\nchanged=true\nremove_selected $selected\nif [ -f \"$release/initialize-storage\" ]; then\n remove_selected storage-init\n compose up -d --no-deps --no-build --pull never storage\n compose up --no-deps --no-build --pull never \"$recreate_option\" --exit-code-from storage-init storage-init\nfi\ncompose up -d --no-deps --no-build --pull never \"$recreate_option\" $orphan_option $selected\ncase \" $selected \" in\n *' app '*)\n case \" $selected \" in *' web '*) ;; *)\n if grep -qx web \"$release/services\"; then compose exec -T web nginx -s reload; fi\n esac\n ;;\nesac\nstep health 'Checking HTTP access'\nfor path in @@HEALTH@@; do\n ready=false\n attempt=0\n while [ \"$attempt\" -lt 40 ]; do\n if curl --noproxy '*' -fsS --max-time 5 \"http://127.0.0.1:@@PORT@@$path\" >/dev/null 2>&1; then ready=true; break; fi\n attempt=$((attempt + 1))\n sleep 3\n done\n test \"$ready\" = true || { printf 'HTTP check failed: %s. Inspect compose logs for selected services.\\n' \"$path\" >&2; exit 1; }\ndone\nstep complete 'Deployment passed all checks'\nprintf '%s\\n' \"$id\" > \"$root/current.next\"\nmv \"$root/current.next\" \"$root/current\"\nprintf '[PASS] %s\\n' \"$id\"\n`.replace(/@@([A-Z]+)@@/g, (_match, name: string) => values[name]!)\n}\n\n/**\n * 生成无 Node/pnpm 依赖的上传脚本;换电脑时可覆盖 SSH 私钥路径。\n * Windows PowerShell 5 会丢弃原生参数内部引号,须直接按 Win32 规则构造命令行。\n * 两个入口执行时读取旁边的 deploy-target.json;apply 阶段 SSH 失败仍须核对远端状态。\n * @returns Linux shell、Windows PowerShell 上传入口及 POSIX awk 配置读取器文本。\n * @example 模块内部上下文\n * ```ts\n * const scripts = createUploadScripts()\n * const files = { 'deploy.sh': scripts.sh, 'deploy.ps1': scripts.ps1, 'read-target.awk': scripts.reader }\n * // 将三个文件与 deploy-target.json 放在操作目录;生成文本不代表已部署。\n * ```\n */\nexport function createUploadScripts(): { sh: string, ps1: string, reader: string } {\n const sh = String.raw`#!/bin/sh\nset -eu\nsource_dir=$(CDPATH= cd -- \"$(dirname -- \"$0\")\" && pwd)\ncd \"$source_dir/..\"\ncommand -v awk >/dev/null || { printf 'Install POSIX awk to read deploy-target.json.\\n' >&2; exit 1; }\nread_target() {\n LC_ALL=C awk -v field=\"$1\" -v expected=\"$2\" -v fallback=\"$3\" -f \"$source_dir/read-target.awk\" \"$source_dir/deploy-target.json\"\n}\nhost=$(read_target host string SERVER_HOST)\nuser=$(read_target username string deploy)\nport=$(read_target port number 22)\nremote=$(read_target directory string '')\nbundle=$(read_target bundle string '')\nidentity=$(read_target identityFile string '')\nknown_hosts=$(read_target knownHostsFile string '')\nstrict=$(read_target strictHostKeyChecking boolean true)\ntimeout=$(read_target connectTimeoutSeconds number 10)\nif [ \"$#\" -ge 1 ]; then host=$1; fi\nif [ \"$#\" -ge 2 ]; then port=$2; fi\nif [ \"$#\" -ge 3 ]; then user=$3; fi\nif value=$(printenv HAI_DEPLOY_IDENTITY_FILE) && [ -n \"$value\" ]; then identity=$value; fi\nif value=$(printenv HAI_DEPLOY_KNOWN_HOSTS_FILE) && [ -n \"$value\" ]; then known_hosts=$value; fi\ninvalid_target() { printf 'Invalid deployment target. Edit deploy-target.json before running this script.\\n' >&2; exit 1; }\ntest \"$host\" != SERVER_HOST || { printf 'Specify the server: sh deploy.sh SERVER [PORT] [USER].\\n' >&2; exit 1; }\ncase \"$host\" in ''|*[!a-zA-Z0-9.:-]*|[!a-zA-Z0-9]*) invalid_target;; esac\ncase \"$user\" in ''|*[!a-zA-Z0-9_-]*|[!a-zA-Z_]*) invalid_target;; esac\ncase \"$port\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$port\" -ge 1 && test \"$port\" -le 65535 || invalid_target\ncase \"$timeout\" in ''|*[!0-9]*|???????????*) invalid_target;; esac\ntest \"$timeout\" -ge 1 && test \"$timeout\" -le 2147483647 || invalid_target\ncase \"$remote\" in /*) ;; *) invalid_target;; esac\ncase \"$remote\" in *[!a-zA-Z0-9/_.\\ -]*|*/../*|*/..|/..) invalid_target;; esac\ncase \"$bundle\" in *.tar) ;; *) invalid_target;; esac\ncase \"$bundle\" in ''|*[!a-zA-Z0-9_.+-]*) invalid_target;; esac\ncase \"$strict\" in true) strict=accept-new;; false) strict=no;; *) invalid_target;; esac\ntest -f \"./$bundle\" || { printf 'Bundle missing: %s\\n' \"$bundle\" >&2; exit 1; }\nfor tool in ssh scp; do command -v \"$tool\" >/dev/null || { printf 'Install OpenSSH (%s).\\n' \"$tool\" >&2; exit 1; }; done\nset -- -o BatchMode=yes -o \"StrictHostKeyChecking=$strict\" -o \"ConnectTimeout=$timeout\"\nif [ -n \"$identity\" ]; then set -- \"$@\" -i \"$identity\" -o IdentitiesOnly=yes; fi\nif [ -n \"$known_hosts\" ]; then\n known_hosts=$(printf '%s' \"$known_hosts\" | sed 's/[\\\\\"]/\\\\&/g')\n set -- \"$@\" -o \"UserKnownHostsFile=\\\"$known_hosts\\\"\"\nfi\nprintf '[1/3] Connecting to %s\\n' \"$host\"\nssh \"$@\" -p \"$port\" \"$user@$host\" \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"\nprintf '[2/3] Uploading %s\\n' \"$bundle\"\nscp_host=$host\ncase \"$host\" in *:*) scp_host=\"[$host]\";; esac\nscp \"$@\" -P \"$port\" \"./$bundle\" \"$user@$scp_host:$remote/incoming/$bundle\"\nprintf '[3/3] Applying package and checking HTTP access\\n'\nif ssh \"$@\" -p \"$port\" \"$user@$host\" \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote'\"; then\n :\nelse\n code=$?\n printf '[UNKNOWN] Remote execution may continue. Inspect %s/result-<deploymentId>.json (ID in manifest.json), current and containers before retrying.\\n' \"$remote\" >&2\n exit \"$code\"\nfi\n`\n const ps1 = String.raw`param([string]$IdentityFile = $env:HAI_DEPLOY_IDENTITY_FILE)\n$ErrorActionPreference = 'Stop'\nSet-Location -LiteralPath (Split-Path -Parent $PSScriptRoot)\n$target = Get-Content -LiteralPath (Join-Path $PSScriptRoot 'deploy-target.json') -Raw -Encoding UTF8 | ConvertFrom-Json\nif ($target.host -eq 'SERVER_HOST') { throw 'Set the server host in deploy-target.json.' }\nif ($target.host -isnot [string] -or $target.host -notmatch '^[a-zA-Z0-9][a-zA-Z0-9.:-]*$' -or $target.username -isnot [string] -or $target.username -notmatch '^[a-zA-Z_][a-zA-Z0-9_-]*$' -or $target.directory -isnot [string] -or $target.directory -notmatch '^/[a-zA-Z0-9/_. -]*$' -or $target.directory -match '(^|/)\\.\\.(/|$)' -or $target.bundle -isnot [string] -or $target.bundle -notmatch '^[a-zA-Z0-9_.+-]+\\.tar$') { throw 'Invalid deployment target.' }\n$port = if ($null -eq $target.port) { 22 } else { $target.port }\n$timeout = if ($null -eq $target.connectTimeoutSeconds) { 10 } else { $target.connectTimeoutSeconds }\nif ($port -is [string] -or [string]$port -notmatch '^[0-9]+$' -or $port -lt 1 -or $port -gt 65535 -or $timeout -is [string] -or [string]$timeout -notmatch '^[0-9]+$' -or $timeout -lt 1 -or $timeout -gt 2147483647) { throw 'Invalid deployment port or timeout.' }\nif ($null -ne $target.strictHostKeyChecking -and $target.strictHostKeyChecking -isnot [bool]) { throw 'Invalid host key policy.' }\nif (($null -ne $target.identityFile -and $target.identityFile -isnot [string]) -or ($null -ne $target.knownHostsFile -and $target.knownHostsFile -isnot [string])) { throw 'Invalid SSH file path.' }\n$strict = if ($target.strictHostKeyChecking -eq $false) { 'no' } else { 'accept-new' }\n$options = @('-o', 'BatchMode=yes', '-o', \"StrictHostKeyChecking=$strict\", '-o', \"ConnectTimeout=$timeout\")\nif (-not $IdentityFile) { $IdentityFile = $target.identityFile }\nif ($IdentityFile) { $options += @('-i', $IdentityFile, '-o', 'IdentitiesOnly=yes') }\n$knownHosts = if ($env:HAI_DEPLOY_KNOWN_HOSTS_FILE) { $env:HAI_DEPLOY_KNOWN_HOSTS_FILE } else { $target.knownHostsFile }\nif ($knownHosts) {\n $knownHosts = $knownHosts.Replace('\\', '\\\\').Replace('\"', '\\\"')\n $options += @('-o', ('UserKnownHostsFile=\"' + $knownHosts + '\"'))\n}\n$destination = \"$($target.username)@$($target.host)\"\n$scpDestination = if ($target.host.Contains(':')) { \"$($target.username)@[$($target.host)]\" } else { $destination }\n$remote = $target.directory\n$bundle = $target.bundle\nif (-not (Test-Path -LiteralPath \"./$bundle\" -PathType Leaf)) { throw \"Bundle missing: $bundle\" }\nfunction ConvertTo-NativeArgument([string]$Value) {\n if ($Value.Length -gt 0 -and $Value -notmatch '[\\s\"]') { return $Value }\n $escaped = [regex]::Replace($Value, '(\\\\*)\"', '$1$1\\\"')\n $escaped = [regex]::Replace($escaped, '(\\\\+)$', '$1$1')\n return '\"' + $escaped + '\"'\n}\nfunction Invoke-Step([string]$Name, [string]$Command, [string[]]$Arguments) {\n Write-Host \"[$Name]\"\n $nativeCommand = Get-Command $Command -ErrorAction Stop\n if ($PSVersionTable.PSVersion.Major -lt 6 -and $nativeCommand.CommandType -eq 'Application') {\n $start = New-Object System.Diagnostics.ProcessStartInfo\n $start.FileName = $nativeCommand.Source\n $start.WorkingDirectory = (Get-Location).ProviderPath\n $start.UseShellExecute = $false\n $start.CreateNoWindow = $true\n $start.Arguments = ($Arguments | ForEach-Object { ConvertTo-NativeArgument $_ }) -join ' '\n $child = [System.Diagnostics.Process]::Start($start)\n try { $child.WaitForExit(); $code = $child.ExitCode } finally { $child.Dispose() }\n } else {\n & $Command @Arguments\n $code = $LASTEXITCODE\n }\n $global:LASTEXITCODE = $code\n if ($code -ne 0) { throw \"$Name failed (exit $code).\" }\n}\n$applying = $false\ntry {\n foreach ($tool in @('ssh', 'scp')) { Get-Command $tool -ErrorAction Stop | Out-Null }\n Invoke-Step '1/3 Connect' 'ssh' ($options + @('-p', [string]$port, $destination, \"mkdir -p '$remote/incoming' && chmod 700 '$remote' '$remote/incoming'\"))\n Invoke-Step '2/3 Upload' 'scp' ($options + @('-P', [string]$port, \"./$bundle\", \"$($scpDestination):$remote/incoming/$bundle\"))\n $applying = $true\n Invoke-Step '3/3 Apply and verify HTTP' 'ssh' ($options + @('-p', [string]$port, $destination, \"cd '$remote/incoming' && mkdir -p '$bundle.contents' && tar -xf '$bundle' -C '$bundle.contents' && sh '$bundle.contents/apply.sh' '$remote'\"))\n} catch {\n if ($applying) { [Console]::Error.WriteLine(\"[UNKNOWN] Remote execution may continue. Inspect $remote/result-<deploymentId>.json (ID in manifest.json), current and containers before retrying.\") }\n Write-Error $_\n exit 1\n}\n`\n return { sh, ps1, reader: createTargetReader() }\n}\n","/** 完整或增量交付包,包含所选服务需要的全部镜像及跨平台部署入口。 */\nimport type { DeploymentArtifact } from '../deploy-artifact.js'\nimport type { DockerSshProviderConfig } from '../deploy-config.js'\nimport { chmodSync, copyFileSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join, resolve } from 'node:path'\nimport { parse } from 'yaml'\nimport { artifactChecksum } from '../deploy-artifact.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { runCommand } from './deploy-command.js'\nimport { createApplyScript, createUploadScripts } from './deploy-scripts.js'\n\n/**\n * 打包所选服务;完整交付自动导出中间件,服务器启动时禁止联网拉取。\n * @throws Error - 制品、Compose、文件读取、镜像导出或打包失败;包含私有运行环境的 tar 必须按秘密传输与保存。\n * @param options - 本次操作选项;字段含义见各子项。\n * @param options.directory - 包含已准备制品或部署文件的目录;具体见函数用途。\n * @param options.artifactDir - 已经验证的镜像 tar 与 manifest 所在目录。\n * @param options.artifact - 已通过结构、路径和文件摘要验证的构建清单。\n * @param options.projectName - 已归一化的项目名称。\n * @param options.deploymentId - 本次不可变部署标识,用于结果匹配和发布目录。\n * @param options.environment - 部署环境标识,通常为 prod。\n * @param options.config - 已通过 Schema 解析的 docker-ssh 配置。\n * @param options.runtime - 容器引擎策略;auto 探测可用引擎并优先 Podman。\n * @param options.output - tar 输出路径,按应用版本自动补文件名后缀。\n * @param options.selected - 本次选择更新的 Compose 服务。\n * @param options.partial - 是否为增量服务部署;不能据此执行首次全量安装。\n * @param options.middlewareEnv - 只用于受保护文件的中间件 dotenv 内容。\n * @param options.healthPaths - 允许执行的应用健康检查路径。\n * @param options.hasWeb - 工程是否包含独立 Web 服务拓扑。\n * @param options.containerPort - 应用容器的实际监听端口。\n * @returns tar 路径、手工执行说明及启动脚本名。\n * @example 模块内部上下文\n * ```ts\n * const { readDeploymentArtifact } = await import('../deploy-artifact.js')\n * const artifactDir = '.hai/build/docker/build-id'\n * const artifact = await readDeploymentArtifact(artifactDir)\n * // directory 已由 Provider 准备好 docker-compose-<版本>.yml 与 .env.runtime。\n * const directory = '.hai/deploy/prod/prepared-id'\n * const result = await createDeploymentBundle({ directory, artifactDir, artifact, projectName: 'shop', deploymentId: 'shop-prod-001', environment: 'prod', config: { type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } }, runtime: 'auto', output: '.hai/deploy/shop.tar', selected: ['app'], partial: false, middlewareEnv: '', healthPaths: ['/health'], hasWeb: false, containerPort: 3000 })\n * ```\n */\nexport async function createDeploymentBundle(options: {\n directory: string\n artifactDir: string\n artifact: DeploymentArtifact\n projectName: string\n deploymentId: string\n environment: string\n config: DockerSshProviderConfig\n runtime: 'auto' | 'podman' | 'docker'\n output: string\n selected: string[]\n partial: boolean\n middlewareEnv: string\n healthPaths: string[]\n hasWeb: boolean\n containerPort: number\n}): Promise<{ bundlePath: string, instructions: string, startName: string }> {\n const { directory, artifactDir, artifact, projectName, environment, config, selected } = options\n const stem = basename(options.output).replace(/\\.tar$/i, '')\n const suffix = `-${artifact.appVersion}`\n const output = resolve(dirname(options.output), `${stem.endsWith(suffix) ? stem : `${stem}${suffix}`}.tar`)\n if (!/^[\\w.+-]+\\.tar$/.test(basename(output)))\n throw new Error(deployM('deploy_bundleNameInvalid'))\n const staging = mkdtempSync(join(directory, '.bundle-'))\n const temporaryTar = `${output}.partial`\n mkdirSync(dirname(output), { recursive: true, mode: 0o700 })\n chmodSync(staging, 0o700)\n const files: string[] = []\n const put = (file: string, content: string): void => {\n mkdirSync(dirname(join(staging, file)), { recursive: true })\n writeFileSync(join(staging, file), content, { mode: 0o600 })\n files.push(file)\n }\n try {\n mkdirSync(join(staging, 'images'))\n const compose = parse(readFileSync(join(directory, `docker-compose-${artifact.appVersion}.yml`), 'utf8')) as {\n services: Record<string, Record<string, unknown>>\n networks?: Record<string, unknown>\n volumes?: Record<string, unknown>\n }\n const dependencies = new Set<string>()\n const references = new Set<string>()\n for (const name of selected) {\n const service = compose.services[name]\n if (!service)\n throw new Error(deployM('deploy_selectionInvalid', { params: { service: name } }))\n if (typeof service.image === 'string')\n references.add(service.image)\n if (service.depends_on) {\n for (const dependency of Array.isArray(service.depends_on) ? service.depends_on as string[] : Object.keys(service.depends_on))\n dependencies.add(dependency)\n }\n if (service.env_file)\n service.env_file = [`../${options.deploymentId}/.env.runtime`, `../${options.deploymentId}/middleware.env`]\n if (Array.isArray(service.volumes))\n service.volumes = service.volumes.map(mount => typeof mount === 'string' ? mount.replace('./web.conf:', `../${options.deploymentId}/web.conf:`) : mount)\n }\n put('compose.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, compose.services[name]])) }))\n // 合并入口仅保存 extends 指向;更新服务时整体切换定义,避免旧 env_file/卷列表累加。\n put('compose-entry.json', JSON.stringify({ ...compose, services: Object.fromEntries(selected.map(name => [name, { extends: { file: `../${options.deploymentId}/compose.json`, service: name } }])) }))\n let runtime: 'podman' | 'docker' | undefined\n const imageList: string[] = []\n for (const reference of references) {\n if (!/:[^/:]+$/.test(reference) || /:latest$/i.test(reference))\n throw new Error(deployM('deploy_imageVersionRequired', { params: { image: reference } }))\n const built = artifact.images.find(image => image.imageRef === reference)\n const file = built?.file ?? `middleware-${imageList.length + 1}.tar`\n if (built) {\n copyFileSync(join(artifactDir, file), join(staging, 'images', file))\n }\n else {\n if (!runtime) {\n const candidates = options.runtime === 'auto' ? ['podman', 'docker'] as const : [options.runtime]\n for (const candidate of candidates) {\n if ((await runCommand(candidate, ['version'])).success) {\n runtime = candidate\n break\n }\n }\n if (!runtime)\n throw new Error(deployM('deploy_bundleRuntimeRequired'))\n }\n if (!(await runCommand(runtime, ['image', 'inspect', reference])).success) {\n const pulled = await runCommand(runtime, ['pull', reference], { timeoutMs: 600_000 })\n if (!pulled.success)\n throw new Error(pulled.error.message)\n }\n const saved = await runCommand(runtime, ['save', ...(runtime === 'podman' ? ['--format', 'docker-archive'] : []), '-o', join(staging, 'images', file), reference], { timeoutMs: 600_000 })\n if (!saved.success)\n throw new Error(saved.error.message)\n }\n files.push(`images/${file}`)\n imageList.push(`${file} ${reference}`)\n }\n put('.env.runtime', readFileSync(join(directory, '.env.runtime'), 'utf8'))\n put('middleware.env', options.middlewareEnv)\n if (selected.includes('web'))\n put('web.conf', readFileSync(join(directory, 'web.conf'), 'utf8'))\n put('manifest.json', `${JSON.stringify({ ...artifact, images: artifact.images.filter(image => references.has(image.imageRef)), deploymentId: options.deploymentId, selectedServices: selected, partial: options.partial }, null, 2)}\\n`)\n put('layout', `${config.expose.hostPort}:${options.containerPort}:${options.hasWeb}:${options.hasWeb ? await artifactChecksum(join(directory, 'web.conf')) : ''}\\n`)\n put('image-list', `${imageList.join('\\n')}\\n`)\n put('dependencies', `${[...dependencies].join('\\n')}\\n`)\n if (selected.includes('storage-init'))\n put('initialize-storage', '')\n put('apply.sh', createApplyScript({ deploymentId: options.deploymentId, projectName, environment, directory: `${config.remote.baseDir}/${projectName}`, runtime: config.remote.runtime, partial: options.partial, selected: selected.filter(name => name !== 'storage-init'), hostPort: config.expose.hostPort, healthPaths: options.healthPaths }))\n const instructionParams = { file: basename(output), start: 'apply.sh', images: [...references].join('\\n'), compose: 'compose.json' }\n const instructions = deployM('deploy_bundleInstructions', { params: instructionParams })\n put('README.txt', `${deployM('deploy_bundleMetadata', { params: { version: artifact.appVersion, buildId: artifact.buildId, compose: 'compose.json' } })}\\n${instructions}\\n`)\n const checksums = []\n for (const file of files)\n checksums.push(`${await artifactChecksum(join(staging, file))} ${file}`)\n writeFileSync(join(staging, 'SHA256SUMS'), `${checksums.join('\\n')}\\n`)\n const tar = await runCommand('tar', ['-cf', temporaryTar, '-C', staging, '.'])\n if (!tar.success)\n throw new Error(tar.error.message)\n chmodSync(temporaryTar, 0o600)\n renameSync(temporaryTar, output)\n const upload = createUploadScripts()\n const scripts = `${output.slice(0, -4)}-deploy`\n mkdirSync(scripts, { recursive: true, mode: 0o700 })\n writeFileSync(join(scripts, 'deploy.sh'), upload.sh, { mode: 0o700 })\n writeFileSync(join(scripts, 'deploy.ps1'), upload.ps1)\n writeFileSync(join(scripts, 'read-target.awk'), upload.reader)\n const target = {\n host: config.ssh?.host ?? 'SERVER_HOST',\n port: config.ssh?.port ?? 22,\n username: config.ssh?.username ?? 'deploy',\n identityFile: config.ssh?.identityFile ?? '',\n knownHostsFile: config.ssh?.knownHostsFile ?? '',\n strictHostKeyChecking: config.ssh?.strictHostKeyChecking ?? true,\n connectTimeoutSeconds: config.ssh?.connectTimeoutSeconds ?? 10,\n directory: `${config.remote.baseDir}/${projectName}`,\n bundle: basename(output),\n }\n const comments = {\n host: deployM('deploy_targetHost'),\n port: deployM('deploy_targetPort'),\n username: deployM('deploy_targetUsername'),\n identityFile: deployM('deploy_targetIdentityFile'),\n knownHostsFile: deployM('deploy_targetKnownHostsFile'),\n strictHostKeyChecking: deployM('deploy_targetStrictHostKeyChecking'),\n connectTimeoutSeconds: deployM('deploy_targetConnectTimeoutSeconds'),\n directory: deployM('deploy_targetDirectory'),\n bundle: deployM('deploy_targetBundle'),\n }\n writeFileSync(join(scripts, 'deploy-target.json'), `${JSON.stringify({ ...target, _comments: comments }, null, 2)}\\n`)\n writeFileSync(join(scripts, 'README.txt'), instructions)\n return { bundlePath: output, instructions: `${deployM('deploy_bundleInstructions', { params: { ...instructionParams, file: output } })}\\n${scripts}`, startName: 'apply.sh' }\n }\n finally {\n rmSync(staging, { recursive: true, force: true })\n rmSync(temporaryTar, { force: true })\n }\n}\n","/**\n * @h-ai/deploy — 容器编排文件生成\n *\n * 根据应用扫描结果生成 compose 文件与运行期环境:按需为 db/cache/storage\n * 追加自建 sidecar 服务,并注入对应的 HAI_DB / HAI_CACHE / HAI_STORAGE 覆盖变量。\n * 敏感值仅写入 .env.runtime,禁止进入 compose 文件。\n * @module deploy-container-compose\n */\n\nimport type { DeployAppOptions, ScanResult, ServiceType } from '../deploy-types.js'\nimport { randomBytes } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { stringify } from 'yaml'\nimport { usesDefaultMiddleware } from '../deploy-functions.js'\nimport { deployM } from '../deploy-i18n.js'\n\n/** sidecar 镜像固定版本,避免 `:latest` 漂移导致行为变化。 */\nconst IMAGES = {\n postgres: 'docker.io/library/postgres:16.15-alpine',\n mysql: 'docker.io/library/mysql:8.4.11',\n redis: 'docker.io/library/redis:7.4.11-alpine',\n rustfs: 'ghcr.io/rustfs/rustfs:1.0.1',\n minio: 'ghcr.io/coollabsio/minio:RELEASE.2025-10-15T17-29-55Z',\n qdrant: 'docker.io/qdrant/qdrant:v1.19.2',\n pgvector: 'docker.io/pgvector/pgvector:0.8.0-pg17',\n chroma: 'docker.io/chromadb/chroma:1.5.5',\n ldap: 'docker.io/osixia/openldap:1.5.0',\n smtp: 'docker.io/axllent/mailpit:v1.27.4',\n} as const\n\n/**\n * compose 服务定义(结构化对象,交由 yaml 序列化)。\n * 内部 Compose 文档对象,不是公开部署配置 Schema。\n * @example 模块内部上下文\n * ```ts\n * const service: ComposeService = { image: 'registry.example.org/shop:1.0.0', ports: ['8080:3000'] }\n * ```\n */\ntype ComposeService = Record<string, unknown>\n\n/**\n * sidecar 规划结果。\n * 无中间件应用的空计划是合法输入;有连接时 env/secrets 可能含私密值,不能整体展示。\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport interface SidecarPlan {\n /** 实际启用的自建服务 */\n services: ServiceType[]\n /** compose services 片段(不含 app) */\n composeServices: Record<string, ComposeService>\n /** 命名卷 */\n volumes: Record<string, unknown>\n /** 挂载到 app 容器的卷(如 sqlite/lancedb 的本地数据目录持久化) */\n appVolumes: string[]\n /** 追加到 .env.runtime 的环境变量(含 HAI_* 覆盖与 sidecar 凭据) */\n env: Record<string, string>\n /** app 服务的 depends_on 列表 */\n dependsOn: string[]\n /** 需要在日志中脱敏的敏感值 */\n secrets: string[]\n}\n\n/**\n * 运行期环境构建结果。\n * @example 模块内部上下文\n * ```ts\n * const plan: RuntimeEnvPlan = { env: { NODE_ENV: 'production' }, sidecar: { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, dependsOn: [], secrets: [] } }\n * const content = serializeEnvFile(plan.env)\n * ```\n */\nexport interface RuntimeEnvPlan {\n /** 完整运行期环境(写入 .env.runtime) */\n env: Record<string, string>\n /** sidecar 规划 */\n sidecar: SidecarPlan\n}\n\n/** 生成随机密码(url 安全)。 */\nfunction generatePassword(): string {\n return randomBytes(24).toString('base64url')\n}\n\n/**\n * 读取或创建稳定的 sidecar 凭据。\n *\n * 为保证重复部署的幂等性(密码不变,避免已存在数据卷认证失败),\n * 凭据持久化到本地 gitignore 的 `.hai/deploy/runtime/<project>.secrets.json`。\n *\n * @param appDir - 应用根目录\n * @param projectName - 项目名\n * @returns 稳定的凭据键值对\n */\nfunction resolveSidecarSecrets(appDir: string, projectName: string): Record<string, string> {\n const secretFile = join(appDir, '.hai', 'deploy', 'runtime', `${projectName}.secrets.json`)\n if (existsSync(secretFile)) {\n try {\n const saved = JSON.parse(readFileSync(secretFile, 'utf-8')) as Record<string, string>\n if (!saved || !['dbPassword', 'storagePassword', 'ldapPassword'].every(key => typeof saved[key] === 'string' && saved[key].length > 0))\n throw new Error('Invalid credentials')\n return saved\n }\n catch {\n throw new Error(deployM('deploy_secretsInvalid', { params: { path: secretFile } }))\n }\n }\n const secrets = {\n dbPassword: generatePassword(),\n storagePassword: generatePassword(),\n ldapPassword: generatePassword(),\n }\n mkdirSync(dirname(secretFile), { recursive: true })\n writeFileSync(secretFile, JSON.stringify(secrets), { mode: 0o600 })\n return secrets\n}\n\n/** 为 app 追加本地数据卷(sqlite / lancedb 等文件型后端持久化)。 */\nfunction addAppDataVolume(plan: SidecarPlan, projectName: string): void {\n const mount = `${projectName}-data:/app/data`\n if (!plan.appVolumes.includes(mount)) {\n plan.appVolumes.push(mount)\n plan.volumes[`${projectName}-data`] = null\n }\n}\n\n/** PostgreSQL sidecar。 */\nfunction planPostgresDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.postgres,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['.env.runtime'],\n volumes: [`${projectName}-db-data:/var/lib/postgresql/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.env.POSTGRES_USER = 'hai'\n plan.env.POSTGRES_PASSWORD = password\n plan.env.POSTGRES_DB = 'hai'\n plan.env.HAI_DB = JSON.stringify({ type: 'postgresql', url: `postgresql://hai:${password}@db:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** MySQL sidecar。 */\nfunction planMysqlDb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('db')\n plan.dependsOn.push('db')\n plan.composeServices.db = {\n image: IMAGES.mysql,\n container_name: `hai-${projectName}-db`,\n restart: 'unless-stopped',\n env_file: ['.env.runtime'],\n volumes: [`${projectName}-db-data:/var/lib/mysql`],\n networks: net,\n }\n plan.volumes[`${projectName}-db-data`] = null\n plan.env.MYSQL_ROOT_PASSWORD = password\n plan.env.MYSQL_DATABASE = 'hai'\n plan.env.MYSQL_USER = 'hai'\n plan.env.MYSQL_PASSWORD = password\n plan.env.HAI_DB = JSON.stringify({ type: 'mysql', url: `mysql://hai:${password}@db:3306/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Redis sidecar。 */\nfunction planRedisCache(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('cache')\n plan.dependsOn.push('cache')\n plan.composeServices.cache = {\n image: IMAGES.redis,\n container_name: `hai-${projectName}-cache`,\n restart: 'unless-stopped',\n networks: net,\n }\n plan.env.HAI_CACHE = JSON.stringify({ type: 'redis', url: 'redis://cache:6379' })\n}\n\n/** S3 协议与服务实现分离;RustFS/MinIO 使用相同应用契约及幂等 bucket 初始化。 */\nfunction planS3Storage(plan: SidecarPlan, projectName: string, password: string, net: string[], engine: 'rustfs' | 'minio'): void {\n plan.services.push('storage')\n plan.dependsOn.push('storage')\n plan.composeServices.storage = {\n image: IMAGES[engine],\n container_name: `hai-${projectName}-storage`,\n restart: 'unless-stopped',\n ...(engine === 'minio' ? { command: ['server', '/data'] } : {}),\n env_file: ['.env.runtime'],\n volumes: [`${projectName}-storage-data:/data`],\n networks: net,\n }\n plan.composeServices['storage-init'] = {\n depends_on: ['storage'],\n env_file: ['.env.runtime'],\n entrypoint: [\n 'node',\n '--input-type=module',\n '-e',\n // 复用应用 @h-ai/storage 已依赖的 SDK;不额外拉取失效的 mc 镜像,不把密钥拼进命令。\n `import { S3Client, HeadBucketCommand, CreateBucketCommand } from '@aws-sdk/client-s3';\nconst config = JSON.parse(process.env.HAI_STORAGE);\nconst client = new S3Client({ endpoint: config.endpoint, region: config.region, forcePathStyle: config.forcePathStyle, credentials: { accessKeyId: config.accessKeyId, secretAccessKey: config.secretAccessKey } });\nlet ready = false;\nfor (let attempt = 0; attempt < 120; attempt++) {\n try {\n try { await client.send(new HeadBucketCommand({ Bucket: config.bucket })); }\n catch (error) {\n if (error.$$metadata?.httpStatusCode !== 404) throw error;\n await client.send(new CreateBucketCommand({ Bucket: config.bucket }));\n }\n ready = true; break;\n } catch { await new Promise(resolve => setTimeout(resolve, 1000)); }\n}\nclient.destroy();\nif (!ready) throw new Error('S3 bucket initialization failed');`,\n ],\n networks: net,\n }\n plan.volumes[`${projectName}-storage-data`] = null\n if (engine === 'rustfs') {\n Object.assign(plan.env, { RUSTFS_ACCESS_KEY: 'hai-storage', RUSTFS_SECRET_KEY: password, RUSTFS_ADDRESS: '0.0.0.0:9000', RUSTFS_VOLUMES: '/data', RUSTFS_CONSOLE_ENABLE: 'false' })\n }\n else {\n Object.assign(plan.env, { MINIO_ROOT_USER: 'hai-storage', MINIO_ROOT_PASSWORD: password })\n }\n plan.env.HAI_STORAGE = JSON.stringify({\n type: 's3',\n endpoint: 'http://storage:9000',\n bucket: 'hai',\n region: 'us-east-1',\n accessKeyId: 'hai-storage',\n secretAccessKey: password,\n forcePathStyle: true,\n })\n plan.secrets.push(password)\n}\n\n/** Qdrant 向量库 sidecar。 */\nfunction planQdrantVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.qdrant,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/qdrant/storage`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'qdrant', url: 'http://vecdb:6333' })\n}\n\n/** pgvector 向量库 sidecar(PostgreSQL + pgvector 扩展)。 */\nfunction planPgvectorVecdb(plan: SidecarPlan, projectName: string, password: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.pgvector,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n env_file: ['.env.runtime'],\n volumes: [`${projectName}-vecdb-data:/var/lib/postgresql/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n // 与 postgres db sidecar 共用 POSTGRES_* 凭据(不同实例、不同卷,值一致即可)\n plan.env.POSTGRES_USER = 'hai'\n plan.env.POSTGRES_PASSWORD = password\n plan.env.POSTGRES_DB = 'hai'\n plan.env.HAI_VECDB = JSON.stringify({ type: 'pgvector', url: `postgresql://hai:${password}@vecdb:5432/hai`, database: 'hai' })\n plan.secrets.push(password)\n}\n\n/** Chroma 向量库 sidecar。 */\nfunction planChromaVecdb(plan: SidecarPlan, projectName: string, net: string[]): void {\n plan.services.push('vecdb')\n plan.dependsOn.push('vecdb')\n plan.composeServices.vecdb = {\n image: IMAGES.chroma,\n container_name: `hai-${projectName}-vecdb`,\n restart: 'unless-stopped',\n volumes: [`${projectName}-vecdb-data:/data`],\n networks: net,\n }\n plan.volumes[`${projectName}-vecdb-data`] = null\n plan.env.HAI_VECDB = JSON.stringify({ type: 'chroma', url: 'http://vecdb:8000' })\n}\n\n/**\n * 规划自建 sidecar 服务。\n *\n * 仅为 scan.requiredServices 中、且 Provisioner 未提供对应 HAI_* 变量的服务追加 sidecar;\n * db 与 vecdb 按扫描到的后端类型(postgresql/mysql/sqlite、qdrant/pgvector/chroma/lancedb)生成匹配实现。\n * keep 不创建 sidecar;云开通结果和现有连接分别处理,不能把任何依赖都当成需要新建服务。\n * @param appDir - 应用根目录\n * @param projectName - 项目名\n * @param scan - 扫描结果\n * @param provisionEnv - Provisioner 输出的环境变量\n * @returns sidecar 规划\n * @param options - 本次操作选项;字段含义见各子项。\n * @param s3Engine - 自建 S3 服务实现;协议仍为 s3,默认 rustfs。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const plan = planSidecars(process.cwd(), 'shop', scanned.data, {}, { serviceModes: { db: 'keep' } })\n * ```\n */\nexport function planSidecars(\n appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n options?: DeployAppOptions,\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n): SidecarPlan {\n // 保持配置不变仍需交付自建服务镜像;已保存的容器服务地址可明确区分外部连接。\n const serviceModes = { ...options?.serviceModes }\n for (const requirement of scan.middlewares ?? []) {\n if (options?.selectedServices && !options.selectedServices.includes(requirement.service))\n continue\n const mode = serviceModes[requirement.envPrefix] ?? serviceModes[requirement.service]\n if (mode !== 'keep')\n continue\n const endpoint = requirement.config.url ?? requirement.config.endpoint\n let host = requirement.config.host\n if (typeof endpoint === 'string') {\n try {\n host = new URL(endpoint).hostname\n }\n catch {\n continue\n }\n }\n if (host === requirement.service || ['sqlite', 'local', 'memory', 'lancedb'].includes(requirement.backend)) {\n serviceModes[requirement.envPrefix] = 'default'\n serviceModes[requirement.service] = 'default'\n }\n }\n options = { ...options, serviceModes }\n const plan: SidecarPlan = {\n services: [],\n composeServices: {},\n volumes: {},\n appVolumes: [],\n env: {},\n dependsOn: [],\n secrets: [],\n }\n // 全部保持不变时,连默认中间件凭据文件也不读取或创建。\n if (!scan.requiredServices.some(service => usesDefaultMiddleware(scan, service, options)))\n return plan\n const secrets = resolveSidecarSecrets(appDir, projectName)\n const net = ['hai-app']\n const backends = scan.serviceBackends\n\n for (const service of scan.requiredServices) {\n if (!usesDefaultMiddleware(scan, service, options))\n continue\n if (service === 'db' && !provisionEnv.HAI_DB) {\n const backend = backends.db ?? 'postgresql'\n if (backend === 'mysql')\n planMysqlDb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'sqlite')\n addAppDataVolume(plan, projectName) // 文件库:仅持久化数据目录,保留应用自身 sqlite 配置\n else\n planPostgresDb(plan, projectName, secrets.dbPassword, net)\n }\n else if (service === 'cache' && !provisionEnv.HAI_CACHE) {\n if ((backends.cache ?? 'redis') === 'redis')\n planRedisCache(plan, projectName, net)\n }\n else if (service === 'storage' && !provisionEnv.HAI_STORAGE) {\n if ((backends.storage ?? 's3') === 's3')\n planS3Storage(plan, projectName, secrets.storagePassword, net, s3Engine)\n else\n addAppDataVolume(plan, projectName)\n }\n else if (service === 'vecdb' && !provisionEnv.HAI_VECDB) {\n const backend = backends.vecdb ?? 'qdrant'\n if (backend === 'pgvector')\n planPgvectorVecdb(plan, projectName, secrets.dbPassword, net)\n else if (backend === 'chroma')\n planChromaVecdb(plan, projectName, net)\n else if (backend === 'lancedb')\n addAppDataVolume(plan, projectName) // 嵌入式:持久化本地向量文件\n else\n planQdrantVecdb(plan, projectName, net)\n }\n else if (service === 'ldap' && backends.ldap === 'ldap' && !provisionEnv.HAI_IAM_LDAP) {\n const password = secrets.ldapPassword ?? secrets.dbPassword\n plan.services.push('ldap')\n plan.dependsOn.push('ldap')\n plan.composeServices.ldap = { image: IMAGES.ldap, restart: 'unless-stopped', env_file: ['.env.runtime'], networks: net, volumes: [`${projectName}-ldap-data:/var/lib/ldap`, `${projectName}-ldap-config:/etc/ldap/slapd.d`] }\n plan.volumes[`${projectName}-ldap-data`] = null\n plan.volumes[`${projectName}-ldap-config`] = null\n Object.assign(plan.env, { LDAP_DOMAIN: 'example.org', LDAP_ORGANISATION: 'HAI', LDAP_ADMIN_PASSWORD: password, LDAP_TLS: 'false', HAI_IAM_LOGIN_LDAP: 'true', HAI_IAM_LDAP: JSON.stringify({ url: 'ldap://ldap:389', bindDn: 'cn=admin,dc=example,dc=org', bindPassword: password, searchBase: 'dc=example,dc=org' }) })\n plan.secrets.push(password)\n }\n else if (service === 'email' && (scan.middlewares ? scan.middlewares.some(item => item.service === 'email' && item.backend === 'smtp' && (options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email ?? 'default') === 'default') : backends.email === 'smtp') && !provisionEnv.HAI_REACH_PROVIDERS) {\n plan.services.push('email')\n plan.dependsOn.push('email')\n plan.composeServices.email = { image: IMAGES.smtp, restart: 'unless-stopped', networks: net }\n const requirements = scan.middlewares?.filter(item => item.service === 'email' && item.backend === 'smtp' && ['default', undefined].includes(options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.email))\n if (requirements?.length) {\n for (const requirement of requirements)\n plan.env[requirement.envPrefix] = JSON.stringify({ name: requirement.config.name ?? 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: 'noreply@example.com' })\n }\n else if (!scan.middlewares) {\n plan.env.HAI_REACH_PROVIDERS_0 = JSON.stringify({ name: 'email', type: 'smtp', host: 'email', port: 1025, secure: false, from: 'noreply@example.com' })\n }\n }\n }\n\n return plan\n}\n\n/**\n * 构建运行期环境变量并规划 sidecar。\n *\n * 合并顺序(后者覆盖前者):框架默认 < sidecar 自建 < Provisioner 输出。\n * @param appDir - 应用根目录\n * @param projectName - 项目名\n * @param scan - 扫描结果\n * @param provisionEnv - Provisioner 输出环境变量\n * @param containerPort - 容器内监听端口\n * @returns 运行期环境与 sidecar 规划\n * @param options - 本次操作选项;字段含义见各子项。\n * @param appEnv - 已加载的应用变量,和云开通结果分别传入。\n * @param s3Engine - 自建 S3 服务实现;协议仍为 s3,默认 rustfs。\n * @example 模块内部上下文\n * ```ts\n * const { scanApp } = await import('../deploy-scanner.js')\n * const scanned = await scanApp(process.cwd())\n * if (!scanned.success) throw new Error(scanned.error.message)\n * const plan = buildRuntimeEnv(process.cwd(), 'shop', scanned.data, {}, 3000, { environment: 'prod' }, { NODE_ENV: 'production' })\n * const text = serializeEnvFile(plan.env)\n * ```\n */\nexport function buildRuntimeEnv(\n appDir: string,\n projectName: string,\n scan: ScanResult,\n provisionEnv: Record<string, string>,\n containerPort: number,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n s3Engine: 'rustfs' | 'minio' = 'rustfs',\n): RuntimeEnvPlan {\n const sidecar = planSidecars(appDir, projectName, scan, provisionEnv, options, s3Engine)\n const env: Record<string, string> = {\n NODE_ENV: 'production',\n HOST: '0.0.0.0',\n PORT: String(containerPort),\n HAI_SERV_SERVER_HOST: '0.0.0.0',\n HAI_SERV_SERVER_PORT: String(containerPort),\n ...appEnv,\n ...sidecar.env,\n ...provisionEnv,\n }\n return { env, sidecar }\n}\n\n/**\n * 生成 compose 文件内容。\n * @param options - 生成参数\n * @param options.projectName - 项目名\n * @param options.imageRef - 应用镜像引用\n * @param options.appVersion - 应用发布版本,例如 1.2.3;不改变持久化卷身份\n * @param options.hostPort - 宿主机映射端口\n * @param options.containerPort - 容器内端口\n * @param options.sidecar - sidecar 规划\n * @param options.web - 同一编排中的 Web 镜像与监听端口,独立于私有应用环境\n * @param options.web.imageRef - Web 镜像引用\n * @param options.web.containerPort - Web 容器监听端口\n * @returns compose YAML 字符串\n * @example 模块内部上下文\n * ```ts\n * const sidecar: SidecarPlan = { services: [], composeServices: {}, volumes: {}, appVolumes: [], env: {}, dependsOn: [], secrets: [] }\n * const yaml = generateComposeFile({ projectName: 'shop', appVersion: '1.0.0', imageRef: 'shop:1.0.0-build1', hostPort: 8080, containerPort: 3000, sidecar })\n * ```\n */\nexport function generateComposeFile(options: {\n projectName: string\n appVersion: string\n imageRef: string\n hostPort: number\n containerPort: number\n sidecar: SidecarPlan\n /** Web 公开入口;私有运行环境仅属于 API 服务。 */\n web?: { imageRef: string, containerPort: number }\n}): string {\n const { projectName, imageRef, hostPort, containerPort, sidecar } = options\n\n const app: ComposeService = {\n image: imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-app`,\n restart: 'unless-stopped',\n // 镜像已由 load 注入本地,禁止 compose 再从 registry 拉取\n pull_policy: 'never',\n env_file: ['.env.runtime'],\n ports: [`${hostPort}:${containerPort}`],\n networks: ['hai-app'],\n }\n if (sidecar.appVolumes.length > 0)\n app.volumes = sidecar.appVolumes\n if (sidecar.dependsOn.length > 0)\n app.depends_on = sidecar.dependsOn\n\n const services: Record<string, ComposeService> = { app, ...sidecar.composeServices }\n if (options.web) {\n delete app.ports\n services.web = {\n image: options.web.imageRef,\n labels: { 'org.opencontainers.image.version': options.appVersion },\n container_name: `hai-${projectName}-web`,\n restart: 'unless-stopped',\n pull_policy: 'never',\n ports: [`${hostPort}:${options.web.containerPort}`],\n environment: { PUBLIC_API_BASE: '' },\n healthcheck: { test: ['CMD', 'wget', '-Y', 'off', '-q', '-O', '/dev/null', `http://127.0.0.1:${options.web.containerPort}/_hai/web-health`], interval: '30s', timeout: '5s', retries: 3 },\n volumes: ['./web.conf:/etc/nginx/conf.d/default.conf:ro'],\n depends_on: ['app'],\n networks: ['hai-app'],\n }\n }\n if (services['storage-init'])\n services['storage-init'] = { ...services['storage-init'], image: imageRef }\n const compose: Record<string, unknown> = {\n 'x-hai-version': options.appVersion,\n services,\n 'networks': {\n 'hai-app': { name: `hai-${projectName}` },\n },\n }\n if (Object.keys(sidecar.volumes).length > 0)\n compose.volumes = sidecar.volumes\n\n // S3 服务启动不等于桶已创建;初始化失败必须阻止应用启动,不能只依靠 HTTP 健康检查。\n if (services['storage-init']) {\n app.depends_on = {\n ...Object.fromEntries((app.depends_on as string[] | undefined ?? []).map(name => [name, { condition: 'service_started' }])),\n 'storage-init': { condition: 'service_completed_successfully' },\n }\n }\n\n for (const service of Object.values(services))\n service.pull_policy = 'never'\n return stringify(compose)\n}\n\n/**\n * 生成同源 Web/API 的 Nginx 配置,保留运行时配置及 SPA 页面刷新。\n * API 上限与 @h-ai/crypto 的 TRANSPORT_BODY_LIMITS.encryptedPayloadBytes(2 MiB + 32 KiB)一致;\n * 关闭请求缓冲,让应用在读取过程中执行握手、公钥和正文的更细预算。\n * @param port - API 容器监听端口\n * @param apiPrefix - 应用实际 API 前缀,不允许向 Nginx 配置注入指令\n * @param webPort - Web 容器监听端口\n * @returns 仅含公开路由的 Nginx 配置\n * @example 模块内部上下文\n * ```ts\n * const nginx = generateWebProxyConfig(3000, '/api', 8080) // Web 将同源 /api 转发至 app 服务。\n * ```\n */\nexport function generateWebProxyConfig(port: number, apiPrefix: string, webPort = 8080): string {\n if (!/^\\/[\\w/-]+$/.test(apiPrefix) || ![port, webPort].every(value => Number.isInteger(value) && value >= 1 && value <= 65535))\n throw new Error('Invalid web proxy target')\n return `server {\n listen ${webPort};\n server_name _;\n root /usr/share/nginx/html;\n large_client_header_buffers 4 32k;\n location / {\n try_files $uri $uri/ /index.html;\n }\n location = /runtime-config.js {\n add_header Cache-Control \"no-store\";\n default_type application/javascript;\n return 200 'globalThis.__HAI_PUBLIC_CONFIG__={apiBase:globalThis.location.origin+\"${apiPrefix}\"};';\n }\n location = /_hai/web-health {\n access_log off;\n return 200 'ok';\n }\n location = /health {\n proxy_pass http://app:${port};\n proxy_set_header Host $http_host;\n }\n location ${apiPrefix.replace(/\\/$/, '')}/ {\n client_max_body_size 2129920;\n proxy_pass http://app:${port};\n proxy_http_version 1.1;\n proxy_set_header Host $http_host;\n proxy_set_header X-Forwarded-Proto $scheme;\n proxy_request_buffering off;\n proxy_buffering off;\n proxy_buffer_size 32k;\n proxy_buffers 8 32k;\n }\n}\n`\n}\n\n/**\n * 将环境变量对象序列化为 .env.runtime 内容(每行 KEY=VALUE)。\n * 编码 dotenv 值,不进行脱敏;含密钥时只能写入受保护的运行环境文件。\n * @param env - 要序列化的运行变量,可能包含秘密。\n * @returns 保留字面量值且正确转义的 dotenv 文本,不进行脱敏。\n * @example 模块内部上下文\n * ```ts\n * const content = serializeEnvFile({ NODE_ENV: 'production', HAI_CORE_NAME: 'Shop app' })\n * ```\n */\nexport function serializeEnvFile(env: Record<string, string>): string {\n return `${Object.entries(env)\n .map(([key, value]) => {\n let literal = value\n if (/[\\s#$'\"]/.test(value)) {\n if (value.startsWith('{') || value.startsWith('['))\n literal = `'${value.replaceAll('\\'', '\\\\u0027')}'`\n else if (!value.includes('\\''))\n literal = `'${value}'`\n else\n literal = JSON.stringify(value).replaceAll('$', '$$')\n }\n return `${key}=${literal}`\n })\n .join('\\n')}\\n`\n}\n","/**\n * @h-ai/deploy — SSH 执行器\n *\n * 基于用户机器已有的 OpenSSH 客户端(ssh / scp)封装远程命令执行与文件上传。\n * 复用 ~/.ssh/config、ssh-agent 与 OpenSSH 证书,避免引入 Node SSH SDK 的密钥兼容问题。\n * 所有调用均以 command + args 数组构造,禁止字符串拼接,防止命令注入。\n * @module deploy-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { SshConfig } from '../deploy-config.js'\nimport type { CommandOptions, CommandResult } from './deploy-command.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\nimport { runCommand } from './deploy-command.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'ssh' })\n\n/**\n * SSH 执行器接口\n * 命令通过远端登录 shell 执行;传入的命令文本必须由受信代码构造。远端副作用与本地 SSH 退出状态分开处理。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport interface SshExecutor {\n /** 在远程主机执行命令(通过远程登录 shell 运行) */\n exec: (remoteCommand: string, options?: Pick<CommandOptions, 'timeoutMs' | 'terminationTimeoutMs' | 'secrets' | 'maxCaptureChars' | 'onOutput'>) => Promise<HaiResult<CommandResult>>\n /** 上传本地文件到远程路径 */\n upload: (localPath: string, remotePath: string) => Promise<HaiResult<void>>\n /** 远程连通性预检(执行 true 命令) */\n ping: () => Promise<HaiResult<void>>\n}\n\n/** 构造 ssh 公共连接选项。 */\nfunction buildConnectOptions(config: SshConfig): string[] {\n const args: string[] = ['-o', 'BatchMode=yes']\n args.push('-o', `ConnectTimeout=${config.connectTimeoutSeconds}`)\n args.push('-o', `StrictHostKeyChecking=${config.strictHostKeyChecking ? 'accept-new' : 'no'}`)\n if (config.knownHostsFile) {\n // OpenSSH 会再次按配置语法解析 -o 的值,路径中的空格须保留内部引号。\n const path = config.knownHostsFile.replaceAll('\\\\', '\\\\\\\\').replaceAll('\"', '\\\\\"')\n args.push('-o', `UserKnownHostsFile=\"${path}\"`)\n }\n if (config.identityFile) {\n args.push('-i', config.identityFile)\n args.push('-o', 'IdentitiesOnly=yes')\n }\n return args\n}\n\n/**\n * 构造 ssh 执行命令的参数数组。\n *\n * remoteCommand 作为单个参数传入,不经过本地 shell 解析,避免本地命令注入。\n * @param config - SSH 连接配置\n * @param remoteCommand - 远程命令字符串\n * @returns 交给本地 ssh 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildSshExecArgs(config, 'true')\n * // 参数供本地无 shell 的 ssh 进程使用;不是可再次拼接进 shell 的字符串。\n * ```\n */\nexport function buildSshExecArgs(config: SshConfig, remoteCommand: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-p',\n String(config.port),\n `${config.username}@${config.host}`,\n remoteCommand,\n ]\n}\n\n/**\n * 构造 scp 上传命令的参数数组。\n * 保留参数数组边界;远端路径只使用内部已校验的部署目录。\n * @param config - SSH 连接配置\n * @param localPath - 本地文件路径\n * @param remotePath - 远程目标路径\n * @returns 交给本地 scp 可执行文件的参数数组。\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const args = buildScpUploadArgs(config, '/workspace/shop/.hai/deploy/shop.tar', '/opt/hai/incoming/shop.tar')\n * ```\n */\nexport function buildScpUploadArgs(config: SshConfig, localPath: string, remotePath: string): string[] {\n return [\n ...buildConnectOptions(config),\n '-P',\n String(config.port),\n localPath,\n `${config.username}@${config.host.includes(':') ? `[${config.host}]` : config.host}:${remotePath}`,\n ]\n}\n\n/**\n * 创建 SSH 执行器。\n * 创建执行器不持有长连接;每次 exec/upload/ping 启动独立受管理本地进程并检查 HaiResult。\n * @param config - SSH 连接配置\n * @returns SSH 执行器实例\n * @example 模块内部上下文\n * ```ts\n * const config: SshConfig = { host: 'deploy.example.net', username: 'deploy', port: 22, strictHostKeyChecking: true, connectTimeoutSeconds: 10 }\n * const ssh = createSshExecutor(config)\n * const connected = await ssh.ping()\n * if (!connected.success) throw new Error(connected.error.message)\n * ```\n */\nexport function createSshExecutor(config: SshConfig): SshExecutor {\n const exec: SshExecutor['exec'] = async (remoteCommand, options) => {\n const result = await runCommand('ssh', buildSshExecArgs(config, remoteCommand), {\n timeoutMs: options?.timeoutMs,\n terminationTimeoutMs: options?.terminationTimeoutMs,\n maxCaptureChars: options?.maxCaptureChars,\n secrets: options?.secrets,\n onOutput: options?.onOutput,\n })\n if (result.success)\n return result\n const state = getDeployCommandState(result.error)\n // 连接客户端退出并不能证明远端进程结束;只增加安全状态,不暴露远程命令原文。\n return err({ ...result.error, suggestion: deployM('deploy_remoteUnknown'), ext: { ...result.error.ext, commandExecution: { ...state, reason: state?.reason ?? 'exit', localTermination: state?.localTermination ?? 'unknown', remoteExecution: 'unknown' } } })\n }\n\n const upload: SshExecutor['upload'] = async (localPath, remotePath) => {\n const args = buildScpUploadArgs(config, localPath, remotePath)\n const result = await runCommand('scp', args, { timeoutMs: 600_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.IMAGE_TRANSFER_FAILED, message: deployM('deploy_imageTransferFailed', { params: { error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n const ping: SshExecutor['ping'] = async () => {\n logger.debug('SSH preflight', { host: config.host, port: config.port })\n const result = await exec('true', { timeoutMs: 20_000 })\n if (!result.success) {\n return err({ ...HaiDeployError.REMOTE_CONNECT_FAILED, message: deployM('deploy_remoteConnectFailed', { params: { host: config.host, error: result.error.message } }), ext: result.error.ext })\n }\n return ok(undefined)\n }\n\n return { exec, upload, ping }\n}\n","/**\n * @h-ai/deploy — docker-ssh 部署 Provider\n *\n * 基于 OCI 镜像 + Docker Compose + SSH 的通用主机部署:消费已有镜像 → tar 打包 → SSH 传输 →\n * 远程 load → compose up → HTTP 健康检查。远程需 SSH、Linux flock/基础工具及 docker/podman + compose。\n * @module deploy-provider-docker-ssh\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n ContainerDeployContext,\n ContainerDeployProvider,\n ContainerRuntime,\n} from '../container/deploy-container-types.js'\nimport type { DeployConfig, DockerSshProviderConfig } from '../deploy-config.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { randomBytes } from 'node:crypto'\nimport { chmodSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { basename, join } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { z } from 'zod'\nimport { createDeploymentBundle } from '../container/deploy-bundle.js'\nimport { maskSecrets } from '../container/deploy-command.js'\nimport {\n buildRuntimeEnv,\n generateComposeFile,\n generateWebProxyConfig,\n serializeEnvFile,\n} from '../container/deploy-container-compose.js'\nimport { shellArgument } from '../container/deploy-scripts.js'\nimport { createSshExecutor } from '../container/deploy-ssh.js'\nimport { loadDeploymentConfig, loadDeploymentEnvironment, saveDeploymentEnvironment } from '../deploy-environment.js'\nimport { resolveProjectDirectory } from '../deploy-functions.js'\nimport { deployM } from '../deploy-i18n.js'\nimport { getDeployCommandState } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-docker-ssh' })\n\n/** 健康检查轮询间隔(毫秒) */\nconst HEALTH_POLL_INTERVAL = 3000\n\n/** 健康检查最大轮询次数 */\nconst HEALTH_MAX_ATTEMPTS = 40\n\n/** 只接收服务器脚本原子发布的终态;匹配 ID 后才能确认本次执行完成。 */\nconst ServerResultSchema = z.object({\n deploymentId: z.string(),\n stage: z.enum(['preflight', 'images', 'dependencies', 'start', 'health', 'complete']),\n exitCode: z.number().int().min(0).max(255),\n durationSeconds: z.number().int().nonnegative(),\n})\n\n/** 生成不可变部署 ID:`YYYYMMDD-HHmmss-<random>`。 */\nfunction makeDeploymentId(): string {\n const now = new Date()\n const pad = (n: number): string => String(n).padStart(2, '0')\n const stamp = `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}`\n + `-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`\n return `${stamp}-${randomBytes(3).toString('hex')}`\n}\n\n/** 睡眠指定毫秒。 */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/**\n * 创建 docker-ssh 部署 Provider。\n * @param config - docker-ssh Provider 配置\n * @param container - Compose 中间件参数\n * @returns 容器部署 Provider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createDockerSshProvider({ type: 'docker-ssh', remote: { baseDir: '/opt/hai/apps', runtime: 'auto' }, expose: { type: 'port', hostPort: 8080, containerPort: 3000 } })\n * const name = provider.name // 创建本身不连接 SSH;在线发布仍需有效 SSH 配置。\n * ```\n */\nexport function createDockerSshProvider(\n config: DockerSshProviderConfig,\n container?: DeployConfig['container'],\n): ContainerDeployProvider {\n const ssh = config.ssh ? createSshExecutor(config.ssh) : undefined\n const baseDir = config.remote.baseDir\n\n /** 探测远程容器运行时与 compose 可用性。 */\n async function detectRemoteRuntime(): Promise<HaiResult<ContainerRuntime>> {\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const candidates: ContainerRuntime[] = config.remote.runtime === 'auto'\n ? ['podman', 'docker']\n : [config.remote.runtime]\n\n for (const runtime of candidates) {\n const versionResult = await ssh.exec(`${runtime} version`, { timeoutMs: 20_000 })\n if (!versionResult.success)\n continue\n const composeResult = await ssh.exec(`${runtime} compose version`, { timeoutMs: 20_000 })\n if (composeResult.success) {\n logger.info('Remote container runtime detected', { runtime })\n return ok(runtime)\n }\n }\n return err(\n HaiDeployError.REMOTE_COMMAND_FAILED,\n deployM('deploy_remoteRuntimeMissing', { params: { runtime: candidates.join(' / ') } }),\n )\n }\n\n /** HTTP 健康检查:轮询访问地址直到返回成功。 */\n async function healthCheck(url: string): Promise<boolean> {\n for (let attempt = 0; attempt < HEALTH_MAX_ATTEMPTS; attempt++) {\n try {\n const response = await fetch(url, { signal: AbortSignal.timeout(5000) })\n if (response.ok)\n return true\n }\n catch {\n // 未就绪,继续轮询\n }\n await sleep(HEALTH_POLL_INTERVAL)\n }\n return false\n }\n\n const deploy = async (context: ContainerDeployContext): Promise<HaiResult<DeployResult>> => {\n const { appDir, projectName, scan, provisionEnv, appEnv, options } = context\n const deploymentId = makeDeploymentId()\n const hostPort = config.expose.hostPort\n const artifactDir = join(resolveProjectDirectory(appDir), '.hai', 'deploy', options?.environment ?? 'prod')\n mkdirSync(artifactDir, { recursive: true, mode: 0o700 })\n chmodSync(artifactDir, 0o700)\n const artifact = context.artifact\n const resolvedBuildDir = context.artifactDir\n const images = artifact.images\n const web = images.find(image => image.name === 'web')\n const app = images.find(image => image.name === 'app')\n if (options?.selectedServices) {\n const available: string[] = [...images.map(image => image.name), ...scan.requiredServices]\n const invalid = options.selectedServices.find(name => !available.includes(name))\n if (!options.selectedServices.length || new Set(options.selectedServices).size !== options.selectedServices.length || invalid)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: invalid ?? options.selectedServices.join(', ') } }))\n }\n const hasWeb = artifact.hasWeb || !!web\n const partial = artifact.partial || options?.selectedServices !== undefined\n const containerPort = app?.containerPort ?? artifact.appContainerPort ?? config.expose.containerPort\n const webContainerPort = web?.containerPort ?? artifact.webContainerPort ?? 8080\n const host = config.ssh?.host\n const url = host ? `http://${host.includes(':') ? `[${host}]` : host}:${hostPort}` : `http://SERVER_HOST:${hostPort}`\n\n // 先保存开通结果和 sidecar 凭据,传输失败后仍可检查与复用配置。\n const { env, sidecar } = buildRuntimeEnv(appDir, projectName, scan, provisionEnv, containerPort, options, appEnv, container?.s3Engine)\n if (sidecar.composeServices['storage-init'] && !app && options?.selectedServices?.includes('storage'))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_storageArtifactRequired'))\n let webProxy: string | undefined\n if (hasWeb) {\n // 路由取当前服务的真实配置,不扫描相邻应用或猜测 fullstack 布局。\n const server = loadDeploymentConfig('serv', join(appDir, 'config', '_serv.yml'), env)\n if (!server.success)\n return server\n const http = server.data.http as { apiPrefix?: string } | undefined\n const cors = server.data.cors as { origin?: string } | undefined\n const apiPrefix = http?.apiPrefix ?? '/api/v1'\n if (typeof apiPrefix !== 'string' || !/^\\/[\\w/-]+$/.test(apiPrefix))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_webProxyInvalid'))\n webProxy = generateWebProxyConfig(containerPort, apiPrefix, webContainerPort)\n // 每次从当前配置生成,避免上次运行环境里的父对象遮蔽新修改;保留明确 Origin。\n env.HAI_SERV = JSON.stringify({ ...server.data, cors: { ...cors, origin: (!cors?.origin || cors.origin === '*') && config.ssh ? url : cors?.origin ?? '*' } })\n }\n const envPath = join(artifactDir, '.env.runtime')\n writeFileSync(envPath, serializeEnvFile(env), { mode: 0o600 })\n if (options?.environment) {\n const environment = loadDeploymentEnvironment({ environment: options.environment, envDir: options.envDir ?? scan.envDir ?? appDir })\n if (!environment.success)\n return environment\n const saved = saveDeploymentEnvironment(environment.data, { HAI_DEPLOY_ENVIRONMENT: environment.data.environment, HAI_CORE_ENV: environment.data.values.HAI_CORE_ENV, ...sidecar.env, ...provisionEnv })\n if (!saved.success)\n return saved\n }\n\n const composeName = `docker-compose-${artifact.appVersion}.yml`\n const composeContent = generateComposeFile({\n projectName,\n appVersion: artifact.appVersion,\n imageRef: app?.imageRef ?? 'localhost/hai-unselected:0',\n hostPort,\n containerPort,\n sidecar,\n web: hasWeb ? { imageRef: web?.imageRef ?? 'localhost/hai-unselected:0', containerPort: webContainerPort } : undefined,\n })\n const composePath = join(artifactDir, composeName)\n writeFileSync(composePath, composeContent)\n if (webProxy)\n writeFileSync(join(artifactDir, 'web.conf'), webProxy)\n const selected = options?.selectedServices ? [...options.selectedServices] : artifact.partial ? images.map(image => image.name) : [...images.map(image => image.name), ...Object.keys(sidecar.composeServices)]\n if (!selected.length || selected.some(name => !/^[a-z][a-z0-9-]*$/.test(name)) || new Set(selected).size !== selected.length)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: selected.join(', ') } }))\n for (const name of selected) {\n if (['app', 'web'].includes(name) && !images.some(image => image.name === name))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectionInvalid', { params: { service: name } }))\n }\n if (selected.includes('storage') && sidecar.composeServices['storage-init'] && !selected.includes('storage-init'))\n selected.push('storage-init')\n options?.onProgress?.('packaging')\n const bundle = await createDeploymentBundle({\n directory: artifactDir,\n artifactDir: resolvedBuildDir,\n artifact,\n projectName,\n environment: options?.environment ?? 'prod',\n deploymentId,\n config,\n runtime: options?.runtime ?? 'auto',\n selected,\n partial,\n hasWeb,\n containerPort,\n middlewareEnv: serializeEnvFile(sidecar.env),\n healthPaths: hasWeb ? ['/health', '/_hai/web-health', '/'] : [scan.isSvelteKit ? '/' : '/health'],\n output: options?.output ?? join(artifactDir, `bundle-${projectName}-${deploymentId}-${artifact.appVersion}.tar`),\n })\n if (options?.bundleOnly)\n return ok({ url: '', deploymentId, status: 'packaged', provider: 'docker-ssh', healthCheck: 'skipped', envVarsSet: Object.keys(env), ...bundle })\n if (!ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n const ping = await ssh.ping()\n if (!ping.success)\n return ping\n const remoteRuntime = await detectRemoteRuntime()\n if (!remoteRuntime.success)\n return remoteRuntime\n const remoteDir = `${baseDir}/${projectName}`\n const remoteTar = `${remoteDir}/incoming/${basename(bundle.bundlePath)}`\n const prepared = await ssh.exec(`mkdir -p -- ${shellArgument(`${remoteDir}/incoming`)} && chmod 700 -- ${shellArgument(remoteDir)} ${shellArgument(`${remoteDir}/incoming`)}`)\n if (!prepared.success)\n return prepared\n const uploaded = await ssh.upload(bundle.bundlePath, remoteTar)\n if (!uploaded.success)\n return uploaded\n let pendingOutput = ''\n const started = await ssh.exec(\n `mkdir -p ${shellArgument(`${remoteTar}.contents`)} && chmod 600 ${shellArgument(remoteTar)} && tar -xf ${shellArgument(remoteTar)} -C ${shellArgument(`${remoteTar}.contents`)} && sh ${shellArgument(`${remoteTar}.contents/${bundle.startName}`)} ${shellArgument(remoteDir)}`,\n { timeoutMs: 600_000, secrets: sidecar.secrets, onOutput: (output) => {\n const parts = output.split('\\n')\n for (let index = 0; index < parts.length; index++) {\n // 进度仅解析行首标签,不保留无限长的构建日志行。\n pendingOutput += parts[index]!.slice(0, 512 - pendingOutput.length)\n if (index === parts.length - 1)\n break\n const line = pendingOutput\n pendingOutput = ''\n const stage = /^\\[(preflight|images|dependencies|start|health|complete)\\]/.exec(line)?.[1]\n if (stage)\n options?.onProgress?.(stage as 'preflight' | 'images' | 'dependencies' | 'start' | 'health' | 'complete')\n }\n } },\n )\n if (!started.success) {\n const resultFile = `${remoteDir}/result-${deploymentId}.json`\n const state = getDeployCommandState(started.error)\n // 独立连接只读核对,绝不因超时自动再运行 apply 或无条件恢复容器。\n const checked = await ssh.exec(`if [ -f ${shellArgument(resultFile)} ]; then cat -- ${shellArgument(resultFile)}; fi`, { timeoutMs: 20_000, maxCaptureChars: 8192 })\n let terminal: z.infer<typeof ServerResultSchema> | undefined\n if (checked.success && !checked.data.stdoutTruncated) {\n try {\n const parsed = ServerResultSchema.safeParse(JSON.parse(checked.data.stdout))\n if (parsed.success && parsed.data.deploymentId === deploymentId)\n terminal = parsed.data\n }\n catch {\n // 缺失、损坏、超限或不匹配的记录都不能证明远端已停止。\n }\n }\n return err({ ...started.error, message: `${started.error.message}\\n${terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown')}`, suggestion: terminal ? deployM('deploy_remoteFinished', { params: { stage: terminal.stage, code: String(terminal.exitCode) } }) : deployM('deploy_remoteUnknown'), ext: { ...started.error.ext, commandExecution: {\n ...state,\n reason: state?.reason ?? 'exit',\n localTermination: state?.localTermination ?? 'unknown',\n remoteExecution: terminal ? 'finished' : 'unknown',\n deploymentId,\n resultFile,\n ...(terminal ? { remoteExitCode: terminal.exitCode, remoteStage: terminal.stage } : {}),\n } } })\n }\n\n // 在线部署完成后检查实际公开入口。\n logger.info('Running health check', { url })\n const healthy = await healthCheck(`${url}${!hasWeb && scan.isSvelteKit ? '/' : '/health'}`)\n && (!hasWeb || (await healthCheck(`${url}/_hai/web-health`) && await healthCheck(`${url}/`)))\n if (!healthy) {\n return err(\n HaiDeployError.HEALTH_CHECK_FAILED,\n deployM('deploy_healthCheckFailed', { params: { url } }),\n )\n }\n\n const result: DeployResult = {\n url,\n deploymentId,\n status: 'ready',\n provider: 'docker-ssh',\n healthCheck: 'passed',\n envVarsSet: Object.keys(env),\n bundlePath: bundle.bundlePath,\n }\n logger.info('docker-ssh deployment complete', { url, deploymentId })\n return ok(result)\n }\n\n const deploySafely: ContainerDeployProvider['deploy'] = async (context) => {\n try {\n return await deploy(context)\n }\n catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n let safeReason = 'Deployment bundle failed'\n try {\n safeReason = maskSecrets(reason, Object.values(context.appEnv ?? {}).filter(Boolean))\n }\n catch {\n // 脱敏配置无效时保留固定诊断,不重新暴露原异常。\n }\n logger.error('Deployment bundle failed', { reason: safeReason })\n return err(HaiDeployError.DEPLOY_FAILED, deployM('deploy_bundleFailed', { params: { reason: safeReason } }))\n }\n }\n return { name: 'docker-ssh', deploy: deploySafely }\n}\n","/**\n * @h-ai/deploy — Vercel 部署 Provider\n *\n * 封装 Vercel REST API,实现 DeployProvider 接口。 使用原生 fetch 调用,零外部 SDK 依赖。\n * @module deploy-provider-vercel\n */\n\nimport type { HaiError, HaiErrorDef, HaiResult } from '@h-ai/core'\nimport type { DeployProvider } from '../deploy-internal-types.js'\nimport type { DeployResult } from '../deploy-types.js'\nimport { createHash } from 'node:crypto'\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provider-vercel' })\n\n/** Vercel API 基址 */\nconst VERCEL_API = 'https://api.vercel.com'\n\n/** 部署状态轮询间隔(毫秒) */\nconst POLL_INTERVAL = 3000\n\n/** 部署状态轮询最大次数 */\nconst MAX_POLL_ATTEMPTS = 60\n\n// ─── 内部工具 ───\n\n/** Vercel API 错误,保留状态码用于区分 404 与真实失败 */\nclass VercelApiError extends Error {\n constructor(readonly status: number) {\n super(deployM('deploy_apiError', { params: { service: 'Vercel', status: String(status) } }))\n }\n}\n\n/** 构造标准错误对象 */\nfunction toDeployError(codeDef: HaiErrorDef, messageKey: string, error: unknown): HaiError {\n return {\n ...codeDef,\n message: deployM(messageKey as Parameters<typeof deployM>[0], {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n cause: error,\n }\n}\n\n/**\n * 发送 Vercel API 请求\n *\n * @param token - API Token\n * @param path - API 路径(如 /v2/user)\n * @param options - fetch 选项\n * @returns 解析后的 JSON 响应\n */\nasync function vercelFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const url = `${VERCEL_API}${path}`\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new VercelApiError(response.status)\n }\n\n return response.json() as Promise<T>\n}\n\n/**\n * 递归收集目录中的所有文件\n *\n * @param dir - 目录路径\n * @param baseDir - 基础目录(用于计算相对路径)\n * @returns 文件相对路径列表\n */\nfunction collectFiles(dir: string, baseDir: string): string[] {\n const results: string[] = []\n const entries = readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory()) {\n results.push(...collectFiles(fullPath, baseDir))\n }\n else {\n results.push(relative(baseDir, fullPath).split(sep).join('/'))\n }\n }\n\n return results\n}\n\n// ─── Provider 工厂 ───\n\n/**\n * 创建 Vercel 部署 Provider\n * @returns DeployProvider 实例\n * @example 模块内部上下文\n * ```ts\n * const provider = createVercelProvider()\n * const token = process.env.HAI_DEPLOY_PROVIDER_TOKEN\n * if (!token) throw new Error('Provide HAI_DEPLOY_PROVIDER_TOKEN privately')\n * const result = await provider.authenticate(token)\n * if (!result.success) throw new Error(result.error.message)\n * ```\n */\nexport function createVercelProvider(): DeployProvider {\n let token: string | null = null\n\n return {\n name: 'vercel',\n\n async authenticate(apiToken: string): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Vercel')\n try {\n const user = await vercelFetch<{ user: { username: string, email: string } }>(\n apiToken,\n '/v2/user',\n )\n token = apiToken\n const username = user.user.username || user.user.email\n logger.info('Vercel authenticated', { user: username })\n return ok(username)\n }\n catch (error) {\n logger.error('Vercel authentication failed', { error })\n return err(toDeployError(HaiDeployError.AUTH_FAILED, 'deploy_authFailed', error))\n }\n },\n\n async createProject(projectName: string): Promise<HaiResult<string>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Creating Vercel project', { projectName })\n try {\n // 先查找已有项目\n const existingId = await findExistingProject(token, projectName)\n if (existingId !== null) {\n logger.info('Vercel project found', { projectName, projectId: existingId })\n return ok(existingId)\n }\n\n try {\n const project = await vercelFetch<{ id: string }>(\n token,\n '/v11/projects',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectName,\n framework: 'sveltekit',\n }),\n },\n )\n logger.info('Vercel project created', { projectName, projectId: project.id })\n return ok(project.id)\n }\n catch (error) {\n // 官方文档说明同名项目创建会返回 409;遇到并发竞争时回查现有项目即可实现幂等。\n if (error instanceof VercelApiError && error.status === 409) {\n const concurrentProjectId = await findExistingProject(token, projectName)\n if (concurrentProjectId !== null) {\n logger.info('Vercel project reused after create conflict', {\n projectName,\n projectId: concurrentProjectId,\n })\n return ok(concurrentProjectId)\n }\n }\n throw error\n }\n }\n catch (error) {\n logger.error('Vercel project creation failed', { projectName, error })\n return err(toDeployError(HaiDeployError.PROJECT_CREATE_FAILED, 'deploy_projectCreateFailed', error))\n }\n },\n\n async setEnvVars(projectId: string, envVars: Record<string, string>): Promise<HaiResult<void>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Setting Vercel env vars', { projectId, count: Object.keys(envVars).length })\n try {\n const envEntries = Object.entries(envVars).map(([key, value]) => ({\n key,\n value,\n type: 'encrypted' as const,\n target: ['production', 'preview', 'development'],\n }))\n\n // Vercel 官方 `upsert=true` 支持按 key 覆盖已有环境变量,避免重复部署时报“已存在”。\n await vercelFetch(\n token,\n `/v10/projects/${projectId}/env?upsert=true`,\n {\n method: 'POST',\n body: JSON.stringify(envEntries),\n },\n )\n logger.info('Vercel env vars set', { projectId, count: envEntries.length })\n return ok(undefined)\n }\n catch (error) {\n logger.error('Vercel env vars setup failed', { projectId, error })\n return err(toDeployError(HaiDeployError.ENV_VAR_FAILED, 'deploy_envVarFailed', error))\n }\n },\n\n async deploy(projectId: string, outputDir: string): Promise<HaiResult<DeployResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Deploying to Vercel', { projectId, outputDir })\n try {\n // 只接受 Build Output API v3;不把普通源码交给平台重新构建。\n const outputConfig = JSON.parse(readFileSync(join(outputDir, 'config.json'), 'utf8')) as { version?: unknown }\n if (outputConfig.version !== 3)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n // 收集所有文件\n const filePaths = collectFiles(outputDir, outputDir)\n const files: Array<{ file: string, sha: string, size: number }> = []\n\n // 上传每个文件\n for (const filePath of filePaths) {\n const fullPath = join(outputDir, filePath)\n const content = readFileSync(fullPath)\n const sha = createHash('sha1').update(content).digest('hex')\n const size = statSync(fullPath).size\n\n await uploadFile(token, content, sha)\n files.push({ file: `.vercel/output/${filePath}`, sha, size })\n }\n\n logger.debug('Files uploaded', { count: files.length })\n\n // 创建部署\n const deployment = await vercelFetch<{ id: string, url: string }>(\n token,\n '/v13/deployments?prebuilt=1',\n {\n method: 'POST',\n body: JSON.stringify({\n name: projectId,\n files,\n version: 2,\n project: projectId,\n projectSettings: { framework: null, buildCommand: '', installCommand: '' },\n }),\n },\n )\n\n // 轮询部署状态\n const finalStatus = await pollDeploymentStatus(token, deployment.id)\n\n const result: DeployResult = {\n url: `https://${deployment.url}`,\n deploymentId: deployment.id,\n status: finalStatus,\n envVarsSet: [],\n }\n\n logger.info('Vercel deployment complete', {\n deploymentId: deployment.id,\n url: result.url,\n status: finalStatus,\n })\n\n return ok(result)\n }\n catch (error) {\n logger.error('Vercel deployment failed', { projectId, error })\n return err(toDeployError(HaiDeployError.UPLOAD_FAILED, 'deploy_uploadFailed', error))\n }\n },\n }\n}\n\n// ─── 内部辅助 ───\n\n/**\n * 查找已有的 Vercel 项目\n *\n * @param token - API Token\n * @param projectName - 项目名称\n * @returns 项目 ID,不存在时返回 null\n */\nasync function findExistingProject(token: string, projectName: string): Promise<string | null> {\n try {\n const project = await vercelFetch<{ id: string }>(token, `/v10/projects/${projectName}`)\n return project.id\n }\n catch (error) {\n if (error instanceof VercelApiError && error.status === 404) {\n return null\n }\n throw error\n }\n}\n\n/**\n * 上传单个文件到 Vercel\n *\n * @param token - API Token\n * @param content - 文件内容\n * @param sha - 文件 SHA1 哈希\n */\nasync function uploadFile(token: string, content: Uint8Array, sha: string): Promise<void> {\n const url = `${VERCEL_API}/v2/files`\n const uploadContent = new Uint8Array(content)\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/octet-stream',\n 'x-vercel-digest': sha,\n },\n body: new Blob([uploadContent]),\n })\n\n if (!response.ok && response.status !== 409) {\n // 409 表示文件已存在,可忽略\n throw new Error(deployM('deploy_fileUploadFailed', { params: { status: String(response.status) } }))\n }\n}\n\n/**\n * 轮询部署状态直到完成\n *\n * @param token - API Token\n * @param deploymentId - 部署 ID\n * @returns 最终状态\n */\nasync function pollDeploymentStatus(\n token: string,\n deploymentId: string,\n): Promise<'ready' | 'building' | 'error'> {\n for (let i = 0; i < MAX_POLL_ATTEMPTS; i++) {\n const deployment = await vercelFetch<{ readyState: string }>(\n token,\n `/v13/deployments/${deploymentId}`,\n )\n\n if (deployment.readyState === 'READY') {\n return 'ready'\n }\n if (deployment.readyState === 'ERROR' || deployment.readyState === 'CANCELED') {\n return 'error'\n }\n\n // 等待后重试\n await new Promise(resolve => setTimeout(resolve, POLL_INTERVAL))\n }\n\n // 超时仍在构建\n return 'building'\n}\n","/**\n * @h-ai/deploy — Aliyun SMS Provisioner\n *\n * 验证阿里云 API 凭证用于短信服务。 阿里云短信资源(签名/模板)通常在控制台预配置,此 Provisioner 仅验证凭证。\n * @module deploy-provisioner-aliyun\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-aliyun' })\n\n/**\n * 创建 Aliyun SMS Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYID privately')\n * const accessKeySecret = process.env.HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET\n * if (!accessKeySecret) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_ACCESSKEYSECRET privately')\n * const signName = process.env.HAI_DEPLOY_SERVICES_SMS_SIGNNAME\n * if (!signName) throw new Error('Provide HAI_DEPLOY_SERVICES_SMS_SIGNNAME privately')\n * const provisioner = createAliyunProvisioner()\n * const authenticated = await provisioner.authenticate({ accessKeyId, accessKeySecret, signName })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createAliyunProvisioner(): ServiceProvisioner {\n let accessKey: string | null = null\n let secretKey: string | null = null\n let signName = ''\n\n return {\n name: 'aliyun',\n serviceType: 'sms',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Aliyun')\n try {\n const akId = credentials.accessKeyId ?? credentials.access_key_id ?? credentials.access_key ?? ''\n const akSecret = credentials.accessKeySecret ?? credentials.access_key_secret ?? credentials.secret_key ?? ''\n\n if (!akId || !akSecret || !credentials.signName) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accessKeyId, accessKeySecret, signName' } }))\n }\n\n accessKey = akId\n secretKey = akSecret\n signName = credentials.signName\n logger.info('Aliyun authenticated', { accessKeyId: `${akId.slice(0, 6)}***` })\n return ok(akId)\n }\n catch (error) {\n logger.error('Aliyun authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!accessKey || !secretKey) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Aliyun SMS service')\n\n // 阿里云短信不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'sms',\n provisionerName: 'aliyun',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'sms', type: 'aliyun-sms', accessKeyId: accessKey, accessKeySecret: secretKey, signName }]),\n },\n resourceInfo: 'aliyun:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Neon PostgreSQL Provisioner\n *\n * 通过 Neon REST API 自动创建 PostgreSQL 数据库。\n * @module deploy-provisioner-neon\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-neon' })\n\n/** Neon API 基址 */\nconst NEON_API = 'https://console.neon.tech/api/v2'\n\n/** Neon 新建项目默认生成的数据库名。 */\nconst DEFAULT_NEON_DATABASE_NAME = 'neondb'\n\n/** Neon 新建项目默认生成的角色名。 */\nconst DEFAULT_NEON_ROLE_NAME = 'neondb_owner'\n\n/**\n * Neon 列表中用于按名称核对现有资源的字段。\n * @example 模块内部上下文\n * ```ts\n * const project: NeonProjectSummary = { id: 'project-shop', name: 'shop' }\n * ```\n */\ninterface NeonProjectSummary {\n id: string\n name: string\n}\n\n/**\n * 列表字段可缺失;调用方不能将请求失败解释为资源不存在。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonProjectsResponse = { projects: [{ id: 'project-shop', name: 'shop' }] }\n * const existing = response.projects?.find(project => project.name === 'shop')\n * ```\n */\ninterface NeonProjectsResponse {\n projects?: NeonProjectSummary[]\n}\n\n/**\n * 创建回执的可选形状;连接 URI 可能包含口令,不得输出。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonCreateProjectResponse = { project: { id: 'project-shop' } }\n * const id = response.project?.id // 无连接 URI 时再按已确认 ID 读取,不能重新创建。\n * ```\n */\ninterface NeonCreateProjectResponse {\n connection_uris?: Array<{ connection_uri?: string }>\n project?: { id?: string }\n}\n\n/**\n * 连接读取回执;真实 URI 可能含密码,必须作为私有配置处理。\n * @example 模块内部上下文\n * ```ts\n * const response: NeonConnectionUriResponse = { uri: 'postgresql://app@db.example.org/shop' }\n * const present = Boolean(response.uri)\n * ```\n */\ninterface NeonConnectionUriResponse {\n uri?: string\n}\n\n/** 统一发起 Neon API 请求。 */\nasync function neonFetch<T>(token: string, path: string, options?: RequestInit): Promise<T> {\n const response = await fetch(`${NEON_API}${path}`, {\n ...options,\n headers: {\n 'Accept': 'application/json',\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Neon', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的 Neon 项目。 */\nasync function listNeonProjects(token: string): Promise<NeonProjectSummary[]> {\n const data = await neonFetch<NeonProjectsResponse>(token, '/projects')\n return data.projects ?? []\n}\n\n/** 按名称查找已有的 Neon 项目。 */\nasync function findExistingNeonProject(token: string, projectName: string): Promise<NeonProjectSummary | null> {\n const projects = await listNeonProjects(token)\n return projects.find(project => project.name === projectName) ?? null\n}\n\n/**\n * 获取现有项目的连接串。\n *\n * Neon 官方 OpenAPI 提供 `GET /projects/{project_id}/connection_uri`。\n * 这里使用创建项目时的默认数据库/角色名,保证本模块创建的项目可被幂等复用。\n */\nasync function getNeonConnectionUri(token: string, projectId: string): Promise<string> {\n const query = new URLSearchParams({\n database_name: DEFAULT_NEON_DATABASE_NAME,\n role_name: DEFAULT_NEON_ROLE_NAME,\n })\n const data = await neonFetch<NeonConnectionUriResponse>(\n token,\n `/projects/${projectId}/connection_uri?${query.toString()}`,\n { headers: { 'Content-Type': 'application/json' } },\n )\n\n if (!data.uri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n return data.uri\n}\n\n/** 构建统一的 Neon 开通结果。 */\nfunction buildNeonProvisionResult(projectId: string, connectionUri: string, resourceStatus: 'created' | 'reused'): ProvisionResult {\n return {\n serviceType: 'db',\n provisionerName: 'neon',\n resourceStatus,\n envVars: {\n HAI_DB: JSON.stringify({ type: 'postgresql', url: connectionUri, database: decodeURIComponent(new URL(connectionUri).pathname.slice(1)) }),\n },\n resourceInfo: `neon-project:${projectId}`,\n }\n}\n\n/**\n * 创建 Neon PostgreSQL Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_DB_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_DB_APIKEY privately')\n * const provisioner = createNeonProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createNeonProvisioner(): ServiceProvisioner {\n let token: string | null = null\n\n return {\n name: 'neon',\n serviceType: 'db',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Neon')\n try {\n const apiToken = credentials.apiKey ?? credentials.token ?? credentials.api_key ?? ''\n if (!apiToken) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'token' } }))\n }\n\n await listNeonProjects(apiToken)\n token = apiToken\n logger.info('Neon authenticated')\n return ok('neon-user')\n }\n catch (error) {\n logger.error('Neon authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Neon database', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const projectName = `${appName}-db`\n\n const existingProject = await findExistingNeonProject(token, projectName)\n if (existingProject !== null) {\n resource = { resourceInfo: `neon-project:${existingProject.id}`, resourceStatus: 'reused' }\n const connectionUri = await getNeonConnectionUri(token, existingProject.id)\n logger.info('Neon project reused', {\n projectId: existingProject.id,\n projectName,\n })\n return ok(buildNeonProvisionResult(existingProject.id, connectionUri, 'reused'))\n }\n\n const data = await neonFetch<NeonCreateProjectResponse>(token, '/projects', {\n method: 'POST',\n body: JSON.stringify({\n project: {\n name: projectName,\n pg_version: 16,\n },\n }),\n })\n\n const projectId = data.project?.id ?? ''\n if (projectId)\n resource = { resourceInfo: `neon-project:${projectId}`, resourceStatus: 'created' }\n const connectionUri = data.connection_uris?.[0]?.connection_uri ?? ''\n if (!projectId || !connectionUri) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Neon' } }))\n }\n\n logger.info('Neon database provisioned', { projectId })\n\n return ok(buildNeonProvisionResult(projectId, connectionUri, 'created'))\n }\n catch (error) {\n logger.error('Neon provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:db',\n resources: [{ serviceType: 'db', provisionerName: 'neon', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'neon',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Cloudflare R2 Provisioner\n *\n * 通过 Cloudflare API 自动创建 R2 存储桶。\n * @module deploy-provisioner-r2\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-r2' })\n\n/** Cloudflare API 基址 */\nconst CF_API = 'https://api.cloudflare.com/client/v4'\n\n/**\n * 创建 Cloudflare R2 Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const accountId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID\n * if (!accountId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCOUNTID privately')\n * const apiToken = process.env.HAI_DEPLOY_SERVICES_STORAGE_APITOKEN\n * if (!apiToken) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_APITOKEN privately')\n * const accessKeyId = process.env.HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID\n * if (!accessKeyId) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_ACCESSKEYID privately')\n * const secretAccessKey = process.env.HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY\n * if (!secretAccessKey) throw new Error('Provide HAI_DEPLOY_SERVICES_STORAGE_SECRETACCESSKEY privately')\n * const provisioner = createR2Provisioner()\n * const authenticated = await provisioner.authenticate({ accountId, apiToken, accessKeyId, secretAccessKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createR2Provisioner(): ServiceProvisioner {\n let token: string | null = null\n let accountId: string | null = null\n let accessKey = ''\n let secretKey = ''\n\n return {\n name: 'r2',\n serviceType: 'storage',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Cloudflare')\n try {\n const acctId = credentials.accountId ?? credentials.account_id ?? ''\n const apiTok = credentials.apiToken ?? credentials.api_token ?? credentials.token ?? ''\n if (!acctId || !apiTok || !credentials.accessKeyId || !credentials.secretAccessKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'accountId, apiToken, accessKeyId, secretAccessKey' } }))\n }\n\n const res = await fetch(`${CF_API}/accounts/${acctId}/r2/buckets`, {\n headers: { Authorization: `Bearer ${apiTok}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(res.status) } }))\n }\n\n accountId = acctId\n token = apiTok\n accessKey = credentials.accessKeyId\n secretKey = credentials.secretAccessKey\n logger.info('Cloudflare R2 authenticated', { accountId: acctId })\n return ok(acctId)\n }\n catch (error) {\n logger.error('Cloudflare R2 authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token || !accountId) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n const bucketName = `${appName}-storage`.toLowerCase().replace(/[^a-z0-9-]/g, '-')\n\n logger.debug('Provisioning R2 bucket', { appName, bucketName })\n try {\n // 创建桶\n const createRes = await fetch(\n `${CF_API}/accounts/${accountId}/r2/buckets`,\n {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ name: bucketName }),\n },\n )\n\n // 409 表示桶已存在,可继续\n if (!createRes.ok && createRes.status !== 409) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Cloudflare', status: String(createRes.status) } }))\n }\n\n logger.info('R2 bucket provisioned', { bucketName })\n\n return ok({\n serviceType: 'storage',\n provisionerName: 'r2',\n resourceStatus: createRes.status === 409 ? 'reused' : 'created',\n envVars: {\n HAI_STORAGE: JSON.stringify({\n type: 's3',\n endpoint: `https://${accountId}.r2.cloudflarestorage.com`,\n bucket: bucketName,\n region: 'auto',\n accessKeyId: accessKey,\n secretAccessKey: secretKey,\n }),\n },\n resourceInfo: `r2-bucket:${bucketName}`,\n })\n }\n catch (error) {\n logger.error('R2 provisioning failed', { appName, error })\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'r2',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — Resend Email Provisioner\n *\n * 通过 Resend REST API 验证 API Key 并获取域信息。 Resend 不支持通过 API 创建账户,此 Provisioner 仅验证已有凭证。\n * @module deploy-provisioner-resend\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-resend' })\n\n/** Resend API 基址 */\nconst RESEND_API = 'https://api.resend.com'\n\n/**\n * 创建 Resend Email Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_EMAIL_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_APIKEY privately')\n * const from = process.env.HAI_DEPLOY_SERVICES_EMAIL_FROM\n * if (!from) throw new Error('Provide HAI_DEPLOY_SERVICES_EMAIL_FROM privately')\n * const provisioner = createResendProvisioner()\n * const authenticated = await provisioner.authenticate({ apiKey, from })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createResendProvisioner(): ServiceProvisioner {\n let token: string | null = null\n let from = ''\n\n return {\n name: 'resend',\n serviceType: 'email',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Resend')\n try {\n const apiToken = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!apiToken || !credentials.from) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'apiKey, from' } }))\n }\n\n const res = await fetch(`${RESEND_API}/domains`, {\n headers: { Authorization: `Bearer ${apiToken}` },\n })\n if (!res.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Resend', status: String(res.status) } }))\n }\n token = apiToken\n from = credentials.from\n logger.info('Resend authenticated')\n return ok('resend-user')\n }\n catch (error) {\n logger.error('Resend authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(_appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!token) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Resend email service')\n\n // Resend 不支持 API 创建资源,仅返回凭证作为环境变量\n return ok({\n serviceType: 'email',\n provisionerName: 'resend',\n resourceStatus: 'reused',\n envVars: {\n HAI_REACH_PROVIDERS: JSON.stringify([{ name: 'email', type: 'smtp', host: 'smtp.resend.com', port: 465, secure: true, user: 'resend', pass: token, from }]),\n },\n resourceInfo: 'resend:verify-only',\n })\n },\n }\n}\n","/**\n * @h-ai/deploy — Upstash Redis Provisioner\n *\n * 通过 Upstash REST API 自动创建 Redis 数据库。\n * @module deploy-provisioner-upstash\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ServiceProvisioner } from '../deploy-internal-types.js'\nimport type { ProvisionResult } from '../deploy-types.js'\nimport { Buffer } from 'node:buffer'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { deployM } from '../deploy-i18n.js'\nimport { recoveryFailure } from '../deploy-recovery.js'\nimport { HaiDeployError } from '../deploy-types.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'provisioner-upstash' })\n\n/** Upstash API 基址 */\nconst UPSTASH_API = 'https://api.upstash.com'\n\n/**\n * 供应商 API 的部分字段形状;缺少连接凭据时不能声称已有连接可用。\n * @example 模块内部上下文\n * ```ts\n * const database: UpstashDatabase = { database_id: 'redis-shop', database_name: 'shop', endpoint: 'redis.example.org', port: 6379 }\n * const id = database.database_id\n * ```\n */\ninterface UpstashDatabase {\n database_id?: string\n database_name?: string\n endpoint?: string\n port?: number\n password?: string\n}\n\n/** 构建 Upstash Developer API 的 Basic Auth 请求头。 */\nfunction createUpstashAuthHeader(email: string, apiKey: string): string {\n return `Basic ${Buffer.from(`${email}:${apiKey}`).toString('base64')}`\n}\n\n/** 统一发起 Upstash Developer API 请求。 */\nasync function upstashFetch<T>(\n email: string,\n apiKey: string,\n path: string,\n options?: RequestInit,\n): Promise<T> {\n const response = await fetch(`${UPSTASH_API}${path}`, {\n ...options,\n headers: {\n 'Authorization': createUpstashAuthHeader(email, apiKey),\n 'Content-Type': 'application/json',\n ...options?.headers,\n },\n })\n\n if (!response.ok) {\n throw new Error(deployM('deploy_apiError', { params: { service: 'Upstash', status: String(response.status) } }))\n }\n\n return response.json() as Promise<T>\n}\n\n/** 列出当前账号下的所有 Upstash 数据库。 */\nasync function listUpstashDatabases(email: string, apiKey: string): Promise<UpstashDatabase[]> {\n return upstashFetch<UpstashDatabase[]>(email, apiKey, '/v2/redis/databases')\n}\n\n/** 按数据库名查找已有资源。 */\nasync function findExistingUpstashDatabase(\n email: string,\n apiKey: string,\n databaseName: string,\n): Promise<UpstashDatabase | null> {\n const databases = await listUpstashDatabases(email, apiKey)\n return databases.find(database => database.database_name === databaseName) ?? null\n}\n\n/** 获取单个数据库详情。 */\nasync function getUpstashDatabase(email: string, apiKey: string, databaseId: string): Promise<UpstashDatabase> {\n return upstashFetch<UpstashDatabase>(email, apiKey, `/v2/redis/database/${databaseId}`)\n}\n\n/** 将 Upstash 响应转换为 deploy 统一结果。 */\nfunction buildUpstashProvisionResult(database: UpstashDatabase, resourceStatus: 'created' | 'reused'): ProvisionResult {\n const databaseId = database.database_id ?? ''\n\n if (!databaseId || !database.endpoint || !database.password || !database.port) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n return {\n serviceType: 'cache',\n provisionerName: 'upstash',\n resourceStatus,\n envVars: {\n HAI_CACHE: JSON.stringify({ type: 'redis', url: `rediss://default:${encodeURIComponent(database.password)}@${database.endpoint}:${database.port}` }),\n },\n resourceInfo: `upstash-db:${databaseId}`,\n }\n}\n\n/**\n * 创建 Upstash Redis Provisioner\n * 工厂返回内部接口;认证与开通调用必须逐次检查 HaiResult,返回的连接凭据不能直接记录。\n * @returns ServiceProvisioner 实例\n * @example 模块内部上下文\n * ```ts\n * const email = process.env.HAI_DEPLOY_SERVICES_CACHE_EMAIL\n * if (!email) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_EMAIL privately')\n * const apiKey = process.env.HAI_DEPLOY_SERVICES_CACHE_APIKEY\n * if (!apiKey) throw new Error('Provide HAI_DEPLOY_SERVICES_CACHE_APIKEY privately')\n * const provisioner = createUpstashProvisioner()\n * const authenticated = await provisioner.authenticate({ email, apiKey })\n * if (!authenticated.success) throw new Error(authenticated.error.message)\n * const result = await provisioner.provision('shop')\n * if (!result.success) throw new Error(result.error.message)\n * const status = result.data.resourceStatus\n * ```\n */\nexport function createUpstashProvisioner(): ServiceProvisioner {\n let apiKey: string | null = null\n let email: string | null = null\n\n return {\n name: 'upstash',\n serviceType: 'cache',\n\n async authenticate(credentials: Record<string, string>): Promise<HaiResult<string>> {\n logger.debug('Authenticating with Upstash')\n try {\n const userEmail = credentials.email ?? ''\n const userKey = credentials.apiKey ?? credentials.api_key ?? credentials.token ?? ''\n if (!userEmail || !userKey) {\n throw new Error(deployM('deploy_credentialMissing', { params: { fields: 'email, api_key' } }))\n }\n\n await listUpstashDatabases(userEmail, userKey)\n\n email = userEmail\n apiKey = userKey\n logger.info('Upstash authenticated', { email: userEmail })\n return ok(userEmail)\n }\n catch (error) {\n logger.error('Upstash authentication failed', { error })\n return err(\n HaiDeployError.AUTH_FAILED,\n deployM('deploy_authFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n },\n\n async provision(appName: string): Promise<HaiResult<ProvisionResult>> {\n if (!apiKey || !email) {\n return err(\n HaiDeployError.AUTH_REQUIRED,\n deployM('deploy_authRequired'),\n )\n }\n\n logger.debug('Provisioning Upstash Redis', { appName })\n let resource: { resourceInfo: string, resourceStatus: 'created' | 'reused' } | undefined\n try {\n const databaseName = `${appName}-cache`\n\n const existingDatabase = await findExistingUpstashDatabase(email, apiKey, databaseName)\n if (existingDatabase !== null) {\n const databaseId = existingDatabase.database_id ?? ''\n if (!databaseId) {\n throw new Error(deployM('deploy_provisionNoResult', { params: { service: 'Upstash' } }))\n }\n\n resource = { resourceInfo: `upstash-db:${databaseId}`, resourceStatus: 'reused' }\n const detail = await getUpstashDatabase(email, apiKey, databaseId)\n logger.info('Upstash Redis reused', { databaseId, databaseName })\n return ok(buildUpstashProvisionResult({ ...existingDatabase, ...detail }, 'reused'))\n }\n\n const data = await upstashFetch<UpstashDatabase>(email, apiKey, '/v2/redis/database', {\n method: 'POST',\n body: JSON.stringify({\n name: databaseName,\n region: 'global',\n tls: true,\n }),\n })\n\n if (data.database_id)\n resource = { resourceInfo: `upstash-db:${data.database_id}`, resourceStatus: 'created' }\n logger.info('Upstash Redis provisioned', { databaseId: data.database_id })\n\n return ok(buildUpstashProvisionResult(data, 'created'))\n }\n catch (error) {\n logger.error('Upstash provisioning failed', { appName })\n if (resource) {\n return recoveryFailure({ ...HaiDeployError.PROVISION_FAILED, message: '' }, {\n projectName: appName,\n stage: 'provision:cache',\n resources: [{ serviceType: 'cache', provisionerName: 'upstash', ...resource }],\n })\n }\n return err(\n HaiDeployError.PROVISION_FAILED,\n deployM('deploy_provisionFailed', {\n params: {\n service: 'upstash',\n error: error instanceof Error ? error.message : String(error),\n },\n }),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/deploy — 模块主入口\n *\n * 提供 deploy 单例对象,暴露完整的自动化部署 API。\n * @module deploy-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ContainerDeployProvider } from './container/deploy-container-types.js'\nimport type { DeployConfig, DeployConfigInput } from './deploy-config.js'\nimport type { DeployProvider, ServiceProvisioner } from './deploy-internal-types.js'\nimport type {\n DeployAppOptions,\n DeployCredentialOperations,\n DeployFunctions,\n DeployRecoveryInfo,\n DeployResult,\n DeployScanOptions,\n ProvisionResult,\n ScanResult,\n ServiceType,\n} from './deploy-types.js'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { core, err, ok } from '@h-ai/core'\nimport { readDeploymentArtifact } from './deploy-artifact.js'\nimport { DeployConfigSchema } from './deploy-config.js'\nimport {\n getCredentialsPath,\n loadCredentials,\n saveCredential,\n saveCredentials,\n} from './deploy-credentials.js'\nimport { loadDeploymentEnvironment, saveDeploymentEnvironment } from './deploy-environment.js'\nimport { resolveArtifactDirectory, resolveOutputDir, usesDefaultMiddleware } from './deploy-functions.js'\nimport { deployM } from './deploy-i18n.js'\nimport { getDeployRecovery, recoveryFailure } from './deploy-recovery.js'\nimport { scanApp } from './deploy-scanner.js'\nimport { HaiDeployError } from './deploy-types.js'\nimport { createDockerSshProvider } from './providers/deploy-provider-docker-ssh.js'\nimport { createVercelProvider } from './providers/deploy-provider-vercel.js'\nimport { createAliyunProvisioner } from './provisioners/deploy-provisioner-aliyun.js'\nimport { createNeonProvisioner } from './provisioners/deploy-provisioner-neon.js'\nimport { createR2Provisioner } from './provisioners/deploy-provisioner-r2.js'\nimport { createResendProvisioner } from './provisioners/deploy-provisioner-resend.js'\nimport { createUpstashProvisioner } from './provisioners/deploy-provisioner-upstash.js'\n\nconst logger = core.logger.child({ module: 'deploy', scope: 'main' })\n\n// ─── 内部状态 ───\n\nlet currentConfig: DeployConfig | null = null\nlet currentProvider: DeployProvider | null = null\nlet currentContainerProvider: ContainerDeployProvider | null = null\nconst currentProvisioners: Map<ServiceType, ServiceProvisioner> = new Map()\n\n/** 并发初始化防护标志 */\nlet initInProgress = false\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiDeployError.NOT_INITIALIZED,\n () => deployM('deploy_notInitialized'),\n)\n\n// ─── Provider 工厂 ───\n\n/**\n * 根据配置类型创建对应的 DeployProvider\n *\n * @param type - Provider 类型\n * @returns DeployProvider 实例\n */\nfunction createProviderByType(type: string): DeployProvider {\n switch (type) {\n case 'vercel':\n return createVercelProvider()\n default:\n throw new Error(deployM('deploy_unsupportedProviderType', { params: { type } }))\n }\n}\n\n// ─── Provisioner 工厂 ───\n\n/**\n * 根据 provisioner 名称创建对应的 ServiceProvisioner\n *\n * @param provisioner - Provisioner 标识\n * @returns ServiceProvisioner 实例\n */\nfunction createProvisionerByName(provisioner: string): ServiceProvisioner {\n switch (provisioner) {\n case 'neon':\n return createNeonProvisioner()\n case 'upstash':\n return createUpstashProvisioner()\n case 'cloudflare-r2':\n return createR2Provisioner()\n case 'resend':\n return createResendProvisioner()\n case 'aliyun':\n return createAliyunProvisioner()\n default:\n throw new Error(deployM('deploy_unsupportedProvisionerType', { params: { type: provisioner } }))\n }\n}\n\n/**\n * 从配置中提取 provisioner 凭证并转为 Record<string, string>\n *\n * @param serviceConfig - 服务配置对象\n * @returns 凭证键值对\n */\nfunction extractCredentials(serviceConfig: Record<string, unknown>): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(serviceConfig)) {\n if (key !== 'provisioner' && typeof value === 'string') {\n result[key] = value\n }\n }\n return result\n}\n\n/**\n * Deploy 凭证子功能。\n *\n * 这些操作仅处理本地 `~/.hai/credentials.yml`,供 CLI 在读取 `_deploy.yml`\n * 之前注入 `HAI_DEPLOY_*` 环境变量,因此不依赖 `deploy.init()`。\n */\nconst deployCredentials: DeployCredentialOperations = {\n getPath: () => getCredentialsPath(),\n load: () => loadCredentials(),\n save: (key: string, value: string) => saveCredential(key, value),\n saveAll: (entries: Record<string, string>) => saveCredentials(entries),\n}\n\n/** 归一化项目名为容器/镜像安全的 `[a-z0-9-]`。 */\nfunction normalizeProjectName(name: string): string {\n const normalized = name\n .replace(/^@[^/]+\\//, '')\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return normalized || 'app'\n}\n\n/** 合并 Provisioner 输出环境变量,并聚合 HAI_REACH_PROVIDERS 数组。 */\nfunction mergeProvisionEnv(results: ProvisionResult[], scan?: ScanResult, options?: DeployAppOptions): Record<string, string> {\n let env: Record<string, string> = {}\n const reachRequirements = scan?.middlewares?.filter(item => item.configName === 'reach') ?? []\n const reachProviders: unknown[] = reachRequirements.map(item => item.config)\n let hasReachOutput = false\n for (const prov of results) {\n if (prov.envVars.HAI_REACH_PROVIDERS) {\n hasReachOutput = true\n const supplied = JSON.parse(prov.envVars.HAI_REACH_PROVIDERS) as Record<string, unknown>[]\n for (const provider of supplied) {\n const targets = reachRequirements.filter((item) => {\n const mode = options?.serviceModes?.[item.envPrefix] ?? options?.serviceModes?.[item.service]\n return item.service === prov.serviceType && (!mode || mode === 'default')\n })\n if (targets.length) {\n for (const target of targets)\n reachProviders[reachRequirements.indexOf(target)] = { ...provider, name: target.config.name ?? provider.name }\n }\n else {\n reachProviders.push(provider)\n }\n }\n }\n env = { ...env, ...prov.envVars }\n }\n if (hasReachOutput)\n env.HAI_REACH_PROVIDERS = JSON.stringify(reachProviders)\n return env\n}\n\n// ─── 模块单例 ───\n\n/**\n * Deploy 模块单例\n * 每次 init 检查 HaiResult;只打包不会连接 SSH,成功打包也不代表服务器已部署。远端 unknown 必须先核对匹配部署 ID 的结果,不能盲目重试。\n * @example\n * ```ts\n * import { deploy, getDeployCommandState } from '@h-ai/deploy'\n * const initialized = await deploy.init({ provider: { type: 'docker-ssh', expose: { hostPort: 8080 } } })\n * if (!initialized.success) throw new Error(initialized.error.message)\n * try {\n * // 当前项目已有镜像产物与部署环境;只打包,不连接服务器。\n * const result = await deploy.deployApp(process.cwd(), { environment: 'prod', bundleOnly: true })\n * if (!result.success) {\n * const state = getDeployCommandState(result.error)\n * if (state?.remoteExecution === 'unknown') {\n * process.stderr.write('Inspect the matching server result before retrying\\n')\n * }\n * throw new Error(result.error.message)\n * }\n * if (result.data.status === 'packaged') {\n * const bundle = result.data.bundlePath\n * }\n * }\n * finally {\n * await deploy.close()\n * }\n * ```\n */\nexport const deploy: DeployFunctions = {\n credentials: deployCredentials,\n\n async init(config: DeployConfigInput): Promise<HaiResult<void>> {\n // 并发初始化防护:避免多次 init 同时执行导致资源泄漏\n if (initInProgress) {\n logger.warn('Deploy init already in progress, skipping concurrent call')\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: 'init already in progress' } }),\n )\n }\n initInProgress = true\n\n try {\n if (currentProvider || currentContainerProvider) {\n logger.warn('Deploy module is already initialized, reinitializing')\n await deploy.close()\n }\n\n logger.info('Initializing deploy module')\n\n const parseResult = DeployConfigSchema.safeParse(config)\n if (!parseResult.success) {\n logger.error('Deploy config validation failed', { error: parseResult.error.message })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', { params: { error: parseResult.error.message } }),\n parseResult.error,\n )\n }\n const parsed = parseResult.data\n\n try {\n // 创建部署 Provider:docker-ssh 走容器路径(无远程认证),其余走平台路径并即时认证\n let provider: DeployProvider | null = null\n let containerProvider: ContainerDeployProvider | null = null\n if (parsed.provider.type === 'docker-ssh') {\n containerProvider = createDockerSshProvider(parsed.provider, parsed.container)\n logger.info('Container deploy provider ready', { provider: 'docker-ssh', host: parsed.provider.ssh?.host })\n }\n else {\n provider = createProviderByType(parsed.provider.type)\n const authResult = await provider.authenticate(parsed.provider.token)\n if (!authResult.success) {\n return err(authResult.error)\n }\n logger.info('Provider authenticated', { provider: parsed.provider.type, user: authResult.data })\n }\n\n // 创建 Provisioners(两类 Provider 均可复用云资源开通)\n currentProvisioners.clear()\n if (parsed.services) {\n const serviceEntries = Object.entries(parsed.services) as Array<[ServiceType, Record<string, unknown> | undefined]>\n for (const [serviceType, serviceConfig] of serviceEntries) {\n if (!serviceConfig)\n continue\n\n const provisioner = createProvisionerByName(serviceConfig.provisioner as string)\n const credentials = extractCredentials(serviceConfig as Record<string, unknown>)\n const provAuthResult = await provisioner.authenticate(credentials)\n if (!provAuthResult.success) {\n logger.error('Provisioner authentication failed', {\n service: serviceType,\n provisioner: (serviceConfig as Record<string, unknown>).provisioner,\n })\n currentProvisioners.clear()\n return err(provAuthResult.error)\n }\n logger.info('Provisioner authenticated', {\n service: serviceType,\n user: provAuthResult.data,\n })\n currentProvisioners.set(serviceType, provisioner)\n }\n }\n\n currentProvider = provider\n currentContainerProvider = containerProvider\n currentConfig = parsed\n logger.info('Deploy module initialized', {\n provider: parsed.provider.type,\n provisioners: [...currentProvisioners.keys()],\n })\n return ok(undefined)\n }\n catch (error) {\n // 清理部分赋值的状态\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.error('Deploy module initialization failed', { error })\n return err(\n HaiDeployError.CONFIG_ERROR,\n deployM('deploy_configError', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n }\n finally {\n initInProgress = false\n }\n },\n\n async close(): Promise<void> {\n if (!currentProvider && !currentContainerProvider) {\n logger.info('Deploy module already closed, skipping')\n return\n }\n\n logger.info('Closing deploy module')\n currentProvider = null\n currentContainerProvider = null\n currentConfig = null\n currentProvisioners.clear()\n logger.info('Deploy module closed')\n },\n\n get config(): DeployConfig | null {\n return currentConfig\n },\n\n get isInitialized(): boolean {\n return currentProvider !== null || currentContainerProvider !== null\n },\n\n async scan(appDir: string, options?: DeployScanOptions): Promise<HaiResult<ScanResult>> {\n // scan 仅做本地文件分析,不依赖 Provider / Provisioner 初始化状态。\n logger.debug('Scanning application', { appDir })\n return scanApp(appDir, options)\n },\n\n async provisionAll(projectName: string, services?: ServiceType[]): Promise<HaiResult<ProvisionResult[]>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n logger.info('Provisioning all services', { projectName, count: currentProvisioners.size })\n const results: ProvisionResult[] = []\n\n for (const [serviceType, provisioner] of currentProvisioners) {\n if (services && !services.includes(serviceType))\n continue\n logger.debug('Provisioning service', { serviceType, provisioner: provisioner.name })\n const provResult = await provisioner.provision(projectName)\n if (!provResult.success) {\n logger.error('Service provisioning failed', {\n serviceType,\n provisioner: provisioner.name,\n code: provResult.error.code,\n })\n return recoveryFailure(provResult.error, {\n projectName,\n stage: `provision:${serviceType}`,\n resources: [\n ...results.map(({ envVars: _envVars, ...resource }) => resource),\n ...(getDeployRecovery(provResult.error)?.resources ?? [\n { serviceType, provisionerName: provisioner.name, resourceInfo: projectName, resourceStatus: 'unknown' as const },\n ]),\n ],\n })\n }\n results.push(provResult.data)\n logger.info('Service provisioned', { serviceType, provisioner: provisioner.name })\n }\n\n return ok(results)\n },\n\n async deployApp(\n appDir: string,\n options?: DeployAppOptions,\n ): Promise<HaiResult<DeployResult>> {\n if (!currentProvider && !currentContainerProvider) {\n return notInitialized.result()\n }\n\n logger.info('Starting deployment', { appDir, environment: options?.environment, projectName: options?.projectName })\n\n // 1. 扫描应用\n const scanOptions = { ...options, environment: options?.environment ?? currentConfig?.environment }\n const scanResult = await scanApp(appDir, scanOptions)\n if (!scanResult.success) {\n return err(scanResult.error)\n }\n const scan = scanResult.data\n appDir = scan.appDir ?? appDir\n const environment = loadDeploymentEnvironment({ environment: scanOptions.environment ?? 'prod', envDir: scan.envDir ?? appDir, requireFile: scanOptions.environment !== undefined })\n if (!environment.success)\n return environment\n const appEnv = Object.fromEntries(Object.entries(environment.data.values).filter(([key]) => !key.startsWith('HAI_CLI_') && (!key.startsWith('HAI_DEPLOY_') || key === 'HAI_DEPLOY_ENVIRONMENT')))\n const projectName = `${options?.projectName ?? scan.appName}${scanOptions.environment ? `-${environment.data.environment}` : ''}`\n options = {\n ...options,\n ...(scanOptions.environment ? { environment: environment.data.environment } : {}),\n ...(options?.skipMiddleware ? { serviceModes: Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])) } : {}),\n }\n if (options.selectedServices) {\n options.serviceModes = {\n ...options.serviceModes,\n ...Object.fromEntries(scan.requiredServices.filter(service => !options.selectedServices!.includes(service)).map(service => [service, 'keep' as const])),\n }\n }\n\n // 容器 Provider(docker-ssh):走独立的容器部署编排\n if (currentContainerProvider) {\n return deployContainerApp(currentContainerProvider, appDir, scan, projectName, options, appEnv)\n }\n\n if (options?.bundleOnly)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_bundleOnlyContainer'))\n if (options.selectedServices)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_selectedContainerOnly'))\n\n // 到此必为平台 Provider(vercel)\n if (!currentProvider) {\n return notInitialized.result()\n }\n\n // 2. 检查 adapter\n if (scan.isSvelteKit && !scan.adapterInstalled) {\n return err(\n HaiDeployError.ADAPTER_MISSING,\n deployM('deploy_adapterMissing', {\n params: { adapter: '@sveltejs/adapter-vercel' },\n }),\n )\n }\n\n if (!existsSync(resolveOutputDir(appDir, 'vercel')))\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n\n // 3. 开通基础设施\n let allEnvVars: Record<string, string> = appEnv\n const recovery: DeployRecoveryInfo = { projectName, stage: 'provision', resources: [] }\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n recovery.resources = provResults.data.map(({ envVars: _envVars, ...resource }) => resource)\n allEnvVars = { ...allEnvVars, ...mergeProvisionEnv(provResults.data, scan, options) }\n if (options?.environment) {\n const saved = saveDeploymentEnvironment(environment.data, mergeProvisionEnv(provResults.data, scan, options))\n if (!saved.success)\n return recoveryFailure(saved.error, { ...recovery, stage: 'save-env' })\n }\n }\n\n // 4. 创建平台项目\n const projectResult = await currentProvider.createProject(projectName)\n if (!projectResult.success) {\n return recoveryFailure(projectResult.error, { ...recovery, stage: 'create-project' })\n }\n const projectId = projectResult.data\n recovery.platformProjectId = projectId\n\n // 5. 设置环境变量\n if (Object.keys(allEnvVars).length > 0) {\n const envResult = await currentProvider.setEnvVars(projectId, allEnvVars)\n if (!envResult.success) {\n return recoveryFailure(envResult.error, { ...recovery, stage: 'set-env' })\n }\n }\n\n // 7. 部署\n const outputDir = resolveOutputDir(appDir, currentConfig?.provider.type ?? 'vercel')\n const deployResult = await currentProvider.deploy(projectId, outputDir)\n if (!deployResult.success) {\n return recoveryFailure(deployResult.error, { ...recovery, stage: 'deploy' })\n }\n\n // 补充环境变量列表到结果中\n const result: DeployResult = {\n ...deployResult.data,\n envVarsSet: Object.keys(allEnvVars),\n }\n\n logger.info('Deployment completed', {\n url: result.url,\n deploymentId: result.deploymentId,\n status: result.status,\n })\n\n return ok(result)\n },\n}\n\n/**\n * 容器 Provider(docker-ssh)部署编排。\n *\n * 校验 adapter-node → 开通云资源(可选)→ 交由容器 Provider 完成\n * 打包 / 传输 / compose up / 健康检查。\n *\n * @param provider - 容器部署 Provider\n * @param appDir - 应用根目录\n * @param scan - 扫描结果\n * @param rawProjectName - 原始项目名(未归一化)\n * @param options - 部署选项\n */\nasync function deployContainerApp(\n provider: ContainerDeployProvider,\n appDir: string,\n scan: ScanResult,\n rawProjectName: string,\n options?: DeployAppOptions,\n appEnv: Record<string, string> = {},\n): Promise<HaiResult<DeployResult>> {\n const projectName = normalizeProjectName(rawProjectName)\n\n let artifact\n let artifactDir = options?.artifactDir ?? resolveArtifactDirectory(appDir)\n try {\n if (existsSync(join(artifactDir, 'latest'))) {\n const latest = readFileSync(join(artifactDir, 'latest'), 'utf8').trim()\n if (!/^[a-z0-9][\\w.+-]*$/i.test(latest))\n throw new Error('Invalid artifact pointer')\n artifactDir = join(artifactDir, latest)\n }\n artifact = await readDeploymentArtifact(artifactDir)\n }\n catch {\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_artifactInvalid'))\n }\n if (artifact.partial && !options?.selectedServices) {\n const selectedServices = artifact.images.map(image => image.name)\n options = {\n ...options,\n selectedServices,\n serviceModes: {\n ...options?.serviceModes,\n ...Object.fromEntries(scan.requiredServices.map(service => [service, 'keep' as const])),\n },\n }\n }\n if (!options?.bundleOnly && currentConfig?.provider.type === 'docker-ssh' && !currentConfig.provider.ssh)\n return err(HaiDeployError.CONFIG_ERROR, deployM('deploy_sshRequired'))\n\n let provisionEnv: Record<string, string> = {}\n if (!options?.skipMiddleware) {\n const provResults = await deploy.provisionAll(projectName, options?.serviceModes ? scan.requiredServices.filter(service => usesDefaultMiddleware(scan, service, options)) : undefined)\n if (!provResults.success) {\n return err(provResults.error)\n }\n provisionEnv = mergeProvisionEnv(provResults.data, scan, options)\n }\n\n return provider.deploy({ appDir, artifact, artifactDir, projectName, scan, provisionEnv, appEnv, options })\n}\n","/**\n * 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。\n * 字段名与对应模块公开 Schema 保持一致,不把模块依赖等同于必须创建外部服务。\n * @module deploy-middleware\n */\nimport type { ServiceType } from './deploy-types.js'\nimport { deployM } from './deploy-i18n.js'\n\n/**\n * 连接字段;例如 `{ name: 'port', defaultValue: '5432', kind: 'port' }`。\n * @example\n * ```ts\n * import type { MiddlewareField } from '@h-ai/deploy'\n * const field: MiddlewareField = { name: 'port', defaultValue: '5432', required: true, kind: 'port' }\n * ```\n */\nexport interface MiddlewareField {\n /** 模块配置字段名,camelCase 不拆词。 */\n name: string\n /** 无现有配置时使用的提示默认值。 */\n defaultValue?: string\n /** 是否为连接所必需;可选项允许留空。 */\n required?: boolean\n /** 密码输入与私有环境文件写入标记。 */\n secret?: boolean\n /** 交互校验类型;端口范围为 1–65535。 */\n kind?: 'port' | 'boolean' | 'number' | 'url'\n /** 数值下限;未声明时为 0。 */\n minimum?: number\n /** 数值上限;例如 Redis db 为 15。 */\n maximum?: number\n}\n\n/**\n * 后端目录项;例如 PostgreSQL 对应 `backend: 'postgresql'`。\n * @example\n * ```ts\n * import type { MiddlewareBackend } from '@h-ai/deploy'\n * const backend: MiddlewareBackend = { backend: 'postgresql', label: 'PostgreSQL', purpose: 'deploy_purposeDatabase', fields: [{ name: 'database', required: true }] }\n * ```\n */\nexport interface MiddlewareBackend {\n /** 模块 Schema 接受的后端标识。 */\n backend: string\n /** 可直接识别的产品名称。 */\n label: string\n /** 用途说明的 i18n 消息键。 */\n purpose: Parameters<typeof deployM>[0]\n /** 云自动开通器;缺失表示不能自动开通该云服务。 */\n provisioner?: 'neon' | 'upstash' | 'cloudflare-r2' | 'resend' | 'aliyun'\n /** 自定义连接需要逐项输入的字段。 */\n fields: MiddlewareField[]\n}\n\nconst field = (name: string, defaultValue?: string, kind?: MiddlewareField['kind'], secret = false): MiddlewareField => ({ name, defaultValue, kind, secret })\nconst required = (name: string, defaultValue?: string, kind?: MiddlewareField['kind']): MiddlewareField => ({ ...field(name, defaultValue, kind), required: true })\n\n/**\n * 所有可部署中间件的连接目录。\n * SQLite、memory、local 与 disabled 保留本地/禁用语义,不创建无关 sidecar。\n * 目录同时描述本机、禁用、自建与云后端;存在依赖不等于必须开通新资源。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const choices = DEPLOY_MIDDLEWARE.db.map(backend => ({ value: backend.backend, description: describeMiddlewareBackend(backend) }))\n * ```\n */\nexport const DEPLOY_MIDDLEWARE: Record<ServiceType, MiddlewareBackend[]> = {\n db: [\n { backend: 'sqlite', label: 'SQLite', purpose: 'deploy_purposeSqlite', fields: [required('database', './data/app.db')] },\n ...(['postgresql', 'mysql'] as const).map(backend => ({\n backend,\n label: backend === 'mysql' ? 'MySQL' : 'PostgreSQL',\n purpose: 'deploy_purposeDatabase' as const,\n provisioner: backend === 'postgresql' ? 'neon' as const : undefined,\n fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', backend === 'mysql' ? '3306' : '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true), field('ssl', 'false')],\n })),\n ],\n cache: [\n { backend: 'memory', label: 'Memory', purpose: 'deploy_purposeMemory', fields: [] },\n { backend: 'redis', label: 'Redis', purpose: 'deploy_purposeCache', provisioner: 'upstash', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '6379', 'port'), field('password', '', undefined, true), { ...field('db', '0', 'number'), maximum: 15 }, field('tls', 'false', 'boolean'), field('keyPrefix'), field('connectTimeout', '10000', 'number'), field('commandTimeout', '5000', 'number')] },\n ],\n storage: [\n { backend: 'local', label: 'Local filesystem', purpose: 'deploy_purposeLocal', fields: [required('root', './data/storage')] },\n { backend: 's3', label: 'S3 / RustFS / MinIO / Cloudflare R2', purpose: 'deploy_purposeStorage', provisioner: 'cloudflare-r2', fields: [field('endpoint', '', 'url'), required('bucket', 'hai'), required('region', 'us-east-1'), required('accessKeyId'), { ...required('secretAccessKey'), secret: true }, field('forcePathStyle', 'true', 'boolean')] },\n ],\n vecdb: [\n { backend: 'lancedb', label: 'LanceDB', purpose: 'deploy_purposeLocal', fields: [required('path', './data/vectors')] },\n { backend: 'qdrant', label: 'Qdrant', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:6333', 'url'), field('apiKey', '', undefined, true)] },\n { backend: 'pgvector', label: 'PostgreSQL / pgvector', purpose: 'deploy_purposeVector', fields: [field('url', '', 'url', true), required('host', 'localhost'), required('port', '5432', 'port'), required('database', 'hai'), field('user', 'hai'), field('password', '', undefined, true)] },\n { backend: 'chroma', label: 'Chroma', purpose: 'deploy_purposeVector', fields: [required('url', 'http://localhost:8000', 'url')] },\n ],\n ldap: [\n { backend: 'disabled', label: 'Disabled', purpose: 'deploy_purposeDisabled', fields: [] },\n { backend: 'ldap', label: 'LDAP / OpenLDAP', purpose: 'deploy_purposeLdap', fields: [required('url', 'ldap://localhost:389', 'url'), required('bindDn', 'cn=admin,dc=example,dc=org'), { ...required('bindPassword'), secret: true }, required('searchBase', 'dc=example,dc=org'), field('searchFilter', '(uid={{username}})'), field('usernameAttribute', 'uid'), field('emailAttribute', 'mail'), field('displayNameAttribute', 'cn'), field('useTls', 'false', 'boolean'), { ...field('connectTimeout', '5000', 'number'), minimum: 1000 }] },\n ],\n email: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'smtp', label: 'SMTP', purpose: 'deploy_purposeEmail', provisioner: 'resend', fields: [required('host', 'localhost'), required('port', '465', 'port'), field('secure', 'true', 'boolean'), field('user'), field('pass', '', undefined, true), required('from', 'noreply@example.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeEmail', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n sms: [\n { backend: 'console', label: 'Console', purpose: 'deploy_purposeConsole', fields: [] },\n { backend: 'aliyun-sms', label: 'Aliyun SMS', purpose: 'deploy_purposeSms', provisioner: 'aliyun', fields: [required('accessKeyId'), { ...required('accessKeySecret'), secret: true }, required('signName'), field('endpoint', 'dysmsapi.aliyuncs.com')] },\n { backend: 'api', label: 'HTTP notification API', purpose: 'deploy_purposeSms', fields: [required('url', '', 'url'), field('method', 'POST'), field('headers'), field('timeout', '10000', 'number')] },\n ],\n}\n\n/**\n * 返回当前语言的后端用途说明。\n * @param backend - 部署目录中的后端条目。\n * @returns 当前 locale 的用途说明。\n * @example\n * ```ts\n * import { DEPLOY_MIDDLEWARE, describeMiddlewareBackend } from '@h-ai/deploy'\n * const backend = DEPLOY_MIDDLEWARE.db.find(item => item.backend === 'postgresql')\n * if (backend) {\n * const description = describeMiddlewareBackend(backend)\n * }\n * ```\n */\nexport function describeMiddlewareBackend(backend: MiddlewareBackend): string {\n return deployM(backend.purpose)\n}\n"]}
|