Skip to content

Commit

Permalink
Copy code with basic transformation of v2 to v3 (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr committed Mar 3, 2022
1 parent dbd8346 commit e13f64c
Show file tree
Hide file tree
Showing 18 changed files with 628 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/great-jeans-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"aws-sdk-js-codemod": patch
---

Copy code which performs basic transformation of AWS SDK for JavaScript client from v2 to v3
8 changes: 8 additions & 0 deletions src/transforms/v2-to-v3/__testfixtures__/basic.input.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import AWS from "aws-sdk";

const region = "us-west-2";
const client = new AWS.DynamoDB({ region });
client.listTables({}, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});
10 changes: 10 additions & 0 deletions src/transforms/v2-to-v3/__testfixtures__/basic.output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import AWS from "aws-sdk";

import { DynamoDB } from "@aws-sdk/client-dynamodb";

const region = "us-west-2";
const client = new DynamoDB({ region });
client.listTables({}, function(err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});
4 changes: 4 additions & 0 deletions src/transforms/v2-to-v3/__tests__/transformer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @ts-expects-error Could not find a declaration file for module
import { defineTest } from "jscodeshift/dist/testUtils";

defineTest(__dirname, "./transformer", null, "basic", { parser: "ts" });
22 changes: 22 additions & 0 deletions src/transforms/v2-to-v3/helpers/addV3ClientImport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Collection, JSCodeshift } from "jscodeshift";

export interface AddV3ClientImportOptions {
v3ClientName: string;
v3ClientPackageName: string;
}

export const addV3ClientImport = (
j: JSCodeshift,
source: Collection<any>,
{ v3ClientName, v3ClientPackageName }: AddV3ClientImportOptions
): void => {
source
.find(j.ImportDeclaration)
.filter((path) => path.value.source.value === "aws-sdk")
.insertAfter(
j.importDeclaration(
[j.importSpecifier(j.identifier(v3ClientName))],
j.stringLiteral(v3ClientPackageName)
)
);
};
19 changes: 19 additions & 0 deletions src/transforms/v2-to-v3/helpers/getV2ClientNames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Collection, Identifier, JSCodeshift, MemberExpression } from "jscodeshift";

export const getV2ClientNames = (
j: JSCodeshift,
source: Collection<any>,
importObj: Identifier
): Array<string> =>
source
.find(j.NewExpression, {
callee: {
type: "MemberExpression",
object: { type: "Identifier", name: importObj.name },
property: { type: "Identifier" },
},
})
.nodes()
.map(
(newExpression) => ((newExpression.callee as MemberExpression).property as Identifier).name
);
3 changes: 3 additions & 0 deletions src/transforms/v2-to-v3/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./addV3ClientImport";
export * from "./getV2ClientNames";
export * from "./replaceClientCreation";
27 changes: 27 additions & 0 deletions src/transforms/v2-to-v3/helpers/replaceClientCreation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Collection, Identifier, JSCodeshift } from "jscodeshift";

export interface ReplaceClientCreationOptions {
importObj: Identifier;
v2ClientName: string;
v3ClientName: string;
}

// Replace v2 client creation with v3 client creation.
export const replaceClientCreation = (
j: JSCodeshift,
source: Collection<any>,
{ importObj, v2ClientName, v3ClientName }: ReplaceClientCreationOptions
): void => {
source
.find(j.NewExpression, {
callee: {
object: { type: "Identifier", name: importObj.name },
property: { type: "Identifier", name: v2ClientName },
},
})
.replaceWith((nodePath) => {
const { node } = nodePath;
node.callee = j.identifier(v3ClientName);
return node;
});
};
23 changes: 20 additions & 3 deletions src/transforms/v2-to-v3/transformer.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { API, FileInfo } from "jscodeshift";
import findImports from "jscodeshift-find-imports";

import { addV3ClientImport, getV2ClientNames, replaceClientCreation } from "./helpers";
import { getV3ClientName, getV3ClientPackageName } from "./utils";

export default function transformer(file: FileInfo, api: API) {
const j = api.jscodeshift;
const root = j(file.source);
const { statement } = j.template;
const source = j(file.source);

const imports = findImports(source, statement`import AWS from 'aws-sdk'`);
for (const importObj of Object.values(imports)) {
if (importObj.type === "Identifier") {
const v2ClientNames = getV2ClientNames(j, source, importObj);

// transform `root` here
for (const v2ClientName of v2ClientNames) {
const v3ClientName = getV3ClientName(v2ClientName);
const v3ClientPackageName = getV3ClientPackageName(v2ClientName);
addV3ClientImport(j, source, { v3ClientName, v3ClientPackageName });
replaceClientCreation(j, source, { importObj, v2ClientName, v3ClientName });
}
}
}

return root.toSource();
return source.toSource();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CLIENT_PACKAGE_NAMES_MAP } from "../config";
import { getV3ClientPackageName } from "../getV3ClientPackageName";

describe(getV3ClientPackageName.name, () => {
it.each(Object.entries(CLIENT_PACKAGE_NAMES_MAP))(
"getClientName('%s') === '%s'",
(input, output) => {
expect(getV3ClientPackageName(input)).toBe(`@aws-sdk/${output}`);
}
);

it.each(["ImportExport", "MobileAnalytics", "SimpleDB"])(
"throws for deprecated client '%s'",
(deprecatedClient) => {
expect(() => {
getV3ClientPackageName(deprecatedClient);
}).toThrow(new Error(`Client '${deprecatedClient}' is either deprecated or newly added.`));
}
);

it.each(["UNDEFINED", "NULL", "UNKNOWN"])("throws for unknown client '%s'", (unknownClient) => {
expect(() => {
getV3ClientPackageName(unknownClient);
}).toThrow(new Error(`Client '${unknownClient}' is either deprecated or newly added.`));
});
});
23 changes: 23 additions & 0 deletions src/transforms/v2-to-v3/utils/__tests__/getV3ClientName.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { CLIENT_NAMES_MAP } from "../config";
import { getV3ClientName } from "../getV3ClientName";

describe(getV3ClientName.name, () => {
it.each(Object.entries(CLIENT_NAMES_MAP))("getV3ClientName('%s') === '%s'", (input, output) => {
expect(getV3ClientName(input)).toBe(output);
});

it.each(["ImportExport", "MobileAnalytics", "SimpleDB"])(
"throws for deprecated client '%s'",
(deprecatedClient) => {
expect(() => {
getV3ClientName(deprecatedClient);
}).toThrow(new Error(`Client '${deprecatedClient}' is either deprecated or newly added.`));
}
);

it.each(["UNDEFINED", "NULL", "UNKNOWN"])("throws for unknown client '%s'", (unknownClient) => {
expect(() => {
getV3ClientName(unknownClient);
}).toThrow(new Error(`Client '${unknownClient}' is either deprecated or newly added.`));
});
});
Loading

0 comments on commit e13f64c

Please sign in to comment.