diff --git a/.changeset/brave-humans-wonder.md b/.changeset/brave-humans-wonder.md new file mode 100644 index 000000000..202471ff4 --- /dev/null +++ b/.changeset/brave-humans-wonder.md @@ -0,0 +1,5 @@ +--- +"aws-sdk-js-codemod": patch +--- + +Add namespace import instead of default import diff --git a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/global-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/global-import.output.ts index a469f600d..117fc0cd6 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/global-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/global-import.output.ts @@ -1,3 +1,3 @@ -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_S3 from "@aws-sdk/client-s3"; const testTags: AWS_S3.Tag[] = [{ Key: "key", Value: "value" }]; \ No newline at end of file diff --git a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import-deep.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import-deep.output.ts index a469f600d..117fc0cd6 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import-deep.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import-deep.output.ts @@ -1,3 +1,3 @@ -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_S3 from "@aws-sdk/client-s3"; const testTags: AWS_S3.Tag[] = [{ Key: "key", Value: "value" }]; \ No newline at end of file diff --git a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import.output.ts index a469f600d..117fc0cd6 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-basic-type/service-import.output.ts @@ -1,3 +1,3 @@ -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_S3 from "@aws-sdk/client-s3"; const testTags: AWS_S3.Tag[] = [{ Key: "key", Value: "value" }]; \ No newline at end of file diff --git a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/global-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/global-import.output.ts index 7df899c64..eff5c23a2 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/global-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/global-import.output.ts @@ -1,5 +1,14 @@ -import AWS_DynamoDB, { DynamoDB } from "@aws-sdk/client-dynamodb"; -import AWS_STS, { STS } from "@aws-sdk/client-sts"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; + +const { + DynamoDB +} = AWS_DynamoDB; + +import * as AWS_STS from "@aws-sdk/client-sts"; + +const { + STS +} = AWS_STS; const ddbClient = new DynamoDB({ region: "us-west-2" }); const listTablesInput: AWS_DynamoDB.ListTablesCommandInput = { Limit: 10 }; diff --git a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import-deep.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import-deep.output.ts index 7df899c64..eff5c23a2 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import-deep.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import-deep.output.ts @@ -1,5 +1,14 @@ -import AWS_DynamoDB, { DynamoDB } from "@aws-sdk/client-dynamodb"; -import AWS_STS, { STS } from "@aws-sdk/client-sts"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; + +const { + DynamoDB +} = AWS_DynamoDB; + +import * as AWS_STS from "@aws-sdk/client-sts"; + +const { + STS +} = AWS_STS; const ddbClient = new DynamoDB({ region: "us-west-2" }); const listTablesInput: AWS_DynamoDB.ListTablesCommandInput = { Limit: 10 }; diff --git a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import.output.ts index 7df899c64..eff5c23a2 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-input-output-type/service-import.output.ts @@ -1,5 +1,14 @@ -import AWS_DynamoDB, { DynamoDB } from "@aws-sdk/client-dynamodb"; -import AWS_STS, { STS } from "@aws-sdk/client-sts"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; + +const { + DynamoDB +} = AWS_DynamoDB; + +import * as AWS_STS from "@aws-sdk/client-sts"; + +const { + STS +} = AWS_STS; const ddbClient = new DynamoDB({ region: "us-west-2" }); const listTablesInput: AWS_DynamoDB.ListTablesCommandInput = { Limit: 10 }; diff --git a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/global-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/global-import.output.ts index cb67cd821..f8a3b46c7 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/global-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/global-import.output.ts @@ -1,6 +1,6 @@ -import AWS_APIGateway from "@aws-sdk/client-api-gateway"; -import AWS_DynamoDB from "@aws-sdk/client-dynamodb"; -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_APIGateway from "@aws-sdk/client-api-gateway"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; +import * as AWS_S3 from "@aws-sdk/client-s3"; // Native types const stringType: string = "string"; diff --git a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import-deep.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import-deep.output.ts index cb67cd821..f8a3b46c7 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import-deep.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import-deep.output.ts @@ -1,6 +1,6 @@ -import AWS_APIGateway from "@aws-sdk/client-api-gateway"; -import AWS_DynamoDB from "@aws-sdk/client-dynamodb"; -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_APIGateway from "@aws-sdk/client-api-gateway"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; +import * as AWS_S3 from "@aws-sdk/client-s3"; // Native types const stringType: string = "string"; diff --git a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import.output.ts index cb67cd821..f8a3b46c7 100644 --- a/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/api-redundant-type/service-import.output.ts @@ -1,6 +1,6 @@ -import AWS_APIGateway from "@aws-sdk/client-api-gateway"; -import AWS_DynamoDB from "@aws-sdk/client-dynamodb"; -import AWS_S3 from "@aws-sdk/client-s3"; +import * as AWS_APIGateway from "@aws-sdk/client-api-gateway"; +import * as AWS_DynamoDB from "@aws-sdk/client-dynamodb"; +import * as AWS_S3 from "@aws-sdk/client-s3"; // Native types const stringType: string = "string"; diff --git a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/global-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/global-import.output.ts index af033270d..e90f4c8d6 100644 --- a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/global-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/global-import.output.ts @@ -1,4 +1,9 @@ -import AWS_DynamoDBDocumentClient, { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"; +import * as AWS_DynamoDBDocumentClient from "@aws-sdk/lib-dynamodb"; + +const { + DynamoDBDocument +} = AWS_DynamoDBDocumentClient; + import { DynamoDB } from "@aws-sdk/client-dynamodb"; const docClient = DynamoDBDocument.from(new DynamoDB({ region: "us-west-2" })); diff --git a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import-deep.output.ts b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import-deep.output.ts index 2b137fa70..0cb1352a4 100644 --- a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import-deep.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import-deep.output.ts @@ -1,4 +1,9 @@ -import AWS_DynDBDocumentClient, { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"; +import * as AWS_DynDBDocumentClient from "@aws-sdk/lib-dynamodb"; + +const { + DynamoDBDocument +} = AWS_DynDBDocumentClient; + import { DynamoDB as DynDB } from "@aws-sdk/client-dynamodb"; const docClient = DynamoDBDocument.from(new DynDB({ region: "us-west-2" })); diff --git a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import.output.ts b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import.output.ts index 2b137fa70..0cb1352a4 100644 --- a/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import.output.ts +++ b/src/transforms/v2-to-v3/__fixtures__/ddb-doc-client-input-output-type/service-import.output.ts @@ -1,4 +1,9 @@ -import AWS_DynDBDocumentClient, { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"; +import * as AWS_DynDBDocumentClient from "@aws-sdk/lib-dynamodb"; + +const { + DynamoDBDocument +} = AWS_DynDBDocumentClient; + import { DynamoDB as DynDB } from "@aws-sdk/client-dynamodb"; const docClient = DynamoDBDocument.from(new DynDB({ region: "us-west-2" })); diff --git a/src/transforms/v2-to-v3/modules/importModule/addClientDefaultModule.ts b/src/transforms/v2-to-v3/modules/importModule/addClientDefaultModule.ts index 469623d5a..4e5a7b7e9 100644 --- a/src/transforms/v2-to-v3/modules/importModule/addClientDefaultModule.ts +++ b/src/transforms/v2-to-v3/modules/importModule/addClientDefaultModule.ts @@ -11,7 +11,7 @@ export const addClientDefaultModule = ( { v2ClientLocalName, v2ClientName, v3ClientPackageName }: ClientModulesOptions ) => { const defaultLocalName = getDefaultLocalName(v2ClientLocalName); - const defaultImportSpecifier = j.importDefaultSpecifier(j.identifier(defaultLocalName)); + const importNamespaceSpecifier = j.importNamespaceSpecifier(j.identifier(defaultLocalName)); const importDeclarations = source.find(j.ImportDeclaration, { source: { value: v3ClientPackageName }, @@ -23,7 +23,7 @@ export const addClientDefaultModule = ( if (importDeclarations.length) { if (!importDefaultSpecifiers.find((specifier) => specifier?.local?.name === defaultLocalName)) { - importDeclarations.nodes()[0].specifiers?.push(defaultImportSpecifier); + importDeclarations.nodes()[0].specifiers?.push(importNamespaceSpecifier); return; } } @@ -35,7 +35,7 @@ export const addClientDefaultModule = ( }); const v3ImportDeclaration = j.importDeclaration( - [defaultImportSpecifier], + [importNamespaceSpecifier], j.stringLiteral(v3ClientPackageName) ); diff --git a/src/transforms/v2-to-v3/modules/importModule/addClientNamedModule.ts b/src/transforms/v2-to-v3/modules/importModule/addClientNamedModule.ts index 7cbce4194..d054604af 100644 --- a/src/transforms/v2-to-v3/modules/importModule/addClientNamedModule.ts +++ b/src/transforms/v2-to-v3/modules/importModule/addClientNamedModule.ts @@ -1,9 +1,19 @@ -import { Collection, ImportSpecifier, JSCodeshift } from "jscodeshift"; +import { + Collection, + ImportNamespaceSpecifier, + ImportSpecifier, + JSCodeshift, + Property, + ObjectProperty, +} from "jscodeshift"; +import { OBJECT_PROPERTY_TYPE_LIST } from "../../config"; import { getImportDeclaration } from "../getImportDeclaration"; import { getImportSpecifier } from "../getImportSpecifier"; import { getImportSpecifiers } from "../getImportSpecifiers"; +import { getRequireProperty } from "../getRequireProperty"; import { importSpecifierCompareFn } from "../importSpecifierCompareFn"; +import { objectPatternPropertyCompareFn } from "../objectPatternPropertyCompareFn"; import { ClientModulesOptions, ImportSpecifierOptions } from "../types"; export const addClientNamedModule = ( @@ -19,19 +29,78 @@ export const addClientNamedModule = ( }); if (importDeclarations.size()) { - const allImportSpecifiers = getImportSpecifiers(j, source, v3ClientPackageName).filter( - (importSpecifier) => importSpecifier?.type === "ImportSpecifier" - ) as ImportSpecifier[]; + const importSpecifiers = getImportSpecifiers(j, source, v3ClientPackageName); + // Return if the import specifier already exists. if ( - allImportSpecifiers.find( - (specifier) => - specifier?.imported?.name === importedName && specifier?.local?.name === localName - ) + importSpecifiers + .filter((importSpecifier) => importSpecifier?.type === "ImportSpecifier") + .find( + (specifier) => + (specifier as ImportSpecifier)?.imported?.name === importedName && + specifier?.local?.name === localName + ) ) { return; } + const importNamespaceSpecifiers = importSpecifiers.filter( + (importSpecifier) => importSpecifier?.type === "ImportNamespaceSpecifier" + ) as ImportNamespaceSpecifier[]; + + // If namespace import exists. + if (importNamespaceSpecifiers.length > 0) { + const defaultLocalName = importNamespaceSpecifiers[0].local!.name; + const namedImportObjectProperty = getRequireProperty(j, { importedName, localName }); + + const existingVarDeclarator = source.find(j.VariableDeclarator, { + type: "VariableDeclarator", + init: { type: "Identifier", name: defaultLocalName }, + }); + + // If variable declarator exists. + if (existingVarDeclarator.size()) { + // Return if property exists. + if ( + existingVarDeclarator.some((varDeclarator) => { + const id = varDeclarator.node.id; + if (id.type !== "ObjectPattern") return false; + for (const property of id.properties) { + if (!OBJECT_PROPERTY_TYPE_LIST.includes(property.type)) continue; + const propertyKey = (property as Property | ObjectProperty).key; + if (propertyKey.type !== "Identifier") continue; + if (propertyKey.name === importedName) return true; + } + return false; + }) + ) + return; + + // Add property to the first declarator. + const firstDeclaratorProperties = existingVarDeclarator.get(0).node.id.properties; + firstDeclaratorProperties.push(namedImportObjectProperty); + firstDeclaratorProperties.sort(objectPatternPropertyCompareFn); + return; + } + + const varDeclaration = j.variableDeclaration("const", [ + j.variableDeclarator( + j.objectPattern([namedImportObjectProperty]), + j.identifier(defaultLocalName) + ), + ]); + + source + .find(j.ImportDeclaration, { + type: "ImportDeclaration", + specifiers: [importNamespaceSpecifiers[0]], + source: { value: v3ClientPackageName }, + }) + .insertAfter(varDeclaration); + return; + } + + // Add named import to the first import declaration. const firstImportDeclSpecifiers = importDeclarations.nodes()[0].specifiers; if (firstImportDeclSpecifiers) { firstImportDeclSpecifiers.push(getImportSpecifier(j, { importedName, localName }));