@h-ai/deploy 1.0.0-beta.20 → 1.0.0-beta.22
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 +2 -0
- package/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +163 -50
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/README.en.md
CHANGED
|
@@ -163,6 +163,8 @@ In `hai deploy`, choose a URL or individual fields for custom PostgreSQL, MySQL,
|
|
|
163
163
|
|
|
164
164
|
#### Direct private object storage access
|
|
165
165
|
|
|
166
|
+
Nginx serves a standalone HTTP 404 page when a presigned download reaches the static site fallback or the SSR/API gateway receives an application 404. The page uses Chinese, English, or Japanese based on the browser language. Update the proxy rules with a full deployment bundle. Rebuild independently run static web images from the updated CLI templates. [Download troubleshooting](../../docs/usage/configuration/data.md#下载链接无法访问)
|
|
167
|
+
|
|
166
168
|
Self-hosted S3 uses an internal endpoint. Set `_storage.yml` publicEndpoint to an external address such as `https://app.example.com/delivery/files`. Nginx exposes `/delivery/files/<bucket>/...`, removes the proxy directory and forwards the original bucket URI, signature query and Host directly to storage:9000. Files bypass Serv; omitting the directory retains root bucket routes. A route may sit under the website directory; API, asset and health conflicts fail packaging. Storage ports/consoles remain private, buffering/signature logs are disabled, and S3 handles authorization and cross-origin CORS. External ingress must retain the full entry path and Host so only the SDK gateway removes the prefix.
|
|
167
169
|
|
|
168
170
|
Managed deployments retain bucket/region/prefix/publicEndpoint/publicUrl/operationLog while replacing internal connections and managed credentials. Adding the gateway or changing access settings requires a full baseline; partial preflight rejects mismatching configuration fingerprints. App/storage partial updates refresh retained proxy DNS, and recovery restores the previous topology. External/kept storage gets no local sidecar route; Local does not expose private directories. See the [storage handbook](../../docs/usage/configuration/data.md).
|
package/README.ja.md
CHANGED
|
@@ -163,6 +163,8 @@ SSH 設定は選択環境の `.env.<環境>.local` に保存します。`--bundl
|
|
|
163
163
|
|
|
164
164
|
#### 非公開オブジェクトストレージへの直接アクセス
|
|
165
165
|
|
|
166
|
+
署名付きダウンロードが静的サイトのフォールバックに到達した場合、または SSR/API ゲートウェイがアプリから 404 を受け取った場合、Nginx は専用ページを HTTP 404 で返します。ブラウザーの言語に応じて中国語、英語、日本語で表示します。プロキシのルールを更新するには完全デプロイバンドルを使用し、静的 Web イメージを単独で使う場合は更新後の CLI テンプレートから再構築してください。[ダウンロードのトラブルシューティング](../../docs/usage/configuration/data.md#下载链接无法访问)
|
|
167
|
+
|
|
166
168
|
自前 S3 の endpoint は内部接続先です。publicEndpoint に `https://app.example.com/delivery/files` などの外部アドレスを設定できます。Nginx は `/delivery/files/<bucket>/...` を受け、入口パスだけを除去し、本来のバケット URI、署名クエリ、Host を保持して storage:9000 に転送します。Serv を経由せず、パス省略時は従来のルートバケット形式です。サイト配下に置けますが API、資源、ヘルスパスの競合は拒否します。ポートと管理コンソールは非公開、バッファリングと署名ログは無効です。認可と CORS は S3 に設定し、外部プロキシは入口パスと Host を保持してください。
|
|
167
169
|
|
|
168
170
|
自前構成は bucket/region/prefix/publicEndpoint/publicUrl/operationLog を保持し、内部接続と受管認証情報だけを置き換えます。gateway 追加や公開設定変更には完全デプロイが必要で、部分更新の事前検証は設定摘要の不一致を拒否します。アプリ/ストレージ部分更新では保持プロキシの DNS を更新し、失敗時は以前の構成に復元します。外部/保持接続にローカルルートは生成せず、Local の非公開ディレクトリも公開しません。[ストレージ手引き](../../docs/usage/configuration/data.md)を参照してください。
|
package/README.md
CHANGED
|
@@ -177,6 +177,8 @@ SSH 参数保存到选中环境的 `.env.<环境>.local`。`--bundle-only` 在
|
|
|
177
177
|
|
|
178
178
|
#### 私有对象存储直连
|
|
179
179
|
|
|
180
|
+
预签名下载请求落入静态网站回退,或 SSR/API 网关收到应用的 404 时,Nginx 返回 HTTP 404 和独立的下载提示页。提示按浏览器语言显示中文、英文或日文。现有容器部署使用完整交付包更新代理规则,独立静态 Web 镜像使用更新后的 CLI 模板重新构建。[下载排查](../../docs/usage/configuration/data.md#下载链接无法访问)
|
|
181
|
+
|
|
180
182
|
自建 S3 的 `endpoint` 使用 Compose 内部地址,浏览器地址用 `_storage.yml` 的 `publicEndpoint` 配置,例如 `https://app.example.com/delivery/files`。Nginx 对外开放 `/delivery/files/<bucket>/...`,去掉 `/delivery/files` 后将原始桶 URI、签名查询与 Host 直接转发 storage:9000,文件不经过 Serv;省略目录时继续使用根桶路径。入口可位于网站目录内,API/资源/健康路径冲突会在打包前失败。存储端口与控制台不公开,对象缓冲和签名日志关闭;S3 负责私有桶授权和跨源 CORS。外层代理须保留完整入口路径与 Host,只由 SDK 网关去掉前缀。
|
|
181
183
|
|
|
182
184
|
自建配置保留 bucket/region/prefix/publicEndpoint/publicUrl/operationLog,只替换内部连接与托管凭据。首次增加网关或改变这些访问设置须全量部署,增量预检按配置摘要拒绝不一致;普通应用/存储增量刷新保留代理的服务 DNS,失败恢复使用旧拓扑。外部/保持连接不生成本地存储路由,Local 不公开私有目录。详见[存储配置手册](../../docs/usage/configuration/data.md#配置人员区分三个访问地址).
|
package/dist/index.d.ts
CHANGED
|
@@ -1077,7 +1077,7 @@ declare const deploy: DeployFunctions;
|
|
|
1077
1077
|
* const message = deployM('deploy_sshRequired')
|
|
1078
1078
|
* ```
|
|
1079
1079
|
*/
|
|
1080
|
-
declare const deployM: (key: "deploy_composeHostAddressInvalid" | "deploy_composeHostnameInvalid" | "deploy_composeHostnameConflict" | "deploy_composeProviderRequired" | "deploy_composeServiceUnavailable" | "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleApplyGuide" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_secretImportFailed" | "deploy_projectNameRequired" | "deploy_projectNameOverrideRemoved" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid" | "deploy_bundleRuntime" | "deploy_refreshCookieSecureInvalid" | "deploy_postgresPasswordConflict" | "deploy_bundleVariables" | "deploy_bundleHttpOnly" | "deploy_bundleHttps" | "deploy_bundleAcme" | "deploy_bundleAccounts" | "deploy_bundleDirectories" | "deploy_downloadInvalid" | "deploy_imageSourceMissing" | "deploy_proxySystemUnsupported" | "deploy_middlewareFieldInvalid" | "deploy_middlewareFieldError" | "deploy_middlewareRequired" | "deploy_middlewareInteger" | "deploy_middlewareBoolean" | "deploy_middlewareUrl" | "deploy_middlewareS3Endpoint" | "deploy_middlewareTlsSyntax" | "deploy_middlewareMysqlTls" | "deploy_middlewarePostgresTls" | "deploy_middlewareHeaders" | "deploy_middlewareMethod" | "deploy_configResolutionFailed" | "deploy_reachEmptyProviderOverride" | "deploy_s3Engine", options?: _h_ai_core.MessageOptions) => string;
|
|
1080
|
+
declare const deployM: (key: "deploy_composeHostAddressInvalid" | "deploy_composeHostnameInvalid" | "deploy_composeHostnameConflict" | "deploy_composeProviderRequired" | "deploy_composeServiceUnavailable" | "deploy_notInitialized" | "deploy_initFailed" | "deploy_unsupportedProviderType" | "deploy_unsupportedProvisionerType" | "deploy_configTokenRequired" | "deploy_authRequired" | "deploy_authFailed" | "deploy_projectCreateFailed" | "deploy_uploadFailed" | "deploy_deployFailed" | "deploy_provisionFailed" | "deploy_adapterMissing" | "deploy_scanFailed" | "deploy_envVarFailed" | "deploy_credentialError" | "deploy_credentialInvalidKey" | "deploy_credentialSaved" | "deploy_credentialLoaded" | "deploy_configError" | "deploy_credentialMissing" | "deploy_apiError" | "deploy_fileUploadFailed" | "deploy_provisionNoResult" | "deploy_recoveryFailure" | "deploy_recoverySuggestion" | "deploy_commandTimeout" | "deploy_commandFailed" | "deploy_remoteConnectFailed" | "deploy_remoteRuntimeMissing" | "deploy_imageTransferFailed" | "deploy_healthCheckFailed" | "deploy_invalidEnvironment" | "deploy_environmentMissing" | "deploy_environmentReadFailed" | "deploy_environmentWriteFailed" | "deploy_multipleApplications" | "deploy_purposeSqlite" | "deploy_purposeDatabase" | "deploy_purposeMemory" | "deploy_purposeLocal" | "deploy_purposeCache" | "deploy_purposeStorage" | "deploy_purposeVector" | "deploy_purposeDisabled" | "deploy_purposeLdap" | "deploy_purposeConsole" | "deploy_purposeEmail" | "deploy_purposeSms" | "deploy_webProxyInvalid" | "deploy_webBaseConflict" | "deploy_storageProxyInvalid" | "deploy_storagePublicEndpointInvalid" | "deploy_storageBackendRequired" | "deploy_artifactInvalid" | "deploy_sshRequired" | "deploy_sshPasswordInvalid" | "deploy_sshAskpassFailed" | "deploy_sshAskpassCleanupFailed" | "deploy_targetAuth" | "deploy_targetPasswordEnv" | "deploy_bundleInstructions" | "deploy_bundleApplyGuide" | "deploy_bundleMetadata" | "deploy_targetHost" | "deploy_targetPort" | "deploy_targetUsername" | "deploy_targetIdentityFile" | "deploy_targetKnownHostsFile" | "deploy_targetStrictHostKeyChecking" | "deploy_targetConnectTimeoutSeconds" | "deploy_targetDirectory" | "deploy_targetBundle" | "deploy_bundleOnlyContainer" | "deploy_selectedContainerOnly" | "deploy_selectionInvalid" | "deploy_imageVersionRequired" | "deploy_bundleRuntimeRequired" | "deploy_bundleFailed" | "deploy_configFileInvalid" | "deploy_configFileUnreadable" | "deploy_bundleNameInvalid" | "deploy_localStopped" | "deploy_localUnknown" | "deploy_localNotStarted" | "deploy_commandOutputFailed" | "deploy_commandInputFailed" | "deploy_commandTreeActive" | "deploy_commandExecutionFailed" | "deploy_remoteUnknown" | "deploy_remoteFinished" | "deploy_bundleDirectoryExists" | "deploy_bundleFull" | "deploy_bundlePartial" | "deploy_bundleSelection" | "deploy_transportBodyLimitInvalid" | "deploy_transportKeyRingInvalid" | "deploy_uploadPasswordPrompt" | "deploy_uploadPasswordUnavailable" | "deploy_uploadPasswordCancelled" | "deploy_uploadPasswordInvalid" | "deploy_managedSecretsInvalid" | "deploy_secretImportFailed" | "deploy_projectNameRequired" | "deploy_projectNameOverrideRemoved" | "deploy_requestAccessInvalid" | "deploy_httpsPortsInvalid" | "deploy_httpsCertificateInvalid" | "deploy_bundleRuntime" | "deploy_refreshCookieSecureInvalid" | "deploy_postgresPasswordConflict" | "deploy_bundleVariables" | "deploy_bundleHttpOnly" | "deploy_bundleHttps" | "deploy_bundleAcme" | "deploy_bundleAccounts" | "deploy_bundleDirectories" | "deploy_downloadInvalid" | "deploy_imageSourceMissing" | "deploy_proxySystemUnsupported" | "deploy_middlewareFieldInvalid" | "deploy_middlewareFieldError" | "deploy_middlewareRequired" | "deploy_middlewareInteger" | "deploy_middlewareBoolean" | "deploy_middlewareUrl" | "deploy_middlewareS3Endpoint" | "deploy_middlewareTlsSyntax" | "deploy_middlewareMysqlTls" | "deploy_middlewarePostgresTls" | "deploy_middlewareHeaders" | "deploy_middlewareMethod" | "deploy_configResolutionFailed" | "deploy_reachEmptyProviderOverride" | "deploy_s3Engine" | "deploy_downloadUnavailableTitle" | "deploy_downloadUnavailableInstruction", options?: _h_ai_core.MessageOptions) => string;
|
|
1081
1081
|
|
|
1082
1082
|
/**
|
|
1083
1083
|
* 部署中间件的后端与连接字段目录,供扫描、CLI 和容器规划共同使用。
|
package/dist/index.js
CHANGED
|
@@ -221,7 +221,9 @@ var en_US_default = {
|
|
|
221
221
|
deploy_middlewareMethod: "Enter POST or PUT.",
|
|
222
222
|
deploy_configResolutionFailed: "Cannot resolve {path}. Check the configuration structure and array indices for {fields}.",
|
|
223
223
|
deploy_reachEmptyProviderOverride: "While resolving {path}, {field} refers to a missing provider because HAI_REACH_PROVIDERS is []. Remove stale indexed variables and set HAI_REACH_PROVIDERS to the complete notification provider list in .env.<environment>.local.",
|
|
224
|
-
deploy_s3Engine: "Choose the self-hosted S3 implementation"
|
|
224
|
+
deploy_s3Engine: "Choose the self-hosted S3 implementation",
|
|
225
|
+
deploy_downloadUnavailableTitle: "Download link unavailable",
|
|
226
|
+
deploy_downloadUnavailableInstruction: "Return to the download page to get a new link. If the download still fails, contact your administrator."
|
|
225
227
|
};
|
|
226
228
|
|
|
227
229
|
// messages/ja-JP.json
|
|
@@ -364,7 +366,9 @@ var ja_JP_default = {
|
|
|
364
366
|
deploy_middlewareMethod: "POST \u307E\u305F\u306F PUT \u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
365
367
|
deploy_configResolutionFailed: "{path} \u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093\u3002{fields} \u306B\u5BFE\u5FDC\u3059\u308B\u8A2D\u5B9A\u306E\u69CB\u9020\u3068\u914D\u5217\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
366
368
|
deploy_reachEmptyProviderOverride: "{path} \u306E\u6709\u52B9\u306A\u8A2D\u5B9A\u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093\u3002HAI_REACH_PROVIDERS \u304C [] \u306E\u305F\u3081\u3001{field} \u306B\u5BFE\u5FDC\u3059\u308B\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u53E4\u3044\u30A4\u30F3\u30C7\u30C3\u30AF\u30B9\u4ED8\u304D\u5909\u6570\u3092\u524A\u9664\u3057\u3001.env.<\u74B0\u5883>.local \u306E HAI_REACH_PROVIDERS \u306B\u901A\u77E5\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u306E\u5B8C\u5168\u306A\u4E00\u89A7\u3092\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
367
|
-
deploy_s3Engine: "\u30BB\u30EB\u30D5\u30DB\u30B9\u30C8 S3 \u306E\u5B9F\u88C5\u3092\u9078\u629E"
|
|
369
|
+
deploy_s3Engine: "\u30BB\u30EB\u30D5\u30DB\u30B9\u30C8 S3 \u306E\u5B9F\u88C5\u3092\u9078\u629E",
|
|
370
|
+
deploy_downloadUnavailableTitle: "\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u30EA\u30F3\u30AF\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093",
|
|
371
|
+
deploy_downloadUnavailableInstruction: "\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u30DA\u30FC\u30B8\u306B\u623B\u308A\u3001\u65B0\u3057\u3044\u30EA\u30F3\u30AF\u3092\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u89E3\u6C7A\u3057\u306A\u3044\u5834\u5408\u306F\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u304F\u3060\u3055\u3044\u3002"
|
|
368
372
|
};
|
|
369
373
|
|
|
370
374
|
// messages/zh-CN.json
|
|
@@ -507,7 +511,9 @@ var zh_CN_default = {
|
|
|
507
511
|
deploy_middlewareMethod: "\u8BF7\u8F93\u5165 POST \u6216 PUT\u3002",
|
|
508
512
|
deploy_configResolutionFailed: "\u65E0\u6CD5\u89E3\u6790 {path}\u3002\u8BF7\u68C0\u67E5 {fields} \u5BF9\u5E94\u7684\u914D\u7F6E\u7ED3\u6784\u4E0E\u6570\u7EC4\u7D22\u5F15\u3002",
|
|
509
513
|
deploy_reachEmptyProviderOverride: "\u89E3\u6790 {path} \u7684\u751F\u6548\u914D\u7F6E\u65F6\u53D1\u73B0 {field} \u6307\u5411\u4E0D\u5B58\u5728\u7684 Provider\u3002HAI_REACH_PROVIDERS \u5F53\u524D\u4E3A []\u3002\u8BF7\u5220\u9664\u65E7\u7684\u7D22\u5F15\u53D8\u91CF\uFF0C\u5E76\u5728 .env.<\u73AF\u5883>.local \u4E2D\u7528 HAI_REACH_PROVIDERS \u914D\u7F6E\u5B8C\u6574\u7684\u901A\u77E5 Provider \u5217\u8868\u3002",
|
|
510
|
-
deploy_s3Engine: "\u9009\u62E9\u81EA\u5EFA S3 \u670D\u52A1\u5B9E\u73B0"
|
|
514
|
+
deploy_s3Engine: "\u9009\u62E9\u81EA\u5EFA S3 \u670D\u52A1\u5B9E\u73B0",
|
|
515
|
+
deploy_downloadUnavailableTitle: "\u4E0B\u8F7D\u94FE\u63A5\u65E0\u6CD5\u8BBF\u95EE",
|
|
516
|
+
deploy_downloadUnavailableInstruction: "\u8BF7\u8FD4\u56DE\u4E0B\u8F7D\u9875\u9762\u91CD\u65B0\u83B7\u53D6\u94FE\u63A5\u3002\u82E5\u4ECD\u65E0\u6CD5\u4E0B\u8F7D\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u3002"
|
|
511
517
|
};
|
|
512
518
|
|
|
513
519
|
// src/deploy-i18n.ts
|
|
@@ -1457,7 +1463,26 @@ var deploy_config_shapes_default = {
|
|
|
1457
1463
|
type: "string",
|
|
1458
1464
|
format: "uri"
|
|
1459
1465
|
},
|
|
1466
|
+
multipart: {
|
|
1467
|
+
default: {},
|
|
1468
|
+
type: "object",
|
|
1469
|
+
properties: {
|
|
1470
|
+
partSizeBytes: {
|
|
1471
|
+
default: 5242880,
|
|
1472
|
+
type: "integer",
|
|
1473
|
+
minimum: 5242880,
|
|
1474
|
+
maximum: 5368709120
|
|
1475
|
+
},
|
|
1476
|
+
queueSize: {
|
|
1477
|
+
default: 2,
|
|
1478
|
+
type: "integer",
|
|
1479
|
+
minimum: 1,
|
|
1480
|
+
maximum: 9007199254740991
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
},
|
|
1460
1484
|
operationLog: {
|
|
1485
|
+
default: {},
|
|
1461
1486
|
type: "object",
|
|
1462
1487
|
properties: {
|
|
1463
1488
|
read: {
|
|
@@ -1465,7 +1490,7 @@ var deploy_config_shapes_default = {
|
|
|
1465
1490
|
type: "boolean"
|
|
1466
1491
|
},
|
|
1467
1492
|
write: {
|
|
1468
|
-
default:
|
|
1493
|
+
default: true,
|
|
1469
1494
|
type: "boolean"
|
|
1470
1495
|
},
|
|
1471
1496
|
maxLength: {
|
|
@@ -1473,15 +1498,6 @@ var deploy_config_shapes_default = {
|
|
|
1473
1498
|
type: "integer",
|
|
1474
1499
|
minimum: 0,
|
|
1475
1500
|
maximum: 9007199254740991
|
|
1476
|
-
},
|
|
1477
|
-
level: {
|
|
1478
|
-
default: "debug",
|
|
1479
|
-
type: "string",
|
|
1480
|
-
enum: [
|
|
1481
|
-
"info",
|
|
1482
|
-
"debug",
|
|
1483
|
-
"trace"
|
|
1484
|
-
]
|
|
1485
1501
|
}
|
|
1486
1502
|
}
|
|
1487
1503
|
}
|
|
@@ -1514,6 +1530,7 @@ var deploy_config_shapes_default = {
|
|
|
1514
1530
|
type: "number"
|
|
1515
1531
|
},
|
|
1516
1532
|
operationLog: {
|
|
1533
|
+
default: {},
|
|
1517
1534
|
type: "object",
|
|
1518
1535
|
properties: {
|
|
1519
1536
|
read: {
|
|
@@ -1521,7 +1538,7 @@ var deploy_config_shapes_default = {
|
|
|
1521
1538
|
type: "boolean"
|
|
1522
1539
|
},
|
|
1523
1540
|
write: {
|
|
1524
|
-
default:
|
|
1541
|
+
default: true,
|
|
1525
1542
|
type: "boolean"
|
|
1526
1543
|
},
|
|
1527
1544
|
maxLength: {
|
|
@@ -1529,15 +1546,6 @@ var deploy_config_shapes_default = {
|
|
|
1529
1546
|
type: "integer",
|
|
1530
1547
|
minimum: 0,
|
|
1531
1548
|
maximum: 9007199254740991
|
|
1532
|
-
},
|
|
1533
|
-
level: {
|
|
1534
|
-
default: "debug",
|
|
1535
|
-
type: "string",
|
|
1536
|
-
enum: [
|
|
1537
|
-
"info",
|
|
1538
|
-
"debug",
|
|
1539
|
-
"trace"
|
|
1540
|
-
]
|
|
1541
1549
|
}
|
|
1542
1550
|
}
|
|
1543
1551
|
}
|
|
@@ -10354,6 +10362,87 @@ async function copyArchive(source, destination) {
|
|
|
10354
10362
|
await pipeline(createReadStream(source), digest, createWriteStream(destination, { mode: 384 }));
|
|
10355
10363
|
return hash.digest("hex");
|
|
10356
10364
|
}
|
|
10365
|
+
|
|
10366
|
+
// src/container/deploy-download-error.ts
|
|
10367
|
+
var PAGE_STYLE = `
|
|
10368
|
+
* { box-sizing: border-box; }
|
|
10369
|
+
body {
|
|
10370
|
+
margin: 0;
|
|
10371
|
+
min-height: 100vh;
|
|
10372
|
+
display: grid;
|
|
10373
|
+
place-items: center;
|
|
10374
|
+
padding: 24px;
|
|
10375
|
+
background: #f1f5f9;
|
|
10376
|
+
color: #172033;
|
|
10377
|
+
font-family: Inter, system-ui, "Microsoft YaHei", sans-serif;
|
|
10378
|
+
line-height: 1.7;
|
|
10379
|
+
}
|
|
10380
|
+
main {
|
|
10381
|
+
width: min(100%, 640px);
|
|
10382
|
+
padding: clamp(24px, 6vw, 48px);
|
|
10383
|
+
border: 1px solid #dbe3ee;
|
|
10384
|
+
border-top: 4px solid #2563eb;
|
|
10385
|
+
border-radius: 12px;
|
|
10386
|
+
background: #fff;
|
|
10387
|
+
}
|
|
10388
|
+
h1 { margin: 0 0 16px; font-size: clamp(24px, 5vw, 32px); line-height: 1.4; }
|
|
10389
|
+
p { margin: 0; color: #475569; font-size: 16px; }
|
|
10390
|
+
`;
|
|
10391
|
+
function escapeHtml(value) {
|
|
10392
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
10393
|
+
}
|
|
10394
|
+
function renderPage() {
|
|
10395
|
+
return `<!doctype html>
|
|
10396
|
+
<html lang="$hai_download_language">
|
|
10397
|
+
<head>
|
|
10398
|
+
<meta charset="utf-8">
|
|
10399
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10400
|
+
<meta name="robots" content="noindex">
|
|
10401
|
+
<meta name="referrer" content="no-referrer">
|
|
10402
|
+
<link rel="icon" href="data:,">
|
|
10403
|
+
<title>$hai_download_title</title>
|
|
10404
|
+
<style>${PAGE_STYLE}</style>
|
|
10405
|
+
</head>
|
|
10406
|
+
<body><main><h1>$hai_download_title</h1><p>$hai_download_instruction</p></main></body>
|
|
10407
|
+
</html>`;
|
|
10408
|
+
}
|
|
10409
|
+
function renderDownloadErrorMaps() {
|
|
10410
|
+
return `map "$request_method:$args" $hai_signed_download {
|
|
10411
|
+
default 0;
|
|
10412
|
+
"~*^(GET|HEAD):(?:[^&]*&)*X-Amz-Signature=[^&]+(?:&|$)" 1;
|
|
10413
|
+
}
|
|
10414
|
+
map $http_accept_language $hai_download_language {
|
|
10415
|
+
default zh-CN;
|
|
10416
|
+
~*^en en-US;
|
|
10417
|
+
~*^ja ja-JP;
|
|
10418
|
+
}
|
|
10419
|
+
map $hai_download_language $hai_download_title {
|
|
10420
|
+
default ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableTitle", { locale: "zh-CN" })))};
|
|
10421
|
+
en-US ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableTitle", { locale: "en-US" })))};
|
|
10422
|
+
ja-JP ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableTitle", { locale: "ja-JP" })))};
|
|
10423
|
+
}
|
|
10424
|
+
map $hai_download_language $hai_download_instruction {
|
|
10425
|
+
default ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableInstruction", { locale: "zh-CN" })))};
|
|
10426
|
+
en-US ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableInstruction", { locale: "en-US" })))};
|
|
10427
|
+
ja-JP ${JSON.stringify(escapeHtml(deployM("deploy_downloadUnavailableInstruction", { locale: "ja-JP" })))};
|
|
10428
|
+
}
|
|
10429
|
+
`;
|
|
10430
|
+
}
|
|
10431
|
+
function renderDownloadErrorLocation() {
|
|
10432
|
+
return ` location @hai_download_unavailable {
|
|
10433
|
+
access_log off;
|
|
10434
|
+
error_log /dev/null;
|
|
10435
|
+
types { }
|
|
10436
|
+
default_type text/html;
|
|
10437
|
+
charset utf-8;
|
|
10438
|
+
add_header Cache-Control "private, no-store" always;
|
|
10439
|
+
add_header Referrer-Policy no-referrer always;
|
|
10440
|
+
add_header X-Content-Type-Options nosniff always;
|
|
10441
|
+
add_header Content-Security-Policy "default-src 'none'; style-src 'unsafe-inline'; base-uri 'none'; form-action 'none'; frame-ancestors 'none'" always;
|
|
10442
|
+
return 404 ${JSON.stringify(renderPage())};
|
|
10443
|
+
}
|
|
10444
|
+
`;
|
|
10445
|
+
}
|
|
10357
10446
|
var CERTBOT_IMAGE = "docker.io/certbot/certbot:v5.9.0";
|
|
10358
10447
|
function createHttpsAssets(config, projectDirectory) {
|
|
10359
10448
|
const assets = {
|
|
@@ -11088,6 +11177,7 @@ function generateWebProxyConfig(port, apiPrefix, options = {}) {
|
|
|
11088
11177
|
}
|
|
11089
11178
|
`).join("");
|
|
11090
11179
|
return `include /tmp/hai-dns.conf;
|
|
11180
|
+
${renderDownloadErrorMaps()}
|
|
11091
11181
|
${renderResolvedUpstream("hai_serv_backend", "serv", port)}${options.storageBucket ? renderStorageUpstream(options.storageBucket, options.storageBasePath) : ""}server {
|
|
11092
11182
|
listen ${webPort};
|
|
11093
11183
|
server_name _;
|
|
@@ -11171,17 +11261,7 @@ function generateApplicationProxyConfig(options) {
|
|
|
11171
11261
|
const bodyLimits = resolveTransportBodyLimits(maxPlaintextBytes);
|
|
11172
11262
|
const trustedEdges = renderTrustedEdgeProxies(options.trustedEdgeProxies);
|
|
11173
11263
|
const forwardedProtocol = options.trustedEdgeProxies?.length ? "$hai_request_scheme" : "$scheme";
|
|
11174
|
-
|
|
11175
|
-
${renderResolvedUpstream("hai_application_backend", primaryService, port)}${renderTrustedEdgeProtocol(options.trustedEdgeProxies)}${bucket ? renderStorageUpstream(bucket, options.storageBasePath) : ""}server {
|
|
11176
|
-
listen 8080;
|
|
11177
|
-
server_name _;
|
|
11178
|
-
${trustedEdges} large_client_header_buffers 4 32k;
|
|
11179
|
-
${bucket ? renderStorageLocation(bucket, reservedPaths, options.storageBasePath) : ""} location = /_hai/gateway-health {
|
|
11180
|
-
access_log off;
|
|
11181
|
-
return 200 'ok';
|
|
11182
|
-
}
|
|
11183
|
-
location / {
|
|
11184
|
-
client_max_body_size ${bodyLimits.encryptedPayloadBytes};
|
|
11264
|
+
const proxySettings = ` client_max_body_size ${bodyLimits.encryptedPayloadBytes};
|
|
11185
11265
|
proxy_pass http://hai_application_backend;
|
|
11186
11266
|
proxy_http_version 1.1;
|
|
11187
11267
|
proxy_set_header Host $http_host;
|
|
@@ -11195,7 +11275,29 @@ ${bucket ? renderStorageLocation(bucket, reservedPaths, options.storageBasePath)
|
|
|
11195
11275
|
proxy_request_buffering off;
|
|
11196
11276
|
proxy_buffering off;
|
|
11197
11277
|
proxy_buffer_size 32k;
|
|
11198
|
-
proxy_buffers 8 32k
|
|
11278
|
+
proxy_buffers 8 32k;`;
|
|
11279
|
+
return `include /tmp/hai-dns.conf;
|
|
11280
|
+
${renderDownloadErrorMaps()}
|
|
11281
|
+
${renderResolvedUpstream("hai_application_backend", primaryService, port)}${renderTrustedEdgeProtocol(options.trustedEdgeProxies)}${bucket ? renderStorageUpstream(bucket, options.storageBasePath) : ""}server {
|
|
11282
|
+
listen 8080;
|
|
11283
|
+
server_name _;
|
|
11284
|
+
${trustedEdges} large_client_header_buffers 4 32k;
|
|
11285
|
+
${bucket ? renderStorageLocation(bucket, reservedPaths, options.storageBasePath) : ""} location = /_hai/gateway-health {
|
|
11286
|
+
access_log off;
|
|
11287
|
+
return 200 'ok';
|
|
11288
|
+
}
|
|
11289
|
+
${renderDownloadErrorLocation()} location / {
|
|
11290
|
+
recursive_error_pages on;
|
|
11291
|
+
error_page 418 = @hai_download_proxy;
|
|
11292
|
+
if ($hai_signed_download) { return 418; }
|
|
11293
|
+
${proxySettings}
|
|
11294
|
+
}
|
|
11295
|
+
location @hai_download_proxy {
|
|
11296
|
+
access_log off;
|
|
11297
|
+
error_log /dev/null;
|
|
11298
|
+
proxy_intercept_errors on;
|
|
11299
|
+
error_page 404 = @hai_download_unavailable;
|
|
11300
|
+
${proxySettings}
|
|
11199
11301
|
}
|
|
11200
11302
|
}
|
|
11201
11303
|
`;
|
|
@@ -11234,24 +11336,35 @@ map "$hai_trusted_edge:$http_x_forwarded_proto" $hai_request_scheme {
|
|
|
11234
11336
|
function renderWebLocation(webBasePath) {
|
|
11235
11337
|
if (webBasePath && (!/^\/[\w.-]+(?:\/[\w.-]+)*$/.test(webBasePath) || webBasePath.split("/").some((segment) => segment === "." || segment === "..") || ["/health", "/_hai/web-health"].includes(webBasePath)))
|
|
11236
11338
|
throw new Error("Invalid web base path");
|
|
11237
|
-
|
|
11339
|
+
const fallback = `${renderDownloadErrorLocation()} location @hai_spa_fallback {
|
|
11340
|
+
error_page 418 = @hai_download_unavailable;
|
|
11341
|
+
if ($hai_signed_download) { return 418; }
|
|
11342
|
+
try_files /index.html =404;
|
|
11343
|
+
}
|
|
11344
|
+
`;
|
|
11345
|
+
return fallback + (webBasePath ? ` absolute_redirect off;
|
|
11238
11346
|
location = ${webBasePath} {
|
|
11239
11347
|
return 308 ${webBasePath}/$is_args$args;
|
|
11240
11348
|
}
|
|
11241
11349
|
location ${webBasePath}/ {
|
|
11242
11350
|
rewrite ^${webBasePath.replaceAll(".", "\\.").replaceAll("-", "\\-")}/(.*)$ /$1 break;
|
|
11243
|
-
try_files $uri/index.html $uri
|
|
11351
|
+
try_files $uri/index.html $uri @hai_spa_fallback;
|
|
11352
|
+
}
|
|
11353
|
+
location / {
|
|
11354
|
+
error_page 418 = @hai_download_unavailable;
|
|
11355
|
+
if ($hai_signed_download) { return 418; }
|
|
11356
|
+
return 404;
|
|
11244
11357
|
}
|
|
11245
|
-
location / { return 404; }
|
|
11246
11358
|
` : ` location / {
|
|
11247
|
-
try_files $uri $uri/
|
|
11359
|
+
try_files $uri $uri/ @hai_spa_fallback;
|
|
11248
11360
|
}
|
|
11249
|
-
|
|
11361
|
+
`);
|
|
11250
11362
|
}
|
|
11251
11363
|
function generateStaticWebConfig(port, webBasePath) {
|
|
11252
11364
|
if (!Number.isInteger(port) || port < 1 || port > 65535)
|
|
11253
11365
|
throw new Error("Invalid web proxy target");
|
|
11254
|
-
return
|
|
11366
|
+
return `${renderDownloadErrorMaps()}
|
|
11367
|
+
server {
|
|
11255
11368
|
listen ${port};
|
|
11256
11369
|
server_name _;
|
|
11257
11370
|
root /usr/share/nginx/html;
|
|
@@ -12042,7 +12155,7 @@ function createVercelProvider() {
|
|
|
12042
12155
|
);
|
|
12043
12156
|
token = apiToken;
|
|
12044
12157
|
const username = user.user.username || user.user.email;
|
|
12045
|
-
logger6.info("Vercel authenticated"
|
|
12158
|
+
logger6.info("Vercel authenticated");
|
|
12046
12159
|
return ok(username);
|
|
12047
12160
|
} catch (error) {
|
|
12048
12161
|
logger6.error("Vercel authentication failed", { error });
|
|
@@ -12252,7 +12365,7 @@ function createAliyunProvisioner() {
|
|
|
12252
12365
|
accessKey = akId;
|
|
12253
12366
|
secretKey = akSecret;
|
|
12254
12367
|
signName = credentials.signName;
|
|
12255
|
-
logger7.info("Aliyun authenticated"
|
|
12368
|
+
logger7.info("Aliyun authenticated");
|
|
12256
12369
|
return ok(akId);
|
|
12257
12370
|
} catch (error) {
|
|
12258
12371
|
logger7.error("Aliyun authentication failed", { error });
|
|
@@ -12493,7 +12606,7 @@ function createR2Provisioner() {
|
|
|
12493
12606
|
token = apiTok;
|
|
12494
12607
|
accessKey = credentials.accessKeyId;
|
|
12495
12608
|
secretKey = credentials.secretAccessKey;
|
|
12496
|
-
logger9.info("Cloudflare R2 authenticated"
|
|
12609
|
+
logger9.info("Cloudflare R2 authenticated");
|
|
12497
12610
|
return ok(acctId);
|
|
12498
12611
|
} catch (error) {
|
|
12499
12612
|
logger9.error("Cloudflare R2 authentication failed", { error });
|
|
@@ -12716,7 +12829,7 @@ function createUpstashProvisioner() {
|
|
|
12716
12829
|
await listUpstashDatabases(userEmail, userKey);
|
|
12717
12830
|
email = userEmail;
|
|
12718
12831
|
apiKey = userKey;
|
|
12719
|
-
logger11.info("Upstash authenticated"
|
|
12832
|
+
logger11.info("Upstash authenticated");
|
|
12720
12833
|
return ok(userEmail);
|
|
12721
12834
|
} catch (error) {
|
|
12722
12835
|
logger11.error("Upstash authentication failed", { error });
|
|
@@ -12925,10 +13038,8 @@ var deploy = {
|
|
|
12925
13038
|
} else {
|
|
12926
13039
|
provider = createProviderByType(parsed.provider.type);
|
|
12927
13040
|
const authResult = await provider.authenticate(parsed.provider.token);
|
|
12928
|
-
if (!authResult.success)
|
|
13041
|
+
if (!authResult.success)
|
|
12929
13042
|
return err(authResult.error);
|
|
12930
|
-
}
|
|
12931
|
-
logger12.info("Provider authenticated", { provider: parsed.provider.type, user: authResult.data });
|
|
12932
13043
|
}
|
|
12933
13044
|
currentProvisioners.clear();
|
|
12934
13045
|
if (parsed.services) {
|
|
@@ -12942,14 +13053,16 @@ var deploy = {
|
|
|
12942
13053
|
if (!provAuthResult.success) {
|
|
12943
13054
|
logger12.error("Provisioner authentication failed", {
|
|
12944
13055
|
service: serviceType,
|
|
12945
|
-
provisioner: serviceConfig.provisioner
|
|
13056
|
+
provisioner: serviceConfig.provisioner,
|
|
13057
|
+
errorCode: provAuthResult.error.code,
|
|
13058
|
+
traceId: provAuthResult.error.traceId
|
|
12946
13059
|
});
|
|
12947
13060
|
currentProvisioners.clear();
|
|
12948
13061
|
return err(provAuthResult.error);
|
|
12949
13062
|
}
|
|
12950
13063
|
logger12.info("Provisioner authenticated", {
|
|
12951
13064
|
service: serviceType,
|
|
12952
|
-
|
|
13065
|
+
provisioner: provisioner.name
|
|
12953
13066
|
});
|
|
12954
13067
|
currentProvisioners.set(serviceType, provisioner);
|
|
12955
13068
|
}
|