@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
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SandboxService = void 0;
4
4
  const utils_1 = require("../utils");
5
+ const error_1 = require("../error");
5
6
  class SandboxService {
6
7
  constructor(environment) {
7
8
  this.environment = environment;
@@ -17,23 +18,23 @@ class SandboxService {
17
18
  const { toolId, description, networkConfiguration, tags, customConfiguration } = options;
18
19
  // ToolId 校验:必填
19
20
  if (typeof toolId !== 'string' || toolId.trim().length === 0) {
20
- throw new Error('toolId is required');
21
+ (0, error_1.throwInvalidParam)('toolId is required');
21
22
  }
22
23
  // Description 校验:最大 200 字符
23
24
  if (description !== undefined && description.length > 200) {
24
- throw new Error('description length must be <= 200');
25
+ (0, error_1.throwInvalidParam)('description length must be <= 200');
25
26
  }
26
27
  // NetworkConfiguration 校验
27
28
  if (networkConfiguration !== undefined) {
28
29
  const validModes = ['PUBLIC', 'VPC', 'SANDBOX'];
29
30
  if (!networkConfiguration.NetworkMode || !validModes.includes(networkConfiguration.NetworkMode)) {
30
- throw new Error(`NetworkMode must be one of: ${validModes.join(', ')}`);
31
+ (0, error_1.throwInvalidParam)(`NetworkMode must be one of: ${validModes.join(', ')}`);
31
32
  }
32
33
  }
33
34
  // Tags 校验
34
35
  if (tags !== undefined) {
35
36
  if (!Array.isArray(tags)) {
36
- throw new Error('tags must be an array');
37
+ (0, error_1.throwInvalidParam)('tags must be an array');
37
38
  }
38
39
  }
39
40
  // CustomConfiguration 校验
@@ -41,32 +42,32 @@ class SandboxService {
41
42
  // Image 镜像地址格式基本校验
42
43
  if (customConfiguration.Image !== undefined) {
43
44
  if (typeof customConfiguration.Image !== 'string' || customConfiguration.Image.trim().length === 0) {
44
- throw new Error('Image must be a non-empty string');
45
+ (0, error_1.throwInvalidParam)('Image must be a non-empty string');
45
46
  }
46
47
  }
47
48
  // ImageRegistryType 校验
48
49
  if (customConfiguration.ImageRegistryType !== undefined) {
49
50
  const validTypes = ['enterprise', 'personal'];
50
51
  if (!validTypes.includes(customConfiguration.ImageRegistryType)) {
51
- throw new Error(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
52
+ (0, error_1.throwInvalidParam)(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
52
53
  }
53
54
  }
54
55
  // Ports 校验
55
56
  if (customConfiguration.Ports !== undefined) {
56
57
  if (!Array.isArray(customConfiguration.Ports)) {
57
- throw new Error('Ports must be an array');
58
+ (0, error_1.throwInvalidParam)('Ports must be an array');
58
59
  }
59
60
  }
60
61
  // Env 校验
61
62
  if (customConfiguration.Env !== undefined) {
62
63
  if (!Array.isArray(customConfiguration.Env)) {
63
- throw new Error('Env must be an array');
64
+ (0, error_1.throwInvalidParam)('Env must be an array');
64
65
  }
65
66
  }
66
67
  // DNSConfig.Servers 校验:文档标注为必填
67
68
  if (customConfiguration.DNSConfig !== undefined) {
68
69
  if (!Array.isArray(customConfiguration.DNSConfig.Servers) || customConfiguration.DNSConfig.Servers.length === 0) {
69
- throw new Error('DNSConfig.Servers is required and must be a non-empty array');
70
+ (0, error_1.throwInvalidParam)('DNSConfig.Servers is required and must be a non-empty array');
70
71
  }
71
72
  }
72
73
  }
@@ -98,28 +99,28 @@ class SandboxService {
98
99
  // ToolIds 校验
99
100
  if (toolIds !== undefined) {
100
101
  if (!Array.isArray(toolIds)) {
101
- throw new Error('toolIds must be an array');
102
+ (0, error_1.throwInvalidParam)('toolIds must be an array');
102
103
  }
103
104
  if (toolIds.length > 100) {
104
- throw new Error('toolIds length must be <= 100');
105
+ (0, error_1.throwInvalidParam)('toolIds length must be <= 100');
105
106
  }
106
107
  const invalidId = toolIds.find(id => typeof id !== 'string' || id.trim().length === 0);
107
108
  if (invalidId !== undefined) {
108
- throw new Error('toolIds contains invalid item');
109
+ (0, error_1.throwInvalidParam)('toolIds contains invalid item');
109
110
  }
110
111
  }
111
112
  // Offset 校验
112
113
  if (offset !== undefined && (!Number.isInteger(offset) || offset < 0)) {
113
- throw new Error('offset must be a non-negative integer');
114
+ (0, error_1.throwInvalidParam)('offset must be a non-negative integer');
114
115
  }
115
116
  // Limit 校验
116
117
  if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 100)) {
117
- throw new Error('limit must be an integer between 1 and 100');
118
+ (0, error_1.throwInvalidParam)('limit must be an integer between 1 and 100');
118
119
  }
119
120
  // Filters 校验
120
121
  if (filters !== undefined) {
121
122
  if (!Array.isArray(filters)) {
122
- throw new Error('filters must be an array');
123
+ (0, error_1.throwInvalidParam)('filters must be an array');
123
124
  }
124
125
  }
125
126
  // 构造请求体
@@ -147,69 +148,72 @@ class SandboxService {
147
148
  const { toolName, toolType, networkConfiguration, description, defaultTimeout, tags, clientToken, roleArn, storageMounts, customConfiguration, logConfiguration } = options;
148
149
  // ToolName 校验:必填,1-50 字符,英文/数字/下划线/连接线
149
150
  if (typeof toolName !== 'string' || toolName.trim().length === 0) {
150
- throw new Error('toolName is required');
151
+ (0, error_1.throwInvalidParam)('toolName is required');
151
152
  }
152
153
  if (toolName.length > 50) {
153
- throw new Error('toolName length must be <= 50');
154
+ (0, error_1.throwInvalidParam)('toolName length must be <= 50');
154
155
  }
155
156
  if (!/^[a-zA-Z0-9_-]+$/.test(toolName)) {
156
- throw new Error('toolName can only contain letters, digits, underscores and hyphens');
157
+ (0, error_1.throwInvalidParam)('toolName can only contain letters, digits, underscores and hyphens');
157
158
  }
158
159
  // ToolType 校验:必填,枚举
159
160
  const validToolTypes = ['browser', 'code-interpreter', 'custom'];
160
161
  if (!toolType || !validToolTypes.includes(toolType)) {
161
- throw new Error(`toolType must be one of: ${validToolTypes.join(', ')}`);
162
+ (0, error_1.throwInvalidParam)(`toolType must be one of: ${validToolTypes.join(', ')}`);
162
163
  }
163
164
  // NetworkConfiguration 校验:必填
164
165
  if (!networkConfiguration) {
165
- throw new Error('networkConfiguration is required');
166
+ (0, error_1.throwInvalidParam)('networkConfiguration is required');
166
167
  }
167
168
  const validModes = ['PUBLIC', 'VPC', 'SANDBOX'];
168
169
  if (!networkConfiguration.NetworkMode || !validModes.includes(networkConfiguration.NetworkMode)) {
169
- throw new Error(`NetworkMode must be one of: ${validModes.join(', ')}`);
170
+ (0, error_1.throwInvalidParam)(`NetworkMode must be one of: ${validModes.join(', ')}`);
170
171
  }
171
172
  // Description 校验
172
173
  if (description !== undefined && description.length > 200) {
173
- throw new Error('description length must be <= 200');
174
+ (0, error_1.throwInvalidParam)('description length must be <= 200');
174
175
  }
175
176
  // DefaultTimeout 校验:格式如 5m、300s、1h
176
177
  if (defaultTimeout !== undefined) {
177
178
  if (typeof defaultTimeout !== 'string' || !/^\d+[smh]$/.test(defaultTimeout)) {
178
- throw new Error('defaultTimeout must match format like 5m, 300s, 1h');
179
+ (0, error_1.throwInvalidParam)('defaultTimeout must match format like 5m, 300s, 1h');
179
180
  }
180
181
  }
181
182
  // ClientToken 校验:最大 64 字符
182
183
  if (clientToken !== undefined && clientToken.length > 64) {
183
- throw new Error('clientToken length must be <= 64');
184
+ (0, error_1.throwInvalidParam)('clientToken length must be <= 64');
184
185
  }
185
186
  // Tags 校验
186
187
  if (tags !== undefined) {
187
188
  if (!Array.isArray(tags)) {
188
- throw new Error('tags must be an array');
189
+ (0, error_1.throwInvalidParam)('tags must be an array');
189
190
  }
190
191
  }
191
192
  // StorageMounts 校验
192
193
  if (storageMounts !== undefined) {
193
194
  if (!Array.isArray(storageMounts)) {
194
- throw new Error('storageMounts must be an array');
195
+ (0, error_1.throwInvalidParam)('storageMounts must be an array');
195
196
  }
196
197
  }
197
198
  // CustomConfiguration 校验
198
- if (customConfiguration !== undefined) {
199
+ // customConfiguration 运行时可能被传 null(类型上不允许)⇒ 真值判断,避免取属性时空指针
200
+ if (customConfiguration) {
199
201
  if (customConfiguration.Image !== undefined) {
200
202
  if (typeof customConfiguration.Image !== 'string' || customConfiguration.Image.trim().length === 0) {
201
- throw new Error('Image must be a non-empty string');
203
+ (0, error_1.throwInvalidParam)('Image must be a non-empty string');
202
204
  }
203
205
  }
204
206
  if (customConfiguration.ImageRegistryType !== undefined) {
205
207
  const validTypes = ['enterprise', 'personal'];
206
208
  if (!validTypes.includes(customConfiguration.ImageRegistryType)) {
207
- throw new Error(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
209
+ (0, error_1.throwInvalidParam)(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
208
210
  }
209
211
  }
210
- if (customConfiguration.DNSConfig !== undefined) {
211
- if (!Array.isArray(customConfiguration.DNSConfig.Servers) || customConfiguration.DNSConfig.Servers.length === 0) {
212
- throw new Error('DNSConfig.Servers is required and must be a non-empty array');
212
+ // DNSConfig 同样可能为 null ⇒ 真值判断后再取 Servers
213
+ if (customConfiguration.DNSConfig) {
214
+ const { Servers } = customConfiguration.DNSConfig;
215
+ if (!Array.isArray(Servers) || Servers.length === 0) {
216
+ (0, error_1.throwInvalidParam)('DNSConfig.Servers is required and must be a non-empty array');
213
217
  }
214
218
  }
215
219
  }
@@ -254,7 +258,7 @@ class SandboxService {
254
258
  const { toolId } = options;
255
259
  // ToolId 校验:必填
256
260
  if (typeof toolId !== 'string' || toolId.trim().length === 0) {
257
- throw new Error('toolId is required');
261
+ (0, error_1.throwInvalidParam)('toolId is required');
258
262
  }
259
263
  const reqData = {
260
264
  ToolId: toolId
@@ -270,7 +274,7 @@ class SandboxService {
270
274
  const { instanceId } = options;
271
275
  // InstanceId 校验:必填
272
276
  if (typeof instanceId !== 'string' || instanceId.trim().length === 0) {
273
- throw new Error('instanceId is required');
277
+ (0, error_1.throwInvalidParam)('instanceId is required');
274
278
  }
275
279
  const reqData = {
276
280
  InstanceId: instanceId
@@ -286,7 +290,7 @@ class SandboxService {
286
290
  const { instanceId } = options;
287
291
  // InstanceId 校验:必填
288
292
  if (typeof instanceId !== 'string' || instanceId.trim().length === 0) {
289
- throw new Error('instanceId is required');
293
+ (0, error_1.throwInvalidParam)('instanceId is required');
290
294
  }
291
295
  const reqData = {
292
296
  InstanceId: instanceId
@@ -303,18 +307,18 @@ class SandboxService {
303
307
  const { instanceId, timeout, metadata } = options;
304
308
  // InstanceId 校验:必填
305
309
  if (typeof instanceId !== 'string' || instanceId.trim().length === 0) {
306
- throw new Error('instanceId is required');
310
+ (0, error_1.throwInvalidParam)('instanceId is required');
307
311
  }
308
312
  // Timeout 校验:格式如 30s、5m、1h,最小 30s,最大 24h
309
313
  if (timeout !== undefined) {
310
314
  if (typeof timeout !== 'string' || !/^\d+[smh]$/.test(timeout)) {
311
- throw new Error('timeout must match format like 30s, 5m, 1h');
315
+ (0, error_1.throwInvalidParam)('timeout must match format like 30s, 5m, 1h');
312
316
  }
313
317
  }
314
318
  // Metadata 校验
315
319
  if (metadata !== undefined) {
316
320
  if (!Array.isArray(metadata)) {
317
- throw new Error('metadata must be an array');
321
+ (0, error_1.throwInvalidParam)('metadata must be an array');
318
322
  }
319
323
  }
320
324
  // 构造请求体
@@ -338,7 +342,7 @@ class SandboxService {
338
342
  const { instanceId } = options;
339
343
  // InstanceId 校验:必填
340
344
  if (typeof instanceId !== 'string' || instanceId.trim().length === 0) {
341
- throw new Error('instanceId is required');
345
+ (0, error_1.throwInvalidParam)('instanceId is required');
342
346
  }
343
347
  const reqData = {
344
348
  InstanceId: instanceId
@@ -356,54 +360,57 @@ class SandboxService {
356
360
  const hasToolId = toolId !== undefined && toolId.trim().length > 0;
357
361
  const hasToolName = toolName !== undefined && toolName.trim().length > 0;
358
362
  if (!hasToolId && !hasToolName) {
359
- throw new Error('toolId or toolName is required, at least one must be provided');
363
+ (0, error_1.throwInvalidParam)('toolId or toolName is required, at least one must be provided');
360
364
  }
361
365
  // Timeout 校验:格式如 30s、5m、1h
362
366
  if (timeout !== undefined) {
363
367
  if (typeof timeout !== 'string' || !/^\d+[smh]$/.test(timeout)) {
364
- throw new Error('timeout must match format like 30s, 5m, 1h');
368
+ (0, error_1.throwInvalidParam)('timeout must match format like 30s, 5m, 1h');
365
369
  }
366
370
  }
367
371
  // ClientToken 校验:最大 64 字符
368
372
  if (clientToken !== undefined && clientToken.length > 64) {
369
- throw new Error('clientToken length must be <= 64');
373
+ (0, error_1.throwInvalidParam)('clientToken length must be <= 64');
370
374
  }
371
375
  // MountOptions 校验
372
376
  if (mountOptions !== undefined) {
373
377
  if (!Array.isArray(mountOptions)) {
374
- throw new Error('mountOptions must be an array');
378
+ (0, error_1.throwInvalidParam)('mountOptions must be an array');
375
379
  }
376
380
  }
377
381
  // AuthMode 校验
378
382
  if (authMode !== undefined) {
379
383
  const validAuthModes = ['DEFAULT', 'TOKEN', 'NONE'];
380
384
  if (!validAuthModes.includes(authMode)) {
381
- throw new Error(`authMode must be one of: ${validAuthModes.join(', ')}`);
385
+ (0, error_1.throwInvalidParam)(`authMode must be one of: ${validAuthModes.join(', ')}`);
382
386
  }
383
387
  }
384
388
  // CustomConfiguration 校验
385
- if (customConfiguration !== undefined) {
389
+ // customConfiguration 运行时可能被传 null(类型上不允许)⇒ 真值判断,避免取属性时空指针
390
+ if (customConfiguration) {
386
391
  if (customConfiguration.Image !== undefined) {
387
392
  if (typeof customConfiguration.Image !== 'string' || customConfiguration.Image.trim().length === 0) {
388
- throw new Error('Image must be a non-empty string');
393
+ (0, error_1.throwInvalidParam)('Image must be a non-empty string');
389
394
  }
390
395
  }
391
396
  if (customConfiguration.ImageRegistryType !== undefined) {
392
397
  const validTypes = ['enterprise', 'personal'];
393
398
  if (!validTypes.includes(customConfiguration.ImageRegistryType)) {
394
- throw new Error(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
399
+ (0, error_1.throwInvalidParam)(`ImageRegistryType must be one of: ${validTypes.join(', ')}`);
395
400
  }
396
401
  }
397
- if (customConfiguration.DNSConfig !== undefined) {
398
- if (!Array.isArray(customConfiguration.DNSConfig.Servers) || customConfiguration.DNSConfig.Servers.length === 0) {
399
- throw new Error('DNSConfig.Servers is required and must be a non-empty array');
402
+ // DNSConfig 同样可能为 null ⇒ 真值判断后再取 Servers
403
+ if (customConfiguration.DNSConfig) {
404
+ const { Servers } = customConfiguration.DNSConfig;
405
+ if (!Array.isArray(Servers) || Servers.length === 0) {
406
+ (0, error_1.throwInvalidParam)('DNSConfig.Servers is required and must be a non-empty array');
400
407
  }
401
408
  }
402
409
  }
403
410
  // Metadata 校验
404
411
  if (metadata !== undefined) {
405
412
  if (!Array.isArray(metadata)) {
406
- throw new Error('metadata must be an array');
413
+ (0, error_1.throwInvalidParam)('metadata must be an array');
407
414
  }
408
415
  }
409
416
  // 构造请求体
@@ -444,34 +451,34 @@ class SandboxService {
444
451
  // InstanceIds 校验
445
452
  if (instanceIds !== undefined) {
446
453
  if (!Array.isArray(instanceIds)) {
447
- throw new Error('instanceIds must be an array');
454
+ (0, error_1.throwInvalidParam)('instanceIds must be an array');
448
455
  }
449
456
  if (instanceIds.length > 100) {
450
- throw new Error('instanceIds length must be <= 100');
457
+ (0, error_1.throwInvalidParam)('instanceIds length must be <= 100');
451
458
  }
452
459
  const invalidId = instanceIds.find(id => typeof id !== 'string' || id.trim().length === 0);
453
460
  if (invalidId !== undefined) {
454
- throw new Error('instanceIds contains invalid item');
461
+ (0, error_1.throwInvalidParam)('instanceIds contains invalid item');
455
462
  }
456
463
  }
457
464
  // ToolId 校验
458
465
  if (toolId !== undefined) {
459
466
  if (typeof toolId !== 'string' || toolId.trim().length === 0) {
460
- throw new Error('toolId must be a non-empty string');
467
+ (0, error_1.throwInvalidParam)('toolId must be a non-empty string');
461
468
  }
462
469
  }
463
470
  // Offset 校验
464
471
  if (offset !== undefined && (!Number.isInteger(offset) || offset < 0)) {
465
- throw new Error('offset must be a non-negative integer');
472
+ (0, error_1.throwInvalidParam)('offset must be a non-negative integer');
466
473
  }
467
474
  // Limit 校验
468
475
  if (limit !== undefined && (!Number.isInteger(limit) || limit < 1 || limit > 100)) {
469
- throw new Error('limit must be an integer between 1 and 100');
476
+ (0, error_1.throwInvalidParam)('limit must be an integer between 1 and 100');
470
477
  }
471
478
  // Filters 校验
472
479
  if (filters !== undefined) {
473
480
  if (!Array.isArray(filters)) {
474
- throw new Error('filters must be an array');
481
+ (0, error_1.throwInvalidParam)('filters must be an array');
475
482
  }
476
483
  }
477
484
  // 构造请求体
@@ -504,7 +511,7 @@ class SandboxService {
504
511
  const { instanceId } = options;
505
512
  // InstanceId 校验:必填
506
513
  if (typeof instanceId !== 'string' || instanceId.trim().length === 0) {
507
- throw new Error('instanceId is required');
514
+ (0, error_1.throwInvalidParam)('instanceId is required');
508
515
  }
509
516
  const reqData = {
510
517
  InstanceId: instanceId
@@ -531,7 +538,7 @@ class SandboxService {
531
538
  // Name 校验
532
539
  if (name !== undefined) {
533
540
  if (typeof name !== 'string' || name.trim().length === 0) {
534
- throw new Error('name must be a non-empty string');
541
+ (0, error_1.throwInvalidParam)('name must be a non-empty string');
535
542
  }
536
543
  }
537
544
  // 构造请求体
@@ -551,7 +558,7 @@ class SandboxService {
551
558
  const { keyId } = options;
552
559
  // KeyId 校验:必填
553
560
  if (typeof keyId !== 'string' || keyId.trim().length === 0) {
554
- throw new Error('keyId is required');
561
+ (0, error_1.throwInvalidParam)('keyId is required');
555
562
  }
556
563
  const reqData = {
557
564
  KeyId: keyId