@aws-sdk/find-v2 0.4.2 → 0.5.0
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 +12 -25
- package/dist/cli.js +18 -4
- package/dist/scanLambdaFunctions.js +17 -9
- package/dist/{getLambdaFunctionScanOutput.js → utils/getLambdaFunctionScanOutput.js} +5 -4
- package/dist/utils/getLambdaFunctions.js +5 -3
- package/dist/utils/getLambdaNodeJsMatchingVersions.js +17 -0
- package/dist/utils/printLambdaCommandOutput.js +34 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -32,31 +32,18 @@ Commands:
|
|
|
32
32
|
Run `lambda` command to scan Lambda Node.js Functions for JavaScript SDK v2.
|
|
33
33
|
|
|
34
34
|
```console
|
|
35
|
-
$ npx @aws-sdk/find-v2 lambda --yes
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"FunctionName": "fn-with-aws-sdk-in-package-json-deps",
|
|
50
|
-
"Region": "us-east-2",
|
|
51
|
-
"ContainsAwsSdkJsV2": true,
|
|
52
|
-
"AwsSdkJsV2Location": "Defined in dependencies of 'package.json'"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"FunctionName": "fn-without-aws-sdk-in-package-json-deps",
|
|
56
|
-
"Region": "us-east-2",
|
|
57
|
-
"ContainsAwsSdkJsV2": false
|
|
58
|
-
}
|
|
59
|
-
]
|
|
35
|
+
$ npx @aws-sdk/find-v2 lambda --yes --output table
|
|
36
|
+
┌─────────────────────────────────────────┬───────────┬────────────┬────────────────────────────────────────────────┐
|
|
37
|
+
│ FunctionName │ Region │ Runtime │ ContainsAwsSdkJsV2 │
|
|
38
|
+
├─────────────────────────────────────────┼───────────┼────────────┼────────────────────────────────────────────────┤
|
|
39
|
+
│ fn-without-aws-sdk-in-bundle │ us-east-2 │ nodejs24.x │ No. │
|
|
40
|
+
├─────────────────────────────────────────┼───────────┼────────────┼────────────────────────────────────────────────┤
|
|
41
|
+
│ fn-with-aws-sdk-in-bundle │ us-east-2 │ nodejs24.x │ Yes. Bundled in 'index.js' │
|
|
42
|
+
├─────────────────────────────────────────┼───────────┼────────────┼────────────────────────────────────────────────┤
|
|
43
|
+
│ fn-with-aws-sdk-in-package-json-deps │ us-east-2 │ nodejs24.x │ Yes. Defined in dependencies of 'package.json' │
|
|
44
|
+
├─────────────────────────────────────────┼───────────┼────────────┼────────────────────────────────────────────────┤
|
|
45
|
+
│ fn-without-aws-sdk-in-package-json-deps │ us-east-2 │ nodejs24.x │ No. │
|
|
46
|
+
└─────────────────────────────────────────┴───────────┴────────────┴────────────────────────────────────────────────┘
|
|
60
47
|
```
|
|
61
48
|
|
|
62
49
|
This script requires AWS Managed Policy [AWSLambda_ReadOnlyAccess][].
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
1
|
+
import { Command, Option } from "commander";
|
|
2
|
+
import { satisfies } from "compare-versions";
|
|
2
3
|
import { cpus } from "node:os";
|
|
3
4
|
import packageJson from "../package.json" with { type: "json" };
|
|
4
5
|
import { scanLambdaFunctions } from "./scanLambdaFunctions.js";
|
|
6
|
+
import { LambdaCommandOutputType } from "./utils/printLambdaCommandOutput.js";
|
|
5
7
|
/**
|
|
6
8
|
* Creates and configures the CLI program with available commands.
|
|
7
9
|
*
|
|
@@ -17,9 +19,21 @@ export const createProgram = () => {
|
|
|
17
19
|
program
|
|
18
20
|
.command("lambda")
|
|
19
21
|
.description("Scans Lambda Node.js Functions for JavaScript SDK v2")
|
|
20
|
-
.option("-y, --yes", "answer yes for all prompts")
|
|
21
|
-
.option("
|
|
22
|
-
|
|
22
|
+
.option("-y, --yes", "answer yes for all prompts", false)
|
|
23
|
+
.option("--node <semver>", "Semver range string to select Lambda Node.js major versions", (value) => {
|
|
24
|
+
try {
|
|
25
|
+
satisfies("0", value);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
throw new Error(`Invalid semver range: ${value}`);
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}, ">=20")
|
|
32
|
+
.option("--region <region>", "AWS region to scan")
|
|
33
|
+
.option("--profile <profile>", "AWS profile to use")
|
|
34
|
+
.addOption(new Option("-o, --output <output>", "Output format")
|
|
35
|
+
.choices(Object.values(LambdaCommandOutputType))
|
|
36
|
+
.default(LambdaCommandOutputType.json))
|
|
23
37
|
.option("-j, --jobs <count>", "number of parallel jobs", (value) => {
|
|
24
38
|
const trimmed = value.trim();
|
|
25
39
|
if (!/^\d+$/.test(trimmed)) {
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { Lambda } from "@aws-sdk/client-lambda";
|
|
2
2
|
import pLimit from "p-limit";
|
|
3
|
-
import { getLambdaFunctionScanOutput } from "./getLambdaFunctionScanOutput.js";
|
|
4
3
|
import { getDownloadConfirmation } from "./utils/getDownloadConfirmation.js";
|
|
5
4
|
import { getLambdaFunctions } from "./utils/getLambdaFunctions.js";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { getLambdaFunctionScanOutput } from "./utils/getLambdaFunctionScanOutput.js";
|
|
6
|
+
import { getLambdaNodeJsMatchingVersions } from "./utils/getLambdaNodeJsMatchingVersions.js";
|
|
7
|
+
import { LambdaCommandOutputType, printLambdaCommandOutput, } from "./utils/printLambdaCommandOutput.js";
|
|
8
|
+
export const scanLambdaFunctions = async (options) => {
|
|
9
|
+
const { yes, node, region, profile, output, jobs } = options;
|
|
8
10
|
const client = new Lambda({
|
|
9
11
|
...(region && { region }),
|
|
10
12
|
...(profile && { profile }),
|
|
11
13
|
});
|
|
12
|
-
const
|
|
14
|
+
const lambdaNodeJsMajorVersions = getLambdaNodeJsMatchingVersions(node);
|
|
15
|
+
if (lambdaNodeJsMajorVersions.length === 0) {
|
|
16
|
+
printLambdaCommandOutput([], output);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const functions = await getLambdaFunctions(client, lambdaNodeJsMajorVersions);
|
|
13
20
|
const functionCount = functions.length;
|
|
14
21
|
const concurrency = Math.min(functionCount, jobs || 1);
|
|
15
22
|
const codeSizeToDownload = functions.reduce((acc, fn) => acc + (fn.CodeSize || 0), 0);
|
|
@@ -19,22 +26,23 @@ export const scanLambdaFunctions = async (options = {}) => {
|
|
|
19
26
|
.slice(0, concurrency)
|
|
20
27
|
.reduce((acc, size) => acc + size, 0);
|
|
21
28
|
if (functionCount === 0) {
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
printLambdaCommandOutput([], output);
|
|
30
|
+
return;
|
|
24
31
|
}
|
|
25
32
|
if (!yes) {
|
|
26
33
|
const confirmation = await getDownloadConfirmation(functionCount, codeSizeToDownload, codeSizeToSaveOnDisk);
|
|
27
34
|
console.log();
|
|
28
35
|
if (!confirmation) {
|
|
29
36
|
console.log("Exiting.");
|
|
30
|
-
|
|
37
|
+
return;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
const clientRegion = await client.config.region();
|
|
34
41
|
const limit = pLimit(concurrency);
|
|
35
|
-
const
|
|
42
|
+
const scanOutput = await Promise.all(functions.map((fn) => limit(() => getLambdaFunctionScanOutput(client, {
|
|
36
43
|
functionName: fn.FunctionName,
|
|
37
44
|
region: clientRegion,
|
|
45
|
+
runtime: fn.Runtime,
|
|
38
46
|
}))));
|
|
39
|
-
|
|
47
|
+
printLambdaCommandOutput(scanOutput, output);
|
|
40
48
|
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { downloadFile } from "./
|
|
2
|
-
import { getLambdaFunctionContents, } from "./
|
|
3
|
-
import { hasSdkV2InBundle } from "./
|
|
1
|
+
import { downloadFile } from "./downloadFile.js";
|
|
2
|
+
import { getLambdaFunctionContents, } from "./getLambdaFunctionContents.js";
|
|
3
|
+
import { hasSdkV2InBundle } from "./hasSdkV2InBundle.js";
|
|
4
4
|
import { rm } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
|
-
export const getLambdaFunctionScanOutput = async (client, { functionName, region }) => {
|
|
7
|
+
export const getLambdaFunctionScanOutput = async (client, { functionName, region, runtime }) => {
|
|
8
8
|
const output = {
|
|
9
9
|
FunctionName: functionName,
|
|
10
10
|
Region: region,
|
|
11
|
+
Runtime: runtime,
|
|
11
12
|
ContainsAwsSdkJsV2: null,
|
|
12
13
|
};
|
|
13
14
|
const response = await client.getFunction({ FunctionName: functionName });
|
|
@@ -3,17 +3,19 @@ import { paginateListFunctions } from "@aws-sdk/client-lambda";
|
|
|
3
3
|
* Retrieves all Lambda functions with Node.js runtime from AWS
|
|
4
4
|
*
|
|
5
5
|
* @param client - AWS Lambda client instance
|
|
6
|
+
* @param lambdaNodeJsMajorVersions - Array of Node.js major versions to filter (e.g., ["18", "20"])
|
|
6
7
|
* @returns Promise that resolves to array of Lambda function configurations
|
|
7
8
|
* @description
|
|
8
9
|
* - Uses AWS SDK v3 pagination to handle large number of functions
|
|
9
|
-
* - Filters results to only include Node.js runtimes
|
|
10
|
+
* - Filters results to only include specified Node.js runtimes
|
|
10
11
|
* - Returns empty array if no functions found
|
|
11
12
|
*/
|
|
12
|
-
export const getLambdaFunctions = async (client) => {
|
|
13
|
+
export const getLambdaFunctions = async (client, lambdaNodeJsMajorVersions) => {
|
|
13
14
|
const functions = [];
|
|
15
|
+
const lambdaNodeJsIdentifiers = lambdaNodeJsMajorVersions.map((version) => `nodejs${version}.x`);
|
|
14
16
|
const paginator = paginateListFunctions({ client }, {});
|
|
15
17
|
for await (const page of paginator) {
|
|
16
|
-
functions.push(...(page.Functions ?? []).filter((fn) => fn.Runtime
|
|
18
|
+
functions.push(...(page.Functions ?? []).filter((fn) => lambdaNodeJsIdentifiers.includes(fn.Runtime ?? "")));
|
|
17
19
|
}
|
|
18
20
|
return functions;
|
|
19
21
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { satisfies } from "compare-versions";
|
|
2
|
+
// Refs: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
|
|
3
|
+
export const LambdaNodeJsMajorVersions = ["10", "12", "14", "16", "18", "20", "22", "24"];
|
|
4
|
+
/**
|
|
5
|
+
* Returns Lambda Node.js major versions that satisfy the given semver range.
|
|
6
|
+
* @param semverRange - A valid semver range string (e.g., ">=18")
|
|
7
|
+
* @returns Array of matching Node.js major version strings supported by Lambda
|
|
8
|
+
*/
|
|
9
|
+
export const getLambdaNodeJsMatchingVersions = (semverRange) => {
|
|
10
|
+
const matchingVersions = [];
|
|
11
|
+
for (const nodejsVersion of LambdaNodeJsMajorVersions) {
|
|
12
|
+
if (satisfies(nodejsVersion, semverRange)) {
|
|
13
|
+
matchingVersions.push(nodejsVersion);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return matchingVersions;
|
|
17
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Table from "cli-table3";
|
|
2
|
+
export const LambdaCommandOutputType = {
|
|
3
|
+
// prints output as JSON
|
|
4
|
+
json: "json",
|
|
5
|
+
// prints human-readable representation in a table
|
|
6
|
+
table: "table",
|
|
7
|
+
};
|
|
8
|
+
export const printLambdaCommandOutput = (output, outputType) => {
|
|
9
|
+
// Output as JSON
|
|
10
|
+
if (outputType === LambdaCommandOutputType.json) {
|
|
11
|
+
console.log(JSON.stringify(output, null, 2));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Output as table
|
|
15
|
+
const table = new Table({
|
|
16
|
+
head: ["FunctionName", "Region", "Runtime", "ContainsAwsSdkJsV2"],
|
|
17
|
+
style: { head: ["bold"] },
|
|
18
|
+
});
|
|
19
|
+
for (const scanOutput of output) {
|
|
20
|
+
let notes = scanOutput.ContainsAwsSdkJsV2 === null
|
|
21
|
+
? "N/A."
|
|
22
|
+
: scanOutput.ContainsAwsSdkJsV2
|
|
23
|
+
? "Yes."
|
|
24
|
+
: "No.";
|
|
25
|
+
if (scanOutput.AwsSdkJsV2Error !== undefined) {
|
|
26
|
+
notes += ` ${scanOutput.AwsSdkJsV2Error}`;
|
|
27
|
+
}
|
|
28
|
+
if (scanOutput.AwsSdkJsV2Location !== undefined) {
|
|
29
|
+
notes += ` ${scanOutput.AwsSdkJsV2Location}`;
|
|
30
|
+
}
|
|
31
|
+
table.push([scanOutput.FunctionName, scanOutput.Region, scanOutput.Runtime, notes]);
|
|
32
|
+
}
|
|
33
|
+
console.log(table.toString());
|
|
34
|
+
};
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-sdk/find-v2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "CLI to find resources which call AWS using JavaScript SDK v2",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"types": "dist/cli.d.ts",
|
|
7
7
|
"bin": "bin/@aws-sdk/find-v2",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-lambda": "^3.942.0",
|
|
10
|
+
"cli-table3": "^0.6.5",
|
|
10
11
|
"commander": "^14.0.2",
|
|
12
|
+
"compare-versions": "^6.1.1",
|
|
11
13
|
"node-stream-zip": "^1.15.0",
|
|
12
14
|
"p-limit": "^7.2.0"
|
|
13
15
|
},
|