1
1
import { fromBase64 } from '@aws-sdk/util-base64-node' ;
2
- import { GetParameterError , TransformParameterError } from 'Exceptions' ;
3
- import type { BaseProviderInterface , ExpirableValueInterface , GetMultipleOptionsInterface , GetOptionsInterface , Key , TransformOptions } from './types' ;
2
+ import { GetParameterError , TransformParameterError } from './ Exceptions' ;
3
+ import type { BaseProviderInterface , ExpirableValueInterface , GetMultipleOptionsInterface , GetOptionsInterface , TransformOptions } from './types' ;
4
4
5
5
const DEFAULT_MAX_AGE_SECS = 5 ;
6
- // These providers will be dynamically initialized on first use of the helper functions
7
- const DEFAULT_PROVIDERS = new Map ( ) ;
8
6
const TRANSFORM_METHOD_JSON = 'json' ;
9
7
const TRANSFORM_METHOD_BINARY = 'binary' ;
10
8
@@ -23,7 +21,7 @@ class GetMultipleOptions implements GetMultipleOptionsInterface {
23
21
public forceFetch : boolean = false ;
24
22
public maxAge : number = DEFAULT_MAX_AGE_SECS ;
25
23
public sdkOptions ?: unknown ;
26
- public throwOnTransformError ? : boolean = false ;
24
+ public throwOnTransformError : boolean = false ;
27
25
public transform ?: TransformOptions ;
28
26
29
27
public constructor ( options : GetMultipleOptionsInterface ) {
@@ -47,13 +45,13 @@ class ExpirableValue implements ExpirableValueInterface {
47
45
}
48
46
49
47
abstract class BaseProvider implements BaseProviderInterface {
50
- public store : Map < Key , ExpirableValue > = new Map ;
48
+ public store : Map < string , ExpirableValue > = new Map ;
51
49
52
- private constructor ( ) {
50
+ public constructor ( ) {
53
51
this . store = new Map ( ) ;
54
52
}
55
53
56
- public addToCache ( key : Key , value : string | Record < string , unknown > , maxAge : number ) : void {
54
+ public addToCache ( key : string , value : string | Record < string , unknown > , maxAge : number ) : void {
57
55
if ( maxAge <= 0 ) return ;
58
56
59
57
this . store . set ( key , new ExpirableValue ( value , maxAge ) ) ;
@@ -79,10 +77,11 @@ abstract class BaseProvider implements BaseProviderInterface {
79
77
*/
80
78
public async get ( name : string , options ?: GetOptionsInterface ) : Promise < undefined | string | Record < string , unknown > > {
81
79
const configs = new GetOptions ( options ) ;
82
- const key = { [ name ] : configs . transform } ;
80
+ const key = [ name , configs . transform ] . toString ( ) ;
83
81
84
- if ( ! configs . forceFetch && this . hasNotExpiredInCache ( key ) ) {
85
- return this . store . get ( key ) ?. value ;
82
+ if ( ! configs . forceFetch && ! this . hasKeyExpiredInCache ( key ) ) {
83
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84
+ return this . store . get ( key ) ! . value ;
86
85
}
87
86
88
87
let value ;
@@ -93,7 +92,7 @@ abstract class BaseProvider implements BaseProviderInterface {
93
92
}
94
93
95
94
if ( value && configs . transform ) {
96
- value = transformValue ( value , configs . transform ) ;
95
+ value = transformValue ( value , configs . transform , true ) ;
97
96
}
98
97
99
98
if ( value ) {
@@ -106,10 +105,11 @@ abstract class BaseProvider implements BaseProviderInterface {
106
105
107
106
public async getMultiple ( path : string , options ?: GetMultipleOptionsInterface ) : Promise < undefined | Record < string , unknown > > {
108
107
const configs = new GetMultipleOptions ( options || { } ) ;
109
- const key = { [ path ] : configs . transform } ;
108
+ const key = [ path , configs . transform ] . toString ( ) ;
110
109
111
- if ( ! configs . forceFetch && this . hasNotExpiredInCache ( key ) ) {
112
- return this . store . get ( key ) ?. value as Record < string , unknown > ; // In this case we know that if it exists, this key corresponds to a Record
110
+ if ( ! configs . forceFetch && ! this . hasKeyExpiredInCache ( key ) ) {
111
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
112
+ return this . store . get ( key ) ! . value as Record < string , unknown > ; // In this case we know that if it exists, this key corresponds to a Record
113
113
}
114
114
115
115
let values : Record < string , unknown > = { } ;
@@ -119,8 +119,8 @@ abstract class BaseProvider implements BaseProviderInterface {
119
119
throw new GetParameterError ( ( error as Error ) . message ) ;
120
120
}
121
121
122
- if ( configs . transform ) {
123
- values = transformValues ( values , configs . transform ) ;
122
+ if ( Object . keys ( values ) && configs . transform ) {
123
+ values = transformValues ( values , configs . transform , configs . throwOnTransformError ) ;
124
124
}
125
125
126
126
if ( Array . from ( Object . keys ( values ) ) . length !== 0 ) {
@@ -142,36 +142,48 @@ abstract class BaseProvider implements BaseProviderInterface {
142
142
protected abstract _getMultiple ( path : string , sdkOptions ?: unknown ) : Promise < Record < string , string | undefined > > ;
143
143
144
144
/**
145
- * Check whether a key has not expired in the cache
145
+ * Check whether a key has expired in the cache or not
146
146
*
147
- * It returns false if the key is expired or not present in the cache.
147
+ * It returns true if the key is expired or not present in the cache.
148
148
*
149
- * @param {Key } key - Key to retrieve
149
+ * @param {string } key - Stringified representation of the key to retrieve
150
150
*/
151
- private hasNotExpiredInCache ( key : Key ) : boolean {
151
+ private hasKeyExpiredInCache ( key : string ) : boolean {
152
152
const value = this . store . get ( key ) ;
153
- if ( value ) value . isExpired ( ) ;
153
+ if ( value ) {
154
+ if ( value . isExpired ( ) ) {
155
+ this . store . delete ( key ) ;
156
+
157
+ return true ;
158
+ }
154
159
155
- return false ;
160
+ return value . isExpired ( ) ;
161
+ }
162
+
163
+ return true ;
156
164
}
157
165
158
166
}
159
167
160
- const transformValue = ( value : string , transform : TransformOptions , throwOnTransformError : boolean = true , key : string = '' ) : string | Record < string , unknown > | undefined => {
168
+ // TODO: revisit `value` type once we are clearer on the types returned by the various SDKs
169
+ const transformValue = ( value : unknown , transform : TransformOptions , throwOnTransformError : boolean , key : string = '' ) : string | Record < string , unknown > | undefined => {
161
170
try {
162
171
const normalizedTransform = transform . toLowerCase ( ) ;
163
172
if (
164
- normalizedTransform === TRANSFORM_METHOD_JSON ||
165
- ( normalizedTransform === 'auto' && key . toLowerCase ( ) . endsWith ( `.${ TRANSFORM_METHOD_JSON } ` ) )
173
+ ( normalizedTransform === TRANSFORM_METHOD_JSON ||
174
+ ( normalizedTransform === 'auto' && key . toLowerCase ( ) . endsWith ( `.${ TRANSFORM_METHOD_JSON } ` ) ) ) &&
175
+ typeof value === 'string'
166
176
) {
167
177
return JSON . parse ( value ) as Record < string , unknown > ;
168
178
} else if (
169
- normalizedTransform === TRANSFORM_METHOD_BINARY ||
170
- ( normalizedTransform === 'auto' && key . toLowerCase ( ) . endsWith ( `.${ TRANSFORM_METHOD_BINARY } ` ) )
179
+ ( normalizedTransform === TRANSFORM_METHOD_BINARY ||
180
+ ( normalizedTransform === 'auto' && key . toLowerCase ( ) . endsWith ( `.${ TRANSFORM_METHOD_BINARY } ` ) ) ) &&
181
+ typeof value === 'string'
171
182
) {
172
183
return new TextDecoder ( 'utf-8' ) . decode ( fromBase64 ( value ) ) ;
173
184
} else {
174
- throw Error ( `Invalid transform type ${ normalizedTransform } .` ) ;
185
+ // TODO: revisit this type once we are clearer on types returned by SDKs
186
+ return value as string ;
175
187
}
176
188
} catch ( error ) {
177
189
if ( throwOnTransformError )
@@ -181,27 +193,22 @@ const transformValue = (value: string, transform: TransformOptions, throwOnTrans
181
193
}
182
194
} ;
183
195
184
- const transformValues = ( value : string | Uint8Array | Record < string , unknown > , transform : TransformOptions , throwOnTransformError : boolean = true ) : Record < string , unknown > => {
196
+ const transformValues = ( value : Record < string , unknown > , transform : TransformOptions , throwOnTransformError : boolean ) : Record < string , unknown > => {
185
197
const transformedValues : Record < string , unknown > = { } ;
186
- for ( const entry in Object . entries ( value ) ) {
187
- const [ entryKey , entryValue ] = entry ;
198
+ for ( const [ entryKey , entryValue ] of Object . entries ( value ) ) {
188
199
try {
189
- transformedValues [ entryKey ] = transformValue ( entryValue , transform , true , entryKey ) ;
200
+ transformedValues [ entryKey ] = transformValue ( entryValue , transform , throwOnTransformError , entryKey ) ;
190
201
} catch ( error ) {
191
202
if ( throwOnTransformError )
192
203
throw new TransformParameterError ( transform , ( error as Error ) . message ) ;
193
- transformedValues [ entryKey ] = undefined ;
194
204
}
195
205
}
196
206
197
207
return transformedValues ;
198
208
} ;
199
209
200
- const clearCaches = ( ) : void => DEFAULT_PROVIDERS . clear ( ) ;
201
-
202
210
export {
203
- clearCaches ,
204
211
BaseProvider ,
212
+ ExpirableValue ,
205
213
transformValue ,
206
- DEFAULT_PROVIDERS
207
214
} ;
0 commit comments