Skip to content

Commit ad876a4

Browse files
committed
feat(parameters): add appconfig provider with types
1 parent b9d1977 commit ad876a4

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { BaseProvider, DEFAULT_PROVIDERS } from 'BaseProvider';
2+
import {
3+
AppConfigDataClient,
4+
StartConfigurationSessionCommand,
5+
GetLatestConfigurationCommand,
6+
} from '@aws-sdk/client-appconfigdata';
7+
import type {
8+
StartConfigurationSessionCommandInput,
9+
GetLatestConfigurationCommandInput,
10+
} from '@aws-sdk/client-appconfigdata';
11+
import type { AppConfigGetOptionsInterface } from './types/AppConfigProvider';
12+
13+
class AppConfigProvider extends BaseProvider {
14+
public client: AppConfigDataClient;
15+
private application?: string;
16+
private environment?: string;
17+
private token: string | undefined;
18+
19+
/**
20+
* It initializes the AppConfigProvider class with an optional set of options like region: 'us-west-1'.
21+
* *
22+
* @param {AppConfigDataClientConfig} options
23+
*/
24+
public constructor(options: AppConfigGetOptionsInterface = {}) {
25+
super();
26+
this.client = new AppConfigDataClient(options.config || {});
27+
this.environment = options.environment;
28+
this.application = options.application || 'service_undefined'; // TODO: get value from ENV VARIABLES
29+
}
30+
31+
/**
32+
* Retrieve a parameter value from AWS App config.
33+
*
34+
* @param {string} name - Name of the configuration
35+
* @param {StartConfigurationSessionCommandInput} [sdkOptions] - SDK options to propagate to `StartConfigurationSession` API call
36+
* @returns {Promise<string | undefined>}
37+
*/
38+
protected async _get(
39+
name: string,
40+
options?: AppConfigGetOptionsInterface
41+
): Promise<string | undefined> {
42+
/**
43+
* The new AppConfig APIs require two API calls to return the configuration
44+
* First we start the session and after that we retrieve the configuration
45+
* We need to store the token to use in the next execution
46+
**/
47+
if (!this.token) {
48+
const sessionOptions: StartConfigurationSessionCommandInput = {
49+
ConfigurationProfileIdentifier: name,
50+
EnvironmentIdentifier: this.environment,
51+
ApplicationIdentifier: this.application,
52+
};
53+
if (options && options.hasOwnProperty('sdkOptions')) {
54+
Object.assign(sessionOptions, options.sdkOptions);
55+
}
56+
57+
const sessionCommand = new StartConfigurationSessionCommand(
58+
sessionOptions
59+
);
60+
61+
const session = await this.client.send(sessionCommand);
62+
this.token = session.InitialConfigurationToken;
63+
}
64+
65+
const getConfigurationCommand = new GetLatestConfigurationCommand({
66+
ConfigurationToken: this.token,
67+
});
68+
const response = await this.client.send(getConfigurationCommand);
69+
70+
// Should we cache and flush the token after 24 hours?
71+
// NextPollConfigurationToken expires in 24 hours after the last request and causes `BadRequestException`
72+
this.token = response.NextPollConfigurationToken;
73+
74+
const configuration = response.Configuration;
75+
76+
// should we convert Uint8Array to string?
77+
const utf8decoder = new TextDecoder();
78+
const value = configuration ? utf8decoder.decode(configuration) : undefined;
79+
80+
return value;
81+
}
82+
83+
/**
84+
* Retrieving multiple parameter values is not supported with AWS App Config Provider.
85+
*
86+
* @throws Not Implemented Error.
87+
*/
88+
protected async _getMultiple(
89+
path: string,
90+
sdkOptions?: Partial<GetLatestConfigurationCommandInput>
91+
): Promise<Record<string, string | undefined>> {
92+
return this._notImplementedError();
93+
}
94+
95+
private _notImplementedError(): never {
96+
throw new Error('Not Implemented');
97+
}
98+
}
99+
100+
const getAppConfig = (
101+
name: string,
102+
options?: AppConfigGetOptionsInterface
103+
): Promise<undefined | string | Record<string, unknown>> => {
104+
if (!DEFAULT_PROVIDERS.hasOwnProperty('appconfig')) {
105+
DEFAULT_PROVIDERS.appconfig = new AppConfigProvider(options);
106+
}
107+
108+
return DEFAULT_PROVIDERS.appconfig.get(name, options);
109+
};
110+
111+
export { AppConfigProvider, getAppConfig };
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import type { StartConfigurationSessionCommandInput, AppConfigDataClientConfig } from '@aws-sdk/client-appconfigdata';
2+
import type { GetOptionsInterface } from 'types/BaseProvider';
3+
4+
/**
5+
* Options for the AppConfigProvider get method.
6+
*
7+
* @interface AppConfigGetOptionsInterface
8+
* @extends {GetOptionsInterface}
9+
* @property {Partial<StartConfigurationSessionCommandInput>} sdkOptions - Options for the AWS SDK.
10+
*/
11+
interface AppConfigGetOptionsInterface extends Omit<GetOptionsInterface, 'sdkOptions'> {
12+
application?: string
13+
config?: AppConfigDataClientConfig
14+
environment?: string
15+
sdkOptions?: Partial<StartConfigurationSessionCommandInput>
16+
}
17+
18+
export { AppConfigGetOptionsInterface };

0 commit comments

Comments
 (0)