@cloudbase/manager-node 5.8.9-beta.1 → 5.9.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 (49) hide show
  1. package/.codebuddy/rules/error-code-contract.mdc +13 -0
  2. package/CHANGELOG.md +1 -0
  3. package/lib/agent/index.js +6 -5
  4. package/lib/aiModel/index.js +21 -9
  5. package/lib/cloudApp/index.js +4 -4
  6. package/lib/cloudrun/index.js +16 -15
  7. package/lib/common/index.js +1 -1
  8. package/lib/database/index.js +23 -23
  9. package/lib/deploy/DatabaseDeployer.js +19 -24
  10. package/lib/deploy/DeployOrchestrator.js +2 -2
  11. package/lib/deploy/FunctionDeployer.js +19 -1
  12. package/lib/deploy/GatewayDeployer.js +5 -5
  13. package/lib/deploy/StaticDeployer.js +2 -2
  14. package/lib/deploy/framework.js +2 -1
  15. package/lib/deploy/function/config-guard.js +23 -3
  16. package/lib/deploy/function/enterprise-tcr.js +18 -2
  17. package/lib/docs/index.js +4 -3
  18. package/lib/env/index.js +16 -16
  19. package/lib/environment.js +4 -4
  20. package/lib/environmentManager.js +5 -1
  21. package/lib/error-docs.js +385 -0
  22. package/lib/error-types.js +21 -0
  23. package/lib/error.js +239 -2
  24. package/lib/function/index.js +135 -41
  25. package/lib/function/packer.js +1 -1
  26. package/lib/hosting/index.js +1 -1
  27. package/lib/index.js +2 -1
  28. package/lib/integration/crypto.js +4 -3
  29. package/lib/integration/index.js +1 -1
  30. package/lib/integration/secretKey.js +4 -4
  31. package/lib/monitor/index.js +1 -1
  32. package/lib/mysql/index.js +2 -1
  33. package/lib/permission/index.js +56 -49
  34. package/lib/platform/index.js +2 -2
  35. package/lib/sandbox/index.js +68 -61
  36. package/lib/storage/index.js +164 -162
  37. package/lib/user/index.js +32 -31
  38. package/lib/utils/cloud-api-request.js +13 -5
  39. package/lib/utils/cloudbase-request.js +21 -0
  40. package/lib/utils/fs.js +3 -3
  41. package/lib/utils/http-request.js +2 -2
  42. package/lib/utils/index.js +4 -3
  43. package/lib/utils/storage-config.js +3 -3
  44. package/package.json +2 -2
  45. package/types/error-docs.d.ts +57 -0
  46. package/types/error-types.d.ts +32 -0
  47. package/types/error.d.ts +148 -2
  48. package/types/function/index.d.ts +14 -1
  49. package/types/utils/cloudbase-request.d.ts +22 -0
@@ -114,7 +114,7 @@ class StorageService {
114
114
  const isError = (res) => Object.prototype.toString.call(res) === '[object Error]';
115
115
  const firstError = results.find(isError);
116
116
  if (firstError) {
117
- throw new error_1.CloudBaseError(`计算本地文件摘要失败:${firstError.message}`);
117
+ (0, error_1.throwFileError)(`计算本地文件摘要失败:${firstError.message}`);
118
118
  }
119
119
  return results.filter(res => res !== null);
120
120
  }
@@ -213,7 +213,7 @@ class StorageService {
213
213
  CopySource: copySource
214
214
  });
215
215
  if (res.statusCode !== 200) {
216
- throw new error_1.CloudBaseError(`备份文件失败:${file.key}`);
216
+ (0, error_1.throwApiError)(`备份文件失败:${file.key}`);
217
217
  }
218
218
  return destPath;
219
219
  }));
@@ -221,7 +221,7 @@ class StorageService {
221
221
  const isError = (res) => Object.prototype.toString.call(res) === '[object Error]';
222
222
  const firstError = results.find(isError);
223
223
  if (firstError) {
224
- throw new error_1.CloudBaseError(`远端备份失败:${firstError.message}`);
224
+ (0, error_1.throwApiError)(`远端备份失败:${firstError.message}`);
225
225
  }
226
226
  }
227
227
  /**
@@ -246,7 +246,7 @@ class StorageService {
246
246
  CopySource: copySource
247
247
  });
248
248
  if (res.statusCode !== 200) {
249
- throw new error_1.CloudBaseError(`恢复备份文件失败:${key}`);
249
+ (0, error_1.throwApiError)(`恢复备份文件失败:${key}`);
250
250
  }
251
251
  return key;
252
252
  }));
@@ -254,7 +254,7 @@ class StorageService {
254
254
  const isError = (res) => Object.prototype.toString.call(res) === '[object Error]';
255
255
  const firstRestoreError = restoreResults.find(isError);
256
256
  if (firstRestoreError) {
257
- throw new error_1.CloudBaseError(`从备份恢复远端文件失败:${firstRestoreError.message}`);
257
+ (0, error_1.throwApiError)(`从备份恢复远端文件失败:${firstRestoreError.message}`);
258
258
  }
259
259
  }
260
260
  if (addedKeys.length > 0) {
@@ -418,7 +418,7 @@ class StorageService {
418
418
  });
419
419
  const verifyResult = this.verifyManifest(localManifest, remoteManifest);
420
420
  if (!verifyResult.ok) {
421
- throw new error_1.CloudBaseError(`一致性校验失败:missing=${verifyResult.missing.join(',') || '[]'}; mismatched=${verifyResult.mismatched.join(',') || '[]'}`);
421
+ (0, error_1.throwApiError)(`一致性校验失败:missing=${verifyResult.missing.join(',') || '[]'}; mismatched=${verifyResult.mismatched.join(',') || '[]'}`);
422
422
  }
423
423
  }
424
424
  }
@@ -439,9 +439,9 @@ class StorageService {
439
439
  });
440
440
  }
441
441
  catch (rollbackError) {
442
- throw new error_1.CloudBaseError(`一致性发布失败,且回滚失败,请使用备份人工恢复:${backupPrefix};原始错误:${error.message};回滚错误:${rollbackError.message}`);
442
+ (0, error_1.throwApiError)(`一致性发布失败,且回滚失败,请使用备份人工恢复:${backupPrefix};原始错误:${error.message};回滚错误:${rollbackError.message}`);
443
443
  }
444
- throw new error_1.CloudBaseError(`一致性发布失败,已自动回滚,备份保留于 ${backupPrefix},确认无误后可调用 cleanupBackup 清理:${error.message}`);
444
+ (0, error_1.throwApiError)(`一致性发布失败,已自动回滚,备份保留于 ${backupPrefix},确认无误后可调用 cleanupBackup 清理:${error.message}`);
445
445
  }
446
446
  // 上传与可选校验均成功后才允许清理远端冗余文件。
447
447
  // 删除失败会记录在结果中,不触发已经成功发布内容的回滚。
@@ -530,7 +530,7 @@ class StorageService {
530
530
  localFilePath = resolveLocalPath;
531
531
  }
532
532
  if (!localFilePath) {
533
- throw new error_1.CloudBaseError('本地文件不存在!');
533
+ (0, error_1.throwNotFound)('本地文件不存在!');
534
534
  }
535
535
  const cos = this.getCos();
536
536
  const putObject = util_1.default.promisify(cos.putObject).bind(cos);
@@ -570,7 +570,7 @@ class StorageService {
570
570
  });
571
571
  }
572
572
  if (res.statusCode !== 200) {
573
- throw new error_1.CloudBaseError(`上传文件错误:${JSON.stringify(res)}`);
573
+ (0, error_1.throwApiError)(`上传文件错误:${JSON.stringify(res)}`);
574
574
  }
575
575
  return res;
576
576
  }
@@ -1015,7 +1015,7 @@ class StorageService {
1015
1015
  Body: ''
1016
1016
  });
1017
1017
  if (res.statusCode !== 200) {
1018
- throw new error_1.CloudBaseError(`创建文件夹失败:${JSON.stringify(res)}`);
1018
+ (0, error_1.throwApiError)(`创建文件夹失败:${JSON.stringify(res)}`);
1019
1019
  }
1020
1020
  }
1021
1021
  /**
@@ -1097,7 +1097,7 @@ class StorageService {
1097
1097
  */
1098
1098
  async getTemporaryUrl(fileList) {
1099
1099
  if (!fileList || !Array.isArray(fileList)) {
1100
- throw new error_1.CloudBaseError('fileList 必须是非空的数组');
1100
+ (0, error_1.throwInvalidParam)('fileList 必须是非空的数组');
1101
1101
  }
1102
1102
  const files = fileList.map(item => {
1103
1103
  if (typeof item === 'string') {
@@ -1109,7 +1109,7 @@ class StorageService {
1109
1109
  });
1110
1110
  const invalidData = files.find(item => !item.cloudPath || !item.maxAge || typeof item.cloudPath !== 'string');
1111
1111
  if (invalidData) {
1112
- throw new error_1.CloudBaseError(`非法参数:${JSON.stringify(invalidData)}`);
1112
+ (0, error_1.throwInvalidParam)(`非法参数:${JSON.stringify(invalidData)}`);
1113
1113
  }
1114
1114
  const notExistsFiles = [];
1115
1115
  const checkFileRequests = files.map(file => (async () => {
@@ -1125,7 +1125,7 @@ class StorageService {
1125
1125
  await Promise.all(checkFileRequests);
1126
1126
  // 文件路径不存在
1127
1127
  if (notExistsFiles.length) {
1128
- throw new error_1.CloudBaseError(`以下文件不存在:${notExistsFiles.join(', ')}`);
1128
+ (0, error_1.throwNotFound)(`以下文件不存在:${notExistsFiles.join(', ')}`);
1129
1129
  }
1130
1130
  const data = files.map(item => ({
1131
1131
  fileid: this.cloudPathToFileId(item.cloudPath),
@@ -1153,11 +1153,11 @@ class StorageService {
1153
1153
  */
1154
1154
  async deleteFile(cloudPathList) {
1155
1155
  if (!cloudPathList || !Array.isArray(cloudPathList)) {
1156
- throw new error_1.CloudBaseError('fileList必须是非空的数组');
1156
+ (0, error_1.throwInvalidParam)('fileList必须是非空的数组');
1157
1157
  }
1158
1158
  const hasInvalidFileId = cloudPathList.some(file => !file || typeof file !== 'string');
1159
1159
  if (hasInvalidFileId) {
1160
- throw new error_1.CloudBaseError('fileList的元素必须是非空的字符串');
1160
+ (0, error_1.throwInvalidParam)('fileList的元素必须是非空的字符串');
1161
1161
  }
1162
1162
  const { bucket, env } = this.getStorageConfig();
1163
1163
  const fileIdList = cloudPathList.map(filePath => this.cloudPathToFileId(filePath));
@@ -1170,10 +1170,16 @@ class StorageService {
1170
1170
  },
1171
1171
  method: 'POST'
1172
1172
  });
1173
+ (0, utils_1.assertDataPlaneOk)(res, 'storage.batchDeleteFile');
1173
1174
  const failed = collectBatchDeleteFailures(res.data.delete_list, fileIdList, cloudPathList);
1174
1175
  if (failed.length) {
1175
1176
  const failedList = failed.map(item => `${item.fileId} : ${item.code}`);
1176
1177
  throw new error_1.CloudBaseError(`部分删除文件失败:${JSON.stringify(failedList)}`, {
1178
+ // 稳定码:消费方据此判断「逐项结果可用」,而不是拿「某字段存不存在」猜 SDK 版本。
1179
+ // 与 cloudbase-cli/src/commands/storage/batch-delete.ts 的同名常量**一字不差**(跨仓契约)。
1180
+ code: 'STORAGE_BATCH_DELETE_PARTIAL_FAILED',
1181
+ source: 'manager-node',
1182
+ // 逐项结果放在 meta.failed(v5.8.8 起的既有契约,消费方 batch-delete.ts 按此读取)
1177
1183
  meta: { failed, total: cloudPathList.length }
1178
1184
  });
1179
1185
  }
@@ -1188,11 +1194,11 @@ class StorageService {
1188
1194
  */
1189
1195
  async deleteFileCustom(cloudPathList, bucket, region) {
1190
1196
  if (!cloudPathList || !Array.isArray(cloudPathList)) {
1191
- throw new error_1.CloudBaseError('fileList必须是非空的数组');
1197
+ (0, error_1.throwInvalidParam)('fileList必须是非空的数组');
1192
1198
  }
1193
1199
  const hasInvalidFileId = cloudPathList.some(file => !file || typeof file !== 'string');
1194
1200
  if (hasInvalidFileId) {
1195
- throw new error_1.CloudBaseError('fileList的元素必须是非空的字符串');
1201
+ (0, error_1.throwInvalidParam)('fileList的元素必须是非空的字符串');
1196
1202
  }
1197
1203
  const cos = this.getCos();
1198
1204
  const deleteObject = util_1.default.promisify(cos.deleteObject).bind(cos);
@@ -1218,7 +1224,7 @@ class StorageService {
1218
1224
  Key: (0, storage_config_1.toPhysicalKey)(basePath, cloudPath)
1219
1225
  });
1220
1226
  if (!headers) {
1221
- throw new error_1.CloudBaseError(`[${cloudPath}] 获取文件信息失败`);
1227
+ (0, error_1.throwApiError)(`[${cloudPath}] 获取文件信息失败`);
1222
1228
  }
1223
1229
  // 文件大小 KB
1224
1230
  const size = Number(Number(headers['content-length']) / 1024).toFixed(2);
@@ -1339,10 +1345,10 @@ class StorageService {
1339
1345
  async setStorageAcl(acl, rule) {
1340
1346
  const validAcl = ['READONLY', 'PRIVATE', 'ADMINWRITE', 'ADMINONLY', 'CUSTOM'];
1341
1347
  if (!validAcl.includes(acl)) {
1342
- throw new error_1.CloudBaseError(`非法的权限类型: "${acl}", 有效值: ${validAcl.join(', ')}`);
1348
+ (0, error_1.throwInvalidParam)(`非法的权限类型: "${acl}", 有效值: ${validAcl.join(', ')}`);
1343
1349
  }
1344
1350
  if (acl === 'CUSTOM' && !rule) {
1345
- throw new error_1.CloudBaseError('使用 CUSTOM 权限类型时,必须提供 rule 参数');
1351
+ (0, error_1.throwInvalidParam)('使用 CUSTOM 权限类型时,必须提供 rule 参数');
1346
1352
  }
1347
1353
  const { bucket, env } = this.getStorageConfig();
1348
1354
  const params = {
@@ -1487,7 +1493,7 @@ class StorageService {
1487
1493
  });
1488
1494
  }
1489
1495
  catch (e) {
1490
- throw new error_1.CloudBaseError(e.message);
1496
+ (0, error_1.throwApiError)(e.message);
1491
1497
  }
1492
1498
  }
1493
1499
  /**
@@ -1503,11 +1509,7 @@ class StorageService {
1503
1509
  },
1504
1510
  method: 'POST'
1505
1511
  });
1506
- if (res.code) {
1507
- throw new error_1.CloudBaseError(`${res.code}: ${res.message || ''}`, {
1508
- requestId: res.requestId
1509
- });
1510
- }
1512
+ (0, utils_1.assertDataPlaneOk)(res, 'storage.getUploadMetadata');
1511
1513
  return res.data;
1512
1514
  }
1513
1515
  /**
@@ -1662,7 +1664,7 @@ class StorageService {
1662
1664
  CopySource: copySource
1663
1665
  });
1664
1666
  if (res.statusCode !== 200) {
1665
- throw new error_1.CloudBaseError(`复制文件失败:${JSON.stringify(res)}`);
1667
+ (0, error_1.throwApiError)(`复制文件失败:${JSON.stringify(res)}`);
1666
1668
  }
1667
1669
  // 4. 返回复制结果
1668
1670
  return {
@@ -1952,19 +1954,19 @@ class StorageService {
1952
1954
  async uploadObject(options) {
1953
1955
  const { bucketId, objectName, localPath, body, contentType, contentLength, cacheControl, metadata, xRobotsTag, upsert = false, usePut = false, accessToken, envId: envIdOverride } = options;
1954
1956
  if (!bucketId || typeof bucketId !== 'string') {
1955
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
1957
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
1956
1958
  }
1957
1959
  if (!objectName || typeof objectName !== 'string') {
1958
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
1960
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
1959
1961
  }
1960
1962
  if (!accessToken || typeof accessToken !== 'string') {
1961
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
1963
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
1962
1964
  }
1963
1965
  if (!localPath && !body) {
1964
- throw new error_1.CloudBaseError('localPath 与 body 至少提供一个');
1966
+ (0, error_1.throwInvalidParam)('localPath 与 body 至少提供一个');
1965
1967
  }
1966
1968
  if (localPath && body) {
1967
- throw new error_1.CloudBaseError('localPath 与 body 只能二选一');
1969
+ (0, error_1.throwInvalidParam)('localPath 与 body 只能二选一');
1968
1970
  }
1969
1971
  // env / proxy
1970
1972
  const authConfig = this.environment.getAuthConfig();
@@ -1986,7 +1988,7 @@ class StorageService {
1986
1988
  (0, utils_1.checkFullAccess)(resolvedPath, true);
1987
1989
  const stat = fs_1.default.statSync(resolvedPath);
1988
1990
  if (!stat.isFile()) {
1989
- throw new error_1.CloudBaseError(`localPath 不是文件: ${localPath}`);
1991
+ (0, error_1.throwInvalidParam)(`localPath 不是文件: ${localPath}`);
1990
1992
  }
1991
1993
  fileSize = stat.size;
1992
1994
  }
@@ -1996,8 +1998,8 @@ class StorageService {
1996
1998
  // 文档约束:> 100MB 拒绝
1997
1999
  const LIMIT_100MB = 100 * 1024 * 1024;
1998
2000
  if (fileSize !== undefined && fileSize > LIMIT_100MB) {
1999
- throw new error_1.CloudBaseError('FileSizeLimitExceeded: 文件大小超过 100MB', {
2000
- code: 'FileSizeLimitExceeded'
2001
+ throw new error_1.CloudBaseError('文件大小超过 100MB', {
2002
+ code: 'FILE_SIZE_LIMIT_EXCEEDED'
2001
2003
  });
2002
2004
  }
2003
2005
  const finalContentType = this.resolveUploadContentType({
@@ -2044,9 +2046,9 @@ class StorageService {
2044
2046
  }
2045
2047
  catch (_a) {
2046
2048
  if (!res.ok) {
2047
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2049
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2048
2050
  }
2049
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2051
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2050
2052
  }
2051
2053
  }
2052
2054
  if (!res.ok) {
@@ -2058,7 +2060,7 @@ class StorageService {
2058
2060
  });
2059
2061
  }
2060
2062
  if (!payload || !payload.Id || !payload.Key) {
2061
- throw new error_1.CloudBaseError('上传成功但响应格式异常:缺少 Id 或 Key');
2063
+ (0, error_1.throwApiError)('上传成功但响应格式异常:缺少 Id 或 Key');
2062
2064
  }
2063
2065
  return {
2064
2066
  Id: payload.Id,
@@ -2072,13 +2074,13 @@ class StorageService {
2072
2074
  async deleteObject(options) {
2073
2075
  const { bucketId, objectName, accessToken, envId: envIdOverride } = options;
2074
2076
  if (!bucketId || typeof bucketId !== 'string') {
2075
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2077
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2076
2078
  }
2077
2079
  if (!objectName || typeof objectName !== 'string') {
2078
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2080
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2079
2081
  }
2080
2082
  if (!accessToken || typeof accessToken !== 'string') {
2081
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2083
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2082
2084
  }
2083
2085
  const env = this.environment.getEnvId();
2084
2086
  const envId = envIdOverride || env;
@@ -2103,9 +2105,9 @@ class StorageService {
2103
2105
  }
2104
2106
  catch (_a) {
2105
2107
  if (!res.ok) {
2106
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2108
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2107
2109
  }
2108
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2110
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2109
2111
  }
2110
2112
  }
2111
2113
  if (!res.ok) {
@@ -2128,20 +2130,20 @@ class StorageService {
2128
2130
  async deleteObjects(options) {
2129
2131
  const { bucketId, prefixes, accessToken, envId: envIdOverride } = options;
2130
2132
  if (!bucketId || typeof bucketId !== 'string') {
2131
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2133
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2132
2134
  }
2133
2135
  if (!accessToken || typeof accessToken !== 'string') {
2134
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2136
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2135
2137
  }
2136
2138
  if (!Array.isArray(prefixes) || prefixes.length === 0) {
2137
- throw new error_1.CloudBaseError('prefixes 必须是非空数组');
2139
+ (0, error_1.throwInvalidParam)('prefixes 必须是非空数组');
2138
2140
  }
2139
2141
  if (prefixes.length > 20) {
2140
- throw new error_1.CloudBaseError('prefixes 最多 20 个');
2142
+ (0, error_1.throwInvalidParam)('prefixes 最多 20 个');
2141
2143
  }
2142
2144
  for (const name of prefixes) {
2143
2145
  if (!name || typeof name !== 'string') {
2144
- throw new error_1.CloudBaseError('prefixes 中的每一项必须是非空字符串');
2146
+ (0, error_1.throwInvalidParam)('prefixes 中的每一项必须是非空字符串');
2145
2147
  }
2146
2148
  }
2147
2149
  const env = this.environment.getEnvId();
@@ -2165,9 +2167,9 @@ class StorageService {
2165
2167
  }
2166
2168
  catch (_a) {
2167
2169
  if (!res.ok) {
2168
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2170
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2169
2171
  }
2170
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2172
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2171
2173
  }
2172
2174
  }
2173
2175
  if (!res.ok) {
@@ -2179,7 +2181,7 @@ class StorageService {
2179
2181
  });
2180
2182
  }
2181
2183
  if (!Array.isArray(payload)) {
2182
- throw new error_1.CloudBaseError('批量删除响应格式异常:期望数组');
2184
+ (0, error_1.throwApiError)('批量删除响应格式异常:期望数组');
2183
2185
  }
2184
2186
  return payload;
2185
2187
  }
@@ -2191,29 +2193,29 @@ class StorageService {
2191
2193
  async copyObject(options) {
2192
2194
  const { bucketId, sourceKey, destinationKey, destinationBucket, metadata, userMetadata, copyMetadata, upsert, accessToken, envId: envIdOverride } = options;
2193
2195
  if (!bucketId || typeof bucketId !== 'string') {
2194
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2196
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2195
2197
  }
2196
2198
  if (!sourceKey || typeof sourceKey !== 'string') {
2197
- throw new error_1.CloudBaseError('sourceKey 必须是非空字符串');
2199
+ (0, error_1.throwInvalidParam)('sourceKey 必须是非空字符串');
2198
2200
  }
2199
2201
  if (!destinationKey || typeof destinationKey !== 'string') {
2200
- throw new error_1.CloudBaseError('destinationKey 必须是非空字符串');
2202
+ (0, error_1.throwInvalidParam)('destinationKey 必须是非空字符串');
2201
2203
  }
2202
2204
  if (destinationBucket !== undefined &&
2203
2205
  (typeof destinationBucket !== 'string' || !destinationBucket)) {
2204
- throw new error_1.CloudBaseError('destinationBucket 必须是非空字符串');
2206
+ (0, error_1.throwInvalidParam)('destinationBucket 必须是非空字符串');
2205
2207
  }
2206
2208
  if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null || Array.isArray(metadata))) {
2207
- throw new error_1.CloudBaseError('metadata 必须是对象');
2209
+ (0, error_1.throwInvalidParam)('metadata 必须是对象');
2208
2210
  }
2209
2211
  if (userMetadata !== undefined && (typeof userMetadata !== 'object' || userMetadata === null || Array.isArray(userMetadata))) {
2210
- throw new error_1.CloudBaseError('userMetadata 必须是对象');
2212
+ (0, error_1.throwInvalidParam)('userMetadata 必须是对象');
2211
2213
  }
2212
2214
  if (copyMetadata !== undefined && typeof copyMetadata !== 'boolean') {
2213
- throw new error_1.CloudBaseError('copyMetadata 必须是布尔值');
2215
+ (0, error_1.throwInvalidParam)('copyMetadata 必须是布尔值');
2214
2216
  }
2215
2217
  if (!accessToken || typeof accessToken !== 'string') {
2216
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2218
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2217
2219
  }
2218
2220
  const env = this.environment.getEnvId();
2219
2221
  const envId = envIdOverride || env;
@@ -2254,9 +2256,9 @@ class StorageService {
2254
2256
  }
2255
2257
  catch (_a) {
2256
2258
  if (!res.ok) {
2257
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2259
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2258
2260
  }
2259
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2261
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2260
2262
  }
2261
2263
  }
2262
2264
  if (!res.ok) {
@@ -2268,7 +2270,7 @@ class StorageService {
2268
2270
  });
2269
2271
  }
2270
2272
  if (!payload || !payload.Id || !payload.Key) {
2271
- throw new error_1.CloudBaseError('复制成功但响应格式异常:缺少 Id 或 Key');
2273
+ (0, error_1.throwApiError)('复制成功但响应格式异常:缺少 Id 或 Key');
2272
2274
  }
2273
2275
  return payload;
2274
2276
  }
@@ -2279,20 +2281,20 @@ class StorageService {
2279
2281
  async moveObject(options) {
2280
2282
  const { bucketId, sourceKey, destinationKey, destinationBucket, accessToken, envId: envIdOverride } = options;
2281
2283
  if (!bucketId || typeof bucketId !== 'string') {
2282
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2284
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2283
2285
  }
2284
2286
  if (!sourceKey || typeof sourceKey !== 'string') {
2285
- throw new error_1.CloudBaseError('sourceKey 必须是非空字符串');
2287
+ (0, error_1.throwInvalidParam)('sourceKey 必须是非空字符串');
2286
2288
  }
2287
2289
  if (!destinationKey || typeof destinationKey !== 'string') {
2288
- throw new error_1.CloudBaseError('destinationKey 必须是非空字符串');
2290
+ (0, error_1.throwInvalidParam)('destinationKey 必须是非空字符串');
2289
2291
  }
2290
2292
  if (destinationBucket !== undefined &&
2291
2293
  (typeof destinationBucket !== 'string' || !destinationBucket)) {
2292
- throw new error_1.CloudBaseError('destinationBucket 必须是非空字符串');
2294
+ (0, error_1.throwInvalidParam)('destinationBucket 必须是非空字符串');
2293
2295
  }
2294
2296
  if (!accessToken || typeof accessToken !== 'string') {
2295
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2297
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2296
2298
  }
2297
2299
  const env = this.environment.getEnvId();
2298
2300
  const envId = envIdOverride || env;
@@ -2321,9 +2323,9 @@ class StorageService {
2321
2323
  }
2322
2324
  catch (_a) {
2323
2325
  if (!res.ok) {
2324
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2326
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2325
2327
  }
2326
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2328
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2327
2329
  }
2328
2330
  }
2329
2331
  if (!res.ok) {
@@ -2335,7 +2337,7 @@ class StorageService {
2335
2337
  });
2336
2338
  }
2337
2339
  if (!payload || !payload.Id || !payload.Key) {
2338
- throw new error_1.CloudBaseError('移动成功但响应格式异常:缺少 Id 或 Key');
2340
+ (0, error_1.throwApiError)('移动成功但响应格式异常:缺少 Id 或 Key');
2339
2341
  }
2340
2342
  return {
2341
2343
  message: payload.message || 'Successfully moved',
@@ -2351,41 +2353,41 @@ class StorageService {
2351
2353
  async listObjects(options) {
2352
2354
  const { bucketId, prefix, limit, cursor, withDelimiter, sortBy, accessToken, envId: envIdOverride } = options;
2353
2355
  if (!bucketId || typeof bucketId !== 'string') {
2354
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2356
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2355
2357
  }
2356
2358
  if (prefix !== undefined && typeof prefix !== 'string') {
2357
- throw new error_1.CloudBaseError('prefix 必须是字符串');
2359
+ (0, error_1.throwInvalidParam)('prefix 必须是字符串');
2358
2360
  }
2359
2361
  if (limit !== undefined) {
2360
2362
  if (!Number.isInteger(limit)) {
2361
- throw new error_1.CloudBaseError('limit 必须是整数');
2363
+ (0, error_1.throwInvalidParam)('limit 必须是整数');
2362
2364
  }
2363
2365
  if (limit < 1 || limit > 1000) {
2364
- throw new error_1.CloudBaseError('limit 必须在 1 ~ 1000 之间');
2366
+ (0, error_1.throwInvalidParam)('limit 必须在 1 ~ 1000 之间');
2365
2367
  }
2366
2368
  }
2367
2369
  if (cursor !== undefined && typeof cursor !== 'string') {
2368
- throw new error_1.CloudBaseError('cursor 必须是字符串');
2370
+ (0, error_1.throwInvalidParam)('cursor 必须是字符串');
2369
2371
  }
2370
2372
  if (withDelimiter !== undefined && typeof withDelimiter !== 'boolean') {
2371
- throw new error_1.CloudBaseError('withDelimiter 必须是布尔值');
2373
+ (0, error_1.throwInvalidParam)('withDelimiter 必须是布尔值');
2372
2374
  }
2373
2375
  if (!accessToken || typeof accessToken !== 'string') {
2374
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2376
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2375
2377
  }
2376
2378
  if (sortBy !== undefined) {
2377
2379
  if (typeof sortBy !== 'object' || sortBy === null || Array.isArray(sortBy)) {
2378
- throw new error_1.CloudBaseError('sortBy 必须是对象');
2380
+ (0, error_1.throwInvalidParam)('sortBy 必须是对象');
2379
2381
  }
2380
2382
  const allowedColumns = ['name', 'created_at', 'updated_at'];
2381
2383
  const allowedOrders = ['asc', 'desc'];
2382
2384
  if (sortBy.column !== undefined && !allowedColumns.includes(sortBy.column)) {
2383
- throw new error_1.CloudBaseError(`sortBy.column 非法,允许值:${allowedColumns.join('、')}`);
2385
+ (0, error_1.throwInvalidParam)(`sortBy.column 非法,允许值:${allowedColumns.join('、')}`);
2384
2386
  }
2385
2387
  if (sortBy.order !== undefined) {
2386
2388
  const normalizedOrder = String(sortBy.order).toLowerCase();
2387
2389
  if (!allowedOrders.includes(normalizedOrder)) {
2388
- throw new error_1.CloudBaseError(`sortBy.order 非法,允许值:${allowedOrders.join('、')}`);
2390
+ (0, error_1.throwInvalidParam)(`sortBy.order 非法,允许值:${allowedOrders.join('、')}`);
2389
2391
  }
2390
2392
  sortBy.order = normalizedOrder;
2391
2393
  }
@@ -2422,9 +2424,9 @@ class StorageService {
2422
2424
  }
2423
2425
  catch (_a) {
2424
2426
  if (!res.ok) {
2425
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2427
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2426
2428
  }
2427
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2429
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2428
2430
  }
2429
2431
  }
2430
2432
  if (!res.ok) {
@@ -2436,7 +2438,7 @@ class StorageService {
2436
2438
  });
2437
2439
  }
2438
2440
  if (!payload || !Array.isArray(payload.objects) || !Array.isArray(payload.folders)) {
2439
- throw new error_1.CloudBaseError('列出对象成功但响应格式异常:缺少 folders 或 objects 数组');
2441
+ (0, error_1.throwApiError)('列出对象成功但响应格式异常:缺少 folders 或 objects 数组');
2440
2442
  }
2441
2443
  const result = Object.assign({ folders: payload.folders, objects: payload.objects, hasNext: Boolean(payload.hasNext), nextCursor: payload.nextCursor, nextCursorKey: payload.nextCursorKey }, payload);
2442
2444
  return result;
@@ -2448,19 +2450,19 @@ class StorageService {
2448
2450
  async signObject(options) {
2449
2451
  const { bucketId, objectName, expiresIn, accessToken, envId: envIdOverride } = options;
2450
2452
  if (!bucketId || typeof bucketId !== 'string') {
2451
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2453
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2452
2454
  }
2453
2455
  if (!objectName || typeof objectName !== 'string') {
2454
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2456
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2455
2457
  }
2456
2458
  if (!Number.isInteger(expiresIn)) {
2457
- throw new error_1.CloudBaseError('expiresIn 必须是整数');
2459
+ (0, error_1.throwInvalidParam)('expiresIn 必须是整数');
2458
2460
  }
2459
2461
  if (expiresIn < 1) {
2460
- throw new error_1.CloudBaseError('expiresIn 必须 >= 1');
2462
+ (0, error_1.throwInvalidParam)('expiresIn 必须 >= 1');
2461
2463
  }
2462
2464
  if (!accessToken || typeof accessToken !== 'string') {
2463
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2465
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2464
2466
  }
2465
2467
  const env = this.environment.getEnvId();
2466
2468
  const envId = envIdOverride || env;
@@ -2487,9 +2489,9 @@ class StorageService {
2487
2489
  }
2488
2490
  catch (_a) {
2489
2491
  if (!res.ok) {
2490
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2492
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2491
2493
  }
2492
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2494
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2493
2495
  }
2494
2496
  }
2495
2497
  if (!res.ok) {
@@ -2501,7 +2503,7 @@ class StorageService {
2501
2503
  });
2502
2504
  }
2503
2505
  if (!payload || typeof payload.signedURL !== 'string' || !payload.signedURL) {
2504
- throw new error_1.CloudBaseError('生成签名 URL 成功但响应格式异常:缺少 signedURL');
2506
+ (0, error_1.throwApiError)('生成签名 URL 成功但响应格式异常:缺少 signedURL');
2505
2507
  }
2506
2508
  return {
2507
2509
  signedURL: payload.signedURL
@@ -2514,27 +2516,27 @@ class StorageService {
2514
2516
  async signObjects(options) {
2515
2517
  const { bucketId, expiresIn, paths, accessToken, envId: envIdOverride } = options;
2516
2518
  if (!bucketId || typeof bucketId !== 'string') {
2517
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2519
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2518
2520
  }
2519
2521
  if (!Number.isInteger(expiresIn)) {
2520
- throw new error_1.CloudBaseError('expiresIn 必须是整数');
2522
+ (0, error_1.throwInvalidParam)('expiresIn 必须是整数');
2521
2523
  }
2522
2524
  if (expiresIn < 1) {
2523
- throw new error_1.CloudBaseError('expiresIn 必须 >= 1');
2525
+ (0, error_1.throwInvalidParam)('expiresIn 必须 >= 1');
2524
2526
  }
2525
2527
  if (!Array.isArray(paths) || paths.length === 0) {
2526
- throw new error_1.CloudBaseError('paths 必须是非空数组');
2528
+ (0, error_1.throwInvalidParam)('paths 必须是非空数组');
2527
2529
  }
2528
2530
  if (paths.length > 500) {
2529
- throw new error_1.CloudBaseError('paths 最多 500 个');
2531
+ (0, error_1.throwInvalidParam)('paths 最多 500 个');
2530
2532
  }
2531
2533
  for (const pathItem of paths) {
2532
2534
  if (!pathItem || typeof pathItem !== 'string') {
2533
- throw new error_1.CloudBaseError('paths 中每一项必须是非空字符串');
2535
+ (0, error_1.throwInvalidParam)('paths 中每一项必须是非空字符串');
2534
2536
  }
2535
2537
  }
2536
2538
  if (!accessToken || typeof accessToken !== 'string') {
2537
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2539
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2538
2540
  }
2539
2541
  const env = this.environment.getEnvId();
2540
2542
  const envId = envIdOverride || env;
@@ -2560,9 +2562,9 @@ class StorageService {
2560
2562
  }
2561
2563
  catch (_a) {
2562
2564
  if (!res.ok) {
2563
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2565
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2564
2566
  }
2565
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2567
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2566
2568
  }
2567
2569
  }
2568
2570
  if (!res.ok) {
@@ -2574,7 +2576,7 @@ class StorageService {
2574
2576
  });
2575
2577
  }
2576
2578
  if (!Array.isArray(payload)) {
2577
- throw new error_1.CloudBaseError('批量生成签名 URL 成功但响应格式异常:期望数组');
2579
+ (0, error_1.throwApiError)('批量生成签名 URL 成功但响应格式异常:期望数组');
2578
2580
  }
2579
2581
  return payload;
2580
2582
  }
@@ -2585,16 +2587,16 @@ class StorageService {
2585
2587
  async signUploadObject(options) {
2586
2588
  const { bucketId, objectName, upsert = false, accessToken, envId: envIdOverride } = options;
2587
2589
  if (!bucketId || typeof bucketId !== 'string') {
2588
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2590
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2589
2591
  }
2590
2592
  if (!objectName || typeof objectName !== 'string') {
2591
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2593
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2592
2594
  }
2593
2595
  if (typeof upsert !== 'boolean') {
2594
- throw new error_1.CloudBaseError('upsert 必须是布尔值');
2596
+ (0, error_1.throwInvalidParam)('upsert 必须是布尔值');
2595
2597
  }
2596
2598
  if (!accessToken || typeof accessToken !== 'string') {
2597
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2599
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2598
2600
  }
2599
2601
  const env = this.environment.getEnvId();
2600
2602
  const envId = envIdOverride || env;
@@ -2623,9 +2625,9 @@ class StorageService {
2623
2625
  }
2624
2626
  catch (_a) {
2625
2627
  if (!res.ok) {
2626
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2628
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2627
2629
  }
2628
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2630
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2629
2631
  }
2630
2632
  }
2631
2633
  if (!res.ok) {
@@ -2637,7 +2639,7 @@ class StorageService {
2637
2639
  });
2638
2640
  }
2639
2641
  if (!payload || typeof payload.url !== 'string' || typeof payload.token !== 'string') {
2640
- throw new error_1.CloudBaseError('生成签名上传 URL 成功但响应格式异常:缺少 url 或 token');
2642
+ (0, error_1.throwApiError)('生成签名上传 URL 成功但响应格式异常:缺少 url 或 token');
2641
2643
  }
2642
2644
  return {
2643
2645
  url: payload.url,
@@ -2651,19 +2653,19 @@ class StorageService {
2651
2653
  async uploadObjectBySign(options) {
2652
2654
  const { bucketId, objectName, token, localPath, body, contentType, contentLength, envId: envIdOverride } = options;
2653
2655
  if (!bucketId || typeof bucketId !== 'string') {
2654
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2656
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2655
2657
  }
2656
2658
  if (!objectName || typeof objectName !== 'string') {
2657
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2659
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2658
2660
  }
2659
2661
  if (!token || typeof token !== 'string') {
2660
- throw new error_1.CloudBaseError('token 必须是非空字符串');
2662
+ (0, error_1.throwInvalidParam)('token 必须是非空字符串');
2661
2663
  }
2662
2664
  if (!localPath && !body) {
2663
- throw new error_1.CloudBaseError('localPath 与 body 至少提供一个');
2665
+ (0, error_1.throwInvalidParam)('localPath 与 body 至少提供一个');
2664
2666
  }
2665
2667
  if (localPath && body) {
2666
- throw new error_1.CloudBaseError('localPath 与 body 只能二选一');
2668
+ (0, error_1.throwInvalidParam)('localPath 与 body 只能二选一');
2667
2669
  }
2668
2670
  const env = this.environment.getEnvId();
2669
2671
  const envId = envIdOverride || env;
@@ -2680,7 +2682,7 @@ class StorageService {
2680
2682
  (0, utils_1.checkFullAccess)(resolvedPath, true);
2681
2683
  const stat = fs_1.default.statSync(resolvedPath);
2682
2684
  if (!stat.isFile()) {
2683
- throw new error_1.CloudBaseError(`localPath 不是文件: ${localPath}`);
2685
+ (0, error_1.throwInvalidParam)(`localPath 不是文件: ${localPath}`);
2684
2686
  }
2685
2687
  fileSize = stat.size;
2686
2688
  }
@@ -2715,9 +2717,9 @@ class StorageService {
2715
2717
  }
2716
2718
  catch (_a) {
2717
2719
  if (!res.ok) {
2718
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2720
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2719
2721
  }
2720
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
2722
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
2721
2723
  }
2722
2724
  }
2723
2725
  if (!res.ok) {
@@ -2729,7 +2731,7 @@ class StorageService {
2729
2731
  });
2730
2732
  }
2731
2733
  if (!payload || typeof payload.Key !== 'string' || !payload.Key) {
2732
- throw new error_1.CloudBaseError('签名上传成功但响应格式异常:缺少 Key');
2734
+ (0, error_1.throwApiError)('签名上传成功但响应格式异常:缺少 Key');
2733
2735
  }
2734
2736
  return {
2735
2737
  Key: payload.Key
@@ -2742,18 +2744,18 @@ class StorageService {
2742
2744
  async downloadAuthenticatedObject(options) {
2743
2745
  const { bucketId, objectName, method = 'GET', download, ifNoneMatch, ifModifiedSince, range, accessToken, envId: envIdOverride } = options;
2744
2746
  if (!bucketId || typeof bucketId !== 'string') {
2745
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2747
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2746
2748
  }
2747
2749
  if (!objectName || typeof objectName !== 'string') {
2748
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2750
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2749
2751
  }
2750
2752
  if (!accessToken || typeof accessToken !== 'string') {
2751
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
2753
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
2752
2754
  }
2753
2755
  const normalizedMethod = String(method).toUpperCase();
2754
2756
  const allowedMethods = ['GET', 'HEAD'];
2755
2757
  if (!allowedMethods.includes(normalizedMethod)) {
2756
- throw new error_1.CloudBaseError('method 仅支持 GET 或 HEAD');
2758
+ (0, error_1.throwInvalidParam)('method 仅支持 GET 或 HEAD');
2757
2759
  }
2758
2760
  const env = this.environment.getEnvId();
2759
2761
  const envId = envIdOverride || env;
@@ -2765,7 +2767,7 @@ class StorageService {
2765
2767
  let url = `https://${envId}.api.tcloudbasegateway.com/v1/storages/object/authenticated/${encodedBucketId}/${encodedObjectName}`;
2766
2768
  if (download !== undefined) {
2767
2769
  if (typeof download !== 'string') {
2768
- throw new error_1.CloudBaseError('download 必须是字符串');
2770
+ (0, error_1.throwInvalidParam)('download 必须是字符串');
2769
2771
  }
2770
2772
  url += `?download=${encodeURIComponent(download)}`;
2771
2773
  }
@@ -2774,19 +2776,19 @@ class StorageService {
2774
2776
  };
2775
2777
  if (ifNoneMatch !== undefined) {
2776
2778
  if (typeof ifNoneMatch !== 'string') {
2777
- throw new error_1.CloudBaseError('ifNoneMatch 必须是字符串');
2779
+ (0, error_1.throwInvalidParam)('ifNoneMatch 必须是字符串');
2778
2780
  }
2779
2781
  headers['If-None-Match'] = ifNoneMatch;
2780
2782
  }
2781
2783
  if (ifModifiedSince !== undefined) {
2782
2784
  if (typeof ifModifiedSince !== 'string') {
2783
- throw new error_1.CloudBaseError('ifModifiedSince 必须是字符串');
2785
+ (0, error_1.throwInvalidParam)('ifModifiedSince 必须是字符串');
2784
2786
  }
2785
2787
  headers['If-Modified-Since'] = ifModifiedSince;
2786
2788
  }
2787
2789
  if (range !== undefined) {
2788
2790
  if (typeof range !== 'string') {
2789
- throw new error_1.CloudBaseError('range 必须是字符串');
2791
+ (0, error_1.throwInvalidParam)('range 必须是字符串');
2790
2792
  }
2791
2793
  headers.Range = range;
2792
2794
  }
@@ -2803,7 +2805,7 @@ class StorageService {
2803
2805
  payload = JSON.parse(text);
2804
2806
  }
2805
2807
  catch (_a) {
2806
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2808
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2807
2809
  }
2808
2810
  }
2809
2811
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -2830,18 +2832,18 @@ class StorageService {
2830
2832
  async downloadObject(options) {
2831
2833
  const { bucketId, objectName, method = 'GET', download, ifNoneMatch, ifModifiedSince, range, accessToken, envId: envIdOverride } = options;
2832
2834
  if (!bucketId || typeof bucketId !== 'string') {
2833
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2835
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2834
2836
  }
2835
2837
  if (!objectName || typeof objectName !== 'string') {
2836
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2838
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2837
2839
  }
2838
2840
  if (accessToken !== undefined && typeof accessToken !== 'string') {
2839
- throw new error_1.CloudBaseError('accessToken 必须是字符串');
2841
+ (0, error_1.throwInvalidParam)('accessToken 必须是字符串');
2840
2842
  }
2841
2843
  const normalizedMethod = String(method).toUpperCase();
2842
2844
  const allowedMethods = ['GET', 'HEAD'];
2843
2845
  if (!allowedMethods.includes(normalizedMethod)) {
2844
- throw new error_1.CloudBaseError('method 仅支持 GET 或 HEAD');
2846
+ (0, error_1.throwInvalidParam)('method 仅支持 GET 或 HEAD');
2845
2847
  }
2846
2848
  const env = this.environment.getEnvId();
2847
2849
  const envId = envIdOverride || env;
@@ -2853,7 +2855,7 @@ class StorageService {
2853
2855
  let url = `https://${envId}.api.tcloudbasegateway.com/v1/storages/object/${encodedBucketId}/${encodedObjectName}`;
2854
2856
  if (download !== undefined) {
2855
2857
  if (typeof download !== 'string') {
2856
- throw new error_1.CloudBaseError('download 必须是字符串');
2858
+ (0, error_1.throwInvalidParam)('download 必须是字符串');
2857
2859
  }
2858
2860
  url += `?download=${encodeURIComponent(download)}`;
2859
2861
  }
@@ -2863,19 +2865,19 @@ class StorageService {
2863
2865
  }
2864
2866
  if (ifNoneMatch !== undefined) {
2865
2867
  if (typeof ifNoneMatch !== 'string') {
2866
- throw new error_1.CloudBaseError('ifNoneMatch 必须是字符串');
2868
+ (0, error_1.throwInvalidParam)('ifNoneMatch 必须是字符串');
2867
2869
  }
2868
2870
  headers['If-None-Match'] = ifNoneMatch;
2869
2871
  }
2870
2872
  if (ifModifiedSince !== undefined) {
2871
2873
  if (typeof ifModifiedSince !== 'string') {
2872
- throw new error_1.CloudBaseError('ifModifiedSince 必须是字符串');
2874
+ (0, error_1.throwInvalidParam)('ifModifiedSince 必须是字符串');
2873
2875
  }
2874
2876
  headers['If-Modified-Since'] = ifModifiedSince;
2875
2877
  }
2876
2878
  if (range !== undefined) {
2877
2879
  if (typeof range !== 'string') {
2878
- throw new error_1.CloudBaseError('range 必须是字符串');
2880
+ (0, error_1.throwInvalidParam)('range 必须是字符串');
2879
2881
  }
2880
2882
  headers.Range = range;
2881
2883
  }
@@ -2892,7 +2894,7 @@ class StorageService {
2892
2894
  payload = JSON.parse(text);
2893
2895
  }
2894
2896
  catch (_a) {
2895
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2897
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2896
2898
  }
2897
2899
  }
2898
2900
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -2919,15 +2921,15 @@ class StorageService {
2919
2921
  async downloadPublicObject(options) {
2920
2922
  const { bucketId, objectName, method = 'GET', download, envId: envIdOverride } = options;
2921
2923
  if (!bucketId || typeof bucketId !== 'string') {
2922
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2924
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2923
2925
  }
2924
2926
  if (!objectName || typeof objectName !== 'string') {
2925
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2927
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2926
2928
  }
2927
2929
  const normalizedMethod = String(method).toUpperCase();
2928
2930
  const allowedMethods = ['GET', 'HEAD'];
2929
2931
  if (!allowedMethods.includes(normalizedMethod)) {
2930
- throw new error_1.CloudBaseError('method 仅支持 GET 或 HEAD');
2932
+ (0, error_1.throwInvalidParam)('method 仅支持 GET 或 HEAD');
2931
2933
  }
2932
2934
  const env = this.environment.getEnvId();
2933
2935
  const envId = envIdOverride || env;
@@ -2939,7 +2941,7 @@ class StorageService {
2939
2941
  let url = `https://${envId}.api.tcloudbasegateway.com/v1/storages/object/public/${encodedBucketId}/${encodedObjectName}`;
2940
2942
  if (download !== undefined) {
2941
2943
  if (typeof download !== 'string') {
2942
- throw new error_1.CloudBaseError('download 必须是字符串');
2944
+ (0, error_1.throwInvalidParam)('download 必须是字符串');
2943
2945
  }
2944
2946
  url += `?download=${encodeURIComponent(download)}`;
2945
2947
  }
@@ -2955,7 +2957,7 @@ class StorageService {
2955
2957
  payload = JSON.parse(text);
2956
2958
  }
2957
2959
  catch (_a) {
2958
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
2960
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
2959
2961
  }
2960
2962
  }
2961
2963
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -2982,18 +2984,18 @@ class StorageService {
2982
2984
  async downloadObjectBySign(options) {
2983
2985
  const { bucketId, objectName, token, method = 'GET', download, envId: envIdOverride } = options;
2984
2986
  if (!bucketId || typeof bucketId !== 'string') {
2985
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
2987
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
2986
2988
  }
2987
2989
  if (!objectName || typeof objectName !== 'string') {
2988
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
2990
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
2989
2991
  }
2990
2992
  if (!token || typeof token !== 'string') {
2991
- throw new error_1.CloudBaseError('token 必须是非空字符串');
2993
+ (0, error_1.throwInvalidParam)('token 必须是非空字符串');
2992
2994
  }
2993
2995
  const normalizedMethod = String(method).toUpperCase();
2994
2996
  const allowedMethods = ['GET', 'HEAD'];
2995
2997
  if (!allowedMethods.includes(normalizedMethod)) {
2996
- throw new error_1.CloudBaseError('method 仅支持 GET 或 HEAD');
2998
+ (0, error_1.throwInvalidParam)('method 仅支持 GET 或 HEAD');
2997
2999
  }
2998
3000
  const env = this.environment.getEnvId();
2999
3001
  const envId = envIdOverride || env;
@@ -3005,7 +3007,7 @@ class StorageService {
3005
3007
  let url = `https://${envId}.api.tcloudbasegateway.com/v1/storages/object/sign/${encodedBucketId}/${encodedObjectName}?token=${encodeURIComponent(token)}`;
3006
3008
  if (download !== undefined) {
3007
3009
  if (typeof download !== 'string') {
3008
- throw new error_1.CloudBaseError('download 必须是字符串');
3010
+ (0, error_1.throwInvalidParam)('download 必须是字符串');
3009
3011
  }
3010
3012
  url += `&download=${encodeURIComponent(download)}`;
3011
3013
  }
@@ -3021,7 +3023,7 @@ class StorageService {
3021
3023
  payload = JSON.parse(text);
3022
3024
  }
3023
3025
  catch (_a) {
3024
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
3026
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
3025
3027
  }
3026
3028
  }
3027
3029
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -3048,18 +3050,18 @@ class StorageService {
3048
3050
  async getObjectInfoAuthenticated(options) {
3049
3051
  const { bucketId, objectName, method = 'GET', accessToken, envId: envIdOverride } = options;
3050
3052
  if (!bucketId || typeof bucketId !== 'string') {
3051
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
3053
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
3052
3054
  }
3053
3055
  if (!objectName || typeof objectName !== 'string') {
3054
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
3056
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
3055
3057
  }
3056
3058
  if (!accessToken || typeof accessToken !== 'string') {
3057
- throw new error_1.CloudBaseError('accessToken 必须是非空字符串');
3059
+ (0, error_1.throwInvalidParam)('accessToken 必须是非空字符串');
3058
3060
  }
3059
3061
  const normalizedMethod = String(method).toUpperCase();
3060
3062
  const allowedMethods = ['GET', 'HEAD'];
3061
3063
  if (!allowedMethods.includes(normalizedMethod)) {
3062
- throw new error_1.CloudBaseError('method 仅支持 GET 或 HEAD');
3064
+ (0, error_1.throwInvalidParam)('method 仅支持 GET 或 HEAD');
3063
3065
  }
3064
3066
  const env = this.environment.getEnvId();
3065
3067
  const envId = envIdOverride || env;
@@ -3084,7 +3086,7 @@ class StorageService {
3084
3086
  payload = JSON.parse(text);
3085
3087
  }
3086
3088
  catch (_a) {
3087
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
3089
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
3088
3090
  }
3089
3091
  }
3090
3092
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -3112,11 +3114,11 @@ class StorageService {
3112
3114
  payload = JSON.parse(text);
3113
3115
  }
3114
3116
  catch (_b) {
3115
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
3117
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
3116
3118
  }
3117
3119
  }
3118
3120
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
3119
- throw new error_1.CloudBaseError('获取对象元信息成功但响应格式异常:期望 JSON 对象');
3121
+ (0, error_1.throwApiError)('获取对象元信息成功但响应格式异常:期望 JSON 对象');
3120
3122
  }
3121
3123
  return {
3122
3124
  status: res.status,
@@ -3131,10 +3133,10 @@ class StorageService {
3131
3133
  async getObjectInfoPublic(options) {
3132
3134
  const { bucketId, objectName, envId: envIdOverride } = options;
3133
3135
  if (!bucketId || typeof bucketId !== 'string') {
3134
- throw new error_1.CloudBaseError('bucketId 必须是非空字符串');
3136
+ (0, error_1.throwInvalidParam)('bucketId 必须是非空字符串');
3135
3137
  }
3136
3138
  if (!objectName || typeof objectName !== 'string') {
3137
- throw new error_1.CloudBaseError('objectName 必须是非空字符串');
3139
+ (0, error_1.throwInvalidParam)('objectName 必须是非空字符串');
3138
3140
  }
3139
3141
  const env = this.environment.getEnvId();
3140
3142
  const envId = envIdOverride || env;
@@ -3156,7 +3158,7 @@ class StorageService {
3156
3158
  payload = JSON.parse(text);
3157
3159
  }
3158
3160
  catch (_a) {
3159
- throw new error_1.CloudBaseError(`HTTP_${res.status}: ${text}`);
3161
+ (0, error_1.throwApiError)(`HTTP_${res.status}: ${text}`);
3160
3162
  }
3161
3163
  }
3162
3164
  const code = (payload === null || payload === void 0 ? void 0 : payload.Code) || (payload === null || payload === void 0 ? void 0 : payload.code) || `HTTP_${res.status}`;
@@ -3177,11 +3179,11 @@ class StorageService {
3177
3179
  payload = JSON.parse(text);
3178
3180
  }
3179
3181
  catch (_b) {
3180
- throw new error_1.CloudBaseError(`响应不是合法 JSON: ${text}`);
3182
+ (0, error_1.throwApiError)(`响应不是合法 JSON: ${text}`);
3181
3183
  }
3182
3184
  }
3183
3185
  if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
3184
- throw new error_1.CloudBaseError('获取公开对象元信息成功但响应格式异常:期望 JSON 对象');
3186
+ (0, error_1.throwApiError)('获取公开对象元信息成功但响应格式异常:期望 JSON 对象');
3185
3187
  }
3186
3188
  return {
3187
3189
  status: res.status,
@@ -3398,16 +3400,16 @@ class StorageService {
3398
3400
  assertValidContentType(input) {
3399
3401
  const ct = input.trim();
3400
3402
  if (!ct)
3401
- throw new error_1.CloudBaseError('contentType 不能为空');
3403
+ (0, error_1.throwInvalidParam)('contentType 不能为空');
3402
3404
  // 防 header 注入 / 控制字符
3403
3405
  if (/[\u0000-\u001F\u007F]/.test(ct)) {
3404
- throw new error_1.CloudBaseError('contentType 非法:包含控制字符');
3406
+ (0, error_1.throwInvalidParam)('contentType 非法:包含控制字符');
3405
3407
  }
3406
3408
  // 只校验主类型(; 后参数放宽)
3407
3409
  const base = ct.split(';', 1)[0].trim();
3408
3410
  const typeSubtypeRe = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
3409
3411
  if (!typeSubtypeRe.test(base)) {
3410
- throw new error_1.CloudBaseError('contentType 非法:主类型格式不正确');
3412
+ (0, error_1.throwInvalidParam)('contentType 非法:主类型格式不正确');
3411
3413
  }
3412
3414
  return ct;
3413
3415
  }