lambda-live-debugger 1.0.4 → 1.0.6
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 +3 -0
- package/dist/configuration/getConfigFromCliArgs.mjs +2 -0
- package/dist/configuration/getConfigFromWizard.mjs +22 -4
- package/dist/configuration.mjs +1 -1
- package/dist/extension/extension.zip +0 -0
- package/dist/frameworks/cdkFramework.mjs +60 -29
- package/dist/frameworks/cdkFrameworkWorker.mjs +1 -94
- package/dist/frameworks/iFrameworks.d.ts +1 -1
- package/dist/frameworks/samFramework.d.ts +7 -3
- package/dist/frameworks/samFramework.mjs +31 -11
- package/dist/nodeWorker.mjs +31 -5
- package/dist/nodeWorkerRunner.mjs +8 -8
- package/dist/resourceDiscovery.d.ts +1 -1
- package/dist/resourceDiscovery.mjs +5 -5
- package/dist/types/lldConfig.d.ts +12 -4
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -109,6 +109,8 @@ The configuration is saved to `lldebugger.config.ts`.
|
|
|
109
109
|
-o, --observable Observable mode
|
|
110
110
|
-i --interval <interval> Observable mode interval (default: "3000")
|
|
111
111
|
--config-env <evironment> SAM environment
|
|
112
|
+
--sam-config-file <file> SAM configuration file
|
|
113
|
+
--sam-template-file <file> SAM template file
|
|
112
114
|
--profile <profile> AWS profile to use
|
|
113
115
|
--region <region> AWS region to use
|
|
114
116
|
--role <role> AWS role to use
|
|
@@ -322,6 +324,7 @@ If you have a new feature idea, please create and issue.
|
|
|
322
324
|
|
|
323
325
|
(alphabetical)
|
|
324
326
|
|
|
327
|
+
- [Roger Chi](https://rogerchi.com/)
|
|
325
328
|
- ⭐ Your name here for notable code or documentation contributions or sample projects submitted with a bug report that resulted in tool improvement.
|
|
326
329
|
|
|
327
330
|
## Disclaimer
|
|
@@ -21,6 +21,8 @@ export async function getConfigFromCliArgs(supportedFrameworks = []) {
|
|
|
21
21
|
program.option('-o, --observable', 'Observable mode');
|
|
22
22
|
program.option('-i --interval <interval>', 'Observable mode interval', defaultObservableInterval.toString());
|
|
23
23
|
program.option('--config-env <evironment>', 'SAM environment');
|
|
24
|
+
program.option('--sam-config-file <file>', 'SAM configuration file');
|
|
25
|
+
program.option('--sam-template-file <file>', 'SAM template file');
|
|
24
26
|
program.option('--profile <profile>', 'AWS profile to use');
|
|
25
27
|
program.option('--region <region>', 'AWS region to use');
|
|
26
28
|
program.option('--role <role>', 'AWS role to use');
|
|
@@ -86,6 +86,18 @@ export async function getConfigFromWizard({ configFromCliArgs, supportedFramewor
|
|
|
86
86
|
message: 'Would you like to enter SAM environment?',
|
|
87
87
|
default: configFromCliArgs.configEnv ?? currentConfig?.configEnv,
|
|
88
88
|
},
|
|
89
|
+
{
|
|
90
|
+
type: 'input',
|
|
91
|
+
name: 'samConfigFile',
|
|
92
|
+
message: 'Would you like to enter SAM configuration file (default = samconfig.toml)?',
|
|
93
|
+
default: configFromCliArgs.samConfigFile ?? currentConfig?.samConfigFile,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
type: 'input',
|
|
97
|
+
name: 'samTemplateFile',
|
|
98
|
+
message: 'Would you like to enter SAM template file (default = template.yaml)?',
|
|
99
|
+
default: configFromCliArgs.samTemplateFile ?? currentConfig?.samTemplateFile,
|
|
100
|
+
},
|
|
89
101
|
]);
|
|
90
102
|
answers = { ...answers, ...samAnswers };
|
|
91
103
|
}
|
|
@@ -108,9 +120,9 @@ export async function getConfigFromWizard({ configFromCliArgs, supportedFramewor
|
|
|
108
120
|
type: 'confirm',
|
|
109
121
|
name: 'observable',
|
|
110
122
|
message: 'Do you want to use observable mode, which just sends events to the debugger and do not use the respose?',
|
|
111
|
-
default: configFromCliArgs.observable !== undefined
|
|
123
|
+
default: !!(configFromCliArgs.observable !== undefined
|
|
112
124
|
? configFromCliArgs.observable
|
|
113
|
-
: currentConfig?.observable,
|
|
125
|
+
: currentConfig?.observable),
|
|
114
126
|
},
|
|
115
127
|
]);
|
|
116
128
|
answers = { ...answers, ...answersObservable };
|
|
@@ -273,7 +285,7 @@ import { type LldConfigTs } from "lambda-live-debugger";
|
|
|
273
285
|
export default {
|
|
274
286
|
// Framework to use
|
|
275
287
|
framework: "${config.framework}",
|
|
276
|
-
// AWS CDK context
|
|
288
|
+
// AWS CDK framework context
|
|
277
289
|
context: ${config.context ? JSON.stringify(config.context) : undefined},
|
|
278
290
|
// Serverless Framework stage
|
|
279
291
|
stage: "${config.stage}",
|
|
@@ -287,8 +299,12 @@ export default {
|
|
|
287
299
|
region: "${config.region}",
|
|
288
300
|
// AWS role
|
|
289
301
|
role: "${config.role}",
|
|
290
|
-
// SAM environment
|
|
302
|
+
// SAM framework environment
|
|
291
303
|
configEnv: "${config.configEnv}",
|
|
304
|
+
// SAM framework configuration file
|
|
305
|
+
samConfigFile: "${config.samConfigFile}",
|
|
306
|
+
// SAM framework template file
|
|
307
|
+
samTemplateFile: "${config.samTemplateFile}",
|
|
292
308
|
// Observable mode
|
|
293
309
|
observable: ${config.observable},
|
|
294
310
|
// Observable mode interval
|
|
@@ -327,6 +343,8 @@ function getConfigFromAnswers(answers) {
|
|
|
327
343
|
region: answers.region,
|
|
328
344
|
role: answers.role,
|
|
329
345
|
configEnv: answers.configEnv,
|
|
346
|
+
samConfigFile: answers.samConfigFile,
|
|
347
|
+
samTemplateFile: answers.samTemplateFile,
|
|
330
348
|
observable: answers.observable,
|
|
331
349
|
interval: answers.interval !== undefined
|
|
332
350
|
? answers.interval
|
package/dist/configuration.mjs
CHANGED
|
@@ -17,7 +17,7 @@ async function readConfig() {
|
|
|
17
17
|
const supportedFrameworks = ResourceDiscovery.getSupportedFrameworksNames();
|
|
18
18
|
const configFromCliArgs = await getConfigFromCliArgs(supportedFrameworks);
|
|
19
19
|
Configuration.setConfig(configFromCliArgs); // not complete config
|
|
20
|
-
const currentFramework = await ResourceDiscovery.getCurrentFrameworkName();
|
|
20
|
+
const currentFramework = await ResourceDiscovery.getCurrentFrameworkName(configFromCliArgs);
|
|
21
21
|
Logger.setVerbose(configFromCliArgs.verbose === true);
|
|
22
22
|
const configFileName = configFromCliArgs.config || configFileDefaultName;
|
|
23
23
|
const configFromConfigFile = (await getConfigTsFromConfigFile(configFileName))
|
|
Binary file
|
|
@@ -142,21 +142,64 @@ export class CdkFramework {
|
|
|
142
142
|
*/
|
|
143
143
|
async getLambdasDataFromCdkByCompilingAndRunning(cdkConfigPath, config) {
|
|
144
144
|
const entryFile = await this.getCdkEntryFile(cdkConfigPath);
|
|
145
|
-
|
|
145
|
+
let isESM = false;
|
|
146
|
+
const packageJsonPath = await findPackageJson(entryFile);
|
|
147
|
+
if (packageJsonPath) {
|
|
148
|
+
try {
|
|
149
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, { encoding: 'utf-8' }));
|
|
150
|
+
if (packageJson.type === 'module') {
|
|
151
|
+
isESM = true;
|
|
152
|
+
Logger.verbose(`[CDK] Using ESM format`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (err) {
|
|
156
|
+
Logger.error(`Error reading CDK package.json (${packageJsonPath}): ${err.message}`, err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const rootDir = process.cwd();
|
|
160
|
+
// Plugin that:
|
|
161
|
+
// - Fixes __dirname issues
|
|
162
|
+
// - Injects code to get the file path of the Lambda function and CDK hierarchy
|
|
146
163
|
const injectCodePlugin = {
|
|
147
164
|
name: 'injectCode',
|
|
148
165
|
setup(build) {
|
|
149
166
|
build.onLoad({ filter: /.*/ }, async (args) => {
|
|
150
|
-
|
|
151
|
-
|
|
167
|
+
// fix __dirname issues
|
|
168
|
+
const isWindows = /^win/.test(process.platform);
|
|
169
|
+
const esc = (p) => (isWindows ? p.replace(/\\/g, '/') : p);
|
|
170
|
+
const variables = `
|
|
171
|
+
const __fileloc = {
|
|
172
|
+
filename: "${esc(args.path)}",
|
|
173
|
+
dirname: "${esc(path.dirname(args.path))}",
|
|
174
|
+
relativefilename: "${esc(path.relative(rootDir, args.path))}",
|
|
175
|
+
relativedirname: "${esc(path.relative(rootDir, path.dirname(args.path)))}",
|
|
176
|
+
import: { meta: { url: "file://${esc(args.path)}" } }
|
|
177
|
+
};
|
|
178
|
+
`;
|
|
179
|
+
let fileContent = new TextDecoder().decode(await fs.readFile(args.path));
|
|
180
|
+
// remove shebang
|
|
181
|
+
if (fileContent.startsWith('#!')) {
|
|
182
|
+
const firstNewLine = fileContent.indexOf('\n');
|
|
183
|
+
fileContent = fileContent.slice(firstNewLine + 1);
|
|
184
|
+
}
|
|
185
|
+
let contents;
|
|
186
|
+
if (args.path.endsWith('.ts') || args.path.endsWith('.js')) {
|
|
187
|
+
// add the variables at the top of the file, that contains the file location
|
|
188
|
+
contents = `${variables}\n${fileContent}`;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
contents = fileContent;
|
|
192
|
+
}
|
|
193
|
+
const loader = args.path.split('.').pop();
|
|
194
|
+
// Inject code to get the file path of the Lambda function and CDK hierarchy
|
|
152
195
|
if (args.path.includes('aws-cdk-lib/aws-lambda/lib/function.')) {
|
|
153
196
|
const codeToFind = 'try{jsiiDeprecationWarnings().aws_cdk_lib_aws_lambda_FunctionProps(props)}';
|
|
154
|
-
if (!
|
|
197
|
+
if (!contents.includes(codeToFind)) {
|
|
155
198
|
throw new Error(`Can not find code to inject in ${args.path}`);
|
|
156
199
|
}
|
|
157
200
|
// Inject code to get the file path of the Lambda function and CDK hierarchy
|
|
158
201
|
// path to match it with the Lambda function. Store data in the global variable.
|
|
159
|
-
|
|
202
|
+
contents = contents.replace(codeToFind, `;
|
|
160
203
|
global.lambdas = global.lambdas ?? [];
|
|
161
204
|
|
|
162
205
|
const lambdaInfo = {
|
|
@@ -180,36 +223,20 @@ export class CdkFramework {
|
|
|
180
223
|
}
|
|
181
224
|
if (args.path.includes('aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.')) {
|
|
182
225
|
const codeToFind = 'super(scope,id),this.requestDestinationArn=!1;';
|
|
183
|
-
if (!
|
|
226
|
+
if (!contents.includes(codeToFind)) {
|
|
184
227
|
throw new Error(`Can not find code to inject in ${args.path}`);
|
|
185
228
|
}
|
|
186
229
|
// Inject code to prevent deploying the assets
|
|
187
|
-
|
|
230
|
+
contents = contents.replace(codeToFind, codeToFind + `return;`);
|
|
188
231
|
}
|
|
189
232
|
return {
|
|
190
|
-
contents
|
|
191
|
-
loader
|
|
233
|
+
contents,
|
|
234
|
+
loader,
|
|
192
235
|
};
|
|
193
236
|
});
|
|
194
237
|
},
|
|
195
238
|
};
|
|
196
|
-
let isESM = false;
|
|
197
|
-
// get packgage.json
|
|
198
|
-
const packageJsonPath = await findPackageJson(entryFile);
|
|
199
|
-
if (packageJsonPath) {
|
|
200
|
-
try {
|
|
201
|
-
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, { encoding: 'utf-8' }));
|
|
202
|
-
if (packageJson.type === 'module') {
|
|
203
|
-
isESM = true;
|
|
204
|
-
Logger.verbose(`[CDK] Using ESM format`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
catch (err) {
|
|
208
|
-
Logger.error(`Error reading CDK package.json (${packageJsonPath}): ${err.message}`, err);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
239
|
const compileOutput = path.join(getProjectDirname(), outputFolder, `compiledCdk.${isESM ? 'mjs' : 'cjs'}`);
|
|
212
|
-
const dirname = path.join(...[getProjectDirname(), config.subfolder, 'x'].filter((p) => p));
|
|
213
240
|
try {
|
|
214
241
|
// Build CDK code
|
|
215
242
|
await esbuild.build({
|
|
@@ -228,7 +255,6 @@ export class CdkFramework {
|
|
|
228
255
|
banner: {
|
|
229
256
|
js: [
|
|
230
257
|
`import { createRequire as topLevelCreateRequire } from 'module';`,
|
|
231
|
-
`import.meta.url = 'file:///${dirname}/cdkFrameworkWorker.mjs';`,
|
|
232
258
|
`global.require = global.require ?? topLevelCreateRequire(import.meta.url);`,
|
|
233
259
|
`import { fileURLToPath as topLevelFileUrlToPath, URL as topLevelURL } from "url"`,
|
|
234
260
|
`global.__dirname = global.__dirname ?? topLevelFileUrlToPath(new topLevelURL(".", import.meta.url))`,
|
|
@@ -238,10 +264,15 @@ export class CdkFramework {
|
|
|
238
264
|
: {
|
|
239
265
|
format: 'cjs',
|
|
240
266
|
target: 'node18',
|
|
241
|
-
banner: {
|
|
242
|
-
js: [`__dirname = '${dirname}';`].join('\n'),
|
|
243
|
-
},
|
|
244
267
|
}),
|
|
268
|
+
define: {
|
|
269
|
+
// replace __dirname,... with the a variable that contains the file location
|
|
270
|
+
__filename: '__fileloc.filename',
|
|
271
|
+
__dirname: '__fileloc.dirname',
|
|
272
|
+
__relativefilename: '__fileloc.relativefilename',
|
|
273
|
+
__relativedirname: '__fileloc.relativedirname',
|
|
274
|
+
'import.meta.url': '__fileloc.import.meta.url',
|
|
275
|
+
},
|
|
245
276
|
});
|
|
246
277
|
}
|
|
247
278
|
catch (error) {
|
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import { createRequire as topLevelCreateRequire } from 'module';
|
|
3
|
-
const require = topLevelCreateRequire(import.meta.url);
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
2
|
import { workerData, parentPort } from 'node:worker_threads';
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
8
|
-
import fs from 'fs/promises'; // do not delete this line
|
|
9
|
-
|
|
10
3
|
import { Logger } from '../logger.mjs';
|
|
11
4
|
|
|
12
5
|
Logger.setVerbose(workerData.verbose);
|
|
@@ -21,7 +14,6 @@ parentPort.on('message', async (data) => {
|
|
|
21
14
|
Logger.verbose(`[Worker ${workerData.workerId}] Received message`, data);
|
|
22
15
|
|
|
23
16
|
// execute code to get the data into global.lambdas
|
|
24
|
-
await fixCdkPaths(workerData.awsCdkLibPath);
|
|
25
17
|
await import(data.compileOutput);
|
|
26
18
|
|
|
27
19
|
if (!global.lambdas || global.lambdas?.length === 0) {
|
|
@@ -43,7 +35,7 @@ parentPort.on('message', async (data) => {
|
|
|
43
35
|
}));
|
|
44
36
|
|
|
45
37
|
Logger.verbose(
|
|
46
|
-
`[CDK] [Worker] Sending found
|
|
38
|
+
`[CDK] [Worker] Sending found Lambdas`,
|
|
47
39
|
JSON.stringify(lambdas, null, 2),
|
|
48
40
|
);
|
|
49
41
|
parentPort.postMessage(lambdas);
|
|
@@ -53,91 +45,6 @@ parentPort.on('message', async (data) => {
|
|
|
53
45
|
}
|
|
54
46
|
});
|
|
55
47
|
|
|
56
|
-
/**
|
|
57
|
-
* Some paths are not resolved correctly in the CDK code, so we need to fix them
|
|
58
|
-
*/
|
|
59
|
-
async function fixCdkPaths(awsCdkLibPath) {
|
|
60
|
-
// leave this lines for manual debugging
|
|
61
|
-
//const awsCdkLibPath = path.resolve("node_modules/aws-cdk-lib");
|
|
62
|
-
//const path = require("path");
|
|
63
|
-
|
|
64
|
-
Logger.verbose(`[CDK] [Worker] aws-cdk-lib PATH ${awsCdkLibPath}`);
|
|
65
|
-
|
|
66
|
-
const pathsFix = {
|
|
67
|
-
'custom-resource-handlers/': `${awsCdkLibPath}/custom-resource-handlers/`,
|
|
68
|
-
'aws-custom-resource-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/custom-resources/aws-custom-resource-handler`,
|
|
69
|
-
'auto-delete-objects-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-s3/auto-delete-objects-handler`,
|
|
70
|
-
'notifications-resource-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-s3/notifications-resource-handler`,
|
|
71
|
-
'drop-spam-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-ses/drop-spam-handler`,
|
|
72
|
-
'aws-stepfunctions-tasks/role-policy-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-stepfunctions-tasks/role-policy-handler`,
|
|
73
|
-
'eval-nodejs-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-stepfunctions-tasks/eval-nodejs-handler`,
|
|
74
|
-
'cross-account-zone-delegation-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-route53/cross-account-zone-delegation-handler`,
|
|
75
|
-
'delete-existing-record-set-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-route53/delete-existing-record-set-handler`,
|
|
76
|
-
'aws-api-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-events-targets/aws-api-handler`,
|
|
77
|
-
'log-retention-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-logs/log-retention-handler`,
|
|
78
|
-
'cluster-resource-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-eks/cluster-resource-handler`,
|
|
79
|
-
'auto-delete-images-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-ecr/auto-delete-images-handler`,
|
|
80
|
-
'bucket-deployment-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-s3-deployment/bucket-deployment-handler`,
|
|
81
|
-
'nodejs-entrypoint-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/core/nodejs-entrypoint-handler`,
|
|
82
|
-
'restrict-default-security-group-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-ec2/restrict-default-security-group-handler`,
|
|
83
|
-
'dns-validated-certificate-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-certificatemanager/dns-validated-certificate-handler`,
|
|
84
|
-
'auto-delete-underlying-resources-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-synthetics/auto-delete-underlying-resources-handler`,
|
|
85
|
-
'replica-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-dynamodb/replica-handler`,
|
|
86
|
-
'oidc-handler': `${awsCdkLibPath}/custom-resource-handlers/dist/aws-iam/oidc-handler`,
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
// Create a proxy to intercept calls to the path module so we can fix paths
|
|
90
|
-
const pathProxy = new Proxy(path, {
|
|
91
|
-
get(target, prop) {
|
|
92
|
-
if (typeof target[prop] === 'function') {
|
|
93
|
-
return function (...args) {
|
|
94
|
-
if (prop === 'resolve') {
|
|
95
|
-
let resolvedPath = target[prop].apply(target, args);
|
|
96
|
-
|
|
97
|
-
for (const [key, value] of Object.entries(pathsFix)) {
|
|
98
|
-
if (resolvedPath.includes(key)) {
|
|
99
|
-
// replace the beginning of the path with the value
|
|
100
|
-
const i = resolvedPath.indexOf(key);
|
|
101
|
-
const newResolvedPath = `${value}${resolvedPath.substring(i + key.length)}`;
|
|
102
|
-
Logger.verbose(
|
|
103
|
-
`[CDK] [Worker] Fixing path ${resolvedPath} -> ${newResolvedPath}`,
|
|
104
|
-
);
|
|
105
|
-
resolvedPath = newResolvedPath;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return resolvedPath;
|
|
110
|
-
}
|
|
111
|
-
if (prop === 'join') {
|
|
112
|
-
let resolvedPath = target[prop].apply(target, args);
|
|
113
|
-
|
|
114
|
-
for (const [key, value] of Object.entries(pathsFix)) {
|
|
115
|
-
if (resolvedPath.includes(key)) {
|
|
116
|
-
// replace the beginning of the path with the value
|
|
117
|
-
const i = resolvedPath.indexOf(key);
|
|
118
|
-
const newResolvedPath = `${value}${resolvedPath.substring(i + key.length)}`;
|
|
119
|
-
Logger.verbose(
|
|
120
|
-
`[CDK] [Worker] Fixing path ${resolvedPath} -> ${newResolvedPath}`,
|
|
121
|
-
);
|
|
122
|
-
resolvedPath = newResolvedPath;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return resolvedPath;
|
|
127
|
-
}
|
|
128
|
-
return target[prop].apply(target, args);
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
return target[prop];
|
|
132
|
-
},
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
// Override the path module in the require cache
|
|
136
|
-
require.cache[require.resolve('path')] = {
|
|
137
|
-
exports: pathProxy,
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
48
|
process.on('unhandledRejection', (error) => {
|
|
142
49
|
Logger.error(`[CDK] [Worker] Unhandled Rejection`, error);
|
|
143
50
|
});
|
|
@@ -5,8 +5,6 @@ import { LldConfigBase } from '../types/lldConfig.js';
|
|
|
5
5
|
* Support for AWS SAM framework
|
|
6
6
|
*/
|
|
7
7
|
export declare class SamFramework implements IFramework {
|
|
8
|
-
protected samConfigFile: string;
|
|
9
|
-
protected samTemplateFile: string;
|
|
10
8
|
/**
|
|
11
9
|
* Framework name
|
|
12
10
|
*/
|
|
@@ -15,7 +13,13 @@ export declare class SamFramework implements IFramework {
|
|
|
15
13
|
* Can this class handle the current project
|
|
16
14
|
* @returns
|
|
17
15
|
*/
|
|
18
|
-
canHandle(): Promise<boolean>;
|
|
16
|
+
canHandle(config: LldConfigBase): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Get configuration files
|
|
19
|
+
* @param config Configuration
|
|
20
|
+
* @returns Configuration files
|
|
21
|
+
*/
|
|
22
|
+
private getConfigFiles;
|
|
19
23
|
/**
|
|
20
24
|
* Get Lambda functions
|
|
21
25
|
* @param config Configuration
|
|
@@ -10,8 +10,6 @@ import { Logger } from '../logger.mjs';
|
|
|
10
10
|
* Support for AWS SAM framework
|
|
11
11
|
*/
|
|
12
12
|
export class SamFramework {
|
|
13
|
-
samConfigFile = 'samconfig.toml';
|
|
14
|
-
samTemplateFile = 'template.yaml';
|
|
15
13
|
/**
|
|
16
14
|
* Framework name
|
|
17
15
|
*/
|
|
@@ -22,23 +20,37 @@ export class SamFramework {
|
|
|
22
20
|
* Can this class handle the current project
|
|
23
21
|
* @returns
|
|
24
22
|
*/
|
|
25
|
-
async canHandle() {
|
|
23
|
+
async canHandle(config) {
|
|
24
|
+
const { samConfigFile, samTemplateFile } = this.getConfigFiles(config);
|
|
26
25
|
try {
|
|
27
|
-
await fs.access(
|
|
26
|
+
await fs.access(samConfigFile, constants.F_OK);
|
|
28
27
|
}
|
|
29
28
|
catch {
|
|
30
|
-
Logger.verbose(`[SAM] This is not a SAM framework project. ${
|
|
29
|
+
Logger.verbose(`[SAM] This is not a SAM framework project. ${samConfigFile} not found.`);
|
|
31
30
|
return false;
|
|
32
31
|
}
|
|
33
32
|
try {
|
|
34
|
-
await fs.access(
|
|
33
|
+
await fs.access(samTemplateFile, constants.F_OK);
|
|
35
34
|
}
|
|
36
35
|
catch {
|
|
37
|
-
Logger.verbose(`[SAM] This is not a SAM framework project. ${
|
|
36
|
+
Logger.verbose(`[SAM] This is not a SAM framework project. ${samTemplateFile} not found.`);
|
|
38
37
|
return false;
|
|
39
38
|
}
|
|
40
39
|
return true;
|
|
41
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Get configuration files
|
|
43
|
+
* @param config Configuration
|
|
44
|
+
* @returns Configuration files
|
|
45
|
+
*/
|
|
46
|
+
getConfigFiles(config) {
|
|
47
|
+
const samConfigFile = config.samConfigFile ?? 'samconfig.toml';
|
|
48
|
+
const samTemplateFile = config.samTemplateFile ?? 'template.yaml';
|
|
49
|
+
return {
|
|
50
|
+
samConfigFile: path.resolve(samConfigFile),
|
|
51
|
+
samTemplateFile: path.resolve(samTemplateFile),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
42
54
|
/**
|
|
43
55
|
* Get Lambda functions
|
|
44
56
|
* @param config Configuration
|
|
@@ -50,14 +62,22 @@ export class SamFramework {
|
|
|
50
62
|
profile: config.profile,
|
|
51
63
|
role: config.role,
|
|
52
64
|
};
|
|
65
|
+
const { samConfigFile, samTemplateFile } = this.getConfigFiles(config);
|
|
53
66
|
const environment = config.configEnv ?? 'default';
|
|
54
|
-
const samConfigContent = await fs.readFile(
|
|
55
|
-
|
|
67
|
+
const samConfigContent = await fs.readFile(samConfigFile, 'utf-8');
|
|
68
|
+
let samConfig;
|
|
69
|
+
// is toml extension
|
|
70
|
+
if (samConfigFile.endsWith('.toml')) {
|
|
71
|
+
samConfig = toml.parse(samConfigContent);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
samConfig = yaml.parse(samConfigContent);
|
|
75
|
+
}
|
|
56
76
|
const stackName = samConfig[environment]?.global?.parameters?.stack_name;
|
|
57
77
|
if (!stackName) {
|
|
58
|
-
throw new Error(`Stack name not found in ${
|
|
78
|
+
throw new Error(`Stack name not found in ${samConfigFile}`);
|
|
59
79
|
}
|
|
60
|
-
const samTemplateContent = await fs.readFile(path.resolve(
|
|
80
|
+
const samTemplateContent = await fs.readFile(path.resolve(samTemplateFile), 'utf-8');
|
|
61
81
|
const template = yaml.parse(samTemplateContent);
|
|
62
82
|
const lambdas = [];
|
|
63
83
|
// get all resources of type AWS::Serverless::Function
|
package/dist/nodeWorker.mjs
CHANGED
|
@@ -22,23 +22,31 @@ async function runInWorker(input) {
|
|
|
22
22
|
environment: input.environment,
|
|
23
23
|
verbose: Configuration.config.verbose,
|
|
24
24
|
});
|
|
25
|
+
worker.used = false;
|
|
26
|
+
worker.toKill = false;
|
|
25
27
|
}
|
|
26
28
|
else {
|
|
27
29
|
Logger.verbose(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Reusing worker`);
|
|
28
30
|
}
|
|
29
|
-
worker.
|
|
31
|
+
worker.onMessage = (msg) => {
|
|
30
32
|
Logger.verbose(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Worker message`, JSON.stringify(msg));
|
|
33
|
+
worker.used = false;
|
|
31
34
|
if (msg?.errorType) {
|
|
32
35
|
reject(msg);
|
|
33
36
|
}
|
|
34
37
|
else {
|
|
35
38
|
resolve(msg);
|
|
36
39
|
}
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
if (worker.toKill) {
|
|
41
|
+
worker.toKill = false;
|
|
42
|
+
void worker.terminate();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
worker.onError = (err) => {
|
|
39
46
|
Logger.error(`[Function ${input.fuctionRequest.functionId}] [Worker ${input.fuctionRequest.workerId}] Error`, err);
|
|
40
47
|
reject(err);
|
|
41
|
-
}
|
|
48
|
+
};
|
|
49
|
+
worker.used = true;
|
|
42
50
|
worker.postMessage({
|
|
43
51
|
env: input.fuctionRequest.env,
|
|
44
52
|
event: input.fuctionRequest.event,
|
|
@@ -78,6 +86,12 @@ function startWorker(input) {
|
|
|
78
86
|
workers.delete(input.workerId);
|
|
79
87
|
});
|
|
80
88
|
workers.set(input.workerId, worker);
|
|
89
|
+
worker.on('message', (msg) => {
|
|
90
|
+
worker?.onMessage?.(msg);
|
|
91
|
+
});
|
|
92
|
+
worker.on('error', (err) => {
|
|
93
|
+
worker?.onError?.(err);
|
|
94
|
+
});
|
|
81
95
|
return worker;
|
|
82
96
|
}
|
|
83
97
|
/**
|
|
@@ -87,7 +101,19 @@ async function stopAllWorkers() {
|
|
|
87
101
|
Logger.verbose('Stopping all workers');
|
|
88
102
|
const promises = [];
|
|
89
103
|
for (const worker of workers.values()) {
|
|
90
|
-
|
|
104
|
+
if (worker.used) {
|
|
105
|
+
worker.toKill = true;
|
|
106
|
+
// set timout for 5 minutes and kill the worker if it is still running
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
if (worker.toKill) {
|
|
109
|
+
worker.toKill = false;
|
|
110
|
+
void worker.terminate();
|
|
111
|
+
}
|
|
112
|
+
}, 300000);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
promises.push(worker.terminate());
|
|
116
|
+
}
|
|
91
117
|
}
|
|
92
118
|
workers.clear();
|
|
93
119
|
await Promise.all(promises);
|
|
@@ -13,16 +13,16 @@ Logger.verbose(
|
|
|
13
13
|
|
|
14
14
|
parentPort.on('message', async (data) => {
|
|
15
15
|
Logger.verbose(`[Worker ${workerData.workerId}] Received message`, data);
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
try {
|
|
17
|
+
const mod = await import(workerData.artifactFile);
|
|
18
|
+
const fn = mod[workerData.handler];
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
if (!fn) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Handler '${workerData.handler}' not found for function '${workerData.functionId}'`,
|
|
23
|
+
);
|
|
24
|
+
}
|
|
24
25
|
|
|
25
|
-
try {
|
|
26
26
|
const context = {
|
|
27
27
|
...data.context,
|
|
28
28
|
getRemainingTimeInMillis: () => 2147483647, // Max 32-bit signed integer
|
|
@@ -6,7 +6,7 @@ declare function getSupportedFrameworksNames(): string[];
|
|
|
6
6
|
/**
|
|
7
7
|
* Get the name of the current framework
|
|
8
8
|
*/
|
|
9
|
-
declare function getCurrentFrameworkName(): Promise<string | undefined>;
|
|
9
|
+
declare function getCurrentFrameworkName(config: LldConfig): Promise<string | undefined>;
|
|
10
10
|
declare function getLambdas(config: LldConfig): Promise<{
|
|
11
11
|
codePath: string;
|
|
12
12
|
functionName: string;
|
|
@@ -22,8 +22,8 @@ function getSupportedFrameworksNames() {
|
|
|
22
22
|
/**
|
|
23
23
|
* Get the name of the current framework
|
|
24
24
|
*/
|
|
25
|
-
async function getCurrentFrameworkName() {
|
|
26
|
-
const framework = await getCurrentFramework(frameworksSupported);
|
|
25
|
+
async function getCurrentFrameworkName(config) {
|
|
26
|
+
const framework = await getCurrentFramework(frameworksSupported, config);
|
|
27
27
|
return framework?.name;
|
|
28
28
|
}
|
|
29
29
|
async function getLambdas(config) {
|
|
@@ -37,7 +37,7 @@ async function getLambdas(config) {
|
|
|
37
37
|
frameworks = frameworks.filter((f) => f.name === config.framework);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
const framework = await getCurrentFramework(frameworks);
|
|
40
|
+
const framework = await getCurrentFramework(frameworks, config);
|
|
41
41
|
if (framework) {
|
|
42
42
|
Logger.verbose(`Getting resources with '${framework.name}' framework`);
|
|
43
43
|
resources = await framework.getLambdas(config);
|
|
@@ -61,10 +61,10 @@ async function getLambdas(config) {
|
|
|
61
61
|
/**
|
|
62
62
|
* Get the current framework
|
|
63
63
|
*/
|
|
64
|
-
async function getCurrentFramework(frameworks) {
|
|
64
|
+
async function getCurrentFramework(frameworks, config) {
|
|
65
65
|
let framework;
|
|
66
66
|
for (const f of frameworks) {
|
|
67
|
-
if (await f.canHandle()) {
|
|
67
|
+
if (await f.canHandle(config)) {
|
|
68
68
|
framework = f;
|
|
69
69
|
break;
|
|
70
70
|
}
|
|
@@ -18,10 +18,6 @@ export type LldConfigBase = {
|
|
|
18
18
|
* Filter by function name
|
|
19
19
|
*/
|
|
20
20
|
function?: string;
|
|
21
|
-
/**
|
|
22
|
-
* SAM environment
|
|
23
|
-
*/
|
|
24
|
-
configEnv?: string;
|
|
25
21
|
/**
|
|
26
22
|
* Observable mode
|
|
27
23
|
* @default false
|
|
@@ -40,6 +36,18 @@ export type LldConfigBase = {
|
|
|
40
36
|
* Start debugger
|
|
41
37
|
*/
|
|
42
38
|
start?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* SAM framework cli parameter config-env
|
|
41
|
+
*/
|
|
42
|
+
configEnv?: string;
|
|
43
|
+
/**
|
|
44
|
+
* SAM framework cli parameter config-file
|
|
45
|
+
*/
|
|
46
|
+
samConfigFile?: string;
|
|
47
|
+
/**
|
|
48
|
+
* SAM framework cli parameter template-file
|
|
49
|
+
*/
|
|
50
|
+
samTemplateFile?: string;
|
|
43
51
|
/**
|
|
44
52
|
* Resources discovery function
|
|
45
53
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lambda-live-debugger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Debug Lambda functions locally like it is running in the cloud",
|
|
6
6
|
"repository": {
|
|
@@ -59,6 +59,8 @@
|
|
|
59
59
|
"test-sls-esbuild-esm-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/sls-esbuild-esm.test.ts",
|
|
60
60
|
"test-sam-basic": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/sam-basic.test.ts",
|
|
61
61
|
"test-sam-basic-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/sam-basic.test.ts",
|
|
62
|
+
"test-sam-alt": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/sam-alt.test.ts",
|
|
63
|
+
"test-sam-alt-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/sam-alt.test.ts",
|
|
62
64
|
"test-terraform-basic": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/terraform-basic.test.ts",
|
|
63
65
|
"test-terraform-basic-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/terraform-basic.test.ts",
|
|
64
66
|
"docs:dev": "vitepress dev",
|
|
@@ -137,6 +139,7 @@
|
|
|
137
139
|
"test/sls-basic",
|
|
138
140
|
"test/sls-esbuild",
|
|
139
141
|
"test/sam-basic",
|
|
142
|
+
"test/sam-alt",
|
|
140
143
|
"test/terraform-basic"
|
|
141
144
|
]
|
|
142
145
|
}
|