@geek-fun/serverlessinsight 0.3.4 → 0.4.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/README.md +209 -21
- package/README.zh-CN.md +232 -0
- package/dist/package.json +33 -33
- package/dist/src/commands/index.js +50 -12
- package/dist/src/commands/local.js +6 -3
- package/dist/src/commands/template.js +3 -1
- package/dist/src/common/constants.js +3 -1
- package/dist/src/common/context.js +56 -30
- package/dist/src/common/credentials.js +15 -0
- package/dist/src/common/iacHelper.js +39 -4
- package/dist/src/common/index.d.ts +2 -1
- package/dist/src/common/index.js +2 -1
- package/dist/src/common/logger.js +6 -0
- package/dist/src/common/requestHelper.js +16 -0
- package/dist/src/common/rosClient.js +3 -0
- package/dist/src/parser/eventParser.js +1 -1
- package/dist/src/parser/index.d.ts +2 -1
- package/dist/src/parser/index.js +32 -1
- package/dist/src/stack/localStack/aliyunFc.js +145 -0
- package/dist/src/stack/localStack/bucket.js +226 -0
- package/dist/src/stack/localStack/event.js +133 -26
- package/dist/src/stack/localStack/function.js +120 -0
- package/dist/src/stack/localStack/functionRunner.js +270 -0
- package/dist/src/stack/localStack/index.d.ts +4 -1
- package/dist/src/stack/localStack/index.js +14 -4
- package/dist/src/stack/localStack/localServer.js +111 -0
- package/dist/src/stack/localStack/utils.js +36 -0
- package/dist/src/stack/rosStack/bootstrap.js +1 -1
- package/dist/src/types/localStack/index.d.ts +81 -0
- package/dist/src/types/localStack/index.js +10 -0
- package/dist/src/validator/iacSchema.js +17 -2
- package/dist/src/validator/rootSchema.js +46 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/layers/si-bootstrap-sdk/README.md +63 -0
- package/layers/si-bootstrap-sdk/package-lock.json +39 -33
- package/layers/si-bootstrap-sdk/package.json +5 -5
- package/layers/si-bootstrap-sdk/support/operation-collection/README.md +47 -0
- package/layers/si-bootstrap-sdk/support/operation-collection/package-lock.json +298 -0
- package/layers/si-bootstrap-sdk/support/operation-collection/package.json +18 -0
- package/layers/si-bootstrap-sdk/support/operation-collection/publish.js +257 -0
- package/package.json +33 -33
- package/samples/aliyun-poc-es.yml +16 -12
- package/dist/src/common/domainHelper.js +0 -10
|
@@ -8,26 +8,62 @@ const deploy_1 = require("./deploy");
|
|
|
8
8
|
const template_1 = require("./template");
|
|
9
9
|
const destroy_1 = require("./destroy");
|
|
10
10
|
const local_1 = require("./local");
|
|
11
|
+
// Global error handler
|
|
12
|
+
const handleCommandError = (error, commandName) => {
|
|
13
|
+
// Log error message as string to preserve newlines
|
|
14
|
+
common_1.logger.error(`Command '${commandName}' failed with error:\n${error?.message || 'Unknown error occurred'}`);
|
|
15
|
+
if (error?.stack && process.env.DEBUG) {
|
|
16
|
+
common_1.logger.debug(`Stack trace:\n${error.stack}`);
|
|
17
|
+
}
|
|
18
|
+
let exitCode = 1;
|
|
19
|
+
if (error?.code) {
|
|
20
|
+
if (typeof error.code === 'number') {
|
|
21
|
+
exitCode = error.code;
|
|
22
|
+
}
|
|
23
|
+
else if (typeof error.code === 'string') {
|
|
24
|
+
const errorCodeMap = {
|
|
25
|
+
ENOENT: 2,
|
|
26
|
+
EACCES: 3,
|
|
27
|
+
VALIDATION: 4,
|
|
28
|
+
NETWORK: 5,
|
|
29
|
+
};
|
|
30
|
+
exitCode = errorCodeMap[error.code] || 1;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
process.exit(exitCode);
|
|
34
|
+
};
|
|
35
|
+
const actionWrapper = (commandName, handler) => {
|
|
36
|
+
// Reset context before each command execution
|
|
37
|
+
(0, common_1.clearContext)();
|
|
38
|
+
return async (...args) => {
|
|
39
|
+
try {
|
|
40
|
+
await handler(...args);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
handleCommandError(error, commandName);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
};
|
|
11
47
|
const program = new commander_1.Command();
|
|
12
48
|
program.name('si').description('CLI for ServerlessInsight').version((0, common_1.getVersion)());
|
|
13
49
|
program
|
|
14
50
|
.command('show')
|
|
15
51
|
.description('show string')
|
|
16
|
-
.action(async (options) => {
|
|
52
|
+
.action(actionWrapper('show', async (options) => {
|
|
17
53
|
await (0, common_1.setContext)({ ...options });
|
|
18
54
|
const context = (0, common_1.getContext)();
|
|
19
55
|
const result = await (0, common_1.getIamInfo)(context);
|
|
20
56
|
console.log('result:', JSON.stringify(result));
|
|
21
|
-
});
|
|
57
|
+
}));
|
|
22
58
|
program
|
|
23
59
|
.command('validate [stackName]')
|
|
24
60
|
.description('validate serverless Iac yaml')
|
|
25
61
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
26
62
|
.option('-s, --stage <stage>', 'specify the stage')
|
|
27
|
-
.action(async (stackName, { file, stage }) => {
|
|
63
|
+
.action(actionWrapper('validate', async (stackName, { file, stage }) => {
|
|
28
64
|
common_1.logger.debug('log command info');
|
|
29
65
|
await (0, validate_1.validate)(stackName, { stage, location: file });
|
|
30
|
-
});
|
|
66
|
+
}));
|
|
31
67
|
program
|
|
32
68
|
.command('deploy <stackName>')
|
|
33
69
|
.description('deploy serverless Iac yaml')
|
|
@@ -43,7 +79,7 @@ program
|
|
|
43
79
|
previous[key] = val;
|
|
44
80
|
return previous;
|
|
45
81
|
}, {})
|
|
46
|
-
.action(async (stackName, { stage, parameter, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
82
|
+
.action(actionWrapper('deploy', async (stackName, { stage, parameter, file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
47
83
|
await (0, deploy_1.deploy)(stackName, {
|
|
48
84
|
stage,
|
|
49
85
|
parameters: parameter,
|
|
@@ -54,16 +90,16 @@ program
|
|
|
54
90
|
accessKeySecret,
|
|
55
91
|
securityToken,
|
|
56
92
|
});
|
|
57
|
-
});
|
|
93
|
+
}));
|
|
58
94
|
program
|
|
59
95
|
.command('template <stackName>')
|
|
60
96
|
.description('print platform specific infrastructure as code template')
|
|
61
97
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
62
98
|
.option('-s, --stage <stage>', 'specify the stage')
|
|
63
99
|
.option('-t, --format <type>', 'output content type (JSON or YAML)', 'JSON')
|
|
64
|
-
.action(async (stackName, { format, file, stage }) => {
|
|
100
|
+
.action(actionWrapper('template', async (stackName, { format, file, stage }) => {
|
|
65
101
|
await (0, template_1.template)(stackName, { format, location: file, stage });
|
|
66
|
-
});
|
|
102
|
+
}));
|
|
67
103
|
program
|
|
68
104
|
.command('destroy <stackName>')
|
|
69
105
|
.option('-f, --file <path>', 'specify the yaml file')
|
|
@@ -73,7 +109,7 @@ program
|
|
|
73
109
|
.option('-x, --accessKeySecret <accessKeySecret>', 'specify the AccessKeySecret')
|
|
74
110
|
.option('-n, --securityToken <securityToken>', 'specify the SecurityToken')
|
|
75
111
|
.description('destroy serverless stack')
|
|
76
|
-
.action(async (stackName, { file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
112
|
+
.action(actionWrapper('destroy', async (stackName, { file, region, provider, accessKeyId, accessKeySecret, securityToken }) => {
|
|
77
113
|
await (0, destroy_1.destroyStack)(stackName, {
|
|
78
114
|
location: file,
|
|
79
115
|
region,
|
|
@@ -82,20 +118,22 @@ program
|
|
|
82
118
|
accessKeySecret,
|
|
83
119
|
securityToken,
|
|
84
120
|
});
|
|
85
|
-
});
|
|
121
|
+
}));
|
|
86
122
|
program
|
|
87
123
|
.command('local <stackName>')
|
|
88
124
|
.description('run Serverless application locally for debugging')
|
|
125
|
+
.option('-f, --file <path>', 'specify the yaml file')
|
|
89
126
|
.option('-s, --stage <stage>', 'specify the stage', 'default')
|
|
90
127
|
.option('-p, --port <port>', 'specify the port', '3000')
|
|
91
128
|
.option('-d, --debug', 'enable debug mode')
|
|
92
129
|
.option('-w, --watch', 'enable file watch', true)
|
|
93
|
-
.action(async (stackName, { stage, port, debug, watch }) => {
|
|
130
|
+
.action(actionWrapper('local', async (stackName, { stage, port, debug, watch, file }) => {
|
|
94
131
|
await (0, local_1.runLocal)(stackName, {
|
|
95
132
|
stage,
|
|
96
133
|
port: Number(port) || 3000,
|
|
97
134
|
debug: !!debug,
|
|
98
135
|
watch: typeof watch === 'boolean' ? watch : true,
|
|
136
|
+
location: file,
|
|
99
137
|
});
|
|
100
|
-
});
|
|
138
|
+
}));
|
|
101
139
|
program.parse();
|
|
@@ -3,11 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runLocal = void 0;
|
|
4
4
|
const common_1 = require("../common");
|
|
5
5
|
const localStack_1 = require("../stack/localStack");
|
|
6
|
+
const parser_1 = require("../parser");
|
|
6
7
|
const runLocal = async (stackName, opts) => {
|
|
7
|
-
const { stage, port, debug, watch } = opts;
|
|
8
|
-
await (0, common_1.setContext)({ stage });
|
|
8
|
+
const { stage, port, debug, watch, location } = opts;
|
|
9
|
+
await (0, common_1.setContext)({ stage, location });
|
|
10
|
+
const ctx = (0, common_1.getContext)();
|
|
11
|
+
const iac = (0, parser_1.revalYaml)((0, common_1.getIacLocation)(location), ctx);
|
|
9
12
|
common_1.logger.info(`run-local starting: stack=${stackName} stage=${stage} port=${port} debug=${debug} watch=${watch}`);
|
|
10
|
-
await (0, localStack_1.startLocalStack)();
|
|
13
|
+
await (0, localStack_1.startLocalStack)(iac);
|
|
11
14
|
// if (watch) {
|
|
12
15
|
// const cwd = process.cwd();
|
|
13
16
|
// try {
|
|
@@ -11,7 +11,9 @@ const common_1 = require("../common");
|
|
|
11
11
|
const parser_1 = require("../parser");
|
|
12
12
|
const template = async (stackName, options) => {
|
|
13
13
|
const iac = (0, parser_1.parseYaml)((0, common_1.getIacLocation)(options.location));
|
|
14
|
-
|
|
14
|
+
const credentials = (0, common_1.getCredentials)();
|
|
15
|
+
const shouldFetchIamInfo = (0, common_1.hasCredentials)(credentials);
|
|
16
|
+
await (0, common_1.setContext)({ ...options, stackName, provider: iac.provider.name }, shouldFetchIamInfo);
|
|
15
17
|
const { template } = (0, deploy_1.generateStackTemplate)(stackName, iac);
|
|
16
18
|
if (typeof template === 'string') {
|
|
17
19
|
common_1.logger.info(`\n${template}`);
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SI_BOOTSTRAP_BUCKET_PREFIX = exports.SI_BOOTSTRAP_FC_PREFIX = exports.OSS_DEPLOYMENT_TIMEOUT = exports.CODE_ZIP_SIZE_LIMIT = void 0;
|
|
3
|
+
exports.SI_LOCALSTACK_SERVER_PORT = exports.SI_BOOTSTRAP_BUCKET_PREFIX = exports.SI_BOOTSTRAP_FC_PREFIX = exports.ROS_STACK_OPERATION_TIMEOUT = exports.OSS_DEPLOYMENT_TIMEOUT = exports.CODE_ZIP_SIZE_LIMIT = void 0;
|
|
4
4
|
exports.CODE_ZIP_SIZE_LIMIT = 300 * 1000; // 300 KB ROS TemplateBody size limit 512 KB
|
|
5
5
|
exports.OSS_DEPLOYMENT_TIMEOUT = 3000; // in seconds
|
|
6
|
+
exports.ROS_STACK_OPERATION_TIMEOUT = 3600; // in seconds
|
|
6
7
|
exports.SI_BOOTSTRAP_FC_PREFIX = 'si-bootstrap-api';
|
|
7
8
|
exports.SI_BOOTSTRAP_BUCKET_PREFIX = 'si-bootstrap-artifacts';
|
|
9
|
+
exports.SI_LOCALSTACK_SERVER_PORT = 4567;
|
|
@@ -3,35 +3,53 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
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"));
|
|
6
|
+
exports.clearContext = exports.getContext = exports.setContext = exports.getIacLocation = void 0;
|
|
8
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
-
const
|
|
10
|
-
const
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const credentials_1 = require("./credentials");
|
|
11
10
|
const imsClient_1 = require("./imsClient");
|
|
12
|
-
const
|
|
11
|
+
const providerEnum_1 = require("./providerEnum");
|
|
12
|
+
let context;
|
|
13
|
+
const DEFAULT_IAC_FILES = [
|
|
14
|
+
'serverlessinsight.yml',
|
|
15
|
+
'serverlessInsight.yml',
|
|
16
|
+
'ServerlessInsight.yml',
|
|
17
|
+
'serverless-insight.yml',
|
|
18
|
+
];
|
|
13
19
|
const getIacLocation = (location) => {
|
|
14
20
|
const projectRoot = node_path_1.default.resolve(process.cwd());
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
const searchTargets = location ? [location] : DEFAULT_IAC_FILES;
|
|
22
|
+
const attempted = new Set();
|
|
23
|
+
const toAbsolutePath = (target) => node_path_1.default.isAbsolute(target) ? target : node_path_1.default.resolve(projectRoot, target);
|
|
24
|
+
const tryResolveCandidate = (target) => {
|
|
25
|
+
const resolved = toAbsolutePath(target);
|
|
26
|
+
attempted.add(resolved);
|
|
27
|
+
if (!node_fs_1.default.existsSync(resolved)) {
|
|
28
|
+
return undefined;
|
|
19
29
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
const stats = node_fs_1.default.statSync(resolved);
|
|
31
|
+
if (stats.isDirectory()) {
|
|
32
|
+
for (const fileName of DEFAULT_IAC_FILES) {
|
|
33
|
+
const nested = node_path_1.default.join(resolved, fileName);
|
|
34
|
+
attempted.add(nested);
|
|
35
|
+
if (node_fs_1.default.existsSync(nested) && node_fs_1.default.statSync(nested).isFile()) {
|
|
36
|
+
return nested;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
return resolved;
|
|
42
|
+
};
|
|
43
|
+
for (const candidate of searchTargets) {
|
|
44
|
+
const match = tryResolveCandidate(candidate);
|
|
45
|
+
if (match) {
|
|
46
|
+
return match;
|
|
32
47
|
}
|
|
33
48
|
}
|
|
34
|
-
|
|
49
|
+
const attemptedList = Array.from(attempted)
|
|
50
|
+
.map((n) => `'${n}'`)
|
|
51
|
+
.join(', ');
|
|
52
|
+
throw new Error(`No IaC file found. Tried: ${attemptedList}`);
|
|
35
53
|
};
|
|
36
54
|
exports.getIacLocation = getIacLocation;
|
|
37
55
|
const setContext = async (config, reaValToken = false) => {
|
|
@@ -40,14 +58,19 @@ const setContext = async (config, reaValToken = false) => {
|
|
|
40
58
|
process.env.ROS_REGION_ID ??
|
|
41
59
|
process.env.ALIYUN_REGION ??
|
|
42
60
|
'cn-hangzhou';
|
|
43
|
-
const
|
|
61
|
+
const credentials = (0, credentials_1.getCredentials)({
|
|
62
|
+
accessKeyId: config.accessKeyId,
|
|
63
|
+
accessKeySecret: config.accessKeySecret,
|
|
64
|
+
securityToken: config.securityToken,
|
|
65
|
+
});
|
|
66
|
+
const newContext = {
|
|
44
67
|
stage: config.stage ?? 'default',
|
|
45
68
|
stackName: config.stackName ?? '',
|
|
46
69
|
provider: (config.provider ?? config.iacProvider?.name ?? providerEnum_1.ProviderEnum.ALIYUN),
|
|
47
70
|
region,
|
|
48
|
-
accessKeyId:
|
|
49
|
-
accessKeySecret:
|
|
50
|
-
securityToken:
|
|
71
|
+
accessKeyId: credentials.accessKeyId,
|
|
72
|
+
accessKeySecret: credentials.accessKeySecret,
|
|
73
|
+
securityToken: credentials.securityToken,
|
|
51
74
|
iacLocation: (0, exports.getIacLocation)(config.location),
|
|
52
75
|
parameters: Object.entries(config.parameters ?? {}).map(([key, value]) => ({ key, value })),
|
|
53
76
|
stages: Object.entries(config.stages ?? {}).reduce((acc, [stage, parameters]) => ({
|
|
@@ -56,17 +79,20 @@ const setContext = async (config, reaValToken = false) => {
|
|
|
56
79
|
}), {}),
|
|
57
80
|
};
|
|
58
81
|
if (reaValToken) {
|
|
59
|
-
const iamInfo = await (0, imsClient_1.getIamInfo)(
|
|
60
|
-
|
|
82
|
+
const iamInfo = await (0, imsClient_1.getIamInfo)(newContext);
|
|
83
|
+
newContext.accountId = iamInfo?.accountId;
|
|
61
84
|
}
|
|
62
|
-
|
|
85
|
+
context = newContext;
|
|
63
86
|
};
|
|
64
87
|
exports.setContext = setContext;
|
|
65
88
|
const getContext = () => {
|
|
66
|
-
const context = asyncLocalStorage.getStore();
|
|
67
89
|
if (!context) {
|
|
68
90
|
throw new Error('No context found');
|
|
69
91
|
}
|
|
70
92
|
return context;
|
|
71
93
|
};
|
|
72
94
|
exports.getContext = getContext;
|
|
95
|
+
const clearContext = () => {
|
|
96
|
+
context = undefined;
|
|
97
|
+
};
|
|
98
|
+
exports.clearContext = clearContext;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasCredentials = exports.getCredentials = void 0;
|
|
4
|
+
const getCredentials = (config) => {
|
|
5
|
+
return {
|
|
6
|
+
accessKeyId: config?.accessKeyId ?? process.env.ALIYUN_ACCESS_KEY_ID,
|
|
7
|
+
accessKeySecret: config?.accessKeySecret ?? process.env.ALIYUN_ACCESS_KEY_SECRET,
|
|
8
|
+
securityToken: config?.securityToken ?? process.env.ALIYUN_SECURITY_TOKEN,
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
exports.getCredentials = getCredentials;
|
|
12
|
+
const hasCredentials = (credentials) => {
|
|
13
|
+
return !!credentials.accessKeyId && !!credentials.accessKeySecret;
|
|
14
|
+
};
|
|
15
|
+
exports.hasCredentials = hasCredentials;
|
|
@@ -36,13 +36,15 @@ 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.formatRosId = exports.calcValue = exports.calcRefs = exports.getFileSource = exports.readCodeSize = exports.resolveCode = void 0;
|
|
39
|
+
exports.splitDomain = exports.formatRosId = exports.getIacDefinition = 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
45
|
const lodash_1 = require("lodash");
|
|
46
|
+
const parser_1 = require("../parser");
|
|
47
|
+
const logger_1 = require("./logger");
|
|
46
48
|
const resolveCode = (location) => {
|
|
47
49
|
const filePath = node_path_1.default.resolve(process.cwd(), location);
|
|
48
50
|
const fileContent = node_fs_1.default.readFileSync(filePath);
|
|
@@ -104,7 +106,7 @@ exports.calcRefs = calcRefs;
|
|
|
104
106
|
const getParam = (key, records) => {
|
|
105
107
|
return records?.find((param) => param.key === key)?.value;
|
|
106
108
|
};
|
|
107
|
-
const calcValue = (rawValue, ctx) => {
|
|
109
|
+
const calcValue = (rawValue, ctx, iacVars) => {
|
|
108
110
|
const containsStage = rawValue.match(/\$\{ctx.stage}/);
|
|
109
111
|
const containsVar = rawValue.match(/\$\{vars.\w+}/);
|
|
110
112
|
const containsMap = rawValue.match(/\$\{stages\.(\w+)}/);
|
|
@@ -113,14 +115,40 @@ const calcValue = (rawValue, ctx) => {
|
|
|
113
115
|
value = rawValue.replace(/\$\{ctx.stage}/g, ctx.stage);
|
|
114
116
|
}
|
|
115
117
|
if (containsVar?.length) {
|
|
116
|
-
|
|
118
|
+
// Use provided iacVars or parse from file
|
|
119
|
+
const vars = iacVars ?? (0, parser_1.parseYaml)(ctx.iacLocation).vars;
|
|
120
|
+
const mergedParams = Array.from(new Map([
|
|
121
|
+
...Object.entries(vars ?? {}).map(([key, value]) => [key, String(value)]),
|
|
122
|
+
...(ctx.parameters ?? []).map(({ key, value }) => [key, value]),
|
|
123
|
+
].filter(([, v]) => v !== undefined)).entries()).map(([key, value]) => ({ key, value }));
|
|
124
|
+
value = value.replace(/\$\{vars\.(\w+)}/g, (_, key) => {
|
|
125
|
+
const paramValue = getParam(key, mergedParams);
|
|
126
|
+
if (!paramValue) {
|
|
127
|
+
logger_1.logger.warn(`Variable '${key}' not found in vars or parameters, using empty string`);
|
|
128
|
+
}
|
|
129
|
+
return paramValue || '';
|
|
130
|
+
});
|
|
117
131
|
}
|
|
118
132
|
if (containsMap?.length) {
|
|
119
|
-
value = value.replace(/\$\{stages\.(\w+)}/g, (_, key) =>
|
|
133
|
+
value = value.replace(/\$\{stages\.(\w+)}/g, (_, key) => {
|
|
134
|
+
const stageValue = getParam(key, (0, lodash_1.get)(ctx.stages, `${ctx.stage}`));
|
|
135
|
+
if (!stageValue) {
|
|
136
|
+
logger_1.logger.warn(`Stage variable '${key}' not found in stage '${ctx.stage}', using empty string`);
|
|
137
|
+
}
|
|
138
|
+
return stageValue || '';
|
|
139
|
+
});
|
|
120
140
|
}
|
|
121
141
|
return value;
|
|
122
142
|
};
|
|
123
143
|
exports.calcValue = calcValue;
|
|
144
|
+
const getIacDefinition = (iac, rawValue) => {
|
|
145
|
+
const matchFn = rawValue.match(/^\$\{functions\.(\w+(\.\w+)?)}$/);
|
|
146
|
+
if (matchFn?.length) {
|
|
147
|
+
return iac.functions?.find((fc) => fc.key === matchFn[1]);
|
|
148
|
+
}
|
|
149
|
+
return iac.functions?.find((fc) => fc.key === rawValue);
|
|
150
|
+
};
|
|
151
|
+
exports.getIacDefinition = getIacDefinition;
|
|
124
152
|
const formatRosId = (id) => {
|
|
125
153
|
// Insert underscore before uppercase letters, but only when they follow a lowercase letter
|
|
126
154
|
let result = id.replace(/([a-z])([A-Z])/g, '$1_$2');
|
|
@@ -135,3 +163,10 @@ const formatRosId = (id) => {
|
|
|
135
163
|
return result;
|
|
136
164
|
};
|
|
137
165
|
exports.formatRosId = formatRosId;
|
|
166
|
+
const splitDomain = (domain) => {
|
|
167
|
+
const parts = domain.split('.');
|
|
168
|
+
const rr = parts.length > 2 ? parts[0] : '@';
|
|
169
|
+
const domainName = parts.length > 2 ? parts.slice(1).join('.') : domain;
|
|
170
|
+
return { rr, domainName };
|
|
171
|
+
};
|
|
172
|
+
exports.splitDomain = splitDomain;
|
package/dist/src/common/index.js
CHANGED
|
@@ -24,4 +24,5 @@ __exportStar(require("./constants"), exports);
|
|
|
24
24
|
__exportStar(require("./imsClient"), exports);
|
|
25
25
|
__exportStar(require("./base64"), exports);
|
|
26
26
|
__exportStar(require("./rosAssets"), exports);
|
|
27
|
-
__exportStar(require("./
|
|
27
|
+
__exportStar(require("./requestHelper"), exports);
|
|
28
|
+
__exportStar(require("./credentials"), exports);
|
|
@@ -10,6 +10,12 @@ const logger = (0, pino_1.default)({
|
|
|
10
10
|
level: ['ServerlessInsight', '*'].includes(process.env.DEBUG || '') ? 'debug' : 'info',
|
|
11
11
|
transport: {
|
|
12
12
|
target: 'pino-pretty',
|
|
13
|
+
options: {
|
|
14
|
+
colorize: true,
|
|
15
|
+
translateTime: 'HH:MM:ss',
|
|
16
|
+
ignore: 'pid,hostname',
|
|
17
|
+
messageFormat: '{msg}',
|
|
18
|
+
},
|
|
13
19
|
},
|
|
14
20
|
});
|
|
15
21
|
exports.logger = logger;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readRequestBody = void 0;
|
|
4
|
+
const readRequestBody = (req) => {
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
let body = '';
|
|
7
|
+
req.on('data', (chunk) => {
|
|
8
|
+
body += chunk.toString();
|
|
9
|
+
});
|
|
10
|
+
req.on('end', () => {
|
|
11
|
+
resolve(body);
|
|
12
|
+
});
|
|
13
|
+
req.on('error', reject);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
exports.readRequestBody = readRequestBody;
|
|
@@ -43,11 +43,14 @@ const tea_util_1 = __importDefault(require("@alicloud/tea-util"));
|
|
|
43
43
|
const logger_1 = require("./logger");
|
|
44
44
|
const lang_1 = require("../lang");
|
|
45
45
|
const context_1 = require("./context");
|
|
46
|
+
const constants_1 = require("./constants");
|
|
46
47
|
const client = new ros20190910_1.default(new openapi_client_1.Config({
|
|
47
48
|
accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,
|
|
48
49
|
accessKeySecret: process.env.ALIYUN_ACCESS_KEY_SECRET,
|
|
49
50
|
regionId: process.env.ALIYUN_REGION,
|
|
50
51
|
disableRollback: false,
|
|
52
|
+
readTimeout: constants_1.ROS_STACK_OPERATION_TIMEOUT,
|
|
53
|
+
connectTimeout: constants_1.ROS_STACK_OPERATION_TIMEOUT,
|
|
51
54
|
}));
|
|
52
55
|
const createStack = async (stackName, templateBody, context) => {
|
|
53
56
|
const parameters = context.parameters?.map((parameter) => new ros20190910_1.CreateStackRequestParameters({
|
package/dist/src/parser/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseYaml = void 0;
|
|
3
|
+
exports.revalYaml = exports.parseYaml = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const functionParser_1 = require("./functionParser");
|
|
6
6
|
const eventParser_1 = require("./eventParser");
|
|
@@ -10,6 +10,7 @@ const yaml_1 = require("yaml");
|
|
|
10
10
|
const validator_1 = require("../validator");
|
|
11
11
|
const bucketParser_1 = require("./bucketParser");
|
|
12
12
|
const tableParser_1 = require("./tableParser");
|
|
13
|
+
const common_1 = require("../common");
|
|
13
14
|
const validateExistence = (path) => {
|
|
14
15
|
if (!(0, node_fs_1.existsSync)(path)) {
|
|
15
16
|
throw new Error(`File does not exist at path: ${path}`);
|
|
@@ -38,3 +39,33 @@ const parseYaml = (iacLocation) => {
|
|
|
38
39
|
return transformYaml(iacJson);
|
|
39
40
|
};
|
|
40
41
|
exports.parseYaml = parseYaml;
|
|
42
|
+
const evaluateObject = (obj, ctx, iacVars) => {
|
|
43
|
+
if (typeof obj === 'string') {
|
|
44
|
+
return (0, common_1.calcValue)(obj, ctx, iacVars);
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(obj)) {
|
|
47
|
+
return obj.map((item) => evaluateObject(item, ctx, iacVars));
|
|
48
|
+
}
|
|
49
|
+
if (typeof obj === 'object' && obj !== null) {
|
|
50
|
+
return Object.fromEntries(Object.entries(obj).map(([key, val]) => [key, evaluateObject(val, ctx, iacVars)]));
|
|
51
|
+
}
|
|
52
|
+
return obj;
|
|
53
|
+
};
|
|
54
|
+
const revalYaml = (iacLocation, ctx) => {
|
|
55
|
+
validateExistence(iacLocation);
|
|
56
|
+
const yamlContent = (0, node_fs_1.readFileSync)(iacLocation, 'utf8');
|
|
57
|
+
const iacJson = (0, yaml_1.parse)(yamlContent);
|
|
58
|
+
(0, validator_1.validateYaml)(iacJson);
|
|
59
|
+
const evaluatedIacJson = evaluateObject(iacJson, ctx, iacJson.vars);
|
|
60
|
+
const iac = transformYaml(evaluatedIacJson);
|
|
61
|
+
// Set default values for optional fields in functions
|
|
62
|
+
if (iac.functions) {
|
|
63
|
+
iac.functions = iac.functions.map((fn) => ({
|
|
64
|
+
...fn,
|
|
65
|
+
memory: fn.memory || 128,
|
|
66
|
+
timeout: fn.timeout || 3,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
return iac;
|
|
70
|
+
};
|
|
71
|
+
exports.revalYaml = revalYaml;
|