lambda-live-debugger 1.0.5 → 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
CHANGED
|
@@ -324,6 +324,7 @@ If you have a new feature idea, please create and issue.
|
|
|
324
324
|
|
|
325
325
|
(alphabetical)
|
|
326
326
|
|
|
327
|
+
- [Roger Chi](https://rogerchi.com/)
|
|
327
328
|
- ⭐ Your name here for notable code or documentation contributions or sample projects submitted with a bug report that resulted in tool improvement.
|
|
328
329
|
|
|
329
330
|
## Disclaimer
|
|
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
|
});
|
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
|