From f4ab3d067b0a7c70ba96ad827be4efaa5d0eb485 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Tue, 28 Mar 2023 20:28:08 +0200 Subject: [PATCH 1/5] feat: stronger types for SSM getParameter --- packages/parameters/src/ssm/SSMProvider.ts | 14 +++++----- packages/parameters/src/ssm/getParameter.ts | 14 ++++++---- packages/parameters/src/types/SSMProvider.ts | 27 ++++++++++++++++++-- 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index 14fd6793c2..d13abf8a5c 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -16,7 +16,9 @@ import type { import type { SSMProviderOptions, SSMGetMultipleOptionsInterface, - SSMGetOptionsInterface, + SSMGetOptions, + SSMGetOptionsUnion, + SSMGetOutput, SSMGetParametersByNameOutputInterface, SSMGetParametersByNameOptionsInterface, SSMSplitBatchAndDecryptParametersOutputType, @@ -315,11 +317,11 @@ class SSMProvider extends BaseProvider { * @param {SSMGetOptionsInterface} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ - public async get( + public async get( name: string, - options?: SSMGetOptionsInterface | undefined - ): Promise | undefined> { - return super.get(name, options) as Promise | undefined>; + options?: O & SSMGetOptions + ): Promise | undefined> { + return super.get(name, options) as Promise | undefined>; } /** @@ -471,7 +473,7 @@ class SSMProvider extends BaseProvider { */ protected async _get( name: string, - options?: SSMGetOptionsInterface + options?: SSMGetOptions ): Promise { const sdkOptions: GetParameterCommandInput = { ...(options?.sdkOptions || {}), diff --git a/packages/parameters/src/ssm/getParameter.ts b/packages/parameters/src/ssm/getParameter.ts index 12b09e0c08..f15e022bb1 100644 --- a/packages/parameters/src/ssm/getParameter.ts +++ b/packages/parameters/src/ssm/getParameter.ts @@ -1,5 +1,9 @@ import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider'; -import type { SSMGetOptionsInterface } from '../types/SSMProvider'; +import type { + SSMGetOptions, + SSMGetOptionsUnion, + SSMGetOutput, +} from '../types/SSMProvider'; /** * ## Intro @@ -136,15 +140,15 @@ import type { SSMGetOptionsInterface } from '../types/SSMProvider'; * @param {SSMGetOptionsInterface} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ -const getParameter = ( +const getParameter = ( name: string, - options?: SSMGetOptionsInterface -): Promise> => { + options?: O & SSMGetOptions +): Promise | undefined> => { if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) { DEFAULT_PROVIDERS.ssm = new SSMProvider(); } - return (DEFAULT_PROVIDERS.ssm as SSMProvider).get(name, options); + return (DEFAULT_PROVIDERS.ssm as SSMProvider).get(name, options) as Promise | undefined>; }; export { diff --git a/packages/parameters/src/types/SSMProvider.ts b/packages/parameters/src/types/SSMProvider.ts index 36d5f85cb3..2e55b63fd7 100644 --- a/packages/parameters/src/types/SSMProvider.ts +++ b/packages/parameters/src/types/SSMProvider.ts @@ -54,11 +54,32 @@ type SSMProviderOptions = SSMProviderOptionsWithClientConfig | SSMProviderOption * @property {TransformOptions} transform - Transform to be applied, can be 'json' or 'binary'. * @property {boolean} decrypt - If true, the parameter will be decrypted. */ -interface SSMGetOptionsInterface extends GetOptionsInterface { +interface SSMGetOptions extends GetOptionsInterface { decrypt?: boolean sdkOptions?: Partial } +interface SSMGetOptionsTransformJson extends SSMGetOptions { + transform: 'json' +} + +interface SSMGetOptionsTransformBinary extends SSMGetOptions { + transform: 'binary' +} + +interface SSMGetOptionsTransformNone extends SSMGetOptions { + transform?: never +} + +type SSMGetOptionsUnion = SSMGetOptionsTransformJson | SSMGetOptionsTransformBinary | SSMGetOptionsTransformNone | undefined; + +type SSMGetOutput = + undefined extends O ? string : + O extends SSMGetOptionsTransformNone | SSMGetOptionsTransformBinary ? string : + // eslint-disable-next-line @typescript-eslint/no-explicit-any + O extends SSMGetOptionsTransformJson ? Record : + never; + /** * Options for the SSMProvider getMultiple method. * @@ -121,7 +142,9 @@ type SSMGetParametersByNameFromCacheOutputType = { export type { SSMProviderOptions, - SSMGetOptionsInterface, + SSMGetOptions, + SSMGetOptionsUnion, + SSMGetOutput, SSMGetMultipleOptionsInterface, SSMGetParametersByNameOptionsInterface, SSMSplitBatchAndDecryptParametersOutputType, From f18af60a0b9829e89ca1bfc0d3f31832e4ad9c23 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 29 Mar 2023 16:15:59 +0200 Subject: [PATCH 2/5] feat: improved types for getParameters --- packages/parameters/src/ssm/SSMProvider.ts | 22 +++++---- packages/parameters/src/ssm/getParameter.ts | 6 ++- packages/parameters/src/ssm/getParameters.ts | 18 ++++--- packages/parameters/src/types/SSMProvider.ts | 49 ++++++++++++++++++-- 4 files changed, 73 insertions(+), 22 deletions(-) diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index d13abf8a5c..c276e44f35 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -15,10 +15,12 @@ import type { } from '@aws-sdk/client-ssm'; import type { SSMProviderOptions, - SSMGetMultipleOptionsInterface, SSMGetOptions, SSMGetOptionsUnion, SSMGetOutput, + SSMGetMultipleOptions, + SSMGetMultipleOptionsUnion, + SSMGetMultipleOutput, SSMGetParametersByNameOutputInterface, SSMGetParametersByNameOptionsInterface, SSMSplitBatchAndDecryptParametersOutputType, @@ -314,7 +316,7 @@ class SSMProvider extends BaseProvider { * For usage examples check {@link SSMProvider}. * * @param {string} name - The name of the value to retrieve (i.e. the partition key) - * @param {SSMGetOptionsInterface} options - Options to configure the provider + * @param {SSMGetOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ public async get( @@ -351,14 +353,14 @@ class SSMProvider extends BaseProvider { * For usage examples check {@link SSMProvider}. * * @param {string} path - The path of the parameters to retrieve - * @param {SSMGetMultipleOptionsInterface} options - Options to configure the retrieval + * @param {SSMGetMultipleOptions} options - Options to configure the retrieval * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ - public async getMultiple( + public async getMultiple( path: string, - options?: SSMGetMultipleOptionsInterface | undefined - ): Promise> { - return super.getMultiple(path, options); + options?: O & SSMGetMultipleOptions + ): Promise | undefined> { + return super.getMultiple(path, options) as Promise | undefined>; } /** @@ -469,7 +471,7 @@ class SSMProvider extends BaseProvider { * Retrieve a parameter from AWS Systems Manager. * * @param {string} name - Name of the parameter to retrieve - * @param {SSMGetOptionsInterface} options - Options to customize the retrieval + * @param {SSMGetOptions} options - Options to customize the retrieval */ protected async _get( name: string, @@ -489,11 +491,11 @@ class SSMProvider extends BaseProvider { * Retrieve multiple items from AWS Systems Manager. * * @param {string} path - The path of the parameters to retrieve - * @param {SSMGetMultipleOptionsInterface} options - Options to configure the provider + * @param {SSMGetMultipleOptions} options - Options to configure the provider */ protected async _getMultiple( path: string, - options?: SSMGetMultipleOptionsInterface + options?: SSMGetMultipleOptions ): Promise> { const sdkOptions: GetParametersByPathCommandInput = { ...(options?.sdkOptions || {}), diff --git a/packages/parameters/src/ssm/getParameter.ts b/packages/parameters/src/ssm/getParameter.ts index f15e022bb1..1769ebea2f 100644 --- a/packages/parameters/src/ssm/getParameter.ts +++ b/packages/parameters/src/ssm/getParameter.ts @@ -137,7 +137,7 @@ import type { * For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/). * * @param {string} name - The name of the parameter to retrieve - * @param {SSMGetOptionsInterface} options - Options to configure the provider + * @param {SSMGetOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ const getParameter = ( @@ -148,7 +148,9 @@ const getParameter = ( DEFAULT_PROVIDERS.ssm = new SSMProvider(); } - return (DEFAULT_PROVIDERS.ssm as SSMProvider).get(name, options) as Promise | undefined>; + return ( + DEFAULT_PROVIDERS.ssm as SSMProvider + ).get(name, options) as Promise | undefined>; }; export { diff --git a/packages/parameters/src/ssm/getParameters.ts b/packages/parameters/src/ssm/getParameters.ts index e93daf1ea8..ede4f3e614 100644 --- a/packages/parameters/src/ssm/getParameters.ts +++ b/packages/parameters/src/ssm/getParameters.ts @@ -1,5 +1,9 @@ import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider'; -import type { SSMGetMultipleOptionsInterface } from '../types/SSMProvider'; +import type { + SSMGetMultipleOptions, + SSMGetMultipleOptionsUnion, + SSMGetMultipleOutput, +} from '../types/SSMProvider'; /** * ## Intro @@ -134,18 +138,20 @@ import type { SSMGetMultipleOptionsInterface } from '../types/SSMProvider'; * For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/). * * @param {string} path - The path of the parameters to retrieve - * @param {SSMGetMultipleOptionsInterface} options - Options to configure the provider + * @param {SSMGetMultipleOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ -const getParameters = ( +const getParameters = ( path: string, - options?: SSMGetMultipleOptionsInterface -): Promise> => { + options?: O & SSMGetMultipleOptions +): Promise | undefined> => { if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) { DEFAULT_PROVIDERS.ssm = new SSMProvider(); } - return (DEFAULT_PROVIDERS.ssm as SSMProvider).getMultiple(path, options); + return ( + DEFAULT_PROVIDERS.ssm as SSMProvider + ).getMultiple(path, options) as Promise | undefined>; }; export { diff --git a/packages/parameters/src/types/SSMProvider.ts b/packages/parameters/src/types/SSMProvider.ts index 2e55b63fd7..292ed5a828 100644 --- a/packages/parameters/src/types/SSMProvider.ts +++ b/packages/parameters/src/types/SSMProvider.ts @@ -50,12 +50,18 @@ type SSMProviderOptions = SSMProviderOptionsWithClientConfig | SSMProviderOption * @extends {GetOptionsInterface} * @property {number} maxAge - Maximum age of the value in the cache, in seconds. * @property {boolean} forceFetch - Force fetch the value from the parameter store, ignoring the cache. - * @property {GetItemCommandInput} [sdkOptions] - Additional options to pass to the AWS SDK v3 client. + * @property {GetItemCommandInput} [sdkOptions] - Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParameterCommandInput`. * @property {TransformOptions} transform - Transform to be applied, can be 'json' or 'binary'. - * @property {boolean} decrypt - If true, the parameter will be decrypted. + * @property {boolean} decrypt - If true, the parameter will be decrypted. Defaults to `false`. */ interface SSMGetOptions extends GetOptionsInterface { + /** + * If true, the parameter will be decrypted. Defaults to `false`. + */ decrypt?: boolean + /** + * Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParameterCommandInput`. + */ sdkOptions?: Partial } @@ -93,13 +99,46 @@ type SSMGetOutput = * @property {boolean} recursive - If true, the parameter will be fetched recursively. * @property {boolean} throwOnTransformError - If true, the method will throw an error if the transform fails. */ -interface SSMGetMultipleOptionsInterface extends GetMultipleOptionsInterface { +interface SSMGetMultipleOptions extends GetMultipleOptionsInterface { + /** + * Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParametersByPathCommandInput`. + */ sdkOptions?: Partial + /** + * If true, the parameters will be decrypted. Defaults to `false`. + */ decrypt?: boolean + /** + * If true, the parameters will be fetched recursively. Defaults to `false`. + */ recursive?: boolean + /** + * If true, the method will throw an error if the transform fails. + */ throwOnTransformError?: boolean } +interface SSMGetMultipleOptionsTransformJson extends SSMGetMultipleOptions { + transform: 'json' +} + +interface SSMGetMultipleOptionsTransformBinary extends SSMGetMultipleOptions { + transform: 'binary' +} + +interface SSMGetMultipleOptionsTransformNone extends SSMGetMultipleOptions { + transform?: never +} + +type SSMGetMultipleOptionsUnion = SSMGetMultipleOptionsTransformJson | SSMGetMultipleOptionsTransformBinary | SSMGetMultipleOptionsTransformNone | undefined; + +type SSMGetMultipleOutput = + undefined extends O ? Record : + O extends SSMGetMultipleOptionsTransformNone | SSMGetMultipleOptionsTransformBinary ? Record : + // eslint-disable-next-line @typescript-eslint/no-explicit-any + O extends SSMGetMultipleOptionsTransformJson ? Record> : + never; + /** * Options for the SSMProvider getParametersByName method. * @@ -145,7 +184,9 @@ export type { SSMGetOptions, SSMGetOptionsUnion, SSMGetOutput, - SSMGetMultipleOptionsInterface, + SSMGetMultipleOptions, + SSMGetMultipleOptionsUnion, + SSMGetMultipleOutput, SSMGetParametersByNameOptionsInterface, SSMSplitBatchAndDecryptParametersOutputType, SSMGetParametersByNameOutputInterface, From 971ce1af4a69765b5195fbdbde9bf910a5cda6a6 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 29 Mar 2023 23:14:20 +0200 Subject: [PATCH 3/5] feat: added explicit type override --- packages/parameters/src/ssm/SSMProvider.ts | 20 ++++---- packages/parameters/src/ssm/getParameter.ts | 7 ++- packages/parameters/src/ssm/getParameters.ts | 6 +-- .../parameters/src/ssm/getParametersByName.ts | 11 +++-- packages/parameters/src/types/BaseProvider.ts | 8 ++- packages/parameters/src/types/SSMProvider.ts | 49 ++++++++++++++----- 6 files changed, 65 insertions(+), 36 deletions(-) diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index c276e44f35..6d59f93fed 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -16,11 +16,11 @@ import type { import type { SSMProviderOptions, SSMGetOptions, - SSMGetOptionsUnion, SSMGetOutput, SSMGetMultipleOptions, SSMGetMultipleOptionsUnion, SSMGetMultipleOutput, + SSMGetParametersByNameOutput, SSMGetParametersByNameOutputInterface, SSMGetParametersByNameOptionsInterface, SSMSplitBatchAndDecryptParametersOutputType, @@ -319,11 +319,11 @@ class SSMProvider extends BaseProvider { * @param {SSMGetOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ - public async get( + public async get( name: string, options?: O & SSMGetOptions - ): Promise | undefined> { - return super.get(name, options) as Promise | undefined>; + ): Promise | undefined> { + return super.get(name, options) as Promise | undefined>; } /** @@ -356,11 +356,11 @@ class SSMProvider extends BaseProvider { * @param {SSMGetMultipleOptions} options - Options to configure the retrieval * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ - public async getMultiple( + public async getMultiple( path: string, options?: O & SSMGetMultipleOptions - ): Promise | undefined> { - return super.getMultiple(path, options) as Promise | undefined>; + ): Promise | undefined> { + return super.getMultiple(path, options) as Promise | undefined>; } /** @@ -413,10 +413,10 @@ class SSMProvider extends BaseProvider { * @param {SSMGetParametersByNameOptionsInterface} options - Options to configure the retrieval * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ - public async getParametersByName( + public async getParametersByName( parameters: Record, options?: SSMGetParametersByNameOptionsInterface - ): Promise> { + ): Promise> { const configs = { ...{ decrypt: this.resolveDecryptionConfigValue({}) || false, maxAge: DEFAULT_MAX_AGE_SECS, @@ -464,7 +464,7 @@ class SSMProvider extends BaseProvider { } } - return response; + return response as unknown as Promise>; } /** diff --git a/packages/parameters/src/ssm/getParameter.ts b/packages/parameters/src/ssm/getParameter.ts index 1769ebea2f..9e61bc0c6a 100644 --- a/packages/parameters/src/ssm/getParameter.ts +++ b/packages/parameters/src/ssm/getParameter.ts @@ -1,7 +1,6 @@ import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider'; import type { SSMGetOptions, - SSMGetOptionsUnion, SSMGetOutput, } from '../types/SSMProvider'; @@ -140,17 +139,17 @@ import type { * @param {SSMGetOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ -const getParameter = ( +const getParameter = ( name: string, options?: O & SSMGetOptions -): Promise | undefined> => { +): Promise | undefined> => { if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) { DEFAULT_PROVIDERS.ssm = new SSMProvider(); } return ( DEFAULT_PROVIDERS.ssm as SSMProvider - ).get(name, options) as Promise | undefined>; + ).get(name, options) as Promise | undefined>; }; export { diff --git a/packages/parameters/src/ssm/getParameters.ts b/packages/parameters/src/ssm/getParameters.ts index ede4f3e614..1eb123dbbc 100644 --- a/packages/parameters/src/ssm/getParameters.ts +++ b/packages/parameters/src/ssm/getParameters.ts @@ -141,17 +141,17 @@ import type { * @param {SSMGetMultipleOptions} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ -const getParameters = ( +const getParameters = ( path: string, options?: O & SSMGetMultipleOptions -): Promise | undefined> => { +): Promise | undefined> => { if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) { DEFAULT_PROVIDERS.ssm = new SSMProvider(); } return ( DEFAULT_PROVIDERS.ssm as SSMProvider - ).getMultiple(path, options) as Promise | undefined>; + ).getMultiple(path, options) as Promise | undefined>; }; export { diff --git a/packages/parameters/src/ssm/getParametersByName.ts b/packages/parameters/src/ssm/getParametersByName.ts index 5efd333f5f..f7532206bd 100644 --- a/packages/parameters/src/ssm/getParametersByName.ts +++ b/packages/parameters/src/ssm/getParametersByName.ts @@ -1,6 +1,7 @@ import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider'; import type { - SSMGetParametersByNameOptionsInterface + SSMGetParametersByNameOptionsInterface, + SSMGetParametersByNameOutput, } from '../types/SSMProvider'; /** @@ -160,15 +161,17 @@ import type { * @param {SSMGetParametersByNameOptionsInterface} options - Options to configure the provider * @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/ */ -const getParametersByName = ( +const getParametersByName = ( parameters: Record, options?: SSMGetParametersByNameOptionsInterface -): Promise & { _errors?: string[] }> => { +): Promise> => { if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) { DEFAULT_PROVIDERS.ssm = new SSMProvider(); } - return (DEFAULT_PROVIDERS.ssm as SSMProvider).getParametersByName(parameters, options); + return ( + DEFAULT_PROVIDERS.ssm as SSMProvider + ).getParametersByName(parameters, options) as Promise>; }; export { diff --git a/packages/parameters/src/types/BaseProvider.ts b/packages/parameters/src/types/BaseProvider.ts index c0e5a08c3d..f2a6a79a9b 100644 --- a/packages/parameters/src/types/BaseProvider.ts +++ b/packages/parameters/src/types/BaseProvider.ts @@ -25,9 +25,9 @@ interface GetOptionsInterface { */ sdkOptions?: unknown /** - * Transform to be applied, can be 'json', 'binary', or 'auto'. + * Transform to be applied, can be `json` or `binary`. */ - transform?: TransformOptions + transform?: Omit } /** @@ -40,6 +40,10 @@ interface GetOptionsInterface { * @property {boolean} throwOnTransformError - Whether to throw an error if a value cannot be transformed. */ interface GetMultipleOptionsInterface extends GetOptionsInterface { + /** + * Transform to be applied, can be `json`, `binary`, or `auto`. + */ + transform?: TransformOptions /** * Whether to throw an error if a value cannot be transformed. */ diff --git a/packages/parameters/src/types/SSMProvider.ts b/packages/parameters/src/types/SSMProvider.ts index 292ed5a828..9a4c789978 100644 --- a/packages/parameters/src/types/SSMProvider.ts +++ b/packages/parameters/src/types/SSMProvider.ts @@ -63,6 +63,8 @@ interface SSMGetOptions extends GetOptionsInterface { * Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParameterCommandInput`. */ sdkOptions?: Partial + + transform?: Exclude } interface SSMGetOptionsTransformJson extends SSMGetOptions { @@ -77,14 +79,16 @@ interface SSMGetOptionsTransformNone extends SSMGetOptions { transform?: never } -type SSMGetOptionsUnion = SSMGetOptionsTransformJson | SSMGetOptionsTransformBinary | SSMGetOptionsTransformNone | undefined; - -type SSMGetOutput = +/** + * Generic output type for the SSMProvider get method. + */ +type SSMGetOutput = + undefined extends T ? undefined extends O ? string : O extends SSMGetOptionsTransformNone | SSMGetOptionsTransformBinary ? string : - // eslint-disable-next-line @typescript-eslint/no-explicit-any - O extends SSMGetOptionsTransformJson ? Record : - never; + O extends SSMGetOptionsTransformJson ? Record : + never + : T; /** * Options for the SSMProvider getMultiple method. @@ -126,18 +130,32 @@ interface SSMGetMultipleOptionsTransformBinary extends SSMGetMultipleOptions { transform: 'binary' } +interface SSMGetMultipleOptionsTransformAuto extends SSMGetMultipleOptions { + transform: 'auto' +} + interface SSMGetMultipleOptionsTransformNone extends SSMGetMultipleOptions { transform?: never } -type SSMGetMultipleOptionsUnion = SSMGetMultipleOptionsTransformJson | SSMGetMultipleOptionsTransformBinary | SSMGetMultipleOptionsTransformNone | undefined; +type SSMGetMultipleOptionsUnion = + SSMGetMultipleOptionsTransformJson | + SSMGetMultipleOptionsTransformBinary | + SSMGetMultipleOptionsTransformAuto | + SSMGetMultipleOptionsTransformNone | + undefined; -type SSMGetMultipleOutput = +/** + * Generic output type for the SSMProvider getMultiple method. + */ +type SSMGetMultipleOutput = + undefined extends T ? undefined extends O ? Record : O extends SSMGetMultipleOptionsTransformNone | SSMGetMultipleOptionsTransformBinary ? Record : - // eslint-disable-next-line @typescript-eslint/no-explicit-any - O extends SSMGetMultipleOptionsTransformJson ? Record> : - never; + O extends SSMGetMultipleOptionsTransformAuto ? Record : + O extends SSMGetMultipleOptionsTransformJson ? Record> : + never + : Record; /** * Options for the SSMProvider getParametersByName method. @@ -152,7 +170,7 @@ interface SSMGetParametersByNameOptionsInterface { maxAge?: number throwOnError?: boolean decrypt?: boolean - transform?: TransformOptions + transform?: Exclude } /** @@ -179,10 +197,14 @@ type SSMGetParametersByNameFromCacheOutputType = { toFetch: Record }; +type SSMGetParametersByNameOutput = + undefined extends T ? + Record & { _errors?: string[] } : + Record & { _errors?: string[] }; + export type { SSMProviderOptions, SSMGetOptions, - SSMGetOptionsUnion, SSMGetOutput, SSMGetMultipleOptions, SSMGetMultipleOptionsUnion, @@ -191,4 +213,5 @@ export type { SSMSplitBatchAndDecryptParametersOutputType, SSMGetParametersByNameOutputInterface, SSMGetParametersByNameFromCacheOutputType, + SSMGetParametersByNameOutput, }; \ No newline at end of file From e87c89ff061fa93e8dc6fa8c1da942ad68a9e549 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 29 Mar 2023 23:16:34 +0200 Subject: [PATCH 4/5] chore: rebase --- packages/parameters/src/ssm/SSMProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index 6d59f93fed..ba1794e98f 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -737,7 +737,7 @@ class SSMProvider extends BaseProvider { } protected resolveDecryptionConfigValue( - options: SSMGetOptionsInterface | SSMGetMultipleOptionsInterface = {}, + options: SSMGetOptions | SSMGetMultipleOptions = {}, sdkOptions?: GetParameterCommandInput | GetParametersByPathCommandInput ): boolean | undefined { if (options?.decrypt !== undefined) return options.decrypt; From 1b0cd0bac9a49e6d81b0574b2f81fbe9f9e65fc4 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 5 Apr 2023 13:40:23 +0000 Subject: [PATCH 5/5] chore: added type annotation to tests to use as canary --- .../tests/unit/getParameter.test.ts | 58 +++++++++++++++- .../tests/unit/getParameters.test.ts | 66 ++++++++++++++++++- 2 files changed, 118 insertions(+), 6 deletions(-) diff --git a/packages/parameters/tests/unit/getParameter.test.ts b/packages/parameters/tests/unit/getParameter.test.ts index f13f993cbf..b7bf839f57 100644 --- a/packages/parameters/tests/unit/getParameter.test.ts +++ b/packages/parameters/tests/unit/getParameter.test.ts @@ -9,6 +9,10 @@ import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'; import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; +/** + * Note that the following tests include type annotations on the results of each call. This is to ensure that the + * generic types defined in the utility are working as expected. If they are not, the tests will fail to compile. + */ describe('Function: getParameter', () => { beforeEach(() => { @@ -27,7 +31,7 @@ describe('Function: getParameter', () => { }); // Act - const value = await getParameter(parameterName); + const value: string | undefined = await getParameter(parameterName); // Assess expect(client).toReceiveCommandWith(GetParameterCommand, { @@ -36,7 +40,7 @@ describe('Function: getParameter', () => { expect(value).toBe(parameterValue); }); - + test('when called and a default provider exists, it uses it and returns the value', async () => { // Prepare @@ -51,7 +55,7 @@ describe('Function: getParameter', () => { }); // Act - const value = await getParameter(parameterName); + const value: string | undefined = await getParameter(parameterName); // Assess expect(client).toReceiveCommandWith(GetParameterCommand, { @@ -62,4 +66,52 @@ describe('Function: getParameter', () => { }); + test('when called and transform `JSON` is specified, it returns an object with correct type', async () => { + + // Prepare + const provider = new SSMProvider(); + DEFAULT_PROVIDERS.ssm = provider; + const parameterName = 'foo'; + const parameterValue = JSON.stringify({ hello: 'world' }); + const client = mockClient(SSMClient).on(GetParameterCommand).resolves({ + Parameter: { + Value: parameterValue, + }, + }); + + // Act + const value: Record | undefined = await getParameter(parameterName, { transform: 'json' }); + + // Assess + expect(client).toReceiveCommandWith(GetParameterCommand, { + Name: parameterName, + }); + expect(value).toStrictEqual(JSON.parse(parameterValue)); + + }); + + test('when called and transform `JSON` is specified as well as an explicit `K` type, it returns a result with correct type', async () => { + + // Prepare + const provider = new SSMProvider(); + DEFAULT_PROVIDERS.ssm = provider; + const parameterName = 'foo'; + const parameterValue = JSON.stringify(5); + const client = mockClient(SSMClient).on(GetParameterCommand).resolves({ + Parameter: { + Value: parameterValue, + }, + }); + + // Act + const value: number | undefined = await getParameter(parameterName, { transform: 'json' }); + + // Assess + expect(client).toReceiveCommandWith(GetParameterCommand, { + Name: parameterName, + }); + expect(value).toBe(JSON.parse(parameterValue)); + + }); + }); \ No newline at end of file diff --git a/packages/parameters/tests/unit/getParameters.test.ts b/packages/parameters/tests/unit/getParameters.test.ts index 8f9b68f6bd..2025c0ae7f 100644 --- a/packages/parameters/tests/unit/getParameters.test.ts +++ b/packages/parameters/tests/unit/getParameters.test.ts @@ -9,6 +9,10 @@ import { SSMClient, GetParametersByPathCommand } from '@aws-sdk/client-ssm'; import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; +/** + * Note that the following tests include type annotations on the results of each call. This is to ensure that the + * generic types defined in the utility are working as expected. If they are not, the tests will fail to compile. + */ describe('Function: getParameters', () => { beforeEach(() => { @@ -28,7 +32,7 @@ describe('Function: getParameters', () => { }); // Act - const parameters = await getParameters(parameterPath); + const parameters: Record | undefined = await getParameters(parameterPath); // Assess expect(client).toReceiveCommandWith(GetParametersByPathCommand, { @@ -39,7 +43,7 @@ describe('Function: getParameters', () => { }); }); - + test('when called and a default provider exists, it uses it and returns the value', async () => { // Prepare @@ -55,7 +59,7 @@ describe('Function: getParameters', () => { }); // Act - const parameters = await getParameters(parameterPath); + const parameters: Record | undefined = await getParameters(parameterPath); // Assess expect(client).toReceiveCommandWith(GetParametersByPathCommand, { @@ -68,4 +72,60 @@ describe('Function: getParameters', () => { }); + test('when called and transform `JSON` is specified, it returns an object with correct type', async () => { + + // Prepare + const provider = new SSMProvider(); + DEFAULT_PROVIDERS.ssm = provider; + const parameterPath = '/foo'; + const parameterValue = JSON.stringify({ hello: 'world' }); + const client = mockClient(SSMClient).on(GetParametersByPathCommand).resolves({ + Parameters: [{ + Name: '/foo/bar', + Value: parameterValue, + }], + }); + + // Act + const parameters: Record> | undefined = await getParameters(parameterPath); + + // Assess + expect(client).toReceiveCommandWith(GetParametersByPathCommand, { + Path: parameterPath, + }); + expect(parameters).toStrictEqual({ + 'bar': parameterValue, + }); + expect(DEFAULT_PROVIDERS.ssm).toBe(provider); + + }); + + test('when called and transform `JSON` is specified as well as an explicit `K` type, it returns a result with correct type', async () => { + + // Prepare + const provider = new SSMProvider(); + DEFAULT_PROVIDERS.ssm = provider; + const parameterPath = '/foo'; + const parameterValue = JSON.stringify(5); + const client = mockClient(SSMClient).on(GetParametersByPathCommand).resolves({ + Parameters: [{ + Name: '/foo/bar', + Value: parameterValue, + }], + }); + + // Act + const parameters: Record> | undefined = await getParameters>(parameterPath); + + // Assess + expect(client).toReceiveCommandWith(GetParametersByPathCommand, { + Path: parameterPath, + }); + expect(parameters).toStrictEqual({ + 'bar': parameterValue, + }); + expect(DEFAULT_PROVIDERS.ssm).toBe(provider); + + }); + }); \ No newline at end of file