Skip to content

Commit 9d53942

Browse files
authored
feat(parameters): stronger types for SSM getParameter (#1387)
* feat: stronger types for SSM getParameter * feat: improved types for getParameters * feat: added explicit type override * chore: rebase * chore: added type annotation to tests to use as canary
1 parent 7a9d499 commit 9d53942

File tree

8 files changed

+272
-51
lines changed

8 files changed

+272
-51
lines changed

Diff for: packages/parameters/src/ssm/SSMProvider.ts

+24-20
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ import type {
1515
} from '@aws-sdk/client-ssm';
1616
import type {
1717
SSMProviderOptions,
18-
SSMGetMultipleOptionsInterface,
19-
SSMGetOptionsInterface,
18+
SSMGetOptions,
19+
SSMGetOutput,
20+
SSMGetMultipleOptions,
21+
SSMGetMultipleOptionsUnion,
22+
SSMGetMultipleOutput,
23+
SSMGetParametersByNameOutput,
2024
SSMGetParametersByNameOutputInterface,
2125
SSMGetParametersByNameOptionsInterface,
2226
SSMSplitBatchAndDecryptParametersOutputType,
@@ -312,14 +316,14 @@ class SSMProvider extends BaseProvider {
312316
* For usage examples check {@link SSMProvider}.
313317
*
314318
* @param {string} name - The name of the value to retrieve (i.e. the partition key)
315-
* @param {SSMGetOptionsInterface} options - Options to configure the provider
319+
* @param {SSMGetOptions} options - Options to configure the provider
316320
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
317321
*/
318-
public async get(
322+
public async get<T = undefined, O extends SSMGetOptions | undefined = SSMGetOptions>(
319323
name: string,
320-
options?: SSMGetOptionsInterface | undefined
321-
): Promise<string | Record<string, unknown> | undefined> {
322-
return super.get(name, options) as Promise<string | Record<string, unknown> | undefined>;
324+
options?: O & SSMGetOptions
325+
): Promise<SSMGetOutput<T, O> | undefined> {
326+
return super.get(name, options) as Promise<SSMGetOutput<T, O> | undefined>;
323327
}
324328

325329
/**
@@ -349,14 +353,14 @@ class SSMProvider extends BaseProvider {
349353
* For usage examples check {@link SSMProvider}.
350354
*
351355
* @param {string} path - The path of the parameters to retrieve
352-
* @param {SSMGetMultipleOptionsInterface} options - Options to configure the retrieval
356+
* @param {SSMGetMultipleOptions} options - Options to configure the retrieval
353357
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
354358
*/
355-
public async getMultiple(
359+
public async getMultiple<T = undefined, O extends SSMGetMultipleOptionsUnion | undefined = undefined>(
356360
path: string,
357-
options?: SSMGetMultipleOptionsInterface | undefined
358-
): Promise<undefined | Record<string, unknown>> {
359-
return super.getMultiple(path, options);
361+
options?: O & SSMGetMultipleOptions
362+
): Promise<SSMGetMultipleOutput<T, O> | undefined> {
363+
return super.getMultiple(path, options) as Promise<SSMGetMultipleOutput<T, O> | undefined>;
360364
}
361365

362366
/**
@@ -409,10 +413,10 @@ class SSMProvider extends BaseProvider {
409413
* @param {SSMGetParametersByNameOptionsInterface} options - Options to configure the retrieval
410414
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
411415
*/
412-
public async getParametersByName(
416+
public async getParametersByName<T = undefined>(
413417
parameters: Record<string, SSMGetParametersByNameOptionsInterface>,
414418
options?: SSMGetParametersByNameOptionsInterface
415-
): Promise<Record<string, unknown>> {
419+
): Promise<SSMGetParametersByNameOutput<T>> {
416420
const configs = { ...{
417421
decrypt: this.resolveDecryptionConfigValue({}) || false,
418422
maxAge: DEFAULT_MAX_AGE_SECS,
@@ -460,18 +464,18 @@ class SSMProvider extends BaseProvider {
460464
}
461465
}
462466

463-
return response;
467+
return response as unknown as Promise<SSMGetParametersByNameOutput<T>>;
464468
}
465469

466470
/**
467471
* Retrieve a parameter from AWS Systems Manager.
468472
*
469473
* @param {string} name - Name of the parameter to retrieve
470-
* @param {SSMGetOptionsInterface} options - Options to customize the retrieval
474+
* @param {SSMGetOptions} options - Options to customize the retrieval
471475
*/
472476
protected async _get(
473477
name: string,
474-
options?: SSMGetOptionsInterface
478+
options?: SSMGetOptions
475479
): Promise<string | undefined> {
476480
const sdkOptions: GetParameterCommandInput = {
477481
...(options?.sdkOptions || {}),
@@ -487,11 +491,11 @@ class SSMProvider extends BaseProvider {
487491
* Retrieve multiple items from AWS Systems Manager.
488492
*
489493
* @param {string} path - The path of the parameters to retrieve
490-
* @param {SSMGetMultipleOptionsInterface} options - Options to configure the provider
494+
* @param {SSMGetMultipleOptions} options - Options to configure the provider
491495
*/
492496
protected async _getMultiple(
493497
path: string,
494-
options?: SSMGetMultipleOptionsInterface
498+
options?: SSMGetMultipleOptions
495499
): Promise<Record<string, string | undefined>> {
496500
const sdkOptions: GetParametersByPathCommandInput = {
497501
...(options?.sdkOptions || {}),
@@ -733,7 +737,7 @@ class SSMProvider extends BaseProvider {
733737
}
734738

735739
protected resolveDecryptionConfigValue(
736-
options: SSMGetOptionsInterface | SSMGetMultipleOptionsInterface = {},
740+
options: SSMGetOptions | SSMGetMultipleOptions = {},
737741
sdkOptions?: GetParameterCommandInput | GetParametersByPathCommandInput
738742
): boolean | undefined {
739743
if (options?.decrypt !== undefined) return options.decrypt;

Diff for: packages/parameters/src/ssm/getParameter.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider';
2-
import type { SSMGetOptionsInterface } from '../types/SSMProvider';
2+
import type {
3+
SSMGetOptions,
4+
SSMGetOutput,
5+
} from '../types/SSMProvider';
36

47
/**
58
* ## Intro
@@ -133,18 +136,20 @@ import type { SSMGetOptionsInterface } from '../types/SSMProvider';
133136
* For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/).
134137
*
135138
* @param {string} name - The name of the parameter to retrieve
136-
* @param {SSMGetOptionsInterface} options - Options to configure the provider
139+
* @param {SSMGetOptions} options - Options to configure the provider
137140
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
138141
*/
139-
const getParameter = (
142+
const getParameter = <T = undefined, O extends SSMGetOptions | undefined = SSMGetOptions>(
140143
name: string,
141-
options?: SSMGetOptionsInterface
142-
): Promise<undefined | string | Record<string, unknown>> => {
144+
options?: O & SSMGetOptions
145+
): Promise<SSMGetOutput<T, O> | undefined> => {
143146
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
144147
DEFAULT_PROVIDERS.ssm = new SSMProvider();
145148
}
146149

147-
return (DEFAULT_PROVIDERS.ssm as SSMProvider).get(name, options);
150+
return (
151+
DEFAULT_PROVIDERS.ssm as SSMProvider
152+
).get(name, options) as Promise<SSMGetOutput<T, O> | undefined>;
148153
};
149154

150155
export {

Diff for: packages/parameters/src/ssm/getParameters.ts

+12-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider';
2-
import type { SSMGetMultipleOptionsInterface } from '../types/SSMProvider';
2+
import type {
3+
SSMGetMultipleOptions,
4+
SSMGetMultipleOptionsUnion,
5+
SSMGetMultipleOutput,
6+
} from '../types/SSMProvider';
37

48
/**
59
* ## Intro
@@ -134,18 +138,20 @@ import type { SSMGetMultipleOptionsInterface } from '../types/SSMProvider';
134138
* For more usage examples, see [our documentation](https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/).
135139
*
136140
* @param {string} path - The path of the parameters to retrieve
137-
* @param {SSMGetMultipleOptionsInterface} options - Options to configure the provider
141+
* @param {SSMGetMultipleOptions} options - Options to configure the provider
138142
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
139143
*/
140-
const getParameters = (
144+
const getParameters = <T = undefined, O extends SSMGetMultipleOptionsUnion | undefined = SSMGetMultipleOptionsUnion>(
141145
path: string,
142-
options?: SSMGetMultipleOptionsInterface
143-
): Promise<undefined | Record<string, unknown>> => {
146+
options?: O & SSMGetMultipleOptions
147+
): Promise<SSMGetMultipleOutput<T, O> | undefined> => {
144148
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
145149
DEFAULT_PROVIDERS.ssm = new SSMProvider();
146150
}
147151

148-
return (DEFAULT_PROVIDERS.ssm as SSMProvider).getMultiple(path, options);
152+
return (
153+
DEFAULT_PROVIDERS.ssm as SSMProvider
154+
).getMultiple(path, options) as Promise<SSMGetMultipleOutput<T, O> | undefined>;
149155
};
150156

151157
export {

Diff for: packages/parameters/src/ssm/getParametersByName.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { SSMProvider, DEFAULT_PROVIDERS } from './SSMProvider';
22
import type {
3-
SSMGetParametersByNameOptionsInterface
3+
SSMGetParametersByNameOptionsInterface,
4+
SSMGetParametersByNameOutput,
45
} from '../types/SSMProvider';
56

67
/**
@@ -160,15 +161,17 @@ import type {
160161
* @param {SSMGetParametersByNameOptionsInterface} options - Options to configure the provider
161162
* @see https://awslabs.github.io/aws-lambda-powertools-typescript/latest/utilities/parameters/
162163
*/
163-
const getParametersByName = (
164+
const getParametersByName = <T = undefined>(
164165
parameters: Record<string, SSMGetParametersByNameOptionsInterface>,
165166
options?: SSMGetParametersByNameOptionsInterface
166-
): Promise<Record<string, unknown> & { _errors?: string[] }> => {
167+
): Promise<SSMGetParametersByNameOutput<T>> => {
167168
if (!DEFAULT_PROVIDERS.hasOwnProperty('ssm')) {
168169
DEFAULT_PROVIDERS.ssm = new SSMProvider();
169170
}
170171

171-
return (DEFAULT_PROVIDERS.ssm as SSMProvider).getParametersByName(parameters, options);
172+
return (
173+
DEFAULT_PROVIDERS.ssm as SSMProvider
174+
).getParametersByName(parameters, options) as Promise<SSMGetParametersByNameOutput<T>>;
172175
};
173176

174177
export {

Diff for: packages/parameters/src/types/BaseProvider.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ interface GetOptionsInterface {
2525
*/
2626
sdkOptions?: unknown
2727
/**
28-
* Transform to be applied, can be 'json', 'binary', or 'auto'.
28+
* Transform to be applied, can be `json` or `binary`.
2929
*/
30-
transform?: TransformOptions
30+
transform?: Omit<TransformOptions, 'auto'>
3131
}
3232

3333
/**
@@ -40,6 +40,10 @@ interface GetOptionsInterface {
4040
* @property {boolean} throwOnTransformError - Whether to throw an error if a value cannot be transformed.
4141
*/
4242
interface GetMultipleOptionsInterface extends GetOptionsInterface {
43+
/**
44+
* Transform to be applied, can be `json`, `binary`, or `auto`.
45+
*/
46+
transform?: TransformOptions
4347
/**
4448
* Whether to throw an error if a value cannot be transformed.
4549
*/

Diff for: packages/parameters/src/types/SSMProvider.ts

+94-7
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,46 @@ type SSMProviderOptions = SSMProviderOptionsWithClientConfig | SSMProviderOption
5050
* @extends {GetOptionsInterface}
5151
* @property {number} maxAge - Maximum age of the value in the cache, in seconds.
5252
* @property {boolean} forceFetch - Force fetch the value from the parameter store, ignoring the cache.
53-
* @property {GetItemCommandInput} [sdkOptions] - Additional options to pass to the AWS SDK v3 client.
53+
* @property {GetItemCommandInput} [sdkOptions] - Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParameterCommandInput`.
5454
* @property {TransformOptions} transform - Transform to be applied, can be 'json' or 'binary'.
55-
* @property {boolean} decrypt - If true, the parameter will be decrypted.
55+
* @property {boolean} decrypt - If true, the parameter will be decrypted. Defaults to `false`.
5656
*/
57-
interface SSMGetOptionsInterface extends GetOptionsInterface {
57+
interface SSMGetOptions extends GetOptionsInterface {
58+
/**
59+
* If true, the parameter will be decrypted. Defaults to `false`.
60+
*/
5861
decrypt?: boolean
62+
/**
63+
* Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParameterCommandInput`.
64+
*/
5965
sdkOptions?: Partial<GetParameterCommandInput>
66+
67+
transform?: Exclude<TransformOptions, 'auto'>
68+
}
69+
70+
interface SSMGetOptionsTransformJson extends SSMGetOptions {
71+
transform: 'json'
72+
}
73+
74+
interface SSMGetOptionsTransformBinary extends SSMGetOptions {
75+
transform: 'binary'
6076
}
6177

78+
interface SSMGetOptionsTransformNone extends SSMGetOptions {
79+
transform?: never
80+
}
81+
82+
/**
83+
* Generic output type for the SSMProvider get method.
84+
*/
85+
type SSMGetOutput<T = undefined, O = undefined> =
86+
undefined extends T ?
87+
undefined extends O ? string :
88+
O extends SSMGetOptionsTransformNone | SSMGetOptionsTransformBinary ? string :
89+
O extends SSMGetOptionsTransformJson ? Record<string, unknown> :
90+
never
91+
: T;
92+
6293
/**
6394
* Options for the SSMProvider getMultiple method.
6495
*
@@ -72,13 +103,60 @@ interface SSMGetOptionsInterface extends GetOptionsInterface {
72103
* @property {boolean} recursive - If true, the parameter will be fetched recursively.
73104
* @property {boolean} throwOnTransformError - If true, the method will throw an error if the transform fails.
74105
*/
75-
interface SSMGetMultipleOptionsInterface extends GetMultipleOptionsInterface {
106+
interface SSMGetMultipleOptions extends GetMultipleOptionsInterface {
107+
/**
108+
* Additional options to pass to the AWS SDK v3 client. Supports all options from `GetParametersByPathCommandInput`.
109+
*/
76110
sdkOptions?: Partial<GetParametersByPathCommandInput>
111+
/**
112+
* If true, the parameters will be decrypted. Defaults to `false`.
113+
*/
77114
decrypt?: boolean
115+
/**
116+
* If true, the parameters will be fetched recursively. Defaults to `false`.
117+
*/
78118
recursive?: boolean
119+
/**
120+
* If true, the method will throw an error if the transform fails.
121+
*/
79122
throwOnTransformError?: boolean
80123
}
81124

125+
interface SSMGetMultipleOptionsTransformJson extends SSMGetMultipleOptions {
126+
transform: 'json'
127+
}
128+
129+
interface SSMGetMultipleOptionsTransformBinary extends SSMGetMultipleOptions {
130+
transform: 'binary'
131+
}
132+
133+
interface SSMGetMultipleOptionsTransformAuto extends SSMGetMultipleOptions {
134+
transform: 'auto'
135+
}
136+
137+
interface SSMGetMultipleOptionsTransformNone extends SSMGetMultipleOptions {
138+
transform?: never
139+
}
140+
141+
type SSMGetMultipleOptionsUnion =
142+
SSMGetMultipleOptionsTransformJson |
143+
SSMGetMultipleOptionsTransformBinary |
144+
SSMGetMultipleOptionsTransformAuto |
145+
SSMGetMultipleOptionsTransformNone |
146+
undefined;
147+
148+
/**
149+
* Generic output type for the SSMProvider getMultiple method.
150+
*/
151+
type SSMGetMultipleOutput<T = undefined, O = undefined> =
152+
undefined extends T ?
153+
undefined extends O ? Record<string, string> :
154+
O extends SSMGetMultipleOptionsTransformNone | SSMGetMultipleOptionsTransformBinary ? Record<string, string> :
155+
O extends SSMGetMultipleOptionsTransformAuto ? Record<string, unknown> :
156+
O extends SSMGetMultipleOptionsTransformJson ? Record<string, Record<string, unknown>> :
157+
never
158+
: Record<string, T>;
159+
82160
/**
83161
* Options for the SSMProvider getParametersByName method.
84162
*
@@ -92,7 +170,7 @@ interface SSMGetParametersByNameOptionsInterface {
92170
maxAge?: number
93171
throwOnError?: boolean
94172
decrypt?: boolean
95-
transform?: TransformOptions
173+
transform?: Exclude<TransformOptions, 'auto'>
96174
}
97175

98176
/**
@@ -119,12 +197,21 @@ type SSMGetParametersByNameFromCacheOutputType = {
119197
toFetch: Record<string, SSMGetParametersByNameOptionsInterface>
120198
};
121199

200+
type SSMGetParametersByNameOutput<T = undefined> =
201+
undefined extends T ?
202+
Record<string, unknown> & { _errors?: string[] } :
203+
Record<string, T> & { _errors?: string[] };
204+
122205
export type {
123206
SSMProviderOptions,
124-
SSMGetOptionsInterface,
125-
SSMGetMultipleOptionsInterface,
207+
SSMGetOptions,
208+
SSMGetOutput,
209+
SSMGetMultipleOptions,
210+
SSMGetMultipleOptionsUnion,
211+
SSMGetMultipleOutput,
126212
SSMGetParametersByNameOptionsInterface,
127213
SSMSplitBatchAndDecryptParametersOutputType,
128214
SSMGetParametersByNameOutputInterface,
129215
SSMGetParametersByNameFromCacheOutputType,
216+
SSMGetParametersByNameOutput,
130217
};

0 commit comments

Comments
 (0)