@cloudbase/manager-node 5.8.9-beta.1 → 5.9.1

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 (52) hide show
  1. package/.codebuddy/rules/error-code-contract.mdc +13 -0
  2. package/.coding-ci-publish-beta.yaml +19 -12
  3. package/CHANGELOG.md +8 -0
  4. package/changelog_content_en.md +16 -0
  5. package/changelog_content_zh.md +16 -0
  6. package/lib/agent/index.js +6 -5
  7. package/lib/aiModel/index.js +21 -9
  8. package/lib/cloudApp/index.js +4 -4
  9. package/lib/cloudrun/index.js +16 -15
  10. package/lib/common/index.js +1 -1
  11. package/lib/database/index.js +23 -23
  12. package/lib/deploy/DatabaseDeployer.js +19 -24
  13. package/lib/deploy/DeployOrchestrator.js +2 -2
  14. package/lib/deploy/FunctionDeployer.js +19 -1
  15. package/lib/deploy/GatewayDeployer.js +5 -5
  16. package/lib/deploy/StaticDeployer.js +2 -2
  17. package/lib/deploy/framework.js +2 -1
  18. package/lib/deploy/function/config-guard.js +23 -3
  19. package/lib/deploy/function/enterprise-tcr.js +18 -2
  20. package/lib/docs/index.js +4 -3
  21. package/lib/env/index.js +16 -16
  22. package/lib/environment.js +4 -4
  23. package/lib/environmentManager.js +5 -1
  24. package/lib/error-docs.js +385 -0
  25. package/lib/error-types.js +21 -0
  26. package/lib/error.js +239 -2
  27. package/lib/function/index.js +454 -90
  28. package/lib/function/packer.js +1 -1
  29. package/lib/hosting/index.js +1 -1
  30. package/lib/index.js +2 -1
  31. package/lib/integration/crypto.js +4 -3
  32. package/lib/integration/index.js +1 -1
  33. package/lib/integration/secretKey.js +4 -4
  34. package/lib/monitor/index.js +1 -1
  35. package/lib/mysql/index.js +2 -1
  36. package/lib/permission/index.js +56 -49
  37. package/lib/platform/index.js +2 -2
  38. package/lib/sandbox/index.js +68 -61
  39. package/lib/storage/index.js +164 -162
  40. package/lib/user/index.js +32 -31
  41. package/lib/utils/cloud-api-request.js +13 -5
  42. package/lib/utils/cloudbase-request.js +21 -0
  43. package/lib/utils/fs.js +3 -3
  44. package/lib/utils/http-request.js +2 -2
  45. package/lib/utils/index.js +4 -3
  46. package/lib/utils/storage-config.js +3 -3
  47. package/package.json +2 -2
  48. package/types/error-docs.d.ts +57 -0
  49. package/types/error-types.d.ts +32 -0
  50. package/types/error.d.ts +148 -2
  51. package/types/function/index.d.ts +166 -8
  52. package/types/utils/cloudbase-request.d.ts +22 -0
@@ -0,0 +1,13 @@
1
+ # 错误码契约(manager-node · 本仓指引)
2
+
3
+ **规则的唯一来源** → `cloudbase-cli/specs/error-rules.md`(**改规则只改那一处**;本文件只写**本仓差异**)。
4
+
5
+ ## 本仓差异
6
+
7
+ - **字段**:三仓应有项全有(含 `docs`、`meta`)+ **本仓专属 `meta.failures`**(多项失败明细登记,见 rules §5)
8
+ - **`docs`**:`this.docs = opts.docs ?? resolveErrorDoc(this.code, this.source)`(**类内派生**,依赖本仓 `src/error-docs.ts`)
9
+ > ⚠️ 映射表**只在本仓并不充分**:TB 侧错误拿不到 `docs` ⇒ 按判据 C 应走**单一来源**(文档站生成)或下沉共享基座;本仓不应成为映射表唯一归属点
10
+ - **机制**:有 `isCloudBaseError` / `isValidErrorCode` / 8 个 helper(含 `throwCredentialError`);**缺 `errorSourceOf`**(R3 前置,待对齐)
11
+ - **守卫**:`test/error.test.ts`(burn-down 平衡括号 + 码表)、`test/error-no-code-baseline.json`(`{}`)
12
+ - **本仓特殊约定**:错误对象是**对外 API**(CLI / MCP / 第三方 SDK 直接读 `.code` / `.docs` / `.meta`)⇒ 字段增删按 §3 冻结形状处理,不随基座版本漂移
13
+ - **新增自造码 ⇒ 必须同步文档站**:到 `cloudbase-docs` 跑 `node scripts/generate-sdk-error-code-pages.mjs`(分层登记页由生成器产出,**勿手工建页**、**勿加进 `basic.md`**;详见该仓 `.codebuddy/skills/error-code-manager`)
@@ -138,7 +138,7 @@ stages:
138
138
  - task: 生成并同步 changelog
139
139
  cmds:
140
140
  - plugin: ci_changelog
141
- version: 0.12.0
141
+ version: 1.1.0
142
142
  params:
143
143
  to_ref: HEAD
144
144
  tag_pattern: ^v(\d+\.\d+\.\d+(?:-[\w.]+)?)$
@@ -174,22 +174,22 @@ stages:
174
174
  cmds:
175
175
  - "bash -lc '\nset -e\nexport NVM_DIR=\"$HOME/.nvm\"\n[ -s \"$NVM_DIR/nvm.sh\"\
176
176
  \ ] && . \"$NVM_DIR/nvm.sh\"\nnvm use 22.14.0\necho \"==========================================\"\
177
- \necho \"\U0001F4E6 写回插件生成的 changelog 并打 tag v${MANAGER_NODE_VERSION}\"\
178
- \necho \"==========================================\"\n# 配置 git\ngit config --global\
179
- \ user.email \"cloudbase-ci-bot@tencent.com\"\ngit config --global user.name\
180
- \ \"cloudbase-ci-bot\"\n# 切换到 release 分支\ngit fetch origin release/${MANAGER_NODE_VERSION}\n\
177
+ \necho \"\U0001F4E6 写回插件生成的 changelog 并打 tag v${MANAGER_NODE_VERSION}\"\n\
178
+ echo \"==========================================\"\n# 配置 git\ngit config\
179
+ \ --global user.email \"cloudbase-ci-bot@tencent.com\"\ngit config --global\
180
+ \ user.name \"cloudbase-ci-bot\"\n# 切换到 release 分支\ngit fetch origin release/${MANAGER_NODE_VERSION}\n\
181
181
  git checkout release/${MANAGER_NODE_VERSION}\n# 1. 写回插件生成的 changelog(仅 latest\
182
- \ 版本)\necho \"\"\necho \"\U0001F4DD Step 1: 写回插件产物到 CHANGELOG.md\"\nif [ \"$RELEASE_TYPE\"\
183
- \ = \"latest\" ]; then\n if [ ! -f \"${QCI_WORKSPACE}/changelog_content.md\"\
182
+ \ 版本)\necho \"\"\necho \"\U0001F4DD Step 1: 写回插件产物到 CHANGELOG.md\"\nif [\
183
+ \ \"$RELEASE_TYPE\" = \"latest\" ]; then\n if [ ! -f \"${QCI_WORKSPACE}/changelog_content.md\"\
184
184
  \ ]; then\n echo \"❌ 插件产物 ${QCI_WORKSPACE}/changelog_content.md 不存在\"\
185
185
  \n exit 1\n fi\n cat \"${QCI_WORKSPACE}/changelog_content.md\"\
186
186
  \ CHANGELOG.md > CHANGELOG.md.new\n mv CHANGELOG.md.new CHANGELOG.md\n\
187
187
  \ # 2. 提交 changelog\n echo \"\"\n echo \"\U0001F4DD Step 2: 提交变更\"\
188
188
  \n git add CHANGELOG.md\n git commit -m \"docs(release): changelog\
189
- \ for v${MANAGER_NODE_VERSION}\" || echo \"没有需要提交的变更\"\nelse\n echo\
190
- \ \"⏭️ RELEASE_TYPE !== latest,跳过 CHANGELOG.md 写回\"\nfi\n# 3. 打 tag\necho\
191
- \ \"\"\necho \"\U0001F3F7️ Step 3: 创建 tag v${MANAGER_NODE_VERSION}\"\
192
- \ngit tag -a \"v${MANAGER_NODE_VERSION}\" -m \"Release v${MANAGER_NODE_VERSION}\"\
189
+ \ for v${MANAGER_NODE_VERSION}\" || echo \"没有需要提交的变更\"\nelse\n echo \"\
190
+ ⏭️ RELEASE_TYPE !== latest,跳过 CHANGELOG.md 写回\"\nfi\n# 3. 打 tag\necho \"\
191
+ \"\necho \"\U0001F3F7️ Step 3: 创建 tag v${MANAGER_NODE_VERSION}\"\ngit tag\
192
+ \ -a \"v${MANAGER_NODE_VERSION}\" -m \"Release v${MANAGER_NODE_VERSION}\"\
193
193
  \n# 4. 推送分支和 tag\necho \"\"\necho \"\U0001F680 Step 4: 推送到远程\"\ngit push\
194
194
  \ origin release/${MANAGER_NODE_VERSION}\ngit push origin \"v${MANAGER_NODE_VERSION}\"\
195
195
  \necho \"\"\necho \"✅ 完成!\"\necho \" - changelog.md: 已更新\"\necho \" \
@@ -237,12 +237,19 @@ stages:
237
237
  tasks:
238
238
  - task: 企微群通知
239
239
  cmds:
240
+ - plugin: cmds
241
+ params:
242
+ cmds:
243
+ - echo "📦 @cloudbase/manager-node v${MANAGER_NODE_VERSION} 发布成功" > ${QCI_WORKSPACE}/wework_message.md
244
+ - echo "" >> ${QCI_WORKSPACE}/wework_message.md
245
+ - cat ${QCI_WORKSPACE}/changelog_content.md >> ${QCI_WORKSPACE}/wework_message.md
246
+ - cat ${QCI_WORKSPACE}/wework_message.md
240
247
  - plugin: message_wework_group
241
248
  params:
242
249
  c_type: text
243
250
  env_variable: _WEWORK_GROUP_ID
244
251
  mentioned: lucyqzhang;nenneyu
245
- content_path: ${QCI_WORKSPACE}/changelog_content.md
252
+ content_path: ${QCI_WORKSPACE}/wework_message.md
246
253
  group_id: ww150005365489083
247
254
  if: $RELEASE_TYPE = latest
248
255
  version: '2.0'
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## @cloudbase/manager-node v5.9.0 版本发布 🚀(2026-09-28)
2
+
3
+ - 新增 错误对象契约统一与无 code 抛错清零 + 自造码文档锚点(D5)
4
+ - 新增发布流水线配置
5
+
6
+ ---
7
+
8
+
1
9
  ## @cloudbase/manager-node v5.8.8 版本发布 🚀(2026-09-18)
2
10
 
3
11
  - 新增平台版套餐服务 PlatformService
@@ -0,0 +1,16 @@
1
+ ## [5.9.0] 2026-09-28
2
+
3
+ - [Added] Add `ERROR_TYPES` standard error type table (6 entries) and support `type` option in `CloudBaseError` constructor (decides `code` / `source` with priority and cannot be overridden by caller); helpers now reference `ERROR_TYPES`
4
+ - [Added] error-docs: locate self-made codes by layer registry page (returns `/error-code/<layer>#<lowercase-code>` anchor when `source` is `cli` / `toolbox` / `manager-node`); manager-node soft-fallback whitelist collapsed to layer registry page (`ready: true`)
5
+ - [Added] Unify error object contract and clear no-`code` throws: add `CloudBaseError.toJSON()`, `ErrorSource` union type (with `'toolbox'`), `isCloudBaseError` / `isValidErrorCode`; converge 171 raw `throw new Error` to unified helpers, storage batch delete now carries `code` + `source` + `details`
6
+ - [Added] Upgrade `@cloudbase/toolbox` to `~0.9.0`
7
+ - [Added] Update cloud function and cloud run integration tests: replace fixed sleep with polling wait, unify jest timeout to 10 minutes, add `waitUntil` / `waitForSandboxToolSettled` helpers with fast-fail diagnostics on failed states
8
+ - [Fixed] Fix `function` regression where throw-helper was misused in value position (`reject(throwNetError(...))`) causing Promise to never settle; now construct `new CloudBaseError(msg, { type: ERROR_TYPES.netError })` in value position
9
+ - [Fixed] `error`: `toJSON()` normalizes numeric codes to strings (e.g. `876` ⇒ `"876"`) at output layer while `code` on object stays faithful; `NaN` / `±Infinity` fall back to `ERROR`
10
+ - [Fixed] `error`: add ES5 prototype fallback (`Object.setPrototypeOf(this, CloudBaseError.prototype)`) to avoid lost prototype chain under third-party downlevel compilation
11
+ - [Fixed] Address code review fixes: extract `MODEL_STATUS` constant in `aiModel`; fix `authoration` → `authorization` spelling in `environment` / `cloud-api-request`; use truthy checks in `user` validation; change `error: any` → `unknown` in `function` and use `WeakMap` for idempotency marker; use truthy checks for `customConfiguration` / `DNSConfig` in `sandbox` to avoid null pointer
12
+ - [Fixed] `review`: fix empty `failures[0].id` null pointer when deploy report is inconsistent; narrow `description` with `typeof === 'string'` in `permission`; remove `as any` and tighten `isRetryableError` retry logic in `function`
13
+ - [Fixed] `deploy`: downgrade image `latest` tag from block (`fail`) to hint (`warn`) since platform allows `latest` as suboptimal not mandatory failure
14
+ - [Fixed] `error`: change enterprise image guidance idempotency from `message` text dependency to marker flag to avoid duplicate append after text mutation
15
+ - [Fixed] `error`: governance D14/D15/D16/D22 — pass through TCR permission errors; only retry retryable errors in trigger creation; `waitFunctionActive` tolerates creation-phase `NOT_FOUND`; `toJSON()` emits `stack`
16
+ - [Refactor] `error`: rename throw helpers to `throwXxx` form (e.g. `invalidParam` → `throwInvalidParam`) so call sites signal interruption, 494 sites / 35 files
@@ -0,0 +1,16 @@
1
+ ## [5.9.0] 2026-09-28
2
+
3
+ - [Added] 新增 `ERROR_TYPES` 标准错误类型表(6 条),`CloudBaseError` 构造器支持 `type` 选项(优先决定 `code` / `source` 且不可被调用方覆盖),helper 改引 `ERROR_TYPES`
4
+ - [Added] error-docs:自造码按层登记页定位(`source` 为 `cli` / `toolbox` / `manager-node` 时返回 `/error-code/<layer>#<小写码名>` 锚点),manager-node 软降级白名单收敛为层级登记页(`ready: true`)
5
+ - [Added] 错误对象契约统一与无 `code` 抛错清零:新增 `CloudBaseError.toJSON()`、`ErrorSource` 联合类型(含 `'toolbox'`)、`isCloudBaseError` / `isValidErrorCode` 识别;171 处原生 `throw new Error` 收敛为统一辅助函数,storage 批量删除补 `code` + `source` + `details`
6
+ - [Added] 升级 `@cloudbase/toolbox` 至 `~0.9.0`
7
+ - [Added] 更新云函数与云托管集成测试:轮询等待替代固定 sleep,jest 超时统一抬至 10 分钟,新增 `waitUntil` / `waitForSandboxToolSettled` 等辅助函数并补充失败态快速失败诊断
8
+ - [Fixed] 修复 `function` 模块必抛 helper 误用于值位置(`reject(throwNetError(...))`)导致 Promise 永不 settle 的回归,改为值位置构造 `new CloudBaseError(msg, { type: ERROR_TYPES.netError })`
9
+ - [Fixed] `error`: `toJSON()` 输出层将数值码归一化为字符串(如 `876` ⇒ `"876"`),对象上 `code` 保持保真;`NaN` / `±Infinity` 兜底为 `ERROR`
10
+ - [Fixed] `error`: 补 ES5 原型兜底(`Object.setPrototypeOf(this, CloudBaseError.prototype)`),避免第三方降级编译时丢失原型链
11
+ - [Fixed] 按代码评审修复多处问题:`aiModel` 抽 `MODEL_STATUS` 常量;`environment` / `cloud-api-request` 拼写 `authoration` → `authorization`;`user` 校验改真值判断;`function` 的 `error: any` → `unknown` 并改用 `WeakMap` 缓存幂等标记;`sandbox` 的 `customConfiguration` / `DNSConfig` 改真值判断避免空指针
12
+ - [Fixed] `review`: 响应评审修复 `deploy` 报告不自洽时 `failures[0].id` 空指针;`permission` 的 `description` 改用 `typeof === 'string'` 收窄;`function` 去掉 `as any` 断言并收紧 `isRetryableError` 重试判定
13
+ - [Fixed] `deploy`: 镜像 `latest` 标签由拦截(`fail`)降级为提示(`warn`),平台允许 `latest` 属次优而非必然失败
14
+ - [Fixed] `error`: 企业版镜像排查指引幂等判断由依赖 `message` 文本改为标记位,避免文本被改动后重复追加
15
+ - [Fixed] `error`: 治理 D14/D15/D16/D22 — TCR 权限错误透传上游;触发器创建仅重试可重试错误;`waitFunctionActive` 容忍创建期 `NOT_FOUND`;`toJSON()` 输出 `stack`
16
+ - [Refactor] `error`: 抛错 helper 统一改名为 `throwXxx` 形态(如 `invalidParam` → `throwInvalidParam`),调用点即知会中断,共 494 处 / 35 文件
@@ -13,6 +13,7 @@ exports.AgentService = void 0;
13
13
  const cloudrun_1 = require("../cloudrun");
14
14
  const type_1 = require("../cloudrun/type");
15
15
  const utils_1 = require("../utils");
16
+ const error_1 = require("../error");
16
17
  const path_1 = __importDefault(require("path"));
17
18
  /**
18
19
  * Agent 管理类
@@ -254,7 +255,7 @@ class AgentService {
254
255
  // 1. 查询 Agent 获取类型
255
256
  const agentListRes = await this.describeAgentList({ AgentId });
256
257
  if (!agentListRes.AgentList || agentListRes.AgentList.length === 0) {
257
- throw new Error(`Agent ${AgentId} 不存在`);
258
+ (0, error_1.throwNotFound)(`Agent ${AgentId} 不存在`);
258
259
  }
259
260
  const agentInfo = agentListRes.AgentList[0];
260
261
  const agentType = agentInfo.AgentType;
@@ -273,7 +274,7 @@ class AgentService {
273
274
  });
274
275
  }
275
276
  else {
276
- throw new Error(`不支持的 Agent 类型: ${agentType}`);
277
+ (0, error_1.throwInvalidParam)(`不支持的 Agent 类型: ${agentType}`);
277
278
  }
278
279
  }
279
280
  /**
@@ -333,7 +334,7 @@ class AgentService {
333
334
  // 1. 查询 Agent 获取类型
334
335
  const agentListRes = await this.describeAgentList({ AgentId });
335
336
  if (!agentListRes.AgentList || agentListRes.AgentList.length === 0) {
336
- throw new Error(`Agent ${AgentId} 不存在`);
337
+ (0, error_1.throwNotFound)(`Agent ${AgentId} 不存在`);
337
338
  }
338
339
  const agentInfo = agentListRes.AgentList[0];
339
340
  const agentType = agentInfo.AgentType;
@@ -368,7 +369,7 @@ class AgentService {
368
369
  });
369
370
  }
370
371
  else {
371
- throw new Error(`不支持的 Agent 类型: ${agentType}`);
372
+ (0, error_1.throwInvalidParam)(`不支持的 Agent 类型: ${agentType}`);
372
373
  }
373
374
  }
374
375
  // ==================== TCBR 云托管(内部方法,暂不对外暴露) ====================
@@ -592,7 +593,7 @@ class AgentService {
592
593
  const envConfig = this.environment.lazyEnvironmentConfig;
593
594
  // 判断 params.BotId 的数据格式是否为 ibot-xxx-xxx 的格式
594
595
  if (!/^ibot-[a-z0-9_]+-[a-z0-9_]+$/.test(BotId)) {
595
- throw new Error('BotId格式应为"ibot-xxx-xxx",其中 xxx 仅支持小写字母、数字或下划线');
596
+ (0, error_1.throwInvalidParam)('BotId格式应为"ibot-xxx-xxx",其中 xxx 仅支持小写字母、数字或下划线');
596
597
  }
597
598
  // 获取函数型云托管服务的名称:ibot-xxx-xxx 中的 ibot-xxx
598
599
  const serverName = BotId.split('-').slice(0, 2).join('-');
@@ -8,6 +8,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.AiModelService = void 0;
10
10
  const utils_1 = require("../utils");
11
+ const error_1 = require("../error");
12
+ /** AI 模型分组状态(CreateAIModel / UpdateAIModel 协议值) */
13
+ const MODEL_STATUS = {
14
+ /** 启用 */
15
+ enabled: 1,
16
+ /** 禁用 */
17
+ disabled: 2
18
+ };
11
19
  class AiModelService {
12
20
  constructor(environment) {
13
21
  this.environment = environment;
@@ -20,13 +28,15 @@ class AiModelService {
20
28
  const { EnvId } = this.environment.lazyEnvironmentConfig;
21
29
  const { envId, groupName, baseUrl, models, remark, status, secret } = options;
22
30
  if (!groupName || groupName.trim().length === 0) {
23
- throw new Error('groupName is required');
31
+ (0, error_1.throwInvalidParam)('groupName is required');
24
32
  }
25
33
  if (groupName.toLowerCase().startsWith('cloudbase')) {
26
- throw new Error('groupName cannot start with cloudbase');
34
+ (0, error_1.throwInvalidParam)('groupName cannot start with cloudbase');
27
35
  }
28
- if (status !== undefined && status !== 1 && status !== 2) {
29
- throw new Error('status must be 1 or 2');
36
+ if (status !== undefined &&
37
+ status !== MODEL_STATUS.enabled &&
38
+ status !== MODEL_STATUS.disabled) {
39
+ (0, error_1.throwInvalidParam)(`status must be ${MODEL_STATUS.enabled} or ${MODEL_STATUS.disabled}`);
30
40
  }
31
41
  return this.tcbService.request('CreateAIModel', Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ EnvId: envId || EnvId, GroupName: groupName }, (baseUrl !== undefined ? { BaseUrl: baseUrl } : {})), (models !== undefined ? { Models: models } : {})), (remark !== undefined ? { Remark: remark } : {})), (status !== undefined ? { Status: status } : {})), (secret !== undefined ? { Secret: secret } : {})));
32
42
  }
@@ -37,10 +47,12 @@ class AiModelService {
37
47
  const { EnvId } = this.environment.lazyEnvironmentConfig;
38
48
  const { envId, groupName, baseUrl, models, remark, status, secret } = options;
39
49
  if (!groupName || groupName.trim().length === 0) {
40
- throw new Error('groupName is required');
50
+ (0, error_1.throwInvalidParam)('groupName is required');
41
51
  }
42
- if (status !== undefined && status !== 1 && status !== 2) {
43
- throw new Error('status must be 1 or 2');
52
+ if (status !== undefined &&
53
+ status !== MODEL_STATUS.enabled &&
54
+ status !== MODEL_STATUS.disabled) {
55
+ (0, error_1.throwInvalidParam)(`status must be ${MODEL_STATUS.enabled} or ${MODEL_STATUS.disabled}`);
44
56
  }
45
57
  return this.tcbService.request('UpdateAIModel', Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ EnvId: envId || EnvId, GroupName: groupName }, (baseUrl !== undefined ? { BaseUrl: baseUrl } : {})), (models !== undefined ? { Models: models } : {})), (remark !== undefined ? { Remark: remark } : {})), (status !== undefined ? { Status: status } : {})), (secret !== undefined ? { Secret: secret } : {})));
46
58
  }
@@ -51,11 +63,11 @@ class AiModelService {
51
63
  const { EnvId } = this.environment.lazyEnvironmentConfig;
52
64
  const { envId, groupNames } = options;
53
65
  if (!Array.isArray(groupNames) || groupNames.length === 0) {
54
- throw new Error('groupNames is required');
66
+ (0, error_1.throwInvalidParam)('groupNames is required');
55
67
  }
56
68
  const invalidGroupName = groupNames.find(item => typeof item !== 'string' || item.trim().length === 0);
57
69
  if (invalidGroupName !== undefined) {
58
- throw new Error('groupNames contains invalid item');
70
+ (0, error_1.throwInvalidParam)('groupNames contains invalid item');
59
71
  }
60
72
  return this.tcbService.request('DeleteAIModel', {
61
73
  EnvId: envId || EnvId,
@@ -133,11 +133,11 @@ class CloudAppService {
133
133
  const { serviceName, localPath, ignore = [], excludeNodeModules = true, onPhase } = params;
134
134
  // 1. 验证本地路径
135
135
  if (!fs_1.default.existsSync(localPath)) {
136
- throw new error_1.CloudBaseError(`本地路径不存在: ${localPath}`);
136
+ (0, error_1.throwNotFound)(`本地路径不存在: ${localPath}`);
137
137
  }
138
138
  const stat = fs_1.default.statSync(localPath);
139
139
  if (!stat.isDirectory()) {
140
- throw new error_1.CloudBaseError(`localPath 必须是目录: ${localPath}`);
140
+ (0, error_1.throwInvalidParam)(`localPath 必须是目录: ${localPath}`);
141
141
  }
142
142
  // 2. 打包本地文件为 ZIP(node_modules 按场景决定是否排除)
143
143
  const tmpZipPath = path_1.default.join(os_1.default.tmpdir(), `cloudapp-${Date.now()}-${Math.random().toString(36).slice(2)}.zip`);
@@ -193,7 +193,7 @@ class CloudAppService {
193
193
  catch (_a) {
194
194
  // 解析失败时 errorDetail 保持空串,不影响主错误抛出
195
195
  }
196
- throw new error_1.CloudBaseError(`上传失败: ${response.status} ${response.statusText}${errorDetail}`);
196
+ (0, error_1.throwApiError)(`上传失败: ${response.status} ${response.statusText}${errorDetail}`);
197
197
  }
198
198
  onPhase === null || onPhase === void 0 ? void 0 : onPhase({ phase: 'upload', durationMs: Date.now() - putStart, bytes: zipBuffer.length });
199
199
  // 7. 返回结果(返回 cosTimestamp,用于创建应用)
@@ -226,7 +226,7 @@ class CloudAppService {
226
226
  validateRequiredParams(params, fields) {
227
227
  for (const field of fields) {
228
228
  if (!params[field]) {
229
- throw new error_1.CloudBaseError(`${field} 是必填参数`);
229
+ (0, error_1.throwInvalidParam)(`${field} 是必填参数`);
230
230
  }
231
231
  }
232
232
  }
@@ -15,6 +15,7 @@ exports.parseObjectToDiffConfigItem = parseObjectToDiffConfigItem;
15
15
  const archiver_1 = __importDefault(require("archiver"));
16
16
  const fs_extra_1 = require("fs-extra");
17
17
  const path_1 = __importDefault(require("path"));
18
+ const error_1 = require("../error");
18
19
  const utils_1 = require("../utils");
19
20
  const type_1 = require("./type");
20
21
  /**
@@ -46,7 +47,7 @@ class CloudRunService {
46
47
  const templates = await this.getTemplates();
47
48
  const templateData = templates.find(item => item.identifier === template);
48
49
  if (!templateData || !templateData.zipFileStore) {
49
- throw new Error(`未找到匹配的模板: ${template}`);
50
+ (0, error_1.throwNotFound)(`未找到匹配的模板: ${template}`);
50
51
  }
51
52
  // 2. 下载并解压模板到目标目录
52
53
  const downloadUrl = templateData.zipFileStore;
@@ -75,7 +76,7 @@ class CloudRunService {
75
76
  const cloudRunServerDetailRes = await this.detail({ serverName });
76
77
  const version = (_b = (_a = cloudRunServerDetailRes.OnlineVersionInfos) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.VersionName;
77
78
  if (!version) {
78
- throw new Error('未找到云托管服务版本');
79
+ (0, error_1.throwNotFound)('未找到云托管服务版本');
79
80
  }
80
81
  /**
81
82
  * 获取下载地址
@@ -89,7 +90,7 @@ class CloudRunService {
89
90
  await (0, utils_1.downloadAndExtractRemoteZip)(cloudBaseBuildServiceRes === null || cloudBaseBuildServiceRes === void 0 ? void 0 : cloudBaseBuildServiceRes.DownloadUrl, path_1.default.resolve(targetPath));
90
91
  }
91
92
  else {
92
- throw new Error(`云托管代码下载地址为空(请求ID: ${cloudBaseBuildServiceRes.RequestId})`);
93
+ (0, error_1.throwApiError)(`云托管代码下载地址为空(请求ID: ${cloudBaseBuildServiceRes.RequestId})`);
93
94
  }
94
95
  }
95
96
  /**
@@ -116,7 +117,7 @@ class CloudRunService {
116
117
  const serverName = (_a = params === null || params === void 0 ? void 0 : params.ServerName) === null || _a === void 0 ? void 0 : _a.trim();
117
118
  const status = (_b = params === null || params === void 0 ? void 0 : params.Status) === null || _b === void 0 ? void 0 : _b.trim();
118
119
  if (!serverName) {
119
- throw new Error('Missing required parameters: ServerName');
120
+ (0, error_1.throwInvalidParam)('Missing required parameters: ServerName');
120
121
  }
121
122
  return this.tcbrService.request('DescribeReleaseOrder', Object.assign({ EnvId: envConfig.EnvId, ServerName: serverName }, (status ? { Status: status } : {})));
122
123
  }
@@ -148,7 +149,7 @@ class CloudRunService {
148
149
  async setTraffic(serverName, stablePercent, canaryPercent) {
149
150
  // 校验比例之和是否为100%
150
151
  if (stablePercent + canaryPercent !== 100) {
151
- throw new Error('稳定版本流量比例和灰度版本流量比例之和必须等于 100');
152
+ (0, error_1.throwInvalidParam)('稳定版本流量比例和灰度版本流量比例之和必须等于 100');
152
153
  }
153
154
  const envConfig = this.environment.lazyEnvironmentConfig;
154
155
  const { Task } = await this.tcbrService.request('DescribeServerManageTask', {
@@ -159,7 +160,7 @@ class CloudRunService {
159
160
  // 判断是否存在灰度版本
160
161
  const isGary = (Task === null || Task === void 0 ? void 0 : Task.ReleaseType) === type_1.ReleaseTypeEnum.GRAY && (Task === null || Task === void 0 ? void 0 : Task.Status) === 'running';
161
162
  if (!isGary) {
162
- throw new Error('不存在灰度中的版本或灰度版本部署未完成');
163
+ (0, error_1.throwApiError)('不存在灰度中的版本或灰度版本部署未完成');
163
164
  }
164
165
  // 获取当前版本和灰度版本
165
166
  const { ReleaseOrderInfo } = await this.tcbrService.request('DescribeReleaseOrder', {
@@ -242,13 +243,13 @@ class CloudRunService {
242
243
  const rollbackVersionName = (_c = params === null || params === void 0 ? void 0 : params.RollbackVersionName) === null || _c === void 0 ? void 0 : _c.trim();
243
244
  const operatorRemark = (_d = params === null || params === void 0 ? void 0 : params.OperatorRemark) === null || _d === void 0 ? void 0 : _d.trim();
244
245
  if (!serverName) {
245
- throw new Error('Missing required parameters: ServerName');
246
+ (0, error_1.throwInvalidParam)('Missing required parameters: ServerName');
246
247
  }
247
248
  if (!currentVersionName) {
248
- throw new Error('Missing required parameters: CurrentVersionName');
249
+ (0, error_1.throwInvalidParam)('Missing required parameters: CurrentVersionName');
249
250
  }
250
251
  if (!rollbackVersionName) {
251
- throw new Error('Missing required parameters: RollbackVersionName');
252
+ (0, error_1.throwInvalidParam)('Missing required parameters: RollbackVersionName');
252
253
  }
253
254
  return this.tcbrService.request('SubmitServerRollback', Object.assign({ EnvId: envConfig.EnvId, ServerName: serverName, CurrentVersionName: currentVersionName, RollbackVersionName: rollbackVersionName }, (operatorRemark ? { OperatorRemark: operatorRemark } : {})));
254
255
  }
@@ -262,17 +263,17 @@ class CloudRunService {
262
263
  const envConfig = this.environment.lazyEnvironmentConfig;
263
264
  const operatorRemark = (_a = params === null || params === void 0 ? void 0 : params.OperatorRemark) === null || _a === void 0 ? void 0 : _a.trim();
264
265
  if (!Array.isArray(params === null || params === void 0 ? void 0 : params.SimpleVersions) || params.SimpleVersions.length === 0) {
265
- throw new Error('Missing required parameters: SimpleVersions');
266
+ (0, error_1.throwInvalidParam)('Missing required parameters: SimpleVersions');
266
267
  }
267
268
  const simpleVersions = params.SimpleVersions.map((item, index) => {
268
269
  var _a, _b, _c;
269
270
  const serverName = (_a = item === null || item === void 0 ? void 0 : item.ServerName) === null || _a === void 0 ? void 0 : _a.trim();
270
271
  const versionName = (_b = item === null || item === void 0 ? void 0 : item.VersionName) === null || _b === void 0 ? void 0 : _b.trim();
271
272
  if (!serverName) {
272
- throw new Error(`Invalid SimpleVersions[${index}].ServerName`);
273
+ (0, error_1.throwInvalidParam)(`Invalid SimpleVersions[${index}].ServerName`);
273
274
  }
274
275
  if (!versionName) {
275
- throw new Error(`Invalid SimpleVersions[${index}].VersionName`);
276
+ (0, error_1.throwInvalidParam)(`Invalid SimpleVersions[${index}].VersionName`);
276
277
  }
277
278
  return {
278
279
  EnvId: ((_c = item === null || item === void 0 ? void 0 : item.EnvId) === null || _c === void 0 ? void 0 : _c.trim()) || envConfig.EnvId,
@@ -294,10 +295,10 @@ class CloudRunService {
294
295
  const versionName = (_b = params === null || params === void 0 ? void 0 : params.VersionName) === null || _b === void 0 ? void 0 : _b.trim();
295
296
  const channel = (_c = params === null || params === void 0 ? void 0 : params.Channel) === null || _c === void 0 ? void 0 : _c.trim();
296
297
  if (!serverName) {
297
- throw new Error('Missing required parameters: ServerName');
298
+ (0, error_1.throwInvalidParam)('Missing required parameters: ServerName');
298
299
  }
299
300
  if (!versionName) {
300
- throw new Error('Missing required parameters: VersionName');
301
+ (0, error_1.throwInvalidParam)('Missing required parameters: VersionName');
301
302
  }
302
303
  return this.tcbrService.request('DescribeVersionDetail', Object.assign({ EnvId: envConfig.EnvId, ServerName: serverName, VersionName: versionName }, (channel ? { Channel: channel } : {})));
303
304
  }
@@ -359,7 +360,7 @@ class CloudRunService {
359
360
  * 参数校验和默认值设置
360
361
  */
361
362
  if (!serverName) {
362
- throw new Error('Missing required parameters: serviceName');
363
+ (0, error_1.throwInvalidParam)('Missing required parameters: serviceName');
363
364
  }
364
365
  // 获取当前环境配置(包含EnvId)
365
366
  const envConfig = this.environment.lazyEnvironmentConfig;
@@ -30,7 +30,7 @@ class CommonService {
30
30
  async call(options) {
31
31
  const { Action, Param = {} } = options;
32
32
  if (!Action) {
33
- throw new error_1.CloudBaseError('缺少必填参数 Action');
33
+ (0, error_1.throwInvalidParam)('缺少必填参数 Action');
34
34
  }
35
35
  const res = await this.commonService.request(Action, Object.assign({}, Param));
36
36
  return res;
@@ -201,7 +201,7 @@ class DatabaseService {
201
201
  fileType = path_1.default.extname(filePath).substring(1);
202
202
  }
203
203
  else {
204
- throw new error_1.CloudBaseError('Miss file.filePath or file.objectKey');
204
+ (0, error_1.throwInvalidParam)('Miss file.filePath or file.objectKey');
205
205
  }
206
206
  if (file['FileType']) {
207
207
  fileType = file['FileType'];
@@ -217,7 +217,7 @@ class DatabaseService {
217
217
  fileType = path_1.default.extname(filePath).substring(1);
218
218
  }
219
219
  else {
220
- throw new error_1.CloudBaseError('Miss file.filePath or file.objectKey');
220
+ (0, error_1.throwInvalidParam)('Miss file.filePath or file.objectKey');
221
221
  }
222
222
  if (file['FileType']) {
223
223
  fileType = file['FileType'];
@@ -334,17 +334,17 @@ class DatabaseService {
334
334
  var _a;
335
335
  const { EnvId, Migrations, IncludeAll } = options;
336
336
  if (!Array.isArray(Migrations) || Migrations.length === 0) {
337
- throw new error_1.CloudBaseError('Migrations 至少需要 1 条');
337
+ (0, error_1.throwInvalidParam)('Migrations 至少需要 1 条');
338
338
  }
339
339
  for (const migration of Migrations) {
340
340
  if (!/^\d{14}$/.test(migration.Version)) {
341
- throw new error_1.CloudBaseError('Migration.Version 必须是 14 位数字');
341
+ (0, error_1.throwInvalidParam)('Migration.Version 必须是 14 位数字');
342
342
  }
343
343
  if (!/^[a-z_]+$/.test(migration.Name)) {
344
- throw new error_1.CloudBaseError('Migration.Name 只允许小写字母和下划线');
344
+ (0, error_1.throwInvalidParam)('Migration.Name 只允许小写字母和下划线');
345
345
  }
346
346
  if (!((_a = migration.Query) === null || _a === void 0 ? void 0 : _a.trim())) {
347
- throw new error_1.CloudBaseError('Migration.Query 不能为空');
347
+ (0, error_1.throwInvalidParam)('Migration.Query 不能为空');
348
348
  }
349
349
  }
350
350
  return this.dbOpService.request('PreviewPGUserMigrations', Object.assign({ EnvId: EnvId || this.envId, Migrations }, (IncludeAll !== undefined ? { IncludeAll } : {})));
@@ -358,24 +358,24 @@ class DatabaseService {
358
358
  var _a;
359
359
  const { EnvId, Migrations, LockTimeoutMs, StatementTimeoutMs, IncludeAll } = options;
360
360
  if (!Array.isArray(Migrations) || Migrations.length === 0) {
361
- throw new error_1.CloudBaseError('Migrations 至少需要 1 条');
361
+ (0, error_1.throwInvalidParam)('Migrations 至少需要 1 条');
362
362
  }
363
363
  for (const migration of Migrations) {
364
364
  if (!/^\d{14}$/.test(migration.Version)) {
365
- throw new error_1.CloudBaseError('Migration.Version 必须是 14 位数字');
365
+ (0, error_1.throwInvalidParam)('Migration.Version 必须是 14 位数字');
366
366
  }
367
367
  if (!/^[a-z_]+$/.test(migration.Name)) {
368
- throw new error_1.CloudBaseError('Migration.Name 只允许小写字母和下划线');
368
+ (0, error_1.throwInvalidParam)('Migration.Name 只允许小写字母和下划线');
369
369
  }
370
370
  if (!((_a = migration.Query) === null || _a === void 0 ? void 0 : _a.trim())) {
371
- throw new error_1.CloudBaseError('Migration.Query 不能为空');
371
+ (0, error_1.throwInvalidParam)('Migration.Query 不能为空');
372
372
  }
373
373
  }
374
374
  if (LockTimeoutMs !== undefined && LockTimeoutMs < 0) {
375
- throw new error_1.CloudBaseError('LockTimeoutMs 不能小于 0');
375
+ (0, error_1.throwInvalidParam)('LockTimeoutMs 不能小于 0');
376
376
  }
377
377
  if (StatementTimeoutMs !== undefined && StatementTimeoutMs < 0) {
378
- throw new error_1.CloudBaseError('StatementTimeoutMs 不能小于 0');
378
+ (0, error_1.throwInvalidParam)('StatementTimeoutMs 不能小于 0');
379
379
  }
380
380
  return this.dbOpService.request('PushPGUserMigrations', Object.assign(Object.assign(Object.assign({ EnvId: EnvId || this.envId, Migrations }, (LockTimeoutMs !== undefined ? { LockTimeoutMs } : {})), (StatementTimeoutMs !== undefined ? { StatementTimeoutMs } : {})), (IncludeAll !== undefined ? { IncludeAll } : {})));
381
381
  }
@@ -387,19 +387,19 @@ class DatabaseService {
387
387
  async repairPGUserMigrationHistory(options) {
388
388
  const { EnvId, MigrationVersion, Name, Status, Reason, Query } = options;
389
389
  if (!/^\d{14}$/.test(MigrationVersion)) {
390
- throw new error_1.CloudBaseError('MigrationVersion 必须是 14 位数字');
390
+ (0, error_1.throwInvalidParam)('MigrationVersion 必须是 14 位数字');
391
391
  }
392
392
  if (!/^[a-z_]+$/.test(Name)) {
393
- throw new error_1.CloudBaseError('Name 只允许小写字母和下划线');
393
+ (0, error_1.throwInvalidParam)('Name 只允许小写字母和下划线');
394
394
  }
395
395
  if (Status !== 'applied' && Status !== 'reverted') {
396
- throw new error_1.CloudBaseError('Status 只允许 applied 或 reverted');
396
+ (0, error_1.throwInvalidParam)('Status 只允许 applied 或 reverted');
397
397
  }
398
398
  if (!(Reason === null || Reason === void 0 ? void 0 : Reason.trim())) {
399
- throw new error_1.CloudBaseError('Reason 不能为空');
399
+ (0, error_1.throwInvalidParam)('Reason 不能为空');
400
400
  }
401
401
  if (Status === 'applied' && !(Query === null || Query === void 0 ? void 0 : Query.trim())) {
402
- throw new error_1.CloudBaseError('Status=applied 时 Query 不能为空');
402
+ (0, error_1.throwInvalidParam)('Status=applied 时 Query 不能为空');
403
403
  }
404
404
  const params = {
405
405
  EnvId: EnvId || this.envId,
@@ -421,10 +421,10 @@ class DatabaseService {
421
421
  async listPGUserMigrations(options = {}) {
422
422
  const { EnvId, Limit, Offset } = options;
423
423
  if (Limit !== undefined && (Limit < 1 || Limit > 500)) {
424
- throw new error_1.CloudBaseError('Limit 取值范围为 [1, 500]');
424
+ (0, error_1.throwInvalidParam)('Limit 取值范围为 [1, 500]');
425
425
  }
426
426
  if (Offset !== undefined && Offset < 0) {
427
- throw new error_1.CloudBaseError('Offset 不能小于 0');
427
+ (0, error_1.throwInvalidParam)('Offset 不能小于 0');
428
428
  }
429
429
  return this.dbOpService.request('ListPGUserMigrations', Object.assign(Object.assign({ EnvId: EnvId || this.envId }, (Limit !== undefined ? { Limit } : {})), (Offset !== undefined ? { Offset } : {})));
430
430
  }
@@ -436,7 +436,7 @@ class DatabaseService {
436
436
  async listAllPGUserMigrations(options = {}) {
437
437
  const { EnvId, PageSize = 500 } = options;
438
438
  if (PageSize < 1 || PageSize > 500) {
439
- throw new error_1.CloudBaseError('PageSize 取值范围为 [1, 500]');
439
+ (0, error_1.throwInvalidParam)('PageSize 取值范围为 [1, 500]');
440
440
  }
441
441
  const migrations = [];
442
442
  let offset = 0;
@@ -474,7 +474,7 @@ class DatabaseService {
474
474
  async describePGUserMigration(options) {
475
475
  const { EnvId, MigrationVersion } = options;
476
476
  if (!/^\d{14}$/.test(MigrationVersion)) {
477
- throw new error_1.CloudBaseError('MigrationVersion 必须是 14 位数字');
477
+ (0, error_1.throwInvalidParam)('MigrationVersion 必须是 14 位数字');
478
478
  }
479
479
  return this.dbOpService.request('DescribePGUserMigration', {
480
480
  EnvId: EnvId || this.envId,
@@ -489,7 +489,7 @@ class DatabaseService {
489
489
  async describeTaskResult(options) {
490
490
  const { EnvId, TaskId } = options;
491
491
  if (!(TaskId === null || TaskId === void 0 ? void 0 : TaskId.trim())) {
492
- throw new error_1.CloudBaseError('TaskId 不能为空');
492
+ (0, error_1.throwInvalidParam)('TaskId 不能为空');
493
493
  }
494
494
  return this.dbOpService.request('DescribeTaskResult', {
495
495
  EnvId: EnvId || this.envId,
@@ -501,7 +501,7 @@ class DatabaseService {
501
501
  const currEnv = this.environment;
502
502
  const instanceId = (_c = (_b = (_a = currEnv.lazyEnvironmentConfig) === null || _a === void 0 ? void 0 : _a.Databases) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.InstanceId;
503
503
  if (!instanceId) {
504
- throw new error_1.CloudBaseError('当前环境未开通文档型数据库');
504
+ (0, error_1.throwApiError)('当前环境未开通文档型数据库');
505
505
  }
506
506
  return instanceId;
507
507
  }