@cloudbase/manager-node 5.7.0-beta.3 → 5.7.1-beta.0

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.
Files changed (64) hide show
  1. package/jest.config.unit.js +14 -0
  2. package/lib/cloudApp/index.js +3 -12
  3. package/lib/env/index.js +9 -0
  4. package/lib/environment.js +0 -11
  5. package/lib/function/index.js +67 -26
  6. package/lib/hosting/index.js +1 -4
  7. package/lib/index.js +0 -31
  8. package/lib/storage/index.js +7 -6
  9. package/lib/utils/index.js +5 -62
  10. package/package.json +1 -2
  11. package/types/cloudApp/index.d.ts +0 -4
  12. package/types/cloudApp/types.d.ts +6 -87
  13. package/types/env/index.d.ts +8 -1
  14. package/types/env/type.d.ts +97 -6
  15. package/types/environment.d.ts +0 -7
  16. package/types/function/index.d.ts +3 -0
  17. package/types/function/types.d.ts +0 -15
  18. package/types/hosting/index.d.ts +0 -6
  19. package/types/index.d.ts +0 -18
  20. package/types/interfaces/function.interface.d.ts +1 -1
  21. package/types/storage/index.d.ts +0 -6
  22. package/types/utils/index.d.ts +0 -13
  23. package/lib/deploy/DatabaseDeployer.js +0 -238
  24. package/lib/deploy/DeployOrchestrator.js +0 -632
  25. package/lib/deploy/FunctionDeployer.js +0 -611
  26. package/lib/deploy/GatewayDeployer.js +0 -612
  27. package/lib/deploy/StateStore.js +0 -327
  28. package/lib/deploy/StaticDeployer.js +0 -239
  29. package/lib/deploy/domain.js +0 -41
  30. package/lib/deploy/framework.js +0 -105
  31. package/lib/deploy/function/artifact.js +0 -207
  32. package/lib/deploy/function/builders/cloud.js +0 -536
  33. package/lib/deploy/function/cam-preflight.js +0 -157
  34. package/lib/deploy/function/cloud-build-service.js +0 -170
  35. package/lib/deploy/function/config-guard.js +0 -592
  36. package/lib/deploy/function/docker-preflight.js +0 -87
  37. package/lib/deploy/function/image-preflight.js +0 -164
  38. package/lib/deploy/function/local-builder.js +0 -129
  39. package/lib/deploy/function/planner.js +0 -282
  40. package/lib/deploy/function/preflight.js +0 -264
  41. package/lib/deploy/types.js +0 -99
  42. package/lib/projectValidator/index.js +0 -440
  43. package/lib/projectValidator/types.js +0 -2
  44. package/types/deploy/DatabaseDeployer.d.ts +0 -70
  45. package/types/deploy/DeployOrchestrator.d.ts +0 -168
  46. package/types/deploy/FunctionDeployer.d.ts +0 -158
  47. package/types/deploy/GatewayDeployer.d.ts +0 -194
  48. package/types/deploy/StateStore.d.ts +0 -170
  49. package/types/deploy/StaticDeployer.d.ts +0 -97
  50. package/types/deploy/domain.d.ts +0 -17
  51. package/types/deploy/framework.d.ts +0 -23
  52. package/types/deploy/function/artifact.d.ts +0 -40
  53. package/types/deploy/function/builders/cloud.d.ts +0 -110
  54. package/types/deploy/function/cam-preflight.d.ts +0 -51
  55. package/types/deploy/function/cloud-build-service.d.ts +0 -10
  56. package/types/deploy/function/config-guard.d.ts +0 -41
  57. package/types/deploy/function/docker-preflight.d.ts +0 -17
  58. package/types/deploy/function/image-preflight.d.ts +0 -21
  59. package/types/deploy/function/local-builder.d.ts +0 -26
  60. package/types/deploy/function/planner.d.ts +0 -15
  61. package/types/deploy/function/preflight.d.ts +0 -9
  62. package/types/deploy/types.d.ts +0 -429
  63. package/types/projectValidator/index.d.ts +0 -38
  64. package/types/projectValidator/types.d.ts +0 -26
@@ -1,6 +1,6 @@
1
1
  import { Environment } from '../environment';
2
2
  import { IResponseInfo, AuthDomain, EnvInfo, LoginConfigItem, ICheckTcbServiceRes, ICreatePostpayRes, EnvBillingInfoItem, PriceResult } from '../interfaces';
3
- import { CalculatePackageCreatePriceParams, CalculatePackageRenewPriceParams, CalculatePackageModifyPriceParams, DescribeHttpServiceRouteParams, DescribeHttpServiceRouteRes, CreateHttpServiceRouteParams, CreateHttpServiceRouteRes, ModifyHttpServiceRouteParams, ModifyHttpServiceRouteRes, DeleteHttpServiceRouteParams, DeleteHttpServiceRouteRes, BindCustomDomainParams, BindCustomDomainRes, DeleteCustomDomainParams, DeleteCustomDomainRes } from './type';
3
+ import { CalculatePackageCreatePriceParams, CalculatePackageRenewPriceParams, CalculatePackageModifyPriceParams, DescribeHttpServiceRouteParams, DescribeHttpServiceRouteRes, VerifyHttpServiceRouteParams, VerifyHttpServiceRouteRes, CreateHttpServiceRouteParams, CreateHttpServiceRouteRes, ModifyHttpServiceRouteParams, ModifyHttpServiceRouteRes, DeleteHttpServiceRouteParams, DeleteHttpServiceRouteRes, BindCustomDomainParams, BindCustomDomainRes, DeleteCustomDomainParams, DeleteCustomDomainRes } from './type';
4
4
  import { CreateBillingDealParams, CreateEnvParams, BaasPackageInfo, DescribeBaasPackageListParams, ModifyEnvPlanParams, RenewEnvParams, DestroyEnvParams, DescribeEnvsParams, DescribeEnvInfoParams, DescribeEnvInfoResponse, DescribeEnvAccountCircleParams, DescribeEnvAccountCircleRes, DescribeCreditsUsageDetailParams, EnvPkgCreditsUsage } from '../interfaces/tcb.interface';
5
5
  type SOURCE = 'miniapp' | 'qcloud';
6
6
  interface IDeleteDomainRes {
@@ -888,6 +888,13 @@ export declare class EnvService {
888
888
  * @returns {Promise<DescribeHttpServiceRouteRes>}
889
889
  */
890
890
  describeHttpServiceRoute(params: DescribeHttpServiceRouteParams): Promise<DescribeHttpServiceRouteRes>;
891
+ /**
892
+ * 校验HTTP访问服务域名路由
893
+ * 此操作为只读预检,不会创建任何资源。
894
+ * @param {VerifyHttpServiceRouteParams} params 校验参数
895
+ * @returns {Promise<VerifyHttpServiceRouteRes>}
896
+ */
897
+ verifyHttpServiceRoute(params: VerifyHttpServiceRouteParams): Promise<VerifyHttpServiceRouteRes>;
891
898
  /**
892
899
  * 创建HTTP访问服务域名路由
893
900
  * @param {CreateHttpServiceRouteParams} params 创建参数
@@ -35,18 +35,43 @@ export interface HTTPServicePathRewrite {
35
35
  StaticStorePrefix?: string;
36
36
  Prefix?: string;
37
37
  }
38
+ /**
39
+ * HTTP 访问服务路由添加 header 配置
40
+ */
41
+ export interface HTTPServiceHeaderToAdd {
42
+ Key?: string;
43
+ Value?: string;
44
+ Action?: 'APPEND_IF_EXISTS_OR_ADD' | 'ADD_IF_ABSENT' | 'OVERWRITE_IF_EXISTS_OR_ADD' | 'OVERWRITE_IF_EXISTS';
45
+ }
46
+ /**
47
+ * HTTP 访问服务路由 headers 处理配置
48
+ */
49
+ export interface HTTPServiceHeadersHandler {
50
+ RequestHeadersToAdd?: HTTPServiceHeaderToAdd[];
51
+ RequestHeadersToRemove?: string[];
52
+ ResponseHeadersToAdd?: HTTPServiceHeaderToAdd[];
53
+ ResponseHeadersToRemove?: string[];
54
+ }
55
+ /**
56
+ * HTTP访问服务路由扩展字段
57
+ */
58
+ export interface HTTPServiceExtension {
59
+ HeadersHandler?: HTTPServiceHeadersHandler;
60
+ [key: string]: unknown;
61
+ }
38
62
  /**
39
63
  * HTTP访问服务路由信息
40
64
  */
41
65
  export interface HTTPServiceRoute {
42
66
  Path: string;
43
67
  PathRewrite?: HTTPServicePathRewrite;
44
- UpstreamResourceType: 'SCF' | 'CBR' | 'STATIC_STORE' | 'WEB_SCF' | 'LH';
68
+ UpstreamResourceType: 'SCF' | 'CBR' | 'STATIC_STORE' | 'WEB_SCF' | 'LH' | 'STORAGE';
45
69
  UpstreamResourceName: string;
46
70
  EnableSafeDomain: boolean;
47
71
  EnableAuth: boolean;
48
72
  EnablePathTransmission: boolean;
49
73
  QPSPolicy?: HTTPServiceRouteQPSPolicy;
74
+ Extension?: HTTPServiceExtension;
50
75
  Enable: boolean;
51
76
  CreateTime: string;
52
77
  UpdateTime: string;
@@ -57,7 +82,7 @@ export interface HTTPServiceRoute {
57
82
  export interface HTTPServiceDomain {
58
83
  Domain: string;
59
84
  DomainType: 'HTTPSERVICE' | 'CBR' | 'ANYSERVICE' | 'AI_AGENT' | 'VM' | 'INTEGRATION_CALLBACK';
60
- AccessType: 'DIRECT' | 'CDN' | 'CUSTOM';
85
+ AccessType: 'DIRECT' | 'CDN' | 'CUSTOM' | 'EO';
61
86
  CertId: string;
62
87
  Protocol: 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP';
63
88
  Cname: string;
@@ -66,6 +91,7 @@ export interface HTTPServiceDomain {
66
91
  Status: 'PROCESSING' | 'FAIL' | 'SUCCESS';
67
92
  DNSStatus: 'OK' | 'INVALID';
68
93
  Routes?: HTTPServiceRoute[];
94
+ Extension?: HTTPServiceExtension;
69
95
  CreateTime: string;
70
96
  UpdateTime: string;
71
97
  }
@@ -99,13 +125,14 @@ export interface DescribeHttpServiceRouteRes {
99
125
  */
100
126
  export interface HTTPServiceRouteParam {
101
127
  Path: string;
102
- UpstreamResourceType?: 'SCF' | 'CBR' | 'STATIC_STORE' | 'WEB_SCF' | 'LH';
128
+ UpstreamResourceType?: 'SCF' | 'CBR' | 'STATIC_STORE' | 'WEB_SCF' | 'LH' | 'STORAGE';
103
129
  UpstreamResourceName?: string;
104
130
  PathRewrite?: HTTPServicePathRewrite;
105
131
  EnableSafeDomain?: boolean;
106
132
  EnableAuth?: boolean;
107
133
  EnablePathTransmission?: boolean;
108
134
  QPSPolicy?: HTTPServiceRouteQPSPolicy;
135
+ Extension?: HTTPServiceExtension;
109
136
  Enable?: boolean;
110
137
  }
111
138
  /**
@@ -115,10 +142,74 @@ export interface HTTPServiceDomainParam {
115
142
  Domain: string;
116
143
  AccessType?: 'DIRECT' | 'CDN' | 'CUSTOM' | 'EO';
117
144
  CertId?: string;
118
- Protocol?: 'HTTP' | 'HTTPS' | 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP';
145
+ Protocol?: 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP';
119
146
  CustomCname?: string;
120
147
  Enable?: boolean;
121
148
  Routes?: HTTPServiceRouteParam[];
149
+ Extension?: HTTPServiceExtension;
150
+ }
151
+ /**
152
+ * 前置校验检查状态
153
+ */
154
+ export type VerifyHttpServiceRouteCheckStatus = 'PASS' | 'SKIPPED' | 'FAIL';
155
+ /**
156
+ * 前置校验失败原因
157
+ */
158
+ export type VerifyHttpServiceRouteCheckCode = 'INTERNAL_CHECK_ERROR' | 'OWNERSHIP_DNS_LOOKUP_FAILED' | 'OWNERSHIP_VERIFY_FAILED' | 'CERT_VERIFY_FAILED' | 'QUOTA_EXCEEDED' | 'ROUTE_CONFLICT' | 'DOMAIN_IN_USE' | 'NON_INTERNAL_ACCOUNT' | 'DOMAIN_IN_BLACKLIST' | 'CDN_RESOURCE_PROCESSING' | 'CDN_RESOURCE_OFFLINE' | 'EO_OWNERSHIP_VERIFY_FAILED' | 'EO_DOMAIN_NOT_ICP' | 'EO_DOMAIN_IN_USE';
159
+ /**
160
+ * 域名归属权 DNS 验证指引
161
+ */
162
+ export interface OwnershipVerificationDnsInfo {
163
+ Subdomain?: string;
164
+ RecordType?: string;
165
+ RecordValue?: string;
166
+ }
167
+ /**
168
+ * 域名归属权文件验证指引
169
+ */
170
+ export interface OwnershipVerificationFileInfo {
171
+ Path?: string;
172
+ Content?: string;
173
+ }
174
+ /**
175
+ * 域名归属权验证指引
176
+ */
177
+ export interface OwnershipVerificationInfo {
178
+ Domain?: string;
179
+ DnsVerification?: OwnershipVerificationDnsInfo[];
180
+ FileVerification?: OwnershipVerificationFileInfo[];
181
+ }
182
+ /**
183
+ * VerifyHTTPServiceRoute 单项前置校验结果
184
+ */
185
+ export interface VerifyHttpServiceRouteCheckItem {
186
+ Status: VerifyHttpServiceRouteCheckStatus;
187
+ Code?: VerifyHttpServiceRouteCheckCode;
188
+ Message?: string;
189
+ OwnershipVerification?: OwnershipVerificationInfo;
190
+ }
191
+ /**
192
+ * VerifyHTTPServiceRoute 请求参数
193
+ */
194
+ export interface VerifyHttpServiceRouteParams {
195
+ EnvId: string;
196
+ Domain: HTTPServiceDomainParam;
197
+ }
198
+ /**
199
+ * VerifyHTTPServiceRoute 返回结果
200
+ */
201
+ export interface VerifyHttpServiceRouteRes {
202
+ Passed: boolean;
203
+ Ownership: VerifyHttpServiceRouteCheckItem;
204
+ Cert: VerifyHttpServiceRouteCheckItem;
205
+ Quota: VerifyHttpServiceRouteCheckItem;
206
+ RouteConflict: VerifyHttpServiceRouteCheckItem;
207
+ DomainConflict: VerifyHttpServiceRouteCheckItem;
208
+ InternalAccount: VerifyHttpServiceRouteCheckItem;
209
+ Blacklist: VerifyHttpServiceRouteCheckItem;
210
+ CDNResource: VerifyHttpServiceRouteCheckItem;
211
+ EO: VerifyHttpServiceRouteCheckItem;
212
+ RequestId: string;
122
213
  }
123
214
  /**
124
215
  * CreateHTTPServiceRoute 请求参数
@@ -167,8 +258,8 @@ export interface DeleteHttpServiceRouteRes {
167
258
  export interface BindCustomDomainDomainParam {
168
259
  Domain: string;
169
260
  CertId: string;
170
- AccessType?: 'DIRECT' | 'CDN' | 'CUSTOM' | 'EO';
171
- Protocol?: 'HTTP' | 'HTTPS' | 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP';
261
+ AccessType?: 'DIRECT' | 'CDN' | 'CUSTOM';
262
+ Protocol?: 'HTTP_AND_HTTPS' | 'HTTP_TO_HTTPS' | 'HTTPS_TO_HTTP';
172
263
  Enable?: boolean;
173
264
  CustomCname?: string;
174
265
  }
@@ -1,6 +1,5 @@
1
1
  import { DatabaseService } from './database';
2
2
  import { FunctionService } from './function';
3
- import { FunctionDeployer } from './deploy/FunctionDeployer';
4
3
  import { CloudRunService } from './cloudrun';
5
4
  import { AgentService } from './agent';
6
5
  import { StorageService } from './storage';
@@ -28,7 +27,6 @@ export declare class Environment {
28
27
  private envId;
29
28
  private envType?;
30
29
  private functionService;
31
- private functionDeployer;
32
30
  private cloudRunService;
33
31
  private agentService;
34
32
  private databaseService;
@@ -54,11 +52,6 @@ export declare class Environment {
54
52
  getStorageService(): StorageService;
55
53
  getDatabaseService(): DatabaseService;
56
54
  getFunctionService(): FunctionService;
57
- /**
58
- * 获取函数部署编排器
59
- * 采用懒初始化,避免模块循环引用导致的初始化顺序问题
60
- */
61
- getFunctionDeployer(): FunctionDeployer;
62
55
  getCloudRunService(): CloudRunService;
63
56
  getAgentService(): AgentService;
64
57
  getEnvService(): EnvService;
@@ -232,6 +232,9 @@ export declare class FunctionService {
232
232
  private tcbService;
233
233
  private userService;
234
234
  constructor(environment: Environment);
235
+ private get useTcbFunctionApi();
236
+ private get functionCloudService();
237
+ private get namespaceParamKey();
235
238
  /**
236
239
  * 增量更新函数代码
237
240
  * @param {IUpdateFunctionIncrementalCodeParam} funcParam
@@ -105,21 +105,6 @@ export interface IFunctionInfo {
105
105
  Variables: IEnvVariable[];
106
106
  };
107
107
  Type: string;
108
- /** HTTP 函数协议类型;SCF 缺省时表示普通 HTTP */
109
- ProtocolType?: string;
110
- /** 自定义镜像函数配置 */
111
- ImageConfig?: {
112
- ImageType?: string;
113
- ImageUri?: string;
114
- RegistryId?: string;
115
- EntryPoint?: string;
116
- Command?: string;
117
- Args?: string;
118
- ContainerImageAccelerate?: boolean;
119
- ImagePort?: number;
120
- CommandList?: string[];
121
- ArgsList?: string[];
122
- };
123
108
  EipConfig: {
124
109
  EipFixed: 'FALSE' | 'TRUE';
125
110
  Eips: string[];
@@ -122,12 +122,6 @@ export interface IRoutingRules {
122
122
  export interface IBucketWebsiteOptiosn {
123
123
  indexDocument: string;
124
124
  errorDocument?: string;
125
- /** 错误文档是否保留原始 HTTP 状态码:Enabled / Disabled(SPA 回退需 Disabled) */
126
- originalHttpStatus?: string;
127
- /** 404 是否展示腾讯云公益页面:Enabled / Disabled(SPA 回退需 Disabled) */
128
- charity404?: string;
129
- /** 忽略 HTML 扩展名:Enabled / Disabled */
130
- autoAddressing?: string;
131
125
  routingRules?: Array<IRoutingRules>;
132
126
  }
133
127
  export interface IFindOptions {
package/types/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { EnvService } from './env';
2
2
  import { FunctionService } from './function';
3
- import { FunctionDeployer } from './deploy/FunctionDeployer';
4
3
  import { CloudRunService } from './cloudrun';
5
4
  import { AgentService } from './agent';
6
5
  import { StorageService } from './storage';
@@ -22,8 +21,6 @@ import { CloudAppService } from './cloudApp';
22
21
  import { AiModelService } from './aiModel';
23
22
  import { IntegrationService } from './integration';
24
23
  import { MonitorService } from './monitor';
25
- import { ProjectValidator } from './projectValidator';
26
- import { DeployOrchestrator } from './deploy/DeployOrchestrator';
27
24
  interface CloudBaseConfig {
28
25
  secretId?: string;
29
26
  secretKey?: string;
@@ -50,17 +47,10 @@ declare class CloudBase {
50
47
  private cloudBaseConfig;
51
48
  private environmentManager;
52
49
  private docsService;
53
- private projectValidatorService;
54
- private deployOrchestratorService;
55
50
  constructor(config?: CloudBaseConfig);
56
51
  addEnvironment(envId: string): void;
57
52
  currentEnvironment(): Environment;
58
53
  get functions(): FunctionService;
59
- /**
60
- * 函数部署编排器(FunctionDeployer)
61
- * 在现有 FunctionService 之上,按 buildStrategy 编排 Event/HTTP 函数的创建、更新与访问收敛
62
- */
63
- get functionDeployer(): FunctionDeployer;
64
54
  get cloudrun(): CloudRunService;
65
55
  get agent(): AgentService;
66
56
  get storage(): StorageService;
@@ -111,14 +101,6 @@ declare class CloudBase {
111
101
  */
112
102
  get monitor(): MonitorService;
113
103
  get docs(): DocsService;
114
- get projectValidator(): ProjectValidator;
115
- getProjectValidator(): ProjectValidator;
116
- /**
117
- * 声明式部署编排器
118
- * 顺序:database → functions → app → hosting → gateway;支持 dry-run / only / skip / 幂等重试
119
- */
120
- get deployOrchestrator(): DeployOrchestrator;
121
- getDeployOrchestrator(): DeployOrchestrator;
122
104
  getEnvironmentManager(): EnvironmentManager;
123
105
  getManagerConfig(): CloudBaseConfig;
124
106
  get isInternalEndpoint(): Boolean;
@@ -44,7 +44,7 @@ export interface ICloudFunction extends ICloudFunctionConfig {
44
44
  name: string;
45
45
  description?: string;
46
46
  type?: 'Event' | 'HTTP';
47
- protocolType?: 'HTTP' | 'WS';
47
+ protocolType?: 'WS';
48
48
  protocolParams?: {
49
49
  wsParams?: {
50
50
  idleTimeOut?: number;
@@ -49,12 +49,6 @@ export interface IRoutingRules {
49
49
  export interface IBucketWebsiteOptions {
50
50
  indexDocument: string;
51
51
  errorDocument?: string;
52
- /** 错误文档是否保留原始 HTTP 状态码:Enabled / Disabled(SPA 回退需 Disabled,否则 404 状态码使前端路由失效) */
53
- originalHttpStatus?: string;
54
- /** 404 是否展示腾讯云公益页面:Enabled / Disabled(SPA 回退需 Disabled,否则覆盖错误文档) */
55
- charity404?: string;
56
- /** 忽略 HTML 扩展名:Enabled / Disabled(未传则保持默认 Disabled) */
57
- autoAddressing?: string;
58
52
  routingRules?: Array<IRoutingRules>;
59
53
  region: string;
60
54
  bucket: string;
@@ -6,24 +6,11 @@ export * from './envLazy';
6
6
  export * from './fs';
7
7
  export * from './http-request';
8
8
  export { guid6 } from './uuid';
9
- interface IZipExtraEntry {
10
- /** zip 包内的相对路径 */
11
- zipPath: string;
12
- /** 文件文本内容 */
13
- content: string | Buffer;
14
- /** unix 权限位(八进制),如 0o755 */
15
- mode?: number;
16
- }
17
9
  interface IZipOption {
18
10
  dirPath: string;
19
11
  outputPath: string;
20
12
  ignore?: string | string[];
21
13
  pattern?: string;
22
- /**
23
- * 额外注入 zip 的文件条目(不来自 dirPath),用于把 SDK 生成的辅助文件
24
- * (如构建推送脚本)打进包内,而不污染用户源码目录。
25
- */
26
- extraEntries?: IZipExtraEntry[];
27
14
  }
28
15
  export declare function compressToZip(option: IZipOption): Promise<unknown>;
29
16
  /**
@@ -1,238 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DatabaseDeployer = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const error_1 = require("../error");
10
- /** migration 文件名正则:14位数字 + 下划线 + 小写字母下划线名称 + .sql */
11
- const MIGRATION_FILE_PATTERN = /^(\d{14})_([a-z_]+)\.sql$/;
12
- /** 轮询间隔(毫秒) */
13
- const POLL_INTERVAL_MS = 2000;
14
- /** 默认超时(毫秒) */
15
- const DEFAULT_TIMEOUT_MS = 3000000;
16
- class DatabaseDeployer {
17
- constructor(environment) {
18
- this.environment = environment;
19
- }
20
- /**
21
- * 从本地目录解析 migration 文件列表
22
- *
23
- * 文件名格式:{14位时间戳}_{小写下划线名称}.sql
24
- * 例如:20260526000000_create_users.sql
25
- *
26
- * 按文件名升序排列(即按版本号从早到晚)
27
- */
28
- parseMigrationFiles(migrationsDir) {
29
- if (!fs_1.default.existsSync(migrationsDir)) {
30
- throw new error_1.CloudBaseError(`数据库迁移目录不存在: ${migrationsDir}`);
31
- }
32
- const files = fs_1.default.readdirSync(migrationsDir)
33
- .filter(f => f.endsWith('.sql'))
34
- .sort();
35
- const migrations = [];
36
- for (const file of files) {
37
- const match = file.match(MIGRATION_FILE_PATTERN);
38
- if (!match) {
39
- throw new error_1.CloudBaseError(`migration 文件名格式错误: ${file},应为 {14位时间戳}_{小写下划线名称}.sql`);
40
- }
41
- const [, version, name] = match;
42
- const filePath = path_1.default.join(migrationsDir, file);
43
- const query = fs_1.default.readFileSync(filePath, 'utf-8');
44
- if (!query.trim()) {
45
- throw new error_1.CloudBaseError(`migration 文件内容为空: ${file}`);
46
- }
47
- migrations.push({ Version: version, Name: name, Query: query });
48
- }
49
- return migrations;
50
- }
51
- /**
52
- * 生成部署计划
53
- *
54
- * 调用 previewPGUserMigrations 获取云端对比结果,
55
- * 返回每条migration 的状态(pending / applied / conflict)
56
- */
57
- async plan(config, cwd, envId) {
58
- this.assertDatabaseType(config);
59
- const migrationsDir = this.resolveMigrationsDir(cwd, config.migrations);
60
- const migrations = this.parseMigrationFiles(migrationsDir);
61
- if (migrations.length === 0) {
62
- return [];
63
- }
64
- const dbService = this.environment.getDatabaseService();
65
- let preview;
66
- try {
67
- preview = await dbService.previewPGUserMigrations({
68
- EnvId: envId,
69
- Migrations: migrations
70
- });
71
- }
72
- catch (error) {
73
- const err = error;
74
- throw new error_1.CloudBaseError(`数据库迁移预览失败 [EnvId=${envId}]:${(err === null || err === void 0 ? void 0 : err.message) || String(error)}`, {
75
- requestId: (err === null || err === void 0 ? void 0 : err.RequestId) || (err === null || err === void 0 ? void 0 : err.requestId),
76
- original: err instanceof Error ? err : undefined
77
- });
78
- }
79
- const items = [];
80
- // pending:将要执行的
81
- for (const p of preview.Pending || []) {
82
- items.push({ version: p.Version, name: p.Name, status: 'pending' });
83
- }
84
- // applied:已经执行过的
85
- for (const a of preview.Applied || []) {
86
- items.push({ version: a.Version, name: a.Name, status: 'applied' });
87
- }
88
- // conflict:有冲突的
89
- for (const c of preview.Conflicts || []) {
90
- items.push({
91
- version: c.Version,
92
- name: c.Name || '',
93
- status: 'conflict',
94
- reason: c.Reason || c.Message || 'checksum mismatch'
95
- });
96
- }
97
- return items;
98
- }
99
- /**
100
- * 执行数据库迁移
101
- *
102
- * 流程:
103
- * 1. 解析本地 migration 文件
104
- * 2. 预览确认无冲突(有冲突直接 throw,中断整个部署)
105
- * 3. 无 pending 则跳过
106
- * 4. 提交 pushPGUserMigrations
107
- * 5. 轮询describeTaskResult 等待完成
108
- */
109
- async deploy(config, cwd, envId) {
110
- this.assertDatabaseType(config);
111
- const migrationsDir = this.resolveMigrationsDir(cwd, config.migrations);
112
- const migrations = this.parseMigrationFiles(migrationsDir);
113
- if (migrations.length === 0) {
114
- return { taskId: '' };
115
- }
116
- const dbService = this.environment.getDatabaseService();
117
- // 1. 预览:确认无冲突
118
- let preview;
119
- try {
120
- preview = await dbService.previewPGUserMigrations({
121
- EnvId: envId,
122
- Migrations: migrations
123
- });
124
- }
125
- catch (error) {
126
- const err = error;
127
- throw new error_1.CloudBaseError(`数据库迁移预览失败 [EnvId=${envId}]:${(err === null || err === void 0 ? void 0 : err.message) || String(error)}`, {
128
- requestId: (err === null || err === void 0 ? void 0 : err.RequestId) || (err === null || err === void 0 ? void 0 : err.requestId),
129
- original: err instanceof Error ? err : undefined
130
- });
131
- }
132
- if (!preview.Executable) {
133
- const conflictDetails = (preview.Conflicts || [])
134
- .map((c) => ` - ${c.Version}_${c.Name || '?'}: ${c.Reason || c.Message || 'unknown'}`)
135
- .join('\n');
136
- throw new error_1.CloudBaseError(`数据库迁移存在冲突,中断部署。请先解决以下冲突:\n${conflictDetails}`, {
137
- requestId: preview.RequestId
138
- });
139
- }
140
- // 2. 无 pending → 全部已applied,跳过
141
- if (!preview.Pending || preview.Pending.length === 0) {
142
- return { taskId: '' };
143
- }
144
- // 3. 提交执行
145
- let result;
146
- try {
147
- result = await dbService.pushPGUserMigrations({
148
- EnvId: envId,
149
- Migrations: migrations
150
- });
151
- }
152
- catch (error) {
153
- const err = error;
154
- throw new error_1.CloudBaseError(`数据库迁移提交失败 [EnvId=${envId}]:${(err === null || err === void 0 ? void 0 : err.message) || String(error)}`, {
155
- requestId: (err === null || err === void 0 ? void 0 : err.RequestId) || (err === null || err === void 0 ? void 0 : err.requestId),
156
- original: err instanceof Error ? err : undefined
157
- });
158
- }
159
- // 4. 轮询等待完成
160
- try {
161
- await this.waitForTask(envId, result.TaskId, DEFAULT_TIMEOUT_MS);
162
- }
163
- catch (error) {
164
- if (error instanceof error_1.CloudBaseError) {
165
- throw error;
166
- }
167
- const err = error;
168
- throw new error_1.CloudBaseError(`数据库迁移任务等待失败 [TaskId=${result.TaskId}]:${(err === null || err === void 0 ? void 0 : err.message) || String(error)}`, {
169
- requestId: (err === null || err === void 0 ? void 0 : err.RequestId) || (err === null || err === void 0 ? void 0 : err.requestId),
170
- original: err instanceof Error ? err : undefined
171
- });
172
- }
173
- return { taskId: result.TaskId };
174
- }
175
- /**
176
- * 解析 migrations 目录路径
177
- * - 未配置:默认 ./cloudbase/migrations
178
- * - 仅允许相对路径(禁止 / 开头)
179
- */
180
- resolveMigrationsDir(cwd, migrations) {
181
- const raw = migrations || './cloudbase/migrations';
182
- if (path_1.default.isAbsolute(raw) || raw.startsWith('/')) {
183
- throw new error_1.CloudBaseError('database.migrations 仅支持相对路径(例如 ./cloudbase/migrations)');
184
- }
185
- return path_1.default.resolve(cwd, raw);
186
- }
187
- /**
188
- * 校验 database.type(当前仅支持 postgresql)
189
- */
190
- assertDatabaseType(config) {
191
- if (config.type !== 'postgresql') {
192
- throw new error_1.CloudBaseError(`database.type 仅支持 postgresql,当前为: ${String(config.type)}`);
193
- }
194
- }
195
- /**
196
- * 轮询等待异步任务完成
197
- */
198
- async waitForTask(envId, taskId, timeoutMs) {
199
- const dbService = this.environment.getDatabaseService();
200
- const startTime = Date.now();
201
- while (true) {
202
- let task;
203
- try {
204
- task = await dbService.describeTaskResult({ EnvId: envId, TaskId: taskId });
205
- }
206
- catch (error) {
207
- if (Date.now() - startTime > timeoutMs) {
208
- const err = error;
209
- throw new error_1.CloudBaseError(`数据库迁移任务状态查询超时(${timeoutMs / 1000}s),TaskId: ${taskId},最后错误:${(err === null || err === void 0 ? void 0 : err.message) || String(error)}`, {
210
- requestId: (err === null || err === void 0 ? void 0 : err.RequestId) || (err === null || err === void 0 ? void 0 : err.requestId),
211
- original: err instanceof Error ? err : undefined
212
- });
213
- }
214
- await new Promise(resolve => {
215
- setTimeout(resolve, POLL_INTERVAL_MS);
216
- });
217
- continue;
218
- }
219
- if (task.Status === 'Succeed') {
220
- return;
221
- }
222
- if (task.Status === 'Failed') {
223
- throw new error_1.CloudBaseError(`数据库迁移任务失败 [TaskId=${taskId}]: ${task.Reason || '未知原因'}`, {
224
- requestId: task.RequestId
225
- });
226
- }
227
- if (Date.now() - startTime > timeoutMs) {
228
- throw new error_1.CloudBaseError(`数据库迁移任务超时(${timeoutMs / 1000}s),TaskId: ${taskId},当前状态: ${task.Status}/${task.Phase}`, {
229
- requestId: task.RequestId
230
- });
231
- }
232
- await new Promise(resolve => {
233
- setTimeout(resolve, POLL_INTERVAL_MS);
234
- });
235
- }
236
- }
237
- }
238
- exports.DatabaseDeployer = DatabaseDeployer;