@geek-fun/serverlessinsight 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/package.json +35 -28
  2. package/dist/src/commands/deploy.js +3 -3
  3. package/dist/src/commands/destroy.js +6 -3
  4. package/dist/src/commands/index.js +35 -7
  5. package/dist/src/commands/template.js +2 -2
  6. package/dist/src/commands/validate.js +3 -2
  7. package/dist/src/common/base64.js +3 -1
  8. package/dist/src/common/constants.js +2 -1
  9. package/dist/src/common/context.js +51 -0
  10. package/dist/src/common/domainHelper.js +10 -0
  11. package/dist/src/common/iacHelper.js +55 -28
  12. package/dist/src/common/index.d.ts +3 -1
  13. package/dist/src/common/index.js +3 -1
  14. package/dist/src/common/rosAssets.js +177 -0
  15. package/dist/src/common/rosClient.js +6 -56
  16. package/dist/src/parser/bucketParser.js +35 -0
  17. package/dist/src/parser/eventParser.js +1 -0
  18. package/dist/src/parser/functionParser.js +11 -3
  19. package/dist/src/parser/index.js +2 -0
  20. package/dist/src/stack/deploy.js +30 -13
  21. package/dist/src/stack/rfsStack/function.js +3 -3
  22. package/dist/src/stack/rfsStack/index.d.ts +2 -2
  23. package/dist/src/stack/rfsStack/index.js +2 -1
  24. package/dist/src/stack/rosStack/bootstrap.js +5 -4
  25. package/dist/src/stack/rosStack/bucket.js +126 -0
  26. package/dist/src/stack/rosStack/database.js +10 -10
  27. package/dist/src/stack/rosStack/event.js +62 -55
  28. package/dist/src/stack/rosStack/function.js +175 -30
  29. package/dist/src/stack/rosStack/index.d.ts +2 -2
  30. package/dist/src/stack/rosStack/index.js +6 -3
  31. package/dist/src/stack/rosStack/stage.js +1 -1
  32. package/dist/src/stack/rosStack/tag.js +1 -1
  33. package/dist/src/stack/rosStack/vars.js +3 -3
  34. package/dist/src/types/domains/bucket.js +9 -0
  35. package/dist/src/types/domains/function.js +19 -0
  36. package/dist/src/types/index.d.ts +6 -0
  37. package/dist/src/types/index.js +1 -0
  38. package/dist/src/validator/bucketSchema.js +76 -0
  39. package/dist/src/validator/eventSchema.js +3 -7
  40. package/dist/src/validator/functionSchema.js +93 -19
  41. package/dist/src/validator/iacSchema.js +2 -0
  42. package/dist/src/validator/rootSchema.js +3 -0
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +35 -28
  45. package/samples/{aliyun-poc-fc.yml → aliyun-poc-api.yml} +9 -20
  46. package/samples/aliyun-poc-bucket.yml +20 -0
  47. package/samples/aliyun-poc-domain.yml +23 -0
  48. package/samples/aliyun-poc-fc-gpu.yml +55 -0
  49. package/samples/huawei-poc-fc.yml +4 -3
  50. package/dist/src/common/actionContext.js +0 -31
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geek-fun/serverlessinsight",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Full life cycle cross providers serverless application management for your fast-growing business.",
5
5
  "homepage": "https://serverlessinsight.geekfun.club",
6
6
  "main": "dist/src/index.js",
@@ -49,45 +49,52 @@
49
49
  "function"
50
50
  ],
51
51
  "dependencies": {
52
- "@alicloud/ims20190815": "^2.1.4",
53
- "@alicloud/openapi-client": "^0.4.12",
54
- "@alicloud/ros-cdk-apigateway": "^1.4.0",
55
- "@alicloud/ros-cdk-core": "^1.4.0",
56
- "@alicloud/ros-cdk-elasticsearchserverless": "^1.4.0",
57
- "@alicloud/ros-cdk-fc3": "^1.4.0",
58
- "@alicloud/ros-cdk-oss": "^1.4.0",
59
- "@alicloud/ros-cdk-ossdeployment": "^1.4.0",
60
- "@alicloud/ros-cdk-ram": "^1.4.0",
61
- "@alicloud/ros-cdk-rds": "^1.5.0",
62
- "@alicloud/ros-cdk-sls": "^1.5.0",
63
- "@alicloud/ros20190910": "^3.5.2",
52
+ "@alicloud/ims20190815": "^2.2.0",
53
+ "@alicloud/openapi-client": "^0.4.14",
54
+ "@alicloud/ros-cdk-apigateway": "^1.8.0",
55
+ "@alicloud/ros-cdk-core": "^1.8.0",
56
+ "@alicloud/ros-cdk-dns": "^1.8.0",
57
+ "@alicloud/ros-cdk-ecs": "^1.8.0",
58
+ "@alicloud/ros-cdk-elasticsearchserverless": "^1.8.0",
59
+ "@alicloud/ros-cdk-fc3": "^1.8.0",
60
+ "@alicloud/ros-cdk-nas": "^1.8.0",
61
+ "@alicloud/ros-cdk-oss": "^1.8.0",
62
+ "@alicloud/ros-cdk-ossdeployment": "^1.8.0",
63
+ "@alicloud/ros-cdk-ram": "^1.8.0",
64
+ "@alicloud/ros-cdk-rds": "^1.8.0",
65
+ "@alicloud/ros-cdk-sls": "^1.8.0",
66
+ "@alicloud/ros-cdk-vpc": "^1.8.0",
67
+ "@alicloud/ros20190910": "^3.5.6",
64
68
  "ajv": "^8.17.1",
65
69
  "ali-oss": "^6.22.0",
66
- "chalk": "^5.3.0",
67
- "commander": "^12.1.0",
70
+ "chalk": "^5.4.1",
71
+ "commander": "^13.1.0",
72
+ "i": "^0.3.7",
68
73
  "i18n": "^0.15.1",
74
+ "jszip": "^3.10.1",
69
75
  "lodash": "^4.17.21",
70
- "pino": "^9.5.0",
76
+ "npm": "^11.2.0",
77
+ "pino": "^9.6.0",
71
78
  "pino-pretty": "^13.0.0",
72
- "yaml": "^2.6.1"
79
+ "yaml": "^2.7.1"
73
80
  },
74
81
  "devDependencies": {
75
82
  "@types/ali-oss": "^6.16.11",
76
83
  "@types/i18n": "^0.13.12",
77
84
  "@types/jest": "^29.5.14",
78
- "@types/lodash": "^4.17.13",
79
- "@types/node": "^22.10.1",
80
- "@typescript-eslint/eslint-plugin": "^8.17.0",
81
- "@typescript-eslint/parser": "^8.17.0",
82
- "eslint": "^9.16.0",
83
- "eslint-config-prettier": "^9.1.0",
84
- "eslint-plugin-prettier": "^5.2.1",
85
- "globals": "^15.13.0",
85
+ "@types/lodash": "^4.17.16",
86
+ "@types/node": "^22.14.0",
87
+ "@typescript-eslint/eslint-plugin": "^8.29.0",
88
+ "@typescript-eslint/parser": "^8.29.0",
89
+ "eslint": "^9.24.0",
90
+ "eslint-config-prettier": "^10.1.1",
91
+ "eslint-plugin-prettier": "^5.2.6",
92
+ "globals": "^16.0.0",
86
93
  "husky": "^9.1.7",
87
94
  "jest": "^29.7.0",
88
- "prettier": "^3.4.2",
89
- "ts-jest": "^29.2.5",
95
+ "prettier": "^3.5.3",
96
+ "ts-jest": "^29.3.1",
90
97
  "ts-node": "^10.9.2",
91
- "typescript": "^5.7.2"
98
+ "typescript": "^5.8.3"
92
99
  }
93
100
  }
@@ -5,12 +5,12 @@ const stack_1 = require("../stack");
5
5
  const common_1 = require("../common");
6
6
  const parser_1 = require("../parser");
7
7
  const deploy = async (stackName, options) => {
8
- const context = (0, common_1.constructActionContext)({ ...options, stackName });
9
8
  common_1.logger.info('Validating yaml...');
10
- const iac = (0, parser_1.parseYaml)(context.iacLocation);
9
+ const iac = (0, parser_1.parseYaml)((0, common_1.getIacLocation)(options.location));
11
10
  common_1.logger.info('Yaml is valid! 🎉');
11
+ (0, common_1.setContext)({ ...options, stackName, iacProvider: iac.provider });
12
12
  common_1.logger.info('Deploying stack...');
13
- await (0, stack_1.deployStack)(stackName, iac, context);
13
+ await (0, stack_1.deployStack)(stackName, iac);
14
14
  common_1.logger.info('Stack deployed! 🎉');
15
15
  };
16
16
  exports.deploy = deploy;
@@ -2,9 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.destroyStack = void 0;
4
4
  const common_1 = require("../common");
5
- const destroyStack = async (stackName) => {
6
- const context = (0, common_1.constructActionContext)({ stackName });
7
- common_1.logger.info(`Destroying stack ${stackName}...`);
5
+ const parser_1 = require("../parser");
6
+ const destroyStack = async (stackName, options) => {
7
+ const iac = (0, parser_1.parseYaml)((0, common_1.getIacLocation)(options.location));
8
+ (0, common_1.setContext)({ stackName, ...options, iacProvider: iac.provider });
9
+ const context = (0, common_1.getContext)();
10
+ common_1.logger.info(`Destroying stack: ${stackName}, provider: ${context.provider}, region: ${context.region}...`);
8
11
  await (0, common_1.rosStackDelete)(context);
9
12
  };
10
13
  exports.destroyStack = destroyStack;
@@ -14,7 +14,8 @@ program
14
14
  .command('show')
15
15
  .description('show string')
16
16
  .action(async (options) => {
17
- const context = (0, common_1.constructActionContext)({ ...options });
17
+ (0, common_1.setContext)({ ...options });
18
+ const context = (0, common_1.getContext)();
18
19
  const result = await (0, common_2.getIamInfo)(context);
19
20
  console.log('result:', JSON.stringify(result));
20
21
  });
@@ -25,24 +26,38 @@ program
25
26
  .option('-s, --stage <stage>', 'specify the stage')
26
27
  .action((stackName, { file, stage }) => {
27
28
  common_1.logger.debug('log command info');
28
- (0, validate_1.validate)(file, stage);
29
+ (0, validate_1.validate)(stackName, { stage, location: file });
29
30
  });
30
31
  program
31
32
  .command('deploy <stackName>')
32
33
  .description('deploy serverless Iac yaml')
33
34
  .option('-f, --file <path>', 'specify the yaml file')
34
35
  .option('-s, --stage <stage>', 'specify the stage')
36
+ .option('-r, --region <region>', 'specify the region')
37
+ .option('-v, --provider <provider>', 'specify the provider')
38
+ .option('-k, --accessKeyId <accessKeyId>', 'specify the AccessKeyId')
39
+ .option('-x, --accessKeySecret <accessKeySecret>', 'specify the AccessKeySecret')
40
+ .option('-n, --securityToken <securityToken>', 'specify the SecurityToken')
35
41
  .option('-p, --parameter <key=value>', 'override parameters', (value, previous) => {
36
42
  const [key, val] = value.split('=');
37
43
  previous[key] = val;
38
44
  return previous;
39
45
  }, {})
40
- .action(async (stackName, { file, parameter, stage }) => {
41
- await (0, deploy_1.deploy)(stackName, { location: file, parameters: parameter, stage });
46
+ .action(async (stackName, { stage, parameter, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
47
+ await (0, deploy_1.deploy)(stackName, {
48
+ stage,
49
+ parameters: parameter,
50
+ location: file,
51
+ region,
52
+ provider,
53
+ accessKeyId,
54
+ accessKeySecret,
55
+ securityToken,
56
+ });
42
57
  });
43
58
  program
44
59
  .command('template <stackName>')
45
- .description('print ROS template')
60
+ .description('print platform specific infrastructure as code template')
46
61
  .option('-f, --file <path>', 'specify the yaml file')
47
62
  .option('-s, --stage <stage>', 'specify the stage')
48
63
  .option('-t, --format <type>', 'output content type (JSON or YAML)', 'JSON')
@@ -51,8 +66,21 @@ program
51
66
  });
52
67
  program
53
68
  .command('destroy <stackName>')
69
+ .option('-f, --file <path>', 'specify the yaml file')
70
+ .option('-r, --region <region>', 'specify the region')
71
+ .option('-v, --provider <provider>', 'specify the provider')
72
+ .option('-k, --accessKeyId <accessKeyId>', 'specify the AccessKeyId')
73
+ .option('-x, --accessKeySecret <accessKeySecret>', 'specify the AccessKeySecret')
74
+ .option('-n, --securityToken <securityToken>', 'specify the SecurityToken')
54
75
  .description('destroy serverless stack')
55
- .action(async (stackName) => {
56
- await (0, destroy_1.destroyStack)(stackName);
76
+ .action(async (stackName, { file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
77
+ await (0, destroy_1.destroyStack)(stackName, {
78
+ location: file,
79
+ region,
80
+ provider,
81
+ accessKeyId,
82
+ accessKeySecret,
83
+ securityToken,
84
+ });
57
85
  });
58
86
  program.parse();
@@ -11,8 +11,8 @@ const common_1 = require("../common");
11
11
  const parser_1 = require("../parser");
12
12
  const template = (stackName, options) => {
13
13
  const iac = (0, parser_1.parseYaml)((0, common_1.getIacLocation)(options.location));
14
- const context = (0, common_1.constructActionContext)({ ...options, stackName, provider: iac.provider.name });
15
- const { template } = (0, deploy_1.generateStackTemplate)(stackName, iac, context);
14
+ (0, common_1.setContext)({ ...options, stackName, provider: iac.provider.name });
15
+ const { template } = (0, deploy_1.generateStackTemplate)(stackName, iac);
16
16
  if (typeof template === 'string') {
17
17
  common_1.logger.info(`\n${template}`);
18
18
  }
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validate = void 0;
4
4
  const common_1 = require("../common");
5
5
  const parser_1 = require("../parser");
6
- const validate = (location, stage) => {
7
- const context = (0, common_1.constructActionContext)({ location, stage });
6
+ const validate = (stackName, options) => {
7
+ (0, common_1.setContext)({ stackName, ...options });
8
+ const context = (0, common_1.getContext)();
8
9
  (0, parser_1.parseYaml)(context.iacLocation);
9
10
  common_1.logger.info('Yaml is valid! 🎉');
10
11
  };
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.encodeBase64 = void 0;
3
+ exports.encodeBase64ForRosId = exports.encodeBase64 = void 0;
4
4
  const encodeBase64 = (str) => Buffer.from(str, 'utf-8').toString('base64');
5
5
  exports.encodeBase64 = encodeBase64;
6
+ const encodeBase64ForRosId = (str) => (0, exports.encodeBase64)(str).replace(/=+$/, '');
7
+ exports.encodeBase64ForRosId = encodeBase64ForRosId;
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CODE_ZIP_SIZE_LIMIT = void 0;
3
+ exports.OSS_DEPLOYMENT_TIMEOUT = exports.CODE_ZIP_SIZE_LIMIT = void 0;
4
4
  exports.CODE_ZIP_SIZE_LIMIT = 15 * 1000 * 1000;
5
+ exports.OSS_DEPLOYMENT_TIMEOUT = 3000; // in seconds
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getContext = exports.setContext = exports.getIacLocation = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const providerEnum_1 = require("./providerEnum");
9
+ const node_async_hooks_1 = require("node:async_hooks");
10
+ const asyncLocalStorage = new node_async_hooks_1.AsyncLocalStorage();
11
+ const getIacLocation = (location) => {
12
+ const projectRoot = node_path_1.default.resolve(process.cwd());
13
+ return location
14
+ ? node_path_1.default.resolve(projectRoot, location)
15
+ : node_path_1.default.resolve(projectRoot, 'serverlessinsight.yml') ||
16
+ node_path_1.default.resolve(projectRoot, 'serverlessInsight.yml') ||
17
+ node_path_1.default.resolve(projectRoot, 'ServerlessInsight.yml') ||
18
+ node_path_1.default.resolve(projectRoot, 'serverless-insight.yml');
19
+ };
20
+ exports.getIacLocation = getIacLocation;
21
+ const setContext = (config) => {
22
+ const context = {
23
+ stage: config.stage ?? 'default',
24
+ stackName: config.stackName ?? '',
25
+ provider: (config.provider ?? config.iacProvider?.name ?? providerEnum_1.ProviderEnum.ALIYUN),
26
+ region: config.region ??
27
+ config.iacProvider?.region ??
28
+ process.env.ROS_REGION_ID ??
29
+ process.env.ALIYUN_REGION ??
30
+ 'cn-hangzhou',
31
+ accessKeyId: config.accessKeyId ?? process.env.ALIYUN_ACCESS_KEY_ID,
32
+ accessKeySecret: config.accessKeySecret ?? process.env.ALIYUN_ACCESS_KEY_SECRET,
33
+ securityToken: config.securityToken ?? process.env.ALIYUN_SECURITY_TOKEN,
34
+ iacLocation: (0, exports.getIacLocation)(config.location),
35
+ parameters: Object.entries(config.parameters ?? {}).map(([key, value]) => ({ key, value })),
36
+ stages: Object.entries(config.stages ?? {}).reduce((acc, [stage, parameters]) => ({
37
+ ...acc,
38
+ [stage]: Object.entries(parameters).map(([key, value]) => ({ key, value })),
39
+ }), {}),
40
+ };
41
+ asyncLocalStorage.enterWith(context);
42
+ };
43
+ exports.setContext = setContext;
44
+ const getContext = () => {
45
+ const context = asyncLocalStorage.getStore();
46
+ if (!context) {
47
+ throw new Error('No context found');
48
+ }
49
+ return context;
50
+ };
51
+ exports.getContext = getContext;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splitDomain = void 0;
4
+ const splitDomain = (domain) => {
5
+ const parts = domain.split('.');
6
+ const rr = parts.length > 2 ? parts[0] : '@';
7
+ const domainName = parts.length > 2 ? parts.slice(1).join('.') : domain;
8
+ return { rr, domainName };
9
+ };
10
+ exports.splitDomain = splitDomain;
@@ -36,12 +36,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.replaceReference = exports.getFileSource = exports.readCodeSize = exports.resolveCode = void 0;
39
+ exports.formatRosId = exports.calcValue = exports.calcRefs = exports.getFileSource = exports.readCodeSize = exports.resolveCode = void 0;
40
40
  const node_path_1 = __importDefault(require("node:path"));
41
41
  const node_fs_1 = __importDefault(require("node:fs"));
42
42
  const ros = __importStar(require("@alicloud/ros-cdk-core"));
43
43
  const ossDeployment = __importStar(require("@alicloud/ros-cdk-ossdeployment"));
44
44
  const node_crypto_1 = __importDefault(require("node:crypto"));
45
+ const lodash_1 = require("lodash");
45
46
  const resolveCode = (location) => {
46
47
  const filePath = node_path_1.default.resolve(process.cwd(), location);
47
48
  const fileContent = node_fs_1.default.readFileSync(filePath);
@@ -61,23 +62,21 @@ const getFileSource = (fcName, location) => {
61
62
  }
62
63
  const hash = node_crypto_1.default.createHash('md5').update(node_fs_1.default.readFileSync(filePath)).digest('hex');
63
64
  const objectKey = `${fcName}/${hash}-${filePath.split('/').pop()}`;
64
- const source = ossDeployment.Source.asset(filePath, {}, `${fcName}/${hash}-`);
65
+ const source = ossDeployment.Source.asset(filePath, { deployTime: true }, `${fcName}/${hash}-`);
65
66
  return { source, objectKey };
66
67
  };
67
68
  exports.getFileSource = getFileSource;
68
- const evalCtx = (value, ctx) => {
69
- const containsStage = value.match(/\$\{ctx.\w+}/);
70
- return containsStage ? value.replace(/\$\{ctx.stage}/g, ctx.stage) : value;
71
- };
72
- const replaceReference = (value, ctx) => {
73
- if (typeof value === 'string') {
74
- const matchVar = value.match(/^\$\{vars\.(\w+)}$/);
75
- const containsVar = value.match(/\$\{vars\.(\w+)}/);
76
- const matchMap = value.match(/^\$\{stages\.(\w+)}$/);
77
- const containsMap = value.match(/\$\{stages\.(\w+)}/);
78
- const matchFn = value.match(/^\$\{functions\.(\w+(\.\w+)?)}$/);
79
- if (value.match(/\$\{ctx.\w+}/)) {
80
- return evalCtx(value, ctx);
69
+ const calcRefs = (rawValue, ctx) => {
70
+ if (typeof rawValue === 'string') {
71
+ const containsStage = rawValue.match(/\$\{ctx.\w+}/);
72
+ const matchVar = rawValue.match(/^\$\{vars\.(\w+)}$/);
73
+ const containsVar = rawValue.match(/\$\{vars\.(\w+)}/);
74
+ const matchMap = rawValue.match(/^\$\{stages\.(\w+)}$/);
75
+ const containsMap = rawValue.match(/\$\{stages\.(\w+)}/);
76
+ const matchFn = rawValue.match(/^\$\{functions\.(\w+(\.\w+)?)}$/);
77
+ let value = rawValue;
78
+ if (containsStage) {
79
+ value = value.replace(/\$\{ctx.stage}/g, ctx.stage);
81
80
  }
82
81
  if (matchVar?.length) {
83
82
  return ros.Fn.ref(matchVar[1]);
@@ -88,23 +87,51 @@ const replaceReference = (value, ctx) => {
88
87
  if (matchFn?.length) {
89
88
  return ros.Fn.getAtt(matchFn[1], 'FunctionName');
90
89
  }
91
- if (containsMap?.length && containsVar?.length) {
92
- return ros.Fn.sub(value.replace(/\$\{stages\.(\w+)}/g, '${$1}').replace(/\$\{vars\.(\w+)}/g, '${$1}'));
93
- }
94
- if (containsVar?.length) {
95
- return ros.Fn.sub(value.replace(/\$\{vars\.(\w+)}/g, '${$1}'));
96
- }
97
- if (containsMap?.length) {
98
- return ros.Fn.sub(value.replace(/\$\{stages\.(\w+)}/g, '${$1}'));
90
+ if (containsMap?.length || containsVar?.length) {
91
+ value = ros.Fn.sub(rawValue.replace(/\$\{stages\.(\w+)}/g, '${$1}').replace(/\$\{vars\.(\w+)}/g, '${$1}'));
99
92
  }
100
93
  return value;
101
94
  }
102
- if (Array.isArray(value)) {
103
- return value.map((item) => (0, exports.replaceReference)(item, ctx));
95
+ if (Array.isArray(rawValue)) {
96
+ return rawValue.map((item) => (0, exports.calcRefs)(item, ctx));
104
97
  }
105
- if (typeof value === 'object' && value !== null) {
106
- return Object.fromEntries(Object.entries(value).map(([key, val]) => [key, (0, exports.replaceReference)(val, ctx)]));
98
+ if (typeof rawValue === 'object' && rawValue !== null) {
99
+ return Object.fromEntries(Object.entries(rawValue).map(([key, val]) => [key, (0, exports.calcRefs)(val, ctx)]));
100
+ }
101
+ return rawValue;
102
+ };
103
+ exports.calcRefs = calcRefs;
104
+ const getParam = (key, records) => {
105
+ return records?.find((param) => param.key === key)?.value;
106
+ };
107
+ const calcValue = (rawValue, ctx) => {
108
+ const containsStage = rawValue.match(/\$\{ctx.stage}/);
109
+ const containsVar = rawValue.match(/\$\{vars.\w+}/);
110
+ const containsMap = rawValue.match(/\$\{stages\.(\w+)}/);
111
+ let value = rawValue;
112
+ if (containsStage?.length) {
113
+ value = rawValue.replace(/\$\{ctx.stage}/g, ctx.stage);
114
+ }
115
+ if (containsVar?.length) {
116
+ value = value.replace(/\$\{vars\.(\w+)}/g, (_, key) => getParam(key, ctx.parameters));
117
+ }
118
+ if (containsMap?.length) {
119
+ value = value.replace(/\$\{stages\.(\w+)}/g, (_, key) => getParam(key, (0, lodash_1.get)(ctx.stages, `${ctx.stage}`)));
107
120
  }
108
121
  return value;
109
122
  };
110
- exports.replaceReference = replaceReference;
123
+ exports.calcValue = calcValue;
124
+ const formatRosId = (id) => {
125
+ // Insert underscore before uppercase letters, but only when they follow a lowercase letter
126
+ let result = id.replace(/([a-z])([A-Z])/g, '$1_$2');
127
+ // Convert to lowercase
128
+ result = result.toLowerCase();
129
+ // Replace special characters with underscores
130
+ result = result.replace(/[/#,-]/g, '_');
131
+ // Remove any number of underscores to single one
132
+ result = result.replace(/_+/g, '_');
133
+ // Remove leading underscores
134
+ result = result.replace(/^_/, '');
135
+ return result;
136
+ };
137
+ exports.formatRosId = formatRosId;
@@ -2,8 +2,10 @@ export * from './providerEnum';
2
2
  export * from './logger';
3
3
  export * from './getVersion';
4
4
  export * from './rosClient';
5
- export * from './actionContext';
5
+ export * from './context';
6
6
  export * from './iacHelper';
7
7
  export * from './constants';
8
8
  export * from './imsClient';
9
9
  export * from './base64';
10
+ export * from './rosAssets';
11
+ export * from './domainHelper';
@@ -18,8 +18,10 @@ __exportStar(require("./providerEnum"), exports);
18
18
  __exportStar(require("./logger"), exports);
19
19
  __exportStar(require("./getVersion"), exports);
20
20
  __exportStar(require("./rosClient"), exports);
21
- __exportStar(require("./actionContext"), exports);
21
+ __exportStar(require("./context"), exports);
22
22
  __exportStar(require("./iacHelper"), exports);
23
23
  __exportStar(require("./constants"), exports);
24
24
  __exportStar(require("./imsClient"), exports);
25
25
  __exportStar(require("./base64"), exports);
26
+ __exportStar(require("./rosAssets"), exports);
27
+ __exportStar(require("./domainHelper"), exports);
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.cleanupAssets = exports.publishAssets = exports.constructAssets = exports.getAssets = void 0;
40
+ const node_fs_1 = __importDefault(require("node:fs"));
41
+ const ossDeployment = __importStar(require("@alicloud/ros-cdk-ossdeployment"));
42
+ const node_path_1 = __importDefault(require("node:path"));
43
+ const jszip_1 = __importDefault(require("jszip"));
44
+ const logger_1 = require("./logger");
45
+ const lodash_1 = require("lodash");
46
+ const ali_oss_1 = __importDefault(require("ali-oss"));
47
+ const context_1 = require("./context");
48
+ const buildAssets = (rootPath, relativePath) => {
49
+ const location = node_path_1.default.resolve(rootPath, relativePath);
50
+ if (!node_fs_1.default.existsSync(location)) {
51
+ throw new Error(`Location: ${location} is not exists!`);
52
+ }
53
+ if (node_fs_1.default.lstatSync(location).isFile()) {
54
+ return [
55
+ ossDeployment.Source.asset(location, {}, relativePath.substring(0, relativePath.lastIndexOf('/') + 1)),
56
+ ];
57
+ }
58
+ return node_fs_1.default
59
+ .readdirSync(location)
60
+ .map((file) => buildAssets(rootPath, `${relativePath}/${file}`.replace(/^\//, '')))
61
+ .flat();
62
+ };
63
+ const getAssets = (location) => {
64
+ return buildAssets(location, '');
65
+ };
66
+ exports.getAssets = getAssets;
67
+ const assembleFiles = (folder, zip) => {
68
+ const files = node_fs_1.default.readdirSync(folder);
69
+ files.forEach((file) => {
70
+ const filePath = node_path_1.default.join(folder, file);
71
+ if (node_fs_1.default.lstatSync(filePath).isFile()) {
72
+ const content = node_fs_1.default.readFileSync(filePath);
73
+ zip.file(file, content);
74
+ }
75
+ else {
76
+ const subZip = zip.folder(file);
77
+ if (subZip) {
78
+ assembleFiles(filePath, subZip);
79
+ }
80
+ }
81
+ });
82
+ };
83
+ const zipAssets = async (assetsPath) => {
84
+ const zip = new jszip_1.default();
85
+ assembleFiles(assetsPath, zip);
86
+ const zipPath = `${assetsPath.replace(/\/$/, '').trim()}.zip`;
87
+ await zip
88
+ .generateAsync({ type: 'nodebuffer' })
89
+ .then((content) => {
90
+ node_fs_1.default.writeFileSync(zipPath, content);
91
+ logger_1.logger.info(`Folder compressed to: ${zipPath}`);
92
+ })
93
+ .catch((e) => {
94
+ logger_1.logger.error(`Failed to compress folder: ${e}`);
95
+ throw e;
96
+ });
97
+ return zipPath;
98
+ };
99
+ const constructAssets = async ({ files, rootPath, }) => {
100
+ const { region } = (0, context_1.getContext)();
101
+ const assets = await Promise.all(Object.entries(files)
102
+ .filter(([, fileItem]) => !fileItem.source.path.endsWith('.template.json'))
103
+ .map(async ([, fileItem]) => {
104
+ let sourcePath = `${rootPath}/${fileItem.source.path}`;
105
+ if (fileItem.source.packaging === 'zip') {
106
+ sourcePath = await zipAssets(`${rootPath}/${fileItem.source.path}`);
107
+ }
108
+ return {
109
+ bucketName: (0, lodash_1.get)(fileItem, 'destinations.current_account-current_region.bucketName', '').replace('${ALIYUN::Region}', region),
110
+ source: sourcePath,
111
+ objectKey: (0, lodash_1.get)(fileItem, 'destinations.current_account-current_region.objectKey'),
112
+ };
113
+ }));
114
+ return !(0, lodash_1.isEmpty)(assets) ? assets : undefined;
115
+ };
116
+ exports.constructAssets = constructAssets;
117
+ const ensureBucketExits = async (bucketName, ossClient) => await ossClient.getBucketInfo(bucketName).catch((err) => {
118
+ if (err.code === 'NoSuchBucket') {
119
+ logger_1.logger.info(`Bucket: ${bucketName} not exists, creating...`);
120
+ return ossClient.putBucket(bucketName, {
121
+ storageClass: 'Standard',
122
+ acl: 'private',
123
+ dataRedundancyType: 'LRS',
124
+ });
125
+ }
126
+ else {
127
+ throw err;
128
+ }
129
+ });
130
+ const publishAssets = async (assets) => {
131
+ if (!assets?.length) {
132
+ logger_1.logger.info('No assets to publish, skipped!');
133
+ return;
134
+ }
135
+ const context = (0, context_1.getContext)();
136
+ const bucketName = assets[0].bucketName;
137
+ const client = new ali_oss_1.default({
138
+ region: `oss-${context.region}`,
139
+ accessKeyId: context.accessKeyId,
140
+ accessKeySecret: context.accessKeySecret,
141
+ bucket: bucketName,
142
+ });
143
+ await ensureBucketExits(bucketName, client);
144
+ const headers = {
145
+ 'x-oss-storage-class': 'Standard',
146
+ 'x-oss-object-acl': 'default',
147
+ 'x-oss-forbid-overwrite': 'false',
148
+ };
149
+ await Promise.all(assets.map(async ({ source, objectKey }) => {
150
+ await client.put(objectKey, node_path_1.default.normalize(source), { headers });
151
+ logger_1.logger.debug(`Upload file: ${source} to bucket: ${bucketName} successfully!`);
152
+ }));
153
+ return bucketName;
154
+ };
155
+ exports.publishAssets = publishAssets;
156
+ const cleanupAssets = async (assets) => {
157
+ if (!assets?.length) {
158
+ logger_1.logger.info('No assets to cleanup, skipped!');
159
+ return;
160
+ }
161
+ const context = (0, context_1.getContext)();
162
+ const bucketName = assets[0].bucketName;
163
+ const client = new ali_oss_1.default({
164
+ region: `oss-${context.region}`,
165
+ accessKeyId: context.accessKeyId,
166
+ accessKeySecret: context.accessKeySecret,
167
+ bucket: bucketName,
168
+ });
169
+ await Promise.all(assets.map(async ({ objectKey }) => {
170
+ await client.delete(objectKey);
171
+ logger_1.logger.debug(`Cleanup file: ${objectKey} from bucket: ${bucketName} successfully!`);
172
+ }));
173
+ // delete the bucket
174
+ await client.deleteBucket(bucketName);
175
+ logger_1.logger.debug(`Cleanup bucket: ${bucketName} successfully!`);
176
+ };
177
+ exports.cleanupAssets = cleanupAssets;