Skip to content

Commit 65c166a

Browse files
authored
Support transformation for global require (#62)
1 parent 12c2e5a commit 65c166a

15 files changed

+205
-43
lines changed

.changeset/lemon-mangos-remember.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"aws-sdk-js-codemod": minor
3+
---
4+
5+
Support transformation for global require
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
const AWS = require("aws-sdk");
2+
3+
const client = new AWS.DynamoDB();
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const {
2+
DynamoDB
3+
} = require("@aws-sdk/client-dynamodb");
4+
5+
const client = new DynamoDB();

src/transforms/v2-to-v3/transformer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { API, FileInfo } from "jscodeshift";
22

33
import {
4-
addV3ClientImport,
4+
addV3ClientModule,
55
getClientMetadata,
66
getV2ClientImportNames,
77
getV2ClientNames,
88
getV2DefaultImportName,
9-
removeDefaultImportIfNotUsed,
9+
removeDefaultModuleIfNotUsed,
1010
removePromiseCalls,
1111
removeV2ClientImport,
1212
replaceClientCreation,
@@ -27,13 +27,13 @@ export default function transformer(file: FileInfo, api: API) {
2727

2828
for (const [v2ClientName, v3ClientMetadata] of Object.entries(clientMetadata).reverse()) {
2929
const { v3ClientName, v3ClientPackageName } = v3ClientMetadata;
30-
addV3ClientImport(j, source, { v2ClientName, v3ClientName, v3ClientPackageName });
30+
addV3ClientModule(j, source, { v2ClientName, v3ClientName, v3ClientPackageName });
3131
removeV2ClientImport(j, source, v2ClientName);
3232
removePromiseCalls(j, source, { v2DefaultImportName, v2ClientName });
3333
replaceClientCreation(j, source, { v2DefaultImportName, v2ClientName, v3ClientName });
3434
}
3535

36-
removeDefaultImportIfNotUsed(j, source, v2DefaultImportName);
36+
removeDefaultModuleIfNotUsed(j, source, v2DefaultImportName);
3737

3838
return source.toSource();
3939
}

src/transforms/v2-to-v3/utils/addV3ClientImport.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
import { Collection, JSCodeshift } from "jscodeshift";
22

3-
export interface AddV3ClientImportOptions {
4-
v2ClientName: string;
5-
v3ClientName: string;
6-
v3ClientPackageName: string;
7-
}
3+
import { AddV3ClientModuleOptions } from "./addV3ClientModule";
84

95
export const addV3ClientImport = (
106
j: JSCodeshift,
117
source: Collection<any>,
12-
{ v2ClientName, v3ClientName, v3ClientPackageName }: AddV3ClientImportOptions
8+
{ v2ClientName, v3ClientName, v3ClientPackageName }: AddV3ClientModuleOptions
139
): void => {
1410
const existingImports = source.find(j.ImportDeclaration, {
1511
source: { value: v3ClientPackageName },
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Collection, JSCodeshift } from "jscodeshift";
2+
3+
import { addV3ClientImport } from "./addV3ClientImport";
4+
import { addV3ClientRequire } from "./addV3ClientRequire";
5+
import { containsRequire } from "./containsRequire";
6+
7+
export interface AddV3ClientModuleOptions {
8+
v2ClientName: string;
9+
v3ClientName: string;
10+
v3ClientPackageName: string;
11+
}
12+
13+
export const addV3ClientModule = (
14+
j: JSCodeshift,
15+
source: Collection<any>,
16+
{ v2ClientName, v3ClientName, v3ClientPackageName }: AddV3ClientModuleOptions
17+
): void =>
18+
containsRequire(j, source)
19+
? addV3ClientRequire(j, source, { v2ClientName, v3ClientName, v3ClientPackageName })
20+
: addV3ClientImport(j, source, { v2ClientName, v3ClientName, v3ClientPackageName });
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Collection, Identifier, JSCodeshift, ObjectPattern, Property } from "jscodeshift";
2+
3+
import { AddV3ClientModuleOptions } from "./addV3ClientModule";
4+
import { getRequireVariableDeclaration } from "./getRequireVariableDeclaration";
5+
6+
export const addV3ClientRequire = (
7+
j: JSCodeshift,
8+
source: Collection<any>,
9+
{ v2ClientName, v3ClientName, v3ClientPackageName }: AddV3ClientModuleOptions
10+
): void => {
11+
const v3ClientNameIdentifier = j.identifier(v3ClientName);
12+
const v3ClientNameProperty = j.property.from({
13+
kind: "init",
14+
key: v3ClientNameIdentifier,
15+
shorthand: true,
16+
value: v3ClientNameIdentifier,
17+
});
18+
19+
const existingRequires = source.find(j.VariableDeclarator, {
20+
id: { type: "ObjectPattern" },
21+
init: {
22+
type: "CallExpression",
23+
callee: { type: "Identifier", name: "require" },
24+
arguments: [{ type: "Literal", value: v3ClientPackageName }],
25+
},
26+
});
27+
28+
// Require decleration already exists.
29+
if (existingRequires.size()) {
30+
existingRequires.forEach((nodePath) => {
31+
// Append to existing require if property not present.
32+
if (
33+
!(nodePath.value.id as ObjectPattern).properties.find(
34+
(property) => ((property as Property).key as Identifier).name === v3ClientName
35+
)
36+
) {
37+
(nodePath.value.id as ObjectPattern).properties.push(v3ClientNameProperty);
38+
}
39+
});
40+
return;
41+
}
42+
43+
// Insert after default require if present. If not, insert after client require.
44+
const clientRequireValue = `aws-sdk/clients/${v2ClientName.toLowerCase()}`;
45+
const defaultRequireVarDeclaration = getRequireVariableDeclaration(j, source, "aws-sdk");
46+
const clientRequireVarDeclaration = getRequireVariableDeclaration(j, source, clientRequireValue);
47+
48+
const requireVarDeclaration =
49+
defaultRequireVarDeclaration.size() > 0
50+
? defaultRequireVarDeclaration
51+
: clientRequireVarDeclaration;
52+
requireVarDeclaration.insertAfter(
53+
j.variableDeclaration("const", [
54+
j.variableDeclarator(
55+
j.objectPattern([v3ClientNameProperty]),
56+
j.callExpression(j.identifier("require"), [j.literal(v3ClientPackageName)])
57+
),
58+
])
59+
);
60+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Collection, JSCodeshift } from "jscodeshift";
2+
3+
export const containsRequire = (j: JSCodeshift, source: Collection<any>) =>
4+
source
5+
.find(j.CallExpression, {
6+
callee: { type: "Identifier", name: "require" },
7+
})
8+
.size() > 0;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Collection, JSCodeshift } from "jscodeshift";
2+
3+
export const getRequireVariableDeclaration = (
4+
j: JSCodeshift,
5+
source: Collection<any>,
6+
literalValue: string
7+
) =>
8+
source.find(j.VariableDeclaration, {
9+
declarations: [
10+
{
11+
init: {
12+
type: "CallExpression",
13+
callee: { type: "Identifier", name: "require" },
14+
arguments: [{ type: "Literal", value: literalValue }],
15+
},
16+
},
17+
],
18+
});

src/transforms/v2-to-v3/utils/getV2DefaultImportName.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Collection, JSCodeshift } from "jscodeshift";
1+
import { Collection, Identifier, JSCodeshift } from "jscodeshift";
22

33
export const getV2DefaultImportName = (
44
j: JSCodeshift,
@@ -22,5 +22,19 @@ export const getV2DefaultImportName = (
2222
});
2323
});
2424

25+
// Set specifier name in v2DefaultImportName if it is required in the source.
26+
source
27+
.find(j.VariableDeclarator, {
28+
id: { type: "Identifier" },
29+
init: {
30+
type: "CallExpression",
31+
callee: { type: "Identifier", name: "require" },
32+
arguments: [{ type: "Literal", value: "aws-sdk" }],
33+
},
34+
})
35+
.forEach((declerationPath) => {
36+
v2DefaultImportName = (declerationPath.value.id as Identifier).name;
37+
});
38+
2539
return v2DefaultImportName;
2640
};

0 commit comments

Comments
 (0)