Skip to content

Commit 665fff4

Browse files
authored
chore(parameters): refactor provider constructor to init client as needed (#1757)
* chore(parameters): refactor provider constructor to init client as needed * chore(parameters): moved client instrumentation up in baseprovider * chore(parameters): fix code smells * chore(parameters): fix code smells
1 parent 7da9c26 commit 665fff4

File tree

6 files changed

+98
-114
lines changed

6 files changed

+98
-114
lines changed

Diff for: packages/parameters/src/appconfig/AppConfigProvider.ts

+11-20
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ import type {
1010
AppConfigGetOptions,
1111
AppConfigGetOutput,
1212
} from '../types/AppConfigProvider';
13-
import {
14-
addUserAgentMiddleware,
15-
isSdkClient,
16-
} from '@aws-lambda-powertools/commons';
1713

1814
/**
1915
* ## Intro
@@ -185,7 +181,7 @@ import {
185181
* For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/).
186182
*/
187183
class AppConfigProvider extends BaseProvider {
188-
public client: AppConfigDataClient;
184+
public client!: AppConfigDataClient;
189185
protected configurationTokenStore = new Map<string, string>();
190186
protected valueStore = new Map<string, Uint8Array>();
191187
private application?: string;
@@ -197,27 +193,22 @@ class AppConfigProvider extends BaseProvider {
197193
* @param {AppConfigProviderOptions} options - The configuration object.
198194
*/
199195
public constructor(options: AppConfigProviderOptions) {
200-
super();
201-
this.client = new AppConfigDataClient(options.clientConfig || {});
202-
if (options?.awsSdkV3Client) {
203-
if (isSdkClient(options.awsSdkV3Client)) {
204-
this.client = options.awsSdkV3Client;
205-
} else {
206-
console.warn(
207-
'awsSdkV3Client is not an AWS SDK v3 client, using default client'
208-
);
209-
}
210-
}
211-
addUserAgentMiddleware(this.client, 'parameters');
196+
super({
197+
proto: AppConfigDataClient as new (
198+
config?: unknown
199+
) => AppConfigDataClient,
200+
clientConfig: options.clientConfig,
201+
awsSdkV3Client: options.awsSdkV3Client,
202+
});
212203

213-
this.application =
214-
options?.application || this.envVarsService.getServiceName();
204+
const { application, environment } = options;
205+
this.application = application ?? this.envVarsService.getServiceName();
215206
if (!this.application || this.application.trim().length === 0) {
216207
throw new Error(
217208
'Application name is not defined or POWERTOOLS_SERVICE_NAME is not set'
218209
);
219210
}
220-
this.environment = options.environment;
211+
this.environment = environment;
221212
}
222213

223214
/**

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

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {
2+
addUserAgentMiddleware,
23
isNullOrUndefined,
34
isRecord,
5+
isSdkClient,
46
isString,
57
} from '@aws-lambda-powertools/commons';
68
import { GetOptions } from './GetOptions';
@@ -36,11 +38,33 @@ import type {
3638
*/
3739
abstract class BaseProvider implements BaseProviderInterface {
3840
public envVarsService: EnvironmentVariablesService;
41+
protected client: unknown;
3942
protected store: Map<string, ExpirableValue>;
4043

41-
public constructor() {
44+
public constructor({
45+
awsSdkV3Client,
46+
clientConfig,
47+
proto,
48+
}: {
49+
awsSdkV3Client?: unknown;
50+
clientConfig?: unknown;
51+
proto: new (config?: unknown) => unknown;
52+
}) {
4253
this.store = new Map();
4354
this.envVarsService = new EnvironmentVariablesService();
55+
if (awsSdkV3Client) {
56+
if (!isSdkClient(awsSdkV3Client)) {
57+
console.warn(
58+
'awsSdkV3Client is not an AWS SDK v3 client, using default client'
59+
);
60+
this.client = new proto(clientConfig ?? {});
61+
} else {
62+
this.client = awsSdkV3Client;
63+
}
64+
} else {
65+
this.client = new proto(clientConfig ?? {});
66+
}
67+
addUserAgentMiddleware(this.client, 'parameters');
4468
}
4569

4670
/**

Diff for: packages/parameters/src/dynamodb/DynamoDBProvider.ts

+11-22
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ import type {
1818
} from '@aws-sdk/client-dynamodb';
1919
import type { PaginationConfiguration } from '@aws-sdk/types';
2020
import type { JSONValue } from '@aws-lambda-powertools/commons';
21-
import {
22-
addUserAgentMiddleware,
23-
isSdkClient,
24-
} from '@aws-lambda-powertools/commons';
2521

2622
/**
2723
* ## Intro
@@ -239,7 +235,7 @@ import {
239235
* For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/).
240236
*/
241237
class DynamoDBProvider extends BaseProvider {
242-
public client: DynamoDBClient;
238+
public client!: DynamoDBClient;
243239
protected keyAttr = 'id';
244240
protected sortAttr = 'sk';
245241
protected tableName: string;
@@ -251,24 +247,17 @@ class DynamoDBProvider extends BaseProvider {
251247
* @param {DynamoDBProviderOptions} config - The configuration object.
252248
*/
253249
public constructor(config: DynamoDBProviderOptions) {
254-
super();
255-
256-
this.client = new DynamoDBClient(config?.clientConfig || {});
257-
if (config?.awsSdkV3Client) {
258-
if (isSdkClient(config.awsSdkV3Client)) {
259-
this.client = config.awsSdkV3Client;
260-
} else {
261-
console.warn(
262-
'awsSdkV3Client is not an AWS SDK v3 client, using default client'
263-
);
264-
}
265-
}
266-
addUserAgentMiddleware(this.client, 'parameters');
250+
super({
251+
awsSdkV3Client: config.awsSdkV3Client,
252+
clientConfig: config.clientConfig,
253+
proto: DynamoDBClient as new (config?: unknown) => DynamoDBClient,
254+
});
267255

268-
this.tableName = config.tableName;
269-
if (config.keyAttr) this.keyAttr = config.keyAttr;
270-
if (config.sortAttr) this.sortAttr = config.sortAttr;
271-
if (config.valueAttr) this.valueAttr = config.valueAttr;
256+
const { tableName, keyAttr, sortAttr, valueAttr } = config;
257+
this.tableName = tableName;
258+
if (keyAttr) this.keyAttr = keyAttr;
259+
if (sortAttr) this.sortAttr = sortAttr;
260+
if (valueAttr) this.valueAttr = valueAttr;
272261
}
273262

274263
/**

Diff for: packages/parameters/src/secrets/SecretsProvider.ts

+7-18
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ import type {
99
SecretsGetOptions,
1010
SecretsGetOutput,
1111
} from '../types/SecretsProvider';
12-
import {
13-
addUserAgentMiddleware,
14-
isSdkClient,
15-
} from '@aws-lambda-powertools/commons';
1612

1713
/**
1814
* ## Intro
@@ -149,27 +145,20 @@ import {
149145
* @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/
150146
*/
151147
class SecretsProvider extends BaseProvider {
152-
public client: SecretsManagerClient;
148+
public client!: SecretsManagerClient;
153149

154150
/**
155151
* It initializes the SecretsProvider class.
156152
*
157153
* @param {SecretsProviderOptions} config - The configuration object.
158154
*/
159155
public constructor(config?: SecretsProviderOptions) {
160-
super();
161-
162-
this.client = new SecretsManagerClient(config?.clientConfig || {});
163-
if (config?.awsSdkV3Client) {
164-
if (isSdkClient(config.awsSdkV3Client)) {
165-
this.client = config.awsSdkV3Client;
166-
} else {
167-
console.warn(
168-
'awsSdkV3Client is not an AWS SDK v3 client, using default client'
169-
);
170-
}
171-
}
172-
addUserAgentMiddleware(this.client, 'parameters');
156+
super({
157+
proto: SecretsManagerClient as new (
158+
config?: unknown
159+
) => SecretsManagerClient,
160+
...(config ?? {}),
161+
});
173162
}
174163

175164
/**

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

+5-18
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ import type {
2727
SSMGetParametersByNameFromCacheOutputType,
2828
} from '../types/SSMProvider';
2929
import type { PaginationConfiguration } from '@aws-sdk/types';
30-
import {
31-
addUserAgentMiddleware,
32-
isSdkClient,
33-
} from '@aws-lambda-powertools/commons';
3430

3531
/**
3632
* ## Intro
@@ -266,7 +262,7 @@ import {
266262
* For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/).
267263
*/
268264
class SSMProvider extends BaseProvider {
269-
public client: SSMClient;
265+
public client!: SSMClient;
270266
protected errorsKey = '_errors';
271267
protected maxGetParametersItems = 10;
272268

@@ -276,19 +272,10 @@ class SSMProvider extends BaseProvider {
276272
* @param {SSMProviderOptions} config - The configuration object.
277273
*/
278274
public constructor(config?: SSMProviderOptions) {
279-
super();
280-
281-
this.client = new SSMClient(config?.clientConfig || {});
282-
if (config?.awsSdkV3Client) {
283-
if (isSdkClient(config.awsSdkV3Client)) {
284-
this.client = config.awsSdkV3Client;
285-
} else {
286-
console.warn(
287-
'awsSdkV3Client is not an AWS SDK v3 client, using default client'
288-
);
289-
}
290-
}
291-
addUserAgentMiddleware(this.client, 'parameters');
275+
super({
276+
proto: SSMClient as new (config?: unknown) => SSMClient,
277+
...(config ?? {}),
278+
});
292279
}
293280

294281
/**

Diff for: packages/parameters/tests/unit/BaseProvider.test.ts

+39-35
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,51 @@ import { GetParameterError, TransformParameterError } from '../../src/errors';
99
import { toBase64 } from '@aws-sdk/util-base64-node';
1010

1111
const encoder = new TextEncoder();
12+
jest.mock('@aws-lambda-powertools/commons', () => ({
13+
...jest.requireActual('@aws-lambda-powertools/commons'),
14+
addUserAgentMiddleware: jest.fn(),
15+
}));
16+
17+
class TestProvider extends BaseProvider {
18+
public constructor() {
19+
super({
20+
proto: class {
21+
#name = 'TestProvider';
22+
23+
public hello(): string {
24+
return this.#name;
25+
}
26+
},
27+
});
28+
}
1229

13-
describe('Class: BaseProvider', () => {
14-
afterEach(() => {
15-
jest.clearAllMocks();
16-
});
17-
18-
class TestProvider extends BaseProvider {
19-
public _add(key: string, value: ExpirableValue): void {
20-
this.store.set(key, value);
21-
}
30+
public _add(key: string, value: ExpirableValue): void {
31+
this.store.set(key, value);
32+
}
2233

23-
public _get(_name: string): Promise<string> {
24-
throw Error('Not implemented.');
25-
}
34+
public _get(_name: string): Promise<string> {
35+
throw Error('Not implemented.');
36+
}
2637

27-
public _getKeyTest(key: string): ExpirableValue | undefined {
28-
return this.store.get(key);
29-
}
38+
public _getKeyTest(key: string): ExpirableValue | undefined {
39+
return this.store.get(key);
40+
}
3041

31-
public _getMultiple(
32-
_path: string
33-
): Promise<Record<string, string | undefined>> {
34-
throw Error('Not implemented.');
35-
}
42+
public _getMultiple(
43+
_path: string
44+
): Promise<Record<string, string | undefined>> {
45+
throw Error('Not implemented.');
46+
}
3647

37-
public _getStoreSize(): number {
38-
return this.store.size;
39-
}
48+
public _getStoreSize(): number {
49+
return this.store.size;
4050
}
51+
}
52+
53+
describe('Class: BaseProvider', () => {
54+
afterEach(() => {
55+
jest.clearAllMocks();
56+
});
4157

4258
describe('Method: addToCache', () => {
4359
test('when called with a value and maxAge equal to 0, it skips the cache entirely', () => {
@@ -581,18 +597,6 @@ describe('Class: BaseProvider', () => {
581597
});
582598

583599
describe('Function: clearCaches', () => {
584-
class TestProvider extends BaseProvider {
585-
public _get(_name: string): Promise<string> {
586-
throw Error('Not implemented.');
587-
}
588-
589-
public _getMultiple(
590-
_path: string
591-
): Promise<Record<string, string | undefined>> {
592-
throw Error('Not implemented.');
593-
}
594-
}
595-
596600
test('when called, it clears all the caches', () => {
597601
// Prepare
598602
const provider1 = new TestProvider();

0 commit comments

Comments
 (0)