@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.
- package/dist/package.json +35 -28
- package/dist/src/commands/deploy.js +3 -3
- package/dist/src/commands/destroy.js +6 -3
- package/dist/src/commands/index.js +35 -7
- package/dist/src/commands/template.js +2 -2
- package/dist/src/commands/validate.js +3 -2
- package/dist/src/common/base64.js +3 -1
- package/dist/src/common/constants.js +2 -1
- package/dist/src/common/context.js +51 -0
- package/dist/src/common/domainHelper.js +10 -0
- package/dist/src/common/iacHelper.js +55 -28
- package/dist/src/common/index.d.ts +3 -1
- package/dist/src/common/index.js +3 -1
- package/dist/src/common/rosAssets.js +177 -0
- package/dist/src/common/rosClient.js +6 -56
- package/dist/src/parser/bucketParser.js +35 -0
- package/dist/src/parser/eventParser.js +1 -0
- package/dist/src/parser/functionParser.js +11 -3
- package/dist/src/parser/index.js +2 -0
- package/dist/src/stack/deploy.js +30 -13
- package/dist/src/stack/rfsStack/function.js +3 -3
- package/dist/src/stack/rfsStack/index.d.ts +2 -2
- package/dist/src/stack/rfsStack/index.js +2 -1
- package/dist/src/stack/rosStack/bootstrap.js +5 -4
- package/dist/src/stack/rosStack/bucket.js +126 -0
- package/dist/src/stack/rosStack/database.js +10 -10
- package/dist/src/stack/rosStack/event.js +62 -55
- package/dist/src/stack/rosStack/function.js +175 -30
- package/dist/src/stack/rosStack/index.d.ts +2 -2
- package/dist/src/stack/rosStack/index.js +6 -3
- package/dist/src/stack/rosStack/stage.js +1 -1
- package/dist/src/stack/rosStack/tag.js +1 -1
- package/dist/src/stack/rosStack/vars.js +3 -3
- package/dist/src/types/domains/bucket.js +9 -0
- package/dist/src/types/domains/function.js +19 -0
- package/dist/src/types/index.d.ts +6 -0
- package/dist/src/types/index.js +1 -0
- package/dist/src/validator/bucketSchema.js +76 -0
- package/dist/src/validator/eventSchema.js +3 -7
- package/dist/src/validator/functionSchema.js +93 -19
- package/dist/src/validator/iacSchema.js +2 -0
- package/dist/src/validator/rootSchema.js +3 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +35 -28
- package/samples/{aliyun-poc-fc.yml → aliyun-poc-api.yml} +9 -20
- package/samples/aliyun-poc-bucket.yml +20 -0
- package/samples/aliyun-poc-domain.yml +23 -0
- package/samples/aliyun-poc-fc-gpu.yml +55 -0
- package/samples/huawei-poc-fc.yml +4 -3
- 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.
|
|
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.
|
|
53
|
-
"@alicloud/openapi-client": "^0.4.
|
|
54
|
-
"@alicloud/ros-cdk-apigateway": "^1.
|
|
55
|
-
"@alicloud/ros-cdk-core": "^1.
|
|
56
|
-
"@alicloud/ros-cdk-
|
|
57
|
-
"@alicloud/ros-cdk-
|
|
58
|
-
"@alicloud/ros-cdk-
|
|
59
|
-
"@alicloud/ros-cdk-
|
|
60
|
-
"@alicloud/ros-cdk-
|
|
61
|
-
"@alicloud/ros-cdk-
|
|
62
|
-
"@alicloud/ros-cdk-
|
|
63
|
-
"@alicloud/
|
|
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.
|
|
67
|
-
"commander": "^
|
|
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
|
-
"
|
|
76
|
+
"npm": "^11.2.0",
|
|
77
|
+
"pino": "^9.6.0",
|
|
71
78
|
"pino-pretty": "^13.0.0",
|
|
72
|
-
"yaml": "^2.
|
|
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.
|
|
79
|
-
"@types/node": "^22.
|
|
80
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
81
|
-
"@typescript-eslint/parser": "^8.
|
|
82
|
-
"eslint": "^9.
|
|
83
|
-
"eslint-config-prettier": "^
|
|
84
|
-
"eslint-plugin-prettier": "^5.2.
|
|
85
|
-
"globals": "^
|
|
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.
|
|
89
|
-
"ts-jest": "^29.
|
|
95
|
+
"prettier": "^3.5.3",
|
|
96
|
+
"ts-jest": "^29.3.1",
|
|
90
97
|
"ts-node": "^10.9.2",
|
|
91
|
-
"typescript": "^5.
|
|
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)(
|
|
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
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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)(
|
|
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, {
|
|
41
|
-
await (0, deploy_1.deploy)(stackName, {
|
|
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
|
|
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
|
-
|
|
15
|
-
const { template } = (0, deploy_1.generateStackTemplate)(stackName, iac
|
|
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 = (
|
|
7
|
-
|
|
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.
|
|
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
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
};
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|
92
|
-
|
|
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(
|
|
103
|
-
return
|
|
95
|
+
if (Array.isArray(rawValue)) {
|
|
96
|
+
return rawValue.map((item) => (0, exports.calcRefs)(item, ctx));
|
|
104
97
|
}
|
|
105
|
-
if (typeof
|
|
106
|
-
return Object.fromEntries(Object.entries(
|
|
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.
|
|
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 './
|
|
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';
|
package/dist/src/common/index.js
CHANGED
|
@@ -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("./
|
|
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;
|