Skip to content

Commit e13f64c

Browse files
authored
Copy code with basic transformation of v2 to v3 (#14)
1 parent dbd8346 commit e13f64c

18 files changed

+628
-3
lines changed

.changeset/great-jeans-explain.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": patch
3+
---
4+
5+
Copy code which performs basic transformation of AWS SDK for JavaScript client from v2 to v3
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import AWS from "aws-sdk";
2+
3+
const region = "us-west-2";
4+
const client = new AWS.DynamoDB({ region });
5+
client.listTables({}, function(err, data) {
6+
if (err) console.log(err, err.stack);
7+
else console.log(data);
8+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import AWS from "aws-sdk";
2+
3+
import { DynamoDB } from "@aws-sdk/client-dynamodb";
4+
5+
const region = "us-west-2";
6+
const client = new DynamoDB({ region });
7+
client.listTables({}, function(err, data) {
8+
if (err) console.log(err, err.stack);
9+
else console.log(data);
10+
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// @ts-expects-error Could not find a declaration file for module
2+
import { defineTest } from "jscodeshift/dist/testUtils";
3+
4+
defineTest(__dirname, "./transformer", null, "basic", { parser: "ts" });
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Collection, JSCodeshift } from "jscodeshift";
2+
3+
export interface AddV3ClientImportOptions {
4+
v3ClientName: string;
5+
v3ClientPackageName: string;
6+
}
7+
8+
export const addV3ClientImport = (
9+
j: JSCodeshift,
10+
source: Collection<any>,
11+
{ v3ClientName, v3ClientPackageName }: AddV3ClientImportOptions
12+
): void => {
13+
source
14+
.find(j.ImportDeclaration)
15+
.filter((path) => path.value.source.value === "aws-sdk")
16+
.insertAfter(
17+
j.importDeclaration(
18+
[j.importSpecifier(j.identifier(v3ClientName))],
19+
j.stringLiteral(v3ClientPackageName)
20+
)
21+
);
22+
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Collection, Identifier, JSCodeshift, MemberExpression } from "jscodeshift";
2+
3+
export const getV2ClientNames = (
4+
j: JSCodeshift,
5+
source: Collection<any>,
6+
importObj: Identifier
7+
): Array<string> =>
8+
source
9+
.find(j.NewExpression, {
10+
callee: {
11+
type: "MemberExpression",
12+
object: { type: "Identifier", name: importObj.name },
13+
property: { type: "Identifier" },
14+
},
15+
})
16+
.nodes()
17+
.map(
18+
(newExpression) => ((newExpression.callee as MemberExpression).property as Identifier).name
19+
);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from "./addV3ClientImport";
2+
export * from "./getV2ClientNames";
3+
export * from "./replaceClientCreation";
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Collection, Identifier, JSCodeshift } from "jscodeshift";
2+
3+
export interface ReplaceClientCreationOptions {
4+
importObj: Identifier;
5+
v2ClientName: string;
6+
v3ClientName: string;
7+
}
8+
9+
// Replace v2 client creation with v3 client creation.
10+
export const replaceClientCreation = (
11+
j: JSCodeshift,
12+
source: Collection<any>,
13+
{ importObj, v2ClientName, v3ClientName }: ReplaceClientCreationOptions
14+
): void => {
15+
source
16+
.find(j.NewExpression, {
17+
callee: {
18+
object: { type: "Identifier", name: importObj.name },
19+
property: { type: "Identifier", name: v2ClientName },
20+
},
21+
})
22+
.replaceWith((nodePath) => {
23+
const { node } = nodePath;
24+
node.callee = j.identifier(v3ClientName);
25+
return node;
26+
});
27+
};
Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,27 @@
11
import { API, FileInfo } from "jscodeshift";
2+
import findImports from "jscodeshift-find-imports";
3+
4+
import { addV3ClientImport, getV2ClientNames, replaceClientCreation } from "./helpers";
5+
import { getV3ClientName, getV3ClientPackageName } from "./utils";
26

37
export default function transformer(file: FileInfo, api: API) {
48
const j = api.jscodeshift;
5-
const root = j(file.source);
9+
const { statement } = j.template;
10+
const source = j(file.source);
11+
12+
const imports = findImports(source, statement`import AWS from 'aws-sdk'`);
13+
for (const importObj of Object.values(imports)) {
14+
if (importObj.type === "Identifier") {
15+
const v2ClientNames = getV2ClientNames(j, source, importObj);
616

7-
// transform `root` here
17+
for (const v2ClientName of v2ClientNames) {
18+
const v3ClientName = getV3ClientName(v2ClientName);
19+
const v3ClientPackageName = getV3ClientPackageName(v2ClientName);
20+
addV3ClientImport(j, source, { v3ClientName, v3ClientPackageName });
21+
replaceClientCreation(j, source, { importObj, v2ClientName, v3ClientName });
22+
}
23+
}
24+
}
825

9-
return root.toSource();
26+
return source.toSource();
1027
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { CLIENT_PACKAGE_NAMES_MAP } from "../config";
2+
import { getV3ClientPackageName } from "../getV3ClientPackageName";
3+
4+
describe(getV3ClientPackageName.name, () => {
5+
it.each(Object.entries(CLIENT_PACKAGE_NAMES_MAP))(
6+
"getClientName('%s') === '%s'",
7+
(input, output) => {
8+
expect(getV3ClientPackageName(input)).toBe(`@aws-sdk/${output}`);
9+
}
10+
);
11+
12+
it.each(["ImportExport", "MobileAnalytics", "SimpleDB"])(
13+
"throws for deprecated client '%s'",
14+
(deprecatedClient) => {
15+
expect(() => {
16+
getV3ClientPackageName(deprecatedClient);
17+
}).toThrow(new Error(`Client '${deprecatedClient}' is either deprecated or newly added.`));
18+
}
19+
);
20+
21+
it.each(["UNDEFINED", "NULL", "UNKNOWN"])("throws for unknown client '%s'", (unknownClient) => {
22+
expect(() => {
23+
getV3ClientPackageName(unknownClient);
24+
}).toThrow(new Error(`Client '${unknownClient}' is either deprecated or newly added.`));
25+
});
26+
});

0 commit comments

Comments
 (0)