Skip to content

Commit 531767c

Browse files
authored
Add input/output types mapping to CLIENT_REQ_RESP_TYPES_MAP (#579)
1 parent 14b438b commit 531767c

File tree

6 files changed

+27790
-30
lines changed

6 files changed

+27790
-30
lines changed

.changeset/neat-dolls-agree.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+
Create input/output types mapping in CLIENT_REQ_RESP_TYPES_MAP
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import jscodeshift, {
2+
Identifier,
3+
TSFunctionType,
4+
TSQualifiedName,
5+
TSTypeReference,
6+
} from "jscodeshift";
7+
8+
import { getTypesSource } from "./getTypesSource";
9+
10+
export const getClientReqRespTypesMap = async (
11+
clientName: string
12+
): Promise<Record<string, string>> => {
13+
const clientTypesMap = {};
14+
15+
const j = jscodeshift.withParser("ts");
16+
const source = getTypesSource(j, clientName);
17+
18+
source.find(j.ClassDeclaration, { id: { name: clientName } }).forEach((classDeclaration) => {
19+
const classMethods = j(classDeclaration).find(j.TSDeclareMethod).nodes();
20+
21+
classMethods.forEach((classMethod) => {
22+
if (classMethod.key.type !== "Identifier") return;
23+
if (classMethod.key.name === "constructor") return;
24+
if (classMethod.key.name.startsWith("waitFor")) return;
25+
26+
const classMethodKeyName = (classMethod.key as Identifier).name;
27+
const commandName = classMethodKeyName.charAt(0).toUpperCase() + classMethodKeyName.slice(1);
28+
29+
if (classMethod.params.length !== 2) return;
30+
if (classMethod.params[0].type !== "Identifier") return;
31+
if (classMethod.params[0].name !== "params") return;
32+
33+
const params = classMethod.params[0] as Identifier;
34+
35+
if (!params.typeAnnotation) return;
36+
if (!params.typeAnnotation.typeAnnotation) return;
37+
if (params.typeAnnotation.typeAnnotation.type !== "TSTypeReference") return;
38+
const paramsTypeRef = params.typeAnnotation!.typeAnnotation! as TSTypeReference;
39+
40+
if (!paramsTypeRef.typeName) return;
41+
if (paramsTypeRef.typeName.type !== "TSQualifiedName") return;
42+
const paramsTypeRefName = paramsTypeRef.typeName as TSQualifiedName;
43+
44+
if (!paramsTypeRefName.right) return;
45+
if (paramsTypeRefName.right.type !== "Identifier") return;
46+
const paramsTypeName = paramsTypeRefName.right as Identifier;
47+
const requestTypeName = paramsTypeName.name;
48+
49+
clientTypesMap[requestTypeName] = `${commandName}CommandInput`;
50+
51+
if (classMethod.params[1].type !== "Identifier") return;
52+
if (classMethod.params[1].name !== "callback") return;
53+
const callback = classMethod.params[1] as Identifier;
54+
55+
if (!callback.typeAnnotation) return;
56+
if (!callback.typeAnnotation.typeAnnotation) return;
57+
if (callback.typeAnnotation.typeAnnotation.type !== "TSFunctionType") return;
58+
const callbackTypeRef = callback.typeAnnotation!.typeAnnotation! as TSFunctionType;
59+
60+
if (!callbackTypeRef.parameters) return;
61+
if (callbackTypeRef.parameters.length !== 2) return;
62+
if (callbackTypeRef.parameters[1].type !== "Identifier") return;
63+
const responseType = callbackTypeRef.parameters[1] as Identifier;
64+
65+
if (!responseType.typeAnnotation) return;
66+
if (responseType.typeAnnotation.type !== "TSTypeAnnotation") return;
67+
if (!responseType.typeAnnotation.typeAnnotation) return;
68+
if (responseType.typeAnnotation.typeAnnotation.type !== "TSTypeReference") return;
69+
const responseTypeRef = responseType.typeAnnotation!.typeAnnotation! as TSTypeReference;
70+
71+
if (!responseTypeRef.typeName) return;
72+
if (responseTypeRef.typeName.type !== "TSQualifiedName") return;
73+
const responseTypeRefName = responseTypeRef.typeName as TSQualifiedName;
74+
75+
if (!responseTypeRefName.right) return;
76+
if (responseTypeRefName.right.type !== "Identifier") return;
77+
const responseTypeName = (responseTypeRefName.right as Identifier).name;
78+
79+
clientTypesMap[responseTypeName] = `${commandName}CommandOutput`;
80+
});
81+
});
82+
83+
return Object.entries(clientTypesMap)
84+
.sort(([key1], [key2]) => key1.localeCompare(key2))
85+
.reduce((obj, [key, value]) => {
86+
obj[key] = value;
87+
return obj;
88+
}, {});
89+
};

scripts/generateClientTypesMap/getClientTypesMap.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { readFile } from "fs/promises";
2-
import { join } from "path";
31
import jscodeshift, { Identifier, TSArrayType, TSTypeLiteral, TSTypeReference } from "jscodeshift";
42

5-
import { DOCUMENT_CLIENT } from "../../src/transforms/v2-to-v3/config";
63
import { getClientTypesMapWithKeysRemovedFromValues } from "./getClientTypesMapWithKeysRemovedFromValues";
4+
import { getTypesSource } from "./getTypesSource";
75

86
const TYPES_TO_SKIP = ["apiVersion", "ClientConfiguration"];
97
const ElementTypeToNativeTypeMap = {
@@ -16,16 +14,8 @@ const ElementTypeToNativeTypeMap = {
1614
export const getClientTypesMap = async (clientName: string): Promise<Record<string, string>> => {
1715
const clientTypesMap = {};
1816

19-
const typesPath =
20-
clientName === DOCUMENT_CLIENT
21-
? join("node_modules", "aws-sdk", "lib", "dynamodb", `document_client.d.ts`)
22-
: join("node_modules", "aws-sdk", "clients", `${clientName.toLowerCase()}.d.ts`);
23-
const relativeTypesPath = join(__dirname, "..", "..", typesPath);
24-
25-
const typesCode = await readFile(relativeTypesPath, "utf8");
26-
2717
const j = jscodeshift.withParser("ts");
28-
const source = j(typesCode);
18+
const source = getTypesSource(j, clientName);
2919

3020
source.find(j.TSModuleDeclaration, { id: { name: clientName } }).forEach((moduleDeclaration) => {
3121
const tsTypes = j(moduleDeclaration).find(j.TSTypeAliasDeclaration).nodes();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { readFileSync } from "fs";
2+
import { join } from "path";
3+
import { JSCodeshift } from "jscodeshift";
4+
import { DOCUMENT_CLIENT } from "../../src/transforms/v2-to-v3/config";
5+
6+
export const getTypesSource = (j: JSCodeshift, clientName: string) => {
7+
const typesPath =
8+
clientName === DOCUMENT_CLIENT
9+
? join("node_modules", "aws-sdk", "lib", "dynamodb", `document_client.d.ts`)
10+
: join("node_modules", "aws-sdk", "clients", `${clientName.toLowerCase()}.d.ts`);
11+
const relativeTypesPath = join(__dirname, "..", "..", typesPath);
12+
13+
const typesCode = readFileSync(relativeTypesPath, "utf8");
14+
15+
return j(typesCode);
16+
};

scripts/generateClientTypesMap/index.ts

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,40 @@ import {
88
DYNAMODB,
99
DYNAMODB_DOCUMENT_CLIENT,
1010
} from "../../src/transforms/v2-to-v3/config";
11+
import { getClientReqRespTypesMap } from "./getClientReqRespTypesMap";
1112
import { getClientTypesMap } from "./getClientTypesMap";
1213

1314
const codegenComment = `// This file is generated by scripts/generateClientTypesMap/index.ts
1415
// Do not edit this file directly. Instead, edit the script and run it to regenerate this file.`;
1516

16-
const filePath = join("src", "transforms", "v2-to-v3", "config", "CLIENT_TYPES_MAP.ts");
17-
const relativeFilePath = join(__dirname, "..", "..", filePath);
18-
1917
(async () => {
20-
let fileContent = codegenComment;
18+
for (const [mapName, getTypesMap] of [
19+
["CLIENT_TYPES_MAP", getClientTypesMap],
20+
["CLIENT_REQ_RESP_TYPES_MAP", getClientReqRespTypesMap],
21+
] as [string, (clientName: string) => Promise<Record<string, string>>][]) {
22+
const filePath = join("src", "transforms", "v2-to-v3", "config", `${mapName}.ts`);
23+
const relativeFilePath = join(__dirname, "..", "..", filePath);
24+
25+
let fileContent = codegenComment;
2126

22-
fileContent += `\n\n/* eslint-disable @typescript-eslint/naming-convention */`;
23-
fileContent += `\nexport const CLIENT_TYPES_MAP: Record<string, Record<string, string>> = `;
27+
fileContent += `\n\n/* eslint-disable @typescript-eslint/naming-convention */`;
28+
fileContent += `\nexport const ${mapName}: Record<string, Record<string, string>> = `;
2429

25-
const clientTypesMap = {};
30+
const clientTypesMap = {};
2631

27-
for (const clientName of CLIENT_NAMES) {
28-
clientTypesMap[clientName] = await getClientTypesMap(clientName);
29-
if (clientName === DYNAMODB) {
30-
clientTypesMap[DYNAMODB_DOCUMENT_CLIENT] = await getClientTypesMap(DOCUMENT_CLIENT);
32+
for (const clientName of CLIENT_NAMES) {
33+
clientTypesMap[clientName] = await getTypesMap(clientName);
34+
if (clientName === DYNAMODB) {
35+
clientTypesMap[DYNAMODB_DOCUMENT_CLIENT] = await getTypesMap(DOCUMENT_CLIENT);
36+
}
3137
}
32-
}
3338

34-
fileContent += JSON.stringify(clientTypesMap);
35-
fileContent += `;\n`;
39+
fileContent += JSON.stringify(clientTypesMap);
40+
fileContent += `;\n`;
3641

37-
await writeFile(
38-
relativeFilePath,
39-
await format(fileContent, { parser: "typescript", printWidth: 100 })
40-
);
42+
await writeFile(
43+
relativeFilePath,
44+
await format(fileContent, { parser: "typescript", printWidth: 100 })
45+
);
46+
}
4147
})();

0 commit comments

Comments
 (0)