diff --git a/.changeset/green-flies-sell.md b/.changeset/green-flies-sell.md new file mode 100644 index 000000000..d81c33d38 --- /dev/null +++ b/.changeset/green-flies-sell.md @@ -0,0 +1,5 @@ +--- +"aws-sdk-js-codemod": patch +--- + +Add transformation for AWS.CredentialProviderChain diff --git a/src/transforms/v2-to-v3/__fixtures__/credentials/chain.input.js b/src/transforms/v2-to-v3/__fixtures__/credentials/chain.input.js new file mode 100644 index 000000000..aa9b174e0 --- /dev/null +++ b/src/transforms/v2-to-v3/__fixtures__/credentials/chain.input.js @@ -0,0 +1,3 @@ +import AWS from "aws-sdk"; + +new AWS.CredentialProviderChain(providers); \ No newline at end of file diff --git a/src/transforms/v2-to-v3/__fixtures__/credentials/chain.output.js b/src/transforms/v2-to-v3/__fixtures__/credentials/chain.output.js new file mode 100644 index 000000000..4b7d30460 --- /dev/null +++ b/src/transforms/v2-to-v3/__fixtures__/credentials/chain.output.js @@ -0,0 +1,6 @@ +import { chain as providerChain } from "@smithy/property-provider"; + +// JS SDK v3 switched to credential providers to functions instead of objects. +// The CredentialProviderChain is now a chain of providers. +// Reference: https://www.npmjs.com/package/@aws-sdk/credential-providers +providerChain(providers); \ No newline at end of file diff --git a/src/transforms/v2-to-v3/apis/getAwsCredentialsNewExpressions.ts b/src/transforms/v2-to-v3/apis/getAwsCredentialsNewExpressions.ts deleted file mode 100644 index fa5f24971..000000000 --- a/src/transforms/v2-to-v3/apis/getAwsCredentialsNewExpressions.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Collection, JSCodeshift } from "jscodeshift"; - -export interface GetAwsCredentialsNewExpressionOptions { - v2GlobalName: string; - className: string; -} - -export const getAwsCredentialsNewExpressions = ( - j: JSCodeshift, - source: Collection, - { v2GlobalName, className }: GetAwsCredentialsNewExpressionOptions -) => - source.find(j.NewExpression, { - type: "NewExpression", - callee: { - type: "MemberExpression", - object: { - type: "Identifier", - name: v2GlobalName, - }, - property: { name: className }, - }, - }); diff --git a/src/transforms/v2-to-v3/apis/index.ts b/src/transforms/v2-to-v3/apis/index.ts index dbce9211d..120dfd0f1 100644 --- a/src/transforms/v2-to-v3/apis/index.ts +++ b/src/transforms/v2-to-v3/apis/index.ts @@ -6,7 +6,7 @@ export * from "./getS3SignedUrlApiNames"; export * from "./isS3GetSignedUrlApiUsed"; export * from "./isS3UploadApiUsed"; export * from "./removePromiseCalls"; -export * from "./replaceAwsCredentials"; +export * from "./replaceAwsIdentity"; export * from "./replaceS3GetSignedUrlApi"; export * from "./replaceS3UploadApi"; export * from "./replaceWaiterApi"; diff --git a/src/transforms/v2-to-v3/apis/replaceAwsCredentials.ts b/src/transforms/v2-to-v3/apis/replaceAwsCredentials.ts deleted file mode 100644 index 5333d6e2e..000000000 --- a/src/transforms/v2-to-v3/apis/replaceAwsCredentials.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Collection, JSCodeshift } from "jscodeshift"; -import { AWS_CREDENTIALS_MAP } from "../config"; -import { ImportType, addNamedModule } from "../modules"; -import { getAwsCredentialsNewExpressions } from "./getAwsCredentialsNewExpressions"; - -export interface ReplaceAwsCredentialsOptions { - v2GlobalName?: string; - importType: ImportType; -} - -export const replaceAwsCredentials = ( - j: JSCodeshift, - source: Collection, - { v2GlobalName, importType }: ReplaceAwsCredentialsOptions -) => { - if (!v2GlobalName) return; - - for (const [v2CredentialsName, v3ProviderName] of Object.entries(AWS_CREDENTIALS_MAP)) { - const credsNewExpressions = getAwsCredentialsNewExpressions(j, source, { - v2GlobalName, - className: v2CredentialsName, - }); - const credsNewExpressionCount = credsNewExpressions.size(); - - if (credsNewExpressionCount > 0) { - addNamedModule(j, source, { - importType, - importedName: v3ProviderName, - packageName: "@aws-sdk/credential-providers", - }); - credsNewExpressions.replaceWith(({ node }) => - j.callExpression.from({ - callee: j.identifier(v3ProviderName), - comments: [ - j.commentLine( - " JS SDK v3 switched to credential providers to functions instead of objects." - ), - j.commentLine( - " This is the closest approximation from codemod of what your application needs." - ), - j.commentLine( - " Reference: https://www.npmjs.com/package/@aws-sdk/credential-providers" - ), - ], - arguments: node.arguments, - }) - ); - } - } -}; diff --git a/src/transforms/v2-to-v3/apis/replaceAwsIdentity.ts b/src/transforms/v2-to-v3/apis/replaceAwsIdentity.ts new file mode 100644 index 000000000..3b6a99788 --- /dev/null +++ b/src/transforms/v2-to-v3/apis/replaceAwsIdentity.ts @@ -0,0 +1,88 @@ +import { Collection, JSCodeshift, NewExpression } from "jscodeshift"; +import { AWS_CREDENTIALS_MAP } from "../config"; +import { ImportType, addNamedModule } from "../modules"; + +export interface ReplaceAwsCredentialsOptions { + v2GlobalName?: string; + importType: ImportType; +} + +const PROVIDER_SWITCH_COMMENT = ` JS SDK v3 switched to credential providers to functions instead of objects.`; + +const getNewExpression = (identifier: string, className: string) => + ({ + type: "NewExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + name: identifier, + }, + property: { name: className }, + }, + }) as NewExpression; + +export const replaceAwsIdentity = ( + j: JSCodeshift, + source: Collection, + { v2GlobalName, importType }: ReplaceAwsCredentialsOptions +) => { + if (!v2GlobalName) return; + + // ToDo: Add support for AWS.TokenProviderChain in future. + const chainNewExpressions = source.find( + j.NewExpression, + getNewExpression(v2GlobalName, "CredentialProviderChain") + ); + if (chainNewExpressions.size() > 0) { + const localName = "providerChain"; + addNamedModule(j, source, { + importType, + localName, + importedName: "chain", + packageName: "@smithy/property-provider", + }); + chainNewExpressions.replaceWith(({ node }) => + j.callExpression.from({ + callee: j.identifier(localName), + comments: [ + j.commentLine(PROVIDER_SWITCH_COMMENT), + j.commentLine(" The CredentialProviderChain is now a chain of providers."), + j.commentLine(" Reference: https://www.npmjs.com/package/@aws-sdk/credential-providers"), + ], + arguments: node.arguments, + }) + ); + } + + // ToDo: Add support for AWS.Token in future. + for (const [v2CredentialsName, v3ProviderName] of Object.entries(AWS_CREDENTIALS_MAP)) { + const credsNewExpressions = source.find( + j.NewExpression, + getNewExpression(v2GlobalName, v2CredentialsName) + ); + + if (credsNewExpressions.size() > 0) { + addNamedModule(j, source, { + importType, + importedName: v3ProviderName, + packageName: "@aws-sdk/credential-providers", + }); + credsNewExpressions.replaceWith(({ node }) => + j.callExpression.from({ + callee: j.identifier(v3ProviderName), + comments: [ + j.commentLine(PROVIDER_SWITCH_COMMENT), + j.commentLine( + " This is the closest approximation from codemod of what your application needs." + ), + j.commentLine( + " Reference: https://www.npmjs.com/package/@aws-sdk/credential-providers" + ), + ], + arguments: node.arguments, + }) + ); + } + } +}; diff --git a/src/transforms/v2-to-v3/transformer.ts b/src/transforms/v2-to-v3/transformer.ts index 1e387b474..96ac20cb6 100644 --- a/src/transforms/v2-to-v3/transformer.ts +++ b/src/transforms/v2-to-v3/transformer.ts @@ -8,7 +8,7 @@ import { replaceS3UploadApi, replaceS3GetSignedUrlApi, getClientIdentifiersRecord, - replaceAwsCredentials, + replaceAwsIdentity, } from "./apis"; import { replaceAwsUtilFunctions } from "./aws-util"; import { replaceClientCreation, replaceDocClientCreation } from "./client-instances"; @@ -92,7 +92,7 @@ const transformer = async (file: FileInfo, api: API) => { replaceClientCreation(j, source, { ...v2Options, v3ClientName }); replaceDocClientCreation(j, source, v2Options); } - replaceAwsCredentials(j, source, { v2GlobalName, importType }); + replaceAwsIdentity(j, source, { v2GlobalName, importType }); replaceAwsUtilFunctions(j, source, v2GlobalName); removeGlobalModule(j, source, { v2GlobalName, importType });