lambda-live-debugger 1.0.0 → 1.0.3

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.
@@ -28,7 +28,7 @@ export default defineConfig({
28
28
  ['meta', { property: 'og:image', content: 'https://lldebugger.com/lambda_live_debugger.png' }],
29
29
  ['meta', { property: 'og:url', content: 'https://lldebugger.com/' }],
30
30
 
31
- ['meta', { property: 'twitter:card', content: 'summary' }],
31
+ ['meta', { property: 'twitter:card', content: 'summary_large_image' }],
32
32
  ['meta', { property: 'twitter:site', content: '@serverlessl' }],
33
33
 
34
34
  [
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ![Lambda Live Debugger](public/logo_landscape_light.svg)
2
2
 
3
- Lambda Live Debugger is an indispensable tool for debugging AWS Lambda functions from your computer, even though they are deployed in the cloud. It supports Lambdas written in JavaScript or TypeScript.
3
+ Lambda Live Debugger is an indispensable tool for debugging AWS Lambda functions from your computer, even though they are deployed in the cloud. It supports Lambdas written in JavaScript or TypeScript. It is free and open source.
4
4
 
5
5
  This tool offers similar functionality to [SST](https://sst.dev/) and [Serverless Framework v4](https://www.serverless.com/blog/serverless-framework-v4-general-availability), with the addition of an Observability Mode.
6
6
 
@@ -51,7 +51,11 @@ async function getCloudFormationClient(awsConfiguration) {
51
51
  * @returns
52
52
  */
53
53
  async function getCloudFormationResources(stackName, awsConfiguration) {
54
+ // temporary disable console.error because SAM framework outputs useless errors
55
+ const originalConsoleError = console.error;
56
+ console.error = function () { };
54
57
  const { ListStackResourcesCommand } = await import('@aws-sdk/client-cloudformation');
58
+ console.error = originalConsoleError;
55
59
  const cloudFormationClient = await getCloudFormationClient(awsConfiguration);
56
60
  try {
57
61
  let nextToken = undefined;
Binary file
@@ -193,17 +193,54 @@ export class CdkFramework {
193
193
  });
194
194
  },
195
195
  };
196
- const compileOutput = path.join(getProjectDirname(), outputFolder, `compiledCdk.js`);
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
+ const compileOutput = path.join(getProjectDirname(), outputFolder, `compiledCdk.${isESM ? 'mjs' : 'cjs'}`);
212
+ const dirname = path.join(...[getProjectDirname(), config.subfolder, 'x'].filter((p) => p));
197
213
  try {
198
214
  // Build CDK code
199
215
  await esbuild.build({
200
216
  entryPoints: [entryFile],
201
217
  bundle: true,
202
218
  platform: 'node',
203
- target: 'node18',
219
+ keepNames: true,
204
220
  outfile: compileOutput,
205
221
  sourcemap: false,
206
222
  plugins: [injectCodePlugin],
223
+ ...(isESM
224
+ ? {
225
+ format: 'esm',
226
+ target: 'esnext',
227
+ mainFields: ['module', 'main'],
228
+ banner: {
229
+ js: [
230
+ `import { createRequire as topLevelCreateRequire } from 'module';`,
231
+ `global.require = global.require ?? topLevelCreateRequire(import.meta.url);`,
232
+ `import { fileURLToPath as topLevelFileUrlToPath, URL as topLevelURL } from "url"`,
233
+ `global.__dirname = '${dirname}'`,
234
+ ].join('\n'),
235
+ },
236
+ }
237
+ : {
238
+ format: 'cjs',
239
+ target: 'node18',
240
+ banner: {
241
+ js: [`__dirname = '${dirname}';`].join('\n'),
242
+ },
243
+ }),
207
244
  });
208
245
  }
209
246
  catch (error) {
@@ -296,6 +333,12 @@ export class CdkFramework {
296
333
  reject(new Error(`CDK worker stopped with exit code ${code}`));
297
334
  }
298
335
  });
336
+ // worker.stdout.on('data', (data: Buffer) => {
337
+ // Logger.log(`[CDK]`, data.toString());
338
+ // });
339
+ // worker.stderr.on('data', (data: Buffer) => {
340
+ // Logger.error(`[CDK]`, data.toString());
341
+ // });
299
342
  worker.postMessage({
300
343
  compileOutput: compileCodeFile,
301
344
  });
@@ -4,56 +4,53 @@ const require = topLevelCreateRequire(import.meta.url);
4
4
  import path from 'path';
5
5
 
6
6
  import { workerData, parentPort } from 'node:worker_threads';
7
- import fs from 'fs/promises';
7
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
+ import fs from 'fs/promises'; // do not delete this line
8
9
 
9
10
  import { Logger } from '../logger.mjs';
10
11
 
11
12
  Logger.setVerbose(workerData.verbose);
12
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
- const __dirname = path.resolve(
14
- path.join(
15
- ...[workerData.projectDirname, workerData.subfolder, 'x'].filter((p) => p),
16
- ),
17
- );
18
13
 
19
14
  Logger.verbose(`[CDK] [Worker] Started`);
20
15
 
21
16
  parentPort.on('message', async (data) => {
22
- // this is global variable to store the data from the CDK code once it is executed
23
- global.lambdas = [];
24
-
25
- Logger.verbose(`[Worker ${workerData.workerId}] Received message`, data);
26
-
27
- // execute code to get the data into global.lambdas
28
- const codeFile = await fs.readFile(data.compileOutput, 'utf8');
29
-
30
- await fixCdkPaths(workerData.awsCdkLibPath);
31
-
32
- eval(codeFile);
33
-
34
- if (!global.lambdas || global.lambdas?.length === 0) {
35
- throw new Error('No Lambda functions found in the CDK code');
17
+ try {
18
+ // this is global variable to store the data from the CDK code once it is executed
19
+ global.lambdas = [];
20
+
21
+ Logger.verbose(`[Worker ${workerData.workerId}] Received message`, data);
22
+
23
+ // execute code to get the data into global.lambdas
24
+ await fixCdkPaths(workerData.awsCdkLibPath);
25
+ await import(data.compileOutput);
26
+
27
+ if (!global.lambdas || global.lambdas?.length === 0) {
28
+ throw new Error('No Lambda functions found in the CDK code');
29
+ }
30
+
31
+ const lambdas = global.lambdas.map((lambda) => ({
32
+ handler: lambda.handler,
33
+ stackName: lambda.stackName,
34
+ codePath: lambda.codePath,
35
+ code: {
36
+ path: lambda.code?.path,
37
+ },
38
+ cdkPath: lambda.node.defaultChild.node.path,
39
+ bundling: {
40
+ ...lambda.bundling,
41
+ commandHooks: undefined, // can not be serialized
42
+ },
43
+ }));
44
+
45
+ Logger.verbose(
46
+ `[CDK] [Worker] Sending found lambdas`,
47
+ JSON.stringify(lambdas, null, 2),
48
+ );
49
+ parentPort.postMessage(lambdas);
50
+ } catch (error) {
51
+ Logger.error(`[CDK] [Worker] Error`, error);
52
+ throw error;
36
53
  }
37
-
38
- const lambdas = global.lambdas.map((lambda) => ({
39
- handler: lambda.handler,
40
- stackName: lambda.stackName,
41
- codePath: lambda.codePath,
42
- code: {
43
- path: lambda.code?.path,
44
- },
45
- cdkPath: lambda.node.defaultChild.node.path,
46
- bundling: {
47
- ...lambda.bundling,
48
- commandHooks: undefined, // can not be serialized
49
- },
50
- }));
51
-
52
- Logger.verbose(
53
- `[CDK] [Worker] Sending found lambdas`,
54
- JSON.stringify(lambdas, null, 2),
55
- );
56
- parentPort.postMessage(lambdas);
57
54
  });
58
55
 
59
56
  /**
@@ -69,6 +66,24 @@ async function fixCdkPaths(awsCdkLibPath) {
69
66
  const pathsFix = {
70
67
  'custom-resource-handlers/': `${awsCdkLibPath}/custom-resource-handlers/`,
71
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`,
72
87
  };
73
88
 
74
89
  // Create a proxy to intercept calls to the path module so we can fix paths
@@ -93,6 +108,23 @@ async function fixCdkPaths(awsCdkLibPath) {
93
108
 
94
109
  return resolvedPath;
95
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
+ }
96
128
  return target[prop].apply(target, args);
97
129
  };
98
130
  }
@@ -105,3 +137,7 @@ async function fixCdkPaths(awsCdkLibPath) {
105
137
  exports: pathProxy,
106
138
  };
107
139
  }
140
+
141
+ process.on('unhandledRejection', (error) => {
142
+ Logger.error(`[CDK] [Worker] Unhandled Rejection`, error);
143
+ });
@@ -71,7 +71,7 @@ function startWorker(input) {
71
71
  Logger.log(`[Function ${input.functionId}]`, data.toString());
72
72
  });
73
73
  worker.stderr.on('data', (data) => {
74
- Logger.log(`[Function ${input.functionId}]`, data.toString());
74
+ Logger.error(`[Function ${input.functionId}]`, data.toString());
75
75
  });
76
76
  worker.on('exit', () => {
77
77
  Logger.verbose(`[Function ${input.functionId}] [Worker ${input.workerId}] Worker exited`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambda-live-debugger",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "description": "Debug Lambda functions locally like it is running in the cloud",
6
6
  "repository": {
@@ -49,6 +49,8 @@
49
49
  "test": "npm run build && RUN_TEST_FROM_CLI=true vitest run && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run",
50
50
  "test-cdk-basic": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/cdk-basic.test.ts",
51
51
  "test-cdk-basic-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/cdk-basic.test.ts",
52
+ "test-cdk-esm": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/cdk-esm.test.ts",
53
+ "test-cdk-esm-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/cdk-esm.test.ts",
52
54
  "test-sls-basic": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/sls-basic.test.ts",
53
55
  "test-sls-basic-observable": "npm run build && RUN_TEST_FROM_CLI=true OBSERVABLE_MODE=true vitest run test/sls-basic.test.ts",
54
56
  "test-sls-esbuild-cjs": "npm run build && RUN_TEST_FROM_CLI=true vitest run test/sls-esbuild-cjs.test.ts",
@@ -130,6 +132,7 @@
130
132
  "src/extension/*",
131
133
  "test",
132
134
  "test/cdk-basic",
135
+ "test/cdk-esm",
133
136
  "test/cdk-config",
134
137
  "test/sls-basic",
135
138
  "test/sls-esbuild",
Binary file