@cloudbase/manager-node 4.2.4 → 4.2.5

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 (85) hide show
  1. package/lib/access/index.js +141 -0
  2. package/lib/access/types.js +2 -0
  3. package/lib/billing/index.js +36 -0
  4. package/lib/cam/index.js +77 -0
  5. package/lib/cloudBaseRun/index.js +36 -0
  6. package/lib/cloudBaseRun/types.js +2 -0
  7. package/lib/common/index.js +39 -0
  8. package/lib/constant.js +55 -0
  9. package/lib/context.js +14 -0
  10. package/lib/database/index.js +244 -0
  11. package/lib/debug.js +34 -0
  12. package/lib/env/index.js +289 -0
  13. package/lib/environment.js +124 -0
  14. package/lib/environmentManager.js +44 -0
  15. package/lib/error.js +16 -0
  16. package/lib/function/index.js +1019 -0
  17. package/lib/function/packer.js +129 -0
  18. package/lib/function/types.js +2 -0
  19. package/lib/hosting/index.js +461 -0
  20. package/lib/index.js +83 -0
  21. package/lib/interfaces/base.interface.js +2 -0
  22. package/lib/interfaces/billing.interface.js +2 -0
  23. package/lib/interfaces/cam.interface.js +2 -0
  24. package/lib/interfaces/flexdb.interface.js +2 -0
  25. package/lib/interfaces/function.interface.js +2 -0
  26. package/lib/interfaces/index.js +19 -0
  27. package/lib/interfaces/storage.interface.js +2 -0
  28. package/lib/interfaces/tcb.interface.js +2 -0
  29. package/lib/storage/index.js +1051 -0
  30. package/lib/third/index.js +18 -0
  31. package/lib/user/index.js +136 -0
  32. package/lib/user/types.js +2 -0
  33. package/lib/utils/auth.js +97 -0
  34. package/lib/utils/cloud-api-request.js +212 -0
  35. package/lib/utils/cloudbase-request.js +69 -0
  36. package/lib/utils/envLazy.js +18 -0
  37. package/lib/utils/fs.js +64 -0
  38. package/lib/utils/http-request.js +44 -0
  39. package/lib/utils/index.js +103 -0
  40. package/lib/utils/parallel.js +69 -0
  41. package/lib/utils/runenv.js +8 -0
  42. package/lib/utils/uuid.js +18 -0
  43. package/package.json +1 -1
  44. package/types/access/index.d.ts +38 -0
  45. package/types/access/types.d.ts +42 -0
  46. package/types/billing/index.d.ts +21 -0
  47. package/types/cam/index.d.ts +63 -0
  48. package/types/cloudBaseRun/index.d.ts +12 -0
  49. package/types/cloudBaseRun/types.d.ts +21 -0
  50. package/types/common/index.d.ts +18 -0
  51. package/types/constant.d.ts +44 -0
  52. package/types/context.d.ts +17 -0
  53. package/types/database/index.d.ts +66 -0
  54. package/types/debug.d.ts +1 -0
  55. package/types/env/index.d.ts +127 -0
  56. package/types/environment.d.ts +51 -0
  57. package/types/environmentManager.d.ts +13 -0
  58. package/types/error.d.ts +18 -0
  59. package/types/function/index.d.ts +379 -0
  60. package/types/function/packer.d.ts +37 -0
  61. package/types/function/types.d.ts +154 -0
  62. package/types/hosting/index.d.ts +253 -0
  63. package/types/index.d.ts +52 -0
  64. package/types/interfaces/base.interface.d.ts +7 -0
  65. package/types/interfaces/billing.interface.d.ts +18 -0
  66. package/types/interfaces/cam.interface.d.ts +24 -0
  67. package/types/interfaces/flexdb.interface.d.ts +67 -0
  68. package/types/interfaces/function.interface.d.ts +65 -0
  69. package/types/interfaces/index.d.ts +7 -0
  70. package/types/interfaces/storage.interface.d.ts +26 -0
  71. package/types/interfaces/tcb.interface.d.ts +305 -0
  72. package/types/storage/index.d.ts +324 -0
  73. package/types/third/index.d.ts +11 -0
  74. package/types/user/index.d.ts +52 -0
  75. package/types/user/types.d.ts +20 -0
  76. package/types/utils/auth.d.ts +8 -0
  77. package/types/utils/cloud-api-request.d.ts +21 -0
  78. package/types/utils/cloudbase-request.d.ts +14 -0
  79. package/types/utils/envLazy.d.ts +1 -0
  80. package/types/utils/fs.d.ts +7 -0
  81. package/types/utils/http-request.d.ts +2 -0
  82. package/types/utils/index.d.ts +20 -0
  83. package/types/utils/parallel.d.ts +17 -0
  84. package/types/utils/runenv.d.ts +1 -0
  85. package/types/utils/uuid.d.ts +2 -0
@@ -0,0 +1,1019 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.FunctionService = void 0;
13
+ const fs_1 = __importDefault(require("fs"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const packer_1 = require("./packer");
16
+ const error_1 = require("../error");
17
+ const utils_1 = require("../utils");
18
+ const constant_1 = require("../constant");
19
+ // 是否为 Node 函数
20
+ function isNodeFunction(runtime) {
21
+ // 不严格限制
22
+ return runtime === 'Nodejs10.15' || runtime === 'Nodejs8.9' || (runtime === null || runtime === void 0 ? void 0 : runtime.includes('Nodejs'));
23
+ }
24
+ // 解析函数配置,换成请求参数
25
+ function configToParams(options) {
26
+ var _a, _b, _c, _d, _e;
27
+ const { func, codeSecret, baseParams } = options;
28
+ let installDependency;
29
+ // Node 函数默认安装依赖
30
+ installDependency = isNodeFunction(func.runtime) ? 'TRUE' : 'FALSE';
31
+ // 是否安装依赖,选项可以覆盖
32
+ if (typeof func.installDependency !== 'undefined') {
33
+ installDependency = func.installDependency ? 'TRUE' : 'FALSE';
34
+ }
35
+ // 转换环境变量
36
+ const envVariables = Object.keys(func.envVariables || {}).map(key => ({
37
+ Key: key,
38
+ Value: func.envVariables[key]
39
+ }));
40
+ // 当不存在 L5 配置时,不修改 L5 状态,否则根据 true/false 进行修改
41
+ const l5Enable = typeof (func === null || func === void 0 ? void 0 : func.l5) === 'undefined' ? null : (func === null || func === void 0 ? void 0 : func.l5) ? 'TRUE' : 'FALSE';
42
+ const params = Object.assign(Object.assign({}, baseParams), { FunctionName: func.name,
43
+ // 不可选择
44
+ L5Enable: l5Enable });
45
+ // 函数绑定的角色
46
+ params.Role = func.role || params.Role;
47
+ // 修复参数存在 undefined 字段时,会出现鉴权失败的情况
48
+ // Environment 为覆盖式修改,不保留已有字段
49
+ envVariables.length && (params.Environment = { Variables: envVariables });
50
+ // 处理入口
51
+ params.Handler = func.handler || 'index.main';
52
+ // 默认超时时间为 10S
53
+ params.Timeout = Number(func.timeout) || 10;
54
+ // 默认运行环境 Nodejs8.9
55
+ params.Runtime = func.runtime || 'Nodejs8.9';
56
+ if (((_a = func === null || func === void 0 ? void 0 : func.vpc) === null || _a === void 0 ? void 0 : _a.subnetId) !== undefined && ((_b = func === null || func === void 0 ? void 0 : func.vpc) === null || _b === void 0 ? void 0 : _b.vpcId) !== undefined) {
57
+ // VPC 网络
58
+ params.VpcConfig = {
59
+ SubnetId: (_c = func === null || func === void 0 ? void 0 : func.vpc) === null || _c === void 0 ? void 0 : _c.subnetId,
60
+ VpcId: (_d = func === null || func === void 0 ? void 0 : func.vpc) === null || _d === void 0 ? void 0 : _d.vpcId
61
+ };
62
+ }
63
+ // 运行内存
64
+ params.MemorySize = func.memorySize || 256;
65
+ // 自动安装依赖
66
+ params.InstallDependency = installDependency;
67
+ // 代码保护
68
+ if (codeSecret || func.codeSecret) {
69
+ params.CodeSecret = codeSecret || func.codeSecret;
70
+ }
71
+ // 函数层
72
+ if ((_e = func === null || func === void 0 ? void 0 : func.layers) === null || _e === void 0 ? void 0 : _e.length) {
73
+ const transformLayers = func.layers.map(item => ({
74
+ LayerName: item.name,
75
+ LayerVersion: item.version
76
+ }));
77
+ params.Layers = transformLayers;
78
+ }
79
+ return params;
80
+ }
81
+ class FunctionService {
82
+ constructor(environment) {
83
+ this.environment = environment;
84
+ this.scfService = new utils_1.CloudService(environment.cloudBaseContext, 'scf', '2018-04-16');
85
+ this.vpcService = new utils_1.CloudService(environment.cloudBaseContext, 'vpc', '2017-03-12');
86
+ }
87
+ /**
88
+ * 增量更新函数代码
89
+ * @param {IUpdateFunctionIncrementalCodeParam} funcParam
90
+ * @returns {Promise<void>}
91
+ * @memberof FunctionService
92
+ */
93
+ async updateFunctionIncrementalCode(funcParam) {
94
+ const { namespace } = this.getFunctionConfig();
95
+ const { functionRootPath, func, deleteFiles, addFiles } = funcParam;
96
+ const { name, runtime } = func;
97
+ const params = {
98
+ FunctionName: name,
99
+ Namespace: namespace
100
+ };
101
+ let packer;
102
+ let base64;
103
+ if (deleteFiles) {
104
+ params.DeleteFiles = deleteFiles;
105
+ }
106
+ if (addFiles) {
107
+ // 将选中的增量文件或增量文件夹 转base64
108
+ const codeType = runtime === 'Java8' ? packer_1.CodeType.JavaFile : packer_1.CodeType.File;
109
+ packer = new packer_1.FunctionPacker({
110
+ codeType,
111
+ name,
112
+ root: functionRootPath,
113
+ ignore: [],
114
+ incrementalPath: addFiles
115
+ });
116
+ await packer.build();
117
+ base64 = await packer.getBase64Code();
118
+ if (!base64) {
119
+ throw new error_1.CloudBaseError('函数不存在!');
120
+ }
121
+ params.AddFiles = base64;
122
+ }
123
+ return this.scfService.request('UpdateFunctionIncrementalCode', params);
124
+ }
125
+ /**
126
+ * 创建云函数
127
+ * @param {ICreateFunctionParam} funcParam
128
+ * @returns {(Promise<IResponseInfo | ICreateFunctionRes>)}
129
+ */
130
+ async createFunction(funcParam) {
131
+ const { namespace } = this.getFunctionConfig();
132
+ const { func, functionRootPath, force = false, base64Code, codeSecret, functionPath } = funcParam;
133
+ const funcName = func.name;
134
+ const params = configToParams({
135
+ func,
136
+ codeSecret,
137
+ baseParams: {
138
+ Namespace: namespace,
139
+ Role: 'TCB_QcsRole',
140
+ Stamp: 'MINI_QCBASE'
141
+ }
142
+ });
143
+ params.Code = await this.getCodeParams({
144
+ func,
145
+ base64Code,
146
+ functionPath,
147
+ functionRootPath
148
+ }, params.InstallDependency);
149
+ try {
150
+ // 创建云函数
151
+ const res = await this.scfService.request('CreateFunction', params);
152
+ // 等待函数状态正常
153
+ await this.waitFunctionActive(funcName, codeSecret);
154
+ // 创建函数触发器、失败自动重试
155
+ await this.retryCreateTrigger(funcName, func.triggers);
156
+ // 设置路径,创建云接入路径
157
+ if (func.path) {
158
+ await this.createAccessPath(funcName, func.path);
159
+ }
160
+ // 检查函数状态
161
+ await this.waitFunctionActive(funcName, codeSecret);
162
+ return res;
163
+ }
164
+ catch (e) {
165
+ // 函数存在
166
+ const functionExist = e.code === 'ResourceInUse.FunctionName' || e.code === 'ResourceInUse.Function';
167
+ // 已存在同名函数,强制更新
168
+ if (functionExist && force) {
169
+ // 1. 更新函数配置和代码,同名函数可能存在 codeSecret,先修改代码,清除 codeSecret
170
+ const codeRes = await this.updateFunctionCode({
171
+ func,
172
+ base64Code,
173
+ functionPath,
174
+ functionRootPath,
175
+ codeSecret: codeSecret
176
+ });
177
+ // 等待函数状态正常
178
+ await this.waitFunctionActive(funcName, codeSecret);
179
+ // 2. 更新函数配置
180
+ const configRes = await this.updateFunctionConfig(func);
181
+ // 等待函数状态正常
182
+ await this.waitFunctionActive(funcName, codeSecret);
183
+ // 3. 创建函数触发器
184
+ const triggerRes = await this.retryCreateTrigger(funcName, func.triggers);
185
+ // 设置路径,创建云接入路径
186
+ if (func.path) {
187
+ await this.createAccessPath(funcName, func.path);
188
+ }
189
+ // 检查函数状态
190
+ await this.waitFunctionActive(funcName, codeSecret);
191
+ // 返回全部操作的响应值
192
+ return {
193
+ triggerRes,
194
+ configRes,
195
+ codeRes
196
+ };
197
+ }
198
+ // 不强制覆盖,抛出错误
199
+ if (e.message && !force) {
200
+ throw new error_1.CloudBaseError(`[${funcName}] 部署失败:\n${e.message}`, {
201
+ code: e.code,
202
+ requestId: e.requestId
203
+ });
204
+ }
205
+ throw e;
206
+ }
207
+ }
208
+ /**
209
+ * @param {number} [limit=20]
210
+ * @param {number} [offset=0]
211
+ * @returns {Promise<{
212
+ * Functions: Record<string, string>[]
213
+ * RequestId: string
214
+ * TotalCount: number
215
+ * }>}
216
+ * @memberof FunctionService
217
+ */
218
+ async getFunctionList(limit = 20, offset = 0) {
219
+ // 获取Function 环境配置
220
+ const { namespace } = this.getFunctionConfig();
221
+ const res = await this.scfService.request('ListFunctions', {
222
+ Namespace: namespace,
223
+ Limit: limit,
224
+ Offset: offset
225
+ });
226
+ return res;
227
+ }
228
+ /**
229
+ * 列出函数
230
+ * @param {number} [limit=20]
231
+ * @param {number} [offset=0]
232
+ * @returns {Promise<Record<string, string>[]>}
233
+ */
234
+ async listFunctions(limit = 20, offset = 0) {
235
+ // 获取Function 环境配置
236
+ const { namespace } = this.getFunctionConfig();
237
+ const res = await this.scfService.request('ListFunctions', {
238
+ Namespace: namespace,
239
+ Limit: limit,
240
+ Offset: offset
241
+ });
242
+ const { Functions = [] } = res;
243
+ const data = [];
244
+ Functions.forEach(func => {
245
+ const { FunctionId, FunctionName, Runtime, AddTime, ModTime, Status } = func;
246
+ data.push({
247
+ FunctionId,
248
+ FunctionName,
249
+ Runtime,
250
+ AddTime,
251
+ ModTime,
252
+ Status
253
+ });
254
+ });
255
+ return data;
256
+ }
257
+ /**
258
+ * 删除云函数
259
+ * @param {string} name 云函数名称
260
+ * @param {string} qualifier 需要删除的版本号,不填默认删除函数下全部版本。
261
+ * @returns {Promise<IResponseInfo>}
262
+ */
263
+ async deleteFunction(name, qualifier) {
264
+ const { namespace } = this.getFunctionConfig();
265
+ return this.scfService.request('DeleteFunction', {
266
+ FunctionName: name,
267
+ Namespace: namespace,
268
+ Qualifier: qualifier
269
+ });
270
+ }
271
+ /**
272
+ * 获取云函数详细信息
273
+ * @param {string} name 云函数名称
274
+ * @returns {Promise<Record<string, string>>}
275
+ */
276
+ async getFunctionDetail(name, codeSecret) {
277
+ const { namespace } = this.getFunctionConfig();
278
+ const params = {
279
+ FunctionName: name,
280
+ Namespace: namespace,
281
+ ShowCode: 'TRUE'
282
+ };
283
+ if (codeSecret) {
284
+ params.CodeSecret = codeSecret;
285
+ }
286
+ const data = await this.scfService.request('GetFunction', params);
287
+ // 解析 VPC 配置
288
+ const { VpcId = '', SubnetId = '' } = data.VpcConfig || {};
289
+ if (VpcId && SubnetId) {
290
+ try {
291
+ const vpcs = await this.getVpcs();
292
+ const subnets = await this.getSubnets(VpcId);
293
+ const vpc = vpcs.find(item => item.VpcId === VpcId);
294
+ const subnet = subnets.find(item => item.SubnetId === SubnetId);
295
+ data.VpcConfig = {
296
+ vpc,
297
+ subnet
298
+ };
299
+ }
300
+ catch (e) {
301
+ data.VpcConfig = {
302
+ vpc: '',
303
+ subnet: ''
304
+ };
305
+ }
306
+ }
307
+ return data;
308
+ }
309
+ /**
310
+ * 获取函数日志
311
+ * @param {{
312
+ * name: string
313
+ * offset: number
314
+ * limit: number
315
+ * order: string
316
+ * orderBy: string
317
+ * startTime: string
318
+ * endTime: string
319
+ * requestId: string
320
+ * }} options
321
+ * @returns {Promise<IFunctionLogRes>}
322
+ */
323
+ async getFunctionLogs(options) {
324
+ const { name, offset = 0, limit = 10, order, orderBy, startTime, endTime, requestId } = options;
325
+ const { namespace } = this.getFunctionConfig();
326
+ const params = {
327
+ Namespace: namespace,
328
+ FunctionName: name,
329
+ Offset: offset,
330
+ Limit: limit,
331
+ Order: order,
332
+ OrderBy: orderBy,
333
+ StartTime: startTime,
334
+ EndTime: endTime,
335
+ FunctionRequestId: requestId
336
+ };
337
+ const res = await this.scfService.request('GetFunctionLogs', params);
338
+ return res;
339
+ }
340
+ /**
341
+ * 更新云函数配置
342
+ * @param {ICloudFunction} func 云函数配置
343
+ * @returns {Promise<IResponseInfo>}
344
+ */
345
+ async updateFunctionConfig(func) {
346
+ var _a, _b, _c, _d, _e;
347
+ const { namespace } = this.getFunctionConfig();
348
+ const envVariables = Object.keys(func.envVariables || {}).map(key => ({
349
+ Key: key,
350
+ Value: func.envVariables[key]
351
+ }));
352
+ // 当不存在 L5 配置时,不修改 L5 状态,否则根据 true/false 进行修改
353
+ const l5Enable = typeof func.l5 === 'undefined' ? null : func.l5 ? 'TRUE' : 'FALSE';
354
+ const params = {
355
+ FunctionName: func.name,
356
+ Namespace: namespace,
357
+ L5Enable: l5Enable
358
+ };
359
+ // 修复参数存在 undefined 字段时,会出现鉴权失败的情况
360
+ // Environment 为覆盖式修改,不保留已有字段
361
+ envVariables.length && (params.Environment = { Variables: envVariables });
362
+ // 不设默认超时时间,防止覆盖已有配置
363
+ func.timeout && (params.Timeout = func.timeout);
364
+ // 运行时
365
+ func.runtime && (params.Runtime = func.runtime);
366
+ if (((_a = func === null || func === void 0 ? void 0 : func.vpc) === null || _a === void 0 ? void 0 : _a.subnetId) !== undefined && ((_b = func === null || func === void 0 ? void 0 : func.vpc) === null || _b === void 0 ? void 0 : _b.vpcId) !== undefined) {
367
+ // VPC 网络
368
+ params.VpcConfig = {
369
+ SubnetId: (_c = func === null || func === void 0 ? void 0 : func.vpc) === null || _c === void 0 ? void 0 : _c.subnetId,
370
+ VpcId: (_d = func === null || func === void 0 ? void 0 : func.vpc) === null || _d === void 0 ? void 0 : _d.vpcId
371
+ };
372
+ }
373
+ // 内存
374
+ func.memorySize && (params.MemorySize = func.memorySize);
375
+ // Node 函数默认安装依赖
376
+ isNodeFunction(func.runtime) && (params.InstallDependency = 'TRUE');
377
+ // 是否安装依赖,选项可以覆盖
378
+ if (typeof func.installDependency !== 'undefined') {
379
+ params.InstallDependency = func.installDependency ? 'TRUE' : 'FALSE';
380
+ }
381
+ // 函数层
382
+ if ((_e = func === null || func === void 0 ? void 0 : func.layers) === null || _e === void 0 ? void 0 : _e.length) {
383
+ const transformLayers = func.layers.map(item => ({
384
+ LayerName: item.name,
385
+ LayerVersion: item.version
386
+ }));
387
+ params.Layers = transformLayers;
388
+ }
389
+ return this.scfService.request('UpdateFunctionConfiguration', params);
390
+ }
391
+ /**
392
+ *
393
+ * @param {IUpdateFunctionCodeParam} funcParam
394
+ * @returns {Promise<IResponseInfo>}
395
+ * @memberof FunctionService
396
+ */
397
+ async updateFunctionCode(funcParam) {
398
+ const { func, functionRootPath, base64Code, codeSecret, functionPath } = funcParam;
399
+ const funcName = func.name;
400
+ const { namespace } = this.getFunctionConfig();
401
+ let installDependency;
402
+ // Node 函数默认安装依赖
403
+ installDependency = isNodeFunction(func.runtime) ? 'TRUE' : 'FALSE';
404
+ // 是否安装依赖,选项可以覆盖
405
+ if (typeof func.installDependency !== 'undefined') {
406
+ installDependency = func.installDependency ? 'TRUE' : 'FALSE';
407
+ }
408
+ const codeParams = await this.getCodeParams({
409
+ func,
410
+ functionPath,
411
+ functionRootPath,
412
+ base64Code
413
+ }, installDependency);
414
+ const params = Object.assign({ FunctionName: funcName, Namespace: namespace, Handler: func.handler || 'index.main', InstallDependency: installDependency }, codeParams);
415
+ if (codeSecret) {
416
+ params.CodeSecret = codeSecret;
417
+ }
418
+ try {
419
+ // 等待函数状态正常
420
+ await this.waitFunctionActive(funcName, codeSecret);
421
+ // 更新云函数代码
422
+ const res = await this.scfService.request('UpdateFunctionCode', params);
423
+ if (installDependency && func.isWaitInstall === true) {
424
+ await this.waitFunctionActive(funcName, codeSecret);
425
+ }
426
+ return res;
427
+ }
428
+ catch (e) {
429
+ throw new error_1.CloudBaseError(`[${funcName}] 函数代码更新失败: ${e.message}`, {
430
+ code: e.code
431
+ });
432
+ }
433
+ }
434
+ /**
435
+ * 调用云函数
436
+ * @param {string} name 云函数名称
437
+ * @param {Record<string, any>} params 调用函数传入参数
438
+ * @returns {Promise<IFunctionInvokeRes>}
439
+ */
440
+ async invokeFunction(name, params) {
441
+ const { namespace } = this.getFunctionConfig();
442
+ const _params = {
443
+ FunctionName: name,
444
+ Namespace: namespace,
445
+ LogType: 'Tail'
446
+ };
447
+ if (params) {
448
+ _params.ClientContext = JSON.stringify(params);
449
+ }
450
+ try {
451
+ const { RequestId, Result } = await this.scfService.request('Invoke', _params);
452
+ return Object.assign({ RequestId }, Result);
453
+ }
454
+ catch (e) {
455
+ throw new error_1.CloudBaseError(`[${name}] 调用失败:\n${e.message}`);
456
+ }
457
+ }
458
+ /**
459
+ * 复制云函数
460
+ * @param {string} name 云函数名称
461
+ * @param {string} newFunctionName 新的云函数名称
462
+ * @param {string} targetEnvId 目标环境 Id
463
+ * @param {boolean} [force=false] 是否覆盖同名云函数
464
+ * @returns {Promise<IResponseInfo>}
465
+ */
466
+ /* eslint-disable-next-line */
467
+ async copyFunction(name, newFunctionName, targetEnvId, force = false) {
468
+ const { namespace } = this.getFunctionConfig();
469
+ if (!namespace || !name || !newFunctionName) {
470
+ throw new error_1.CloudBaseError('参数缺失');
471
+ }
472
+ return this.scfService.request('CopyFunction', {
473
+ FunctionName: name,
474
+ NewFunctionName: newFunctionName,
475
+ Namespace: namespace,
476
+ TargetNamespace: targetEnvId || namespace,
477
+ Override: force ? true : false
478
+ });
479
+ }
480
+ /**
481
+ * 创建云函数触发器
482
+ * @param {string} name 云函数名称
483
+ * @param {ICloudFunctionTrigger[]} triggers 云函数触发器配置
484
+ * @returns {Promise<IResponseInfo>}
485
+ */
486
+ async createFunctionTriggers(name, triggers = []) {
487
+ if (!triggers || !triggers.length)
488
+ return null;
489
+ const { namespace } = this.getFunctionConfig();
490
+ const parsedTriggers = triggers.map(item => {
491
+ if (item.type !== 'timer') {
492
+ throw new error_1.CloudBaseError(`不支持的触发器类型 [${item.type}],目前仅支持定时触发器(timer)!`);
493
+ }
494
+ return {
495
+ TriggerName: item.name,
496
+ Type: item.type,
497
+ TriggerDesc: item.config
498
+ };
499
+ });
500
+ return this.scfService.request('BatchCreateTrigger', {
501
+ FunctionName: name,
502
+ Namespace: namespace,
503
+ Triggers: JSON.stringify(parsedTriggers),
504
+ Count: parsedTriggers.length
505
+ });
506
+ }
507
+ /**
508
+ * 删除云函数触发器
509
+ * @param {string} name 云函数名称
510
+ * @param {string} triggerName 云函数触发器名称
511
+ * @returns {Promise<IResponseInfo>}
512
+ */
513
+ async deleteFunctionTrigger(name, triggerName) {
514
+ const { namespace } = this.getFunctionConfig();
515
+ return this.scfService.request('DeleteTrigger', {
516
+ FunctionName: name,
517
+ Namespace: namespace,
518
+ TriggerName: triggerName,
519
+ Type: 'timer'
520
+ });
521
+ }
522
+ /**
523
+ * 获取云函数代码下载 链接
524
+ * @param {string} functionName
525
+ * @param {string} [codeSecret]
526
+ * @returns {Promise<IFunctionDownloadUrlRes>}
527
+ * @memberof FunctionService
528
+ */
529
+ async getFunctionDownloadUrl(functionName, codeSecret) {
530
+ const { namespace } = this.getFunctionConfig();
531
+ const params = {
532
+ FunctionName: functionName,
533
+ Namespace: namespace
534
+ };
535
+ if (codeSecret) {
536
+ params.CodeSecret = codeSecret;
537
+ }
538
+ try {
539
+ const { Url, CodeSha256, RequestId } = await this.scfService.request('GetFunctionAddress', params);
540
+ return { Url, RequestId, CodeSha256 };
541
+ }
542
+ catch (e) {
543
+ throw new error_1.CloudBaseError(`[${functionName}] 获取函数代码下载链接失败:\n${e.message}`);
544
+ }
545
+ }
546
+ // 创建文件层版本
547
+ async createLayer(options) {
548
+ const { env } = this.getFunctionConfig();
549
+ const { contentPath = '', name, base64Content = '', runtimes = [], description = '', licenseInfo = '' } = options;
550
+ let base64;
551
+ if (base64Content) {
552
+ base64 = base64Content;
553
+ }
554
+ else if (utils_1.isDirectory(contentPath)) {
555
+ // 压缩文件夹
556
+ const dirName = path_1.default.parse(contentPath).name;
557
+ const dest = path_1.default.join(process.cwd(), `temp-${dirName}.zip`);
558
+ // ZIP 文件存在,删除 ZIP 文件
559
+ if (utils_1.checkFullAccess(dest)) {
560
+ utils_1.delSync(dest);
561
+ }
562
+ await utils_1.compressToZip({
563
+ dirPath: contentPath,
564
+ outputPath: dest
565
+ });
566
+ // 转换成 base64
567
+ const fileBuffer = await fs_1.default.promises.readFile(dest);
568
+ base64 = fileBuffer.toString('base64');
569
+ utils_1.delSync(dest);
570
+ }
571
+ else {
572
+ const fileType = path_1.default.extname(contentPath);
573
+ if (fileType !== '.zip') {
574
+ throw new error_1.CloudBaseError('文件类型不正确,目前只支持 ZIP 文件!');
575
+ }
576
+ const fileBuffer = await fs_1.default.promises.readFile(contentPath);
577
+ base64 = fileBuffer.toString('base64');
578
+ }
579
+ return this.scfService.request('PublishLayerVersion', {
580
+ LayerName: name,
581
+ CompatibleRuntimes: runtimes,
582
+ Content: {
583
+ // 最大支持 20M
584
+ ZipFile: base64
585
+ },
586
+ Description: description,
587
+ LicenseInfo: licenseInfo,
588
+ Src: `TCB_${env}`
589
+ });
590
+ }
591
+ // 删除文件层版本
592
+ async deleteLayerVersion(options) {
593
+ const { name, version } = options;
594
+ return this.scfService.request('DeleteLayerVersion', {
595
+ LayerName: name,
596
+ LayerVersion: version
597
+ });
598
+ }
599
+ // 获取层版本列表
600
+ async listLayerVersions(options) {
601
+ const { name, runtimes } = options;
602
+ let param = {
603
+ LayerName: name
604
+ };
605
+ if (runtimes === null || runtimes === void 0 ? void 0 : runtimes.length) {
606
+ param.CompatibleRuntime = runtimes;
607
+ }
608
+ return this.scfService.request('ListLayerVersions', param);
609
+ }
610
+ // 获取文件层列表
611
+ async listLayers(options) {
612
+ const { env } = this.getFunctionConfig();
613
+ const { limit = 20, offset = 0, runtime, searchKey } = options;
614
+ let param = {
615
+ Limit: limit,
616
+ Offset: offset,
617
+ SearchKey: searchKey,
618
+ SearchSrc: `TCB_${env}`
619
+ };
620
+ if (runtime) {
621
+ param.CompatibleRuntime = runtime;
622
+ }
623
+ return this.scfService.request('ListLayers', param);
624
+ }
625
+ // 获取层版本详细信息
626
+ async getLayerVersion(options) {
627
+ const { name, version } = options;
628
+ return this.scfService.request('GetLayerVersion', {
629
+ LayerName: name,
630
+ LayerVersion: version
631
+ });
632
+ }
633
+ /**
634
+ * 设置预置并发
635
+ * @private
636
+ * @param {IProvisionedConcurrencyConfig} concurrencyConfig
637
+ * @returns
638
+ * @memberof FunctionService
639
+ */
640
+ async setProvisionedConcurrencyConfig(concurrencyConfig) {
641
+ const { namespace } = this.getFunctionConfig();
642
+ const { functionName: FunctionName, qualifier: Qualifier, versionProvisionedConcurrencyNum: VersionProvisionedConcurrencyNum } = concurrencyConfig;
643
+ return this.scfService.request('PutProvisionedConcurrencyConfig', {
644
+ FunctionName,
645
+ Qualifier,
646
+ VersionProvisionedConcurrencyNum,
647
+ Namespace: namespace
648
+ });
649
+ }
650
+ /**
651
+ * 获取函数预置并发详情
652
+ * @private
653
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
654
+ * @returns {Promise<IGetProvisionedConcurrencyRes>}
655
+ * @memberof FunctionService
656
+ */
657
+ async getProvisionedConcurrencyConfig(concurrencyConfig) {
658
+ const { namespace } = this.getFunctionConfig();
659
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig;
660
+ return this.scfService.request('GetProvisionedConcurrencyConfig', {
661
+ FunctionName,
662
+ Qualifier,
663
+ Namespace: namespace
664
+ });
665
+ }
666
+ /**
667
+ * 删除预置并发
668
+ * @private
669
+ * @param {IGetProvisionedConcurrencyConfig} concurrencyConfig
670
+ * @returns {Promise<IResponseInfo>}
671
+ * @memberof FunctionService
672
+ */
673
+ async deleteProvisionedConcurrencyConfig(concurrencyConfig) {
674
+ const { namespace } = this.getFunctionConfig();
675
+ const { functionName: FunctionName, qualifier: Qualifier } = concurrencyConfig;
676
+ return this.scfService.request('DeleteProvisionedConcurrencyConfig', {
677
+ FunctionName,
678
+ Qualifier,
679
+ Namespace: namespace
680
+ });
681
+ }
682
+ /**
683
+ * 发布新版本
684
+ * @param {IPublishVersionParams} publishParams
685
+ * @returns {Promise<IPublishVersionRes>}
686
+ * @memberof FunctionService
687
+ */
688
+ async publishVersion(publishParams) {
689
+ const { namespace } = this.getFunctionConfig();
690
+ const { functionName: FunctionName, description: Description } = publishParams;
691
+ return this.scfService.request('PublishVersion', {
692
+ FunctionName,
693
+ Description,
694
+ Namespace: namespace
695
+ });
696
+ }
697
+ /**
698
+ * 查询函数版本详情
699
+ * @param {IListFunctionVersionParams} listVersionParams
700
+ * @returns {Promise<IFunctionVersionsRes>}
701
+ * @memberof FunctionService
702
+ */
703
+ async listVersionByFunction(listVersionParams) {
704
+ const { namespace } = this.getFunctionConfig();
705
+ const { functionName: FunctionName, offset: Offset, limit: Limit, order: Order, orderBy: OrderBy } = listVersionParams;
706
+ return this.scfService.request('ListVersionByFunction', {
707
+ FunctionName,
708
+ Namespace: namespace,
709
+ Offset,
710
+ Limit,
711
+ Order,
712
+ OrderBy
713
+ });
714
+ }
715
+ /**
716
+ *
717
+ * @param {IUpdateFunctionAliasConfig} updateVersionConfigParams
718
+ * @returns {Promise<IResponseInfo>}
719
+ * @memberof FunctionService
720
+ */
721
+ async updateFunctionAliasConfig(updateVersionConfigParams) {
722
+ const { namespace } = this.getFunctionConfig();
723
+ const { functionName: FunctionName, name: Name, functionVersion: FunctionVersion, routingConfig: RoutingConfig, description: Description } = updateVersionConfigParams;
724
+ return this.scfService.request('UpdateAlias', {
725
+ FunctionName,
726
+ Name,
727
+ Namespace: namespace,
728
+ FunctionVersion,
729
+ RoutingConfig,
730
+ Description
731
+ });
732
+ }
733
+ /**
734
+ * 查询函数别名详情
735
+ * @param {IGetFunctionAlias} params
736
+ * @returns {Promise<IGetFunctionAliasRes>}
737
+ * @memberof FunctionService
738
+ */
739
+ async getFunctionAlias(params) {
740
+ const { namespace } = this.getFunctionConfig();
741
+ const { functionName: FunctionName, name: Name } = params;
742
+ return this.scfService.request('GetAlias', {
743
+ FunctionName,
744
+ Name,
745
+ Namespace: namespace
746
+ });
747
+ }
748
+ async createAccessPath(name, path) {
749
+ const access = this.environment.getAccessService();
750
+ try {
751
+ await access.createAccess({
752
+ name,
753
+ path
754
+ });
755
+ }
756
+ catch (e) {
757
+ // 当 Path 存在时,校验 Path 绑定的函数是不是当前函数
758
+ if (e.code === 'InvalidParameter.APICreated') {
759
+ const { APISet } = await access.getAccessList({
760
+ name
761
+ });
762
+ if ((APISet === null || APISet === void 0 ? void 0 : APISet[0].Name) !== name || (APISet === null || APISet === void 0 ? void 0 : APISet[0].Type) !== 1) {
763
+ throw e;
764
+ }
765
+ }
766
+ else {
767
+ throw e;
768
+ }
769
+ }
770
+ }
771
+ async getCodeParams(options, installDependency) {
772
+ const { func, functionPath, functionRootPath, base64Code } = options;
773
+ // 20MB
774
+ const BIG_LENGTH = 167772160;
775
+ if ((base64Code === null || base64Code === void 0 ? void 0 : base64Code.length) > BIG_LENGTH) {
776
+ throw new error_1.CloudBaseError('base64 不能大于 20 MB');
777
+ }
778
+ if (base64Code === null || base64Code === void 0 ? void 0 : base64Code.length) {
779
+ return {
780
+ ZipFile: base64Code
781
+ };
782
+ }
783
+ const codeType = func.runtime === 'Java8' ? packer_1.CodeType.JavaFile : packer_1.CodeType.File;
784
+ // 云端安装依赖,自动忽略 node_modules 目录
785
+ const ignore = installDependency === 'TRUE'
786
+ ? ['node_modules/**/*', 'node_modules', ...(func.ignore || [])]
787
+ : [...(func.ignore || [])];
788
+ const packer = new packer_1.FunctionPacker({
789
+ ignore,
790
+ codeType,
791
+ functionPath,
792
+ name: func.name,
793
+ root: functionRootPath
794
+ });
795
+ await packer.build();
796
+ // 通过云 API 传输的代码大小不能超过 50MB
797
+ const reachMax = await packer.isReachMaxSize();
798
+ if (reachMax) {
799
+ throw new error_1.CloudBaseError('函数代码不能大于 50MB');
800
+ }
801
+ const base64 = await packer.getBase64Code();
802
+ if (!(base64 === null || base64 === void 0 ? void 0 : base64.length)) {
803
+ throw new error_1.CloudBaseError('文件不能为空');
804
+ }
805
+ return {
806
+ ZipFile: base64
807
+ };
808
+ }
809
+ // 获取 COS 临时信息
810
+ async getTempCosInfo(name) {
811
+ const { env, appId } = await this.getFunctionConfig();
812
+ /**
813
+ * Response:
814
+ * Date: "2020-03-18"
815
+ * RequestId: "91876f56-7cd3-42bb-bc32-b74df5d0516e"
816
+ * Sign: "Gc8QvXD50dx7yBfsl2yEYFwIL45hPTEyNTM2NjU4MTkm
817
+ */
818
+ return this.scfService.request('GetTempCosInfo', {
819
+ ObjectPath: `${appId}/${env}/${name}.zip"`
820
+ });
821
+ }
822
+ async retryCreateTrigger(name, triggers, count = 0) {
823
+ try {
824
+ const res = await this.createFunctionTriggers(name, triggers);
825
+ return res;
826
+ }
827
+ catch (e) {
828
+ if (count < 3) {
829
+ await utils_1.sleep(500);
830
+ const res = await this.retryCreateTrigger(name, triggers, count + 1);
831
+ return res;
832
+ }
833
+ else {
834
+ throw e;
835
+ }
836
+ }
837
+ }
838
+ /**
839
+ * 获取函数配置信息
840
+ * @private
841
+ * @returns
842
+ * @memberof FunctionService
843
+ */
844
+ getFunctionConfig() {
845
+ var _a;
846
+ const envConfig = this.environment.lazyEnvironmentConfig;
847
+ const namespace = envConfig.Functions[0].Namespace;
848
+ const appId = (_a = envConfig.Storages[0]) === null || _a === void 0 ? void 0 : _a.AppId;
849
+ const { proxy } = this.environment.cloudBaseContext;
850
+ return {
851
+ proxy,
852
+ appId,
853
+ namespace,
854
+ env: envConfig.EnvId
855
+ };
856
+ }
857
+ /**
858
+ * 获取日志cls配置信息
859
+ */
860
+ getClsServiceConfig() {
861
+ var _a, _b;
862
+ const currentEnv = this.environment.lazyEnvironmentConfig;
863
+ const customLogServices = (_a = currentEnv === null || currentEnv === void 0 ? void 0 : currentEnv.CustomLogServices) === null || _a === void 0 ? void 0 : _a[0];
864
+ const logServices = (_b = currentEnv === null || currentEnv === void 0 ? void 0 : currentEnv.LogServices) === null || _b === void 0 ? void 0 : _b[0];
865
+ return {
866
+ TopicId: (customLogServices === null || customLogServices === void 0 ? void 0 : customLogServices.ClsTopicId) || (logServices === null || logServices === void 0 ? void 0 : logServices.TopicId),
867
+ LogsetId: (customLogServices === null || customLogServices === void 0 ? void 0 : customLogServices.ClsLogsetId) || (logServices === null || logServices === void 0 ? void 0 : logServices.LogsetId)
868
+ };
869
+ }
870
+ /**
871
+ * 获取 vpc 信息
872
+ * @returns
873
+ */
874
+ async getVpcs() {
875
+ const { VpcSet } = await this.vpcService.request('DescribeVpcs');
876
+ return VpcSet;
877
+ }
878
+ /**
879
+ * 获取子网
880
+ * @param {string} vpcId
881
+ * @returns
882
+ */
883
+ async getSubnets(vpcId) {
884
+ const { SubnetSet } = await this.vpcService.request('DescribeSubnets', {
885
+ Filters: [
886
+ {
887
+ Name: 'vpc-id',
888
+ Values: [vpcId]
889
+ }
890
+ ]
891
+ });
892
+ return SubnetSet;
893
+ }
894
+ // 检查函数状态,部分操作在函数更新中时不可进行
895
+ async waitFunctionActive(funcName, codeSecret) {
896
+ let ticker;
897
+ let timer;
898
+ let resolved;
899
+ return new Promise((resolve, reject) => {
900
+ // 超时时间 5 分钟
901
+ timer = setTimeout(() => {
902
+ clearInterval(ticker);
903
+ if (!resolved) {
904
+ reject(new error_1.CloudBaseError('函数状态异常,检查超时'));
905
+ }
906
+ }, 300000);
907
+ ticker = setInterval(async () => {
908
+ try {
909
+ const { Status } = await this.getFunctionDetail(funcName, codeSecret);
910
+ // 更新中
911
+ if (Status === constant_1.SCF_STATUS.CREATING || Status === constant_1.SCF_STATUS.UPDATING)
912
+ return;
913
+ // 创建失败
914
+ if (Status === constant_1.SCF_STATUS.CREATE_FAILED) {
915
+ throw new error_1.CloudBaseError('云函数创建失败');
916
+ }
917
+ // 函数状态正常
918
+ clearInterval(ticker);
919
+ clearTimeout(timer);
920
+ resolve();
921
+ }
922
+ catch (e) {
923
+ clearInterval(ticker);
924
+ clearTimeout(timer);
925
+ reject(e);
926
+ }
927
+ resolved = true;
928
+ }, 1000);
929
+ });
930
+ }
931
+ }
932
+ __decorate([
933
+ utils_1.preLazy()
934
+ ], FunctionService.prototype, "updateFunctionIncrementalCode", null);
935
+ __decorate([
936
+ utils_1.preLazy()
937
+ ], FunctionService.prototype, "createFunction", null);
938
+ __decorate([
939
+ utils_1.preLazy()
940
+ ], FunctionService.prototype, "getFunctionList", null);
941
+ __decorate([
942
+ utils_1.preLazy()
943
+ ], FunctionService.prototype, "listFunctions", null);
944
+ __decorate([
945
+ utils_1.preLazy()
946
+ ], FunctionService.prototype, "deleteFunction", null);
947
+ __decorate([
948
+ utils_1.preLazy()
949
+ ], FunctionService.prototype, "getFunctionDetail", null);
950
+ __decorate([
951
+ utils_1.preLazy()
952
+ ], FunctionService.prototype, "getFunctionLogs", null);
953
+ __decorate([
954
+ utils_1.preLazy()
955
+ ], FunctionService.prototype, "updateFunctionConfig", null);
956
+ __decorate([
957
+ utils_1.preLazy()
958
+ ], FunctionService.prototype, "updateFunctionCode", null);
959
+ __decorate([
960
+ utils_1.preLazy()
961
+ ], FunctionService.prototype, "invokeFunction", null);
962
+ __decorate([
963
+ utils_1.preLazy()
964
+ ], FunctionService.prototype, "copyFunction", null);
965
+ __decorate([
966
+ utils_1.preLazy()
967
+ ], FunctionService.prototype, "createFunctionTriggers", null);
968
+ __decorate([
969
+ utils_1.preLazy()
970
+ ], FunctionService.prototype, "deleteFunctionTrigger", null);
971
+ __decorate([
972
+ utils_1.preLazy()
973
+ ], FunctionService.prototype, "getFunctionDownloadUrl", null);
974
+ __decorate([
975
+ utils_1.preLazy()
976
+ ], FunctionService.prototype, "createLayer", null);
977
+ __decorate([
978
+ utils_1.preLazy()
979
+ ], FunctionService.prototype, "deleteLayerVersion", null);
980
+ __decorate([
981
+ utils_1.preLazy()
982
+ ], FunctionService.prototype, "listLayerVersions", null);
983
+ __decorate([
984
+ utils_1.preLazy()
985
+ ], FunctionService.prototype, "listLayers", null);
986
+ __decorate([
987
+ utils_1.preLazy()
988
+ ], FunctionService.prototype, "getLayerVersion", null);
989
+ __decorate([
990
+ utils_1.preLazy()
991
+ ], FunctionService.prototype, "setProvisionedConcurrencyConfig", null);
992
+ __decorate([
993
+ utils_1.preLazy()
994
+ ], FunctionService.prototype, "getProvisionedConcurrencyConfig", null);
995
+ __decorate([
996
+ utils_1.preLazy()
997
+ ], FunctionService.prototype, "deleteProvisionedConcurrencyConfig", null);
998
+ __decorate([
999
+ utils_1.preLazy()
1000
+ ], FunctionService.prototype, "publishVersion", null);
1001
+ __decorate([
1002
+ utils_1.preLazy()
1003
+ ], FunctionService.prototype, "listVersionByFunction", null);
1004
+ __decorate([
1005
+ utils_1.preLazy()
1006
+ ], FunctionService.prototype, "updateFunctionAliasConfig", null);
1007
+ __decorate([
1008
+ utils_1.preLazy()
1009
+ ], FunctionService.prototype, "getFunctionAlias", null);
1010
+ __decorate([
1011
+ utils_1.preLazy()
1012
+ ], FunctionService.prototype, "createAccessPath", null);
1013
+ __decorate([
1014
+ utils_1.preLazy()
1015
+ ], FunctionService.prototype, "getCodeParams", null);
1016
+ __decorate([
1017
+ utils_1.preLazy()
1018
+ ], FunctionService.prototype, "getTempCosInfo", null);
1019
+ exports.FunctionService = FunctionService;