@aws-lambda-powertools/parameters
Version:
The parameters package for the Powertools for AWS Lambda (TypeScript) library
365 lines (364 loc) • 14.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.DynamoDBProvider = void 0;
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
const BaseProvider_js_1 = require("../base/BaseProvider.js");
/**
* ## Intro
* The Parameters utility provides a DynamoDBProvider that allows to retrieve values from Amazon DynamoDB.
*
* ## Getting started
*
* This utility supports AWS SDK v3 for JavaScript only (`@aws-sdk/client-dynamodb` and `@aws-sdk/util-dynamodb`). This allows the utility to be modular, and you to install only
* the SDK packages you need and keep your bundle size small.
*
* ## Basic usage
*
* Retrieve a value from DynamoDB:
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a value from DynamoDB
* const value = await tableProvider.get('my-value-key');
* };
* ```
*
* You can also retrieve multiple values at once:
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve multiple values from DynamoDB
* const values = await tableProvider.getMultiple('my-values-path');
* };
* ```
*
* ## Advanced usage
*
* ### Caching
*
* By default, the provider will cache parameters retrieved in-memory for 5 seconds.
* You can adjust how long values should be kept in cache by using the `maxAge` parameter.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a value and cache it for 10 seconds
* const value = await tableProvider.get('my-value-key', { maxAge: 10 });
* // Retrieve multiple values and cache them for 20 seconds
* const values = await tableProvider.getMultiple('my-values-path', { maxAge: 20 });
* };
* ```
*
* If instead you'd like to always ensure you fetch the latest parameter from the store regardless if already available in cache, use the `forceFetch` parameter.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a value and skip cache
* const value = await tableProvider.get('my-value-key', { forceFetch: true });
* // Retrieve multiple values and skip cache
* const values = await tableProvider.getMultiple('my-values-path', { forceFetch: true });
* };
* ```
*
* ### Transformations
*
* For values stored as JSON you can use the transform argument for deserialization. This will return a JavaScript object instead of a string.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a value and parse it as JSON
* const value = await tableProvider.get('my-value-key', { transform: 'json' });
* // Retrieve multiple values and parse them as JSON
* const values = await tableProvider.getMultiple('my-values-path', { transform: 'json' });
* };
* ```
*
* For values that are instead stored as base64-encoded binary data, you can use the transform argument set to `binary` for decoding. This will return a decoded string.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a base64-encoded string and decode it
* const value = await tableProvider.get('my-value-key', { transform: 'binary' });
* // Retrieve multiple base64-encoded strings and decode them
* const values = await tableProvider.getMultiple('my-values-path', { transform: 'binary' });
* };
* ```
*
* When retrieving multiple values, you can also use the `transform` argument set to `auto` to let the provider automatically detect the type of transformation to apply.
* The provider will use the suffix of the sort key (`sk`) to determine the transformation to apply. For example, if the sort key is `my-value-key.json`, the provider will
* automatically parse the value as JSON. Likewise, if the sort key is `my-value-key.binary`, the provider will automatically decode the value as base64-encoded binary data.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve multiple values and automatically detect the transformation to apply
* const values = await tableProvider.getMultiple('my-values-path', { transform: 'auto' });
* };
* ```
*
* ### Custom key names
*
* By default, the provider will use the following key names: `id` for the partition key, `sk` for the sort key, and `value` for the value.
* You can adjust the key names by using the `keyAttr`, `sortAttr`, and `valueAttr` parameters.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* keyAttr: 'key',
* sortAttr: 'sort',
* valueAttr: 'val',
* });
* ```
*
* ### Extra SDK options
*
* When retrieving values, you can pass extra options to the AWS SDK v3 for JavaScript client by using the `sdkOptions` parameter.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a value and pass extra options to the AWS SDK v3 for JavaScript client
* const value = await tableProvider.get('my-value-key', {
* sdkOptions: {
* ConsistentRead: true,
* },
* });
* };
* ```
*
* The objects accept the same options as respectively the [AWS SDK v3 for JavaScript PutItem command](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/putitemcommand.html) and the [AWS SDK v3 for JavaScript DynamoDB client Query command](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/querycommand.html).
*
* ### Customize AWS SDK v3 for JavaScript client
*
* By default, the provider will create a new DynamoDB client using the default configuration.
*
* You can customize the client by passing a custom configuration object to the provider.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* clientConfig: { region: 'eu-west-1' },
* });
* ```
*
* This object accepts the same options as the [AWS SDK v3 for JavaScript DynamoDB client constructor](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/dynamodbclient.html).
*
* Otherwise, if you want to use a custom client altogether, you can pass it to the provider.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
* import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
*
* const client = new DynamoDBClient({ region: 'eu-west-1' });
* const tableProvider = new DynamoDBProvider({
* awsSdkV3Client: client,
* });
* ```
*
* This object must be an instance of the [AWS SDK v3 for JavaScript DynamoDB client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/dynamodbclient.html).
*
* For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/).
*/
class DynamoDBProvider extends BaseProvider_js_1.BaseProvider {
keyAttr = 'id';
sortAttr = 'sk';
tableName;
valueAttr = 'value';
/**
* It initializes the DynamoDBProvider class.
*
* @param {DynamoDBProviderOptions} config - The configuration object.
*/
constructor(config) {
super({
awsSdkV3ClientPrototype: client_dynamodb_1.DynamoDBClient,
...config,
});
const { tableName, keyAttr, sortAttr, valueAttr } = config;
this.tableName = tableName;
if (keyAttr)
this.keyAttr = keyAttr;
if (sortAttr)
this.sortAttr = sortAttr;
if (valueAttr)
this.valueAttr = valueAttr;
}
/**
* Retrieve a value from Amazon DynamoDB.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve a single value
* const value = await tableProvider.get('my-value-key');
* };
* ```
*
* You can customize the retrieval of the value by passing options to the function:
* * `maxAge` - The maximum age of the value in cache before fetching a new one (in seconds) (default: 5)
* * `forceFetch` - Whether to always fetch a new value from the store regardless if already available in cache
* * `transform` - Whether to transform the value before returning it. Supported values: `json`, `binary`
* * `sdkOptions` - Extra options to pass to the AWS SDK v3 for JavaScript client
*
* For usage examples check {@link DynamoDBProvider}.
*
* @param {string} name - The name of the value to retrieve (i.e. the partition key)
* @param {DynamoDBGetOptionsInterface} options - Options to configure the provider
* @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/
*/
async get(name, options) {
return super.get(name, options);
}
/**
* Retrieve multiple values from Amazon DynamoDB.
*
* @example
* ```typescript
* import { DynamoDBProvider } from '@aws-lambda-powertools/parameters/dynamodb';
*
* const tableProvider = new DynamoDBProvider({
* tableName: 'my-table',
* });
*
* export const handler = async (): Promise<void> => {
* // Retrieve multiple values
* const values = await tableProvider.getMultiple('my-values-path');
* };
* ```
*
* You can customize the retrieval of the values by passing options to the function:
* * `maxAge` - The maximum age of the value in cache before fetching a new one (in seconds) (default: 5)
* * `forceFetch` - Whether to always fetch a new value from the store regardless if already available in cache
* * `transform` - Whether to transform the value before returning it. Supported values: `json`, `binary`
* * `sdkOptions` - Extra options to pass to the AWS SDK v3 for JavaScript client
* * `throwOnTransformError` - Whether to throw an error if the transform fails (default: `true`)
*
* For usage examples check {@link DynamoDBProvider}.
*
* @param {string} path - The path of the values to retrieve (i.e. the partition key)
* @param {DynamoDBGetMultipleOptions} options - Options to configure the provider
* @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/
*/
async getMultiple(path, options) {
return super.getMultiple(path, options);
}
/**
* Retrieve an item from Amazon DynamoDB.
*
* @param {string} name - Key of the item to retrieve (i.e. the partition key)
* @param {DynamoDBGetOptions} options - Options to customize the retrieval
*/
async _get(name, options) {
const sdkOptions = {
...(options?.sdkOptions || {}),
TableName: this.tableName,
Key: (0, util_dynamodb_1.marshall)({ [this.keyAttr]: name }),
ProjectionExpression: '#value',
ExpressionAttributeNames: {
'#value': this.valueAttr,
},
};
const result = await this.client.send(new client_dynamodb_1.GetItemCommand(sdkOptions));
return result.Item ? (0, util_dynamodb_1.unmarshall)(result.Item)[this.valueAttr] : undefined;
}
/**
* Retrieve multiple items from Amazon DynamoDB.
*
* @param {string} path - The path of the values to retrieve (i.e. the partition key)
* @param {DynamoDBGetMultipleOptions} options - Options to customize the retrieval
*/
async _getMultiple(path, options) {
const sdkOptions = {
...(options?.sdkOptions || {}),
TableName: this.tableName,
KeyConditionExpression: '#key = :key',
ExpressionAttributeValues: (0, util_dynamodb_1.marshall)({ ':key': path }),
ExpressionAttributeNames: {
'#key': this.keyAttr,
'#sk': this.sortAttr,
'#value': this.valueAttr,
},
ProjectionExpression: '#sk, #value',
};
const paginationOptions = {
client: this.client,
pageSize: options?.sdkOptions?.Limit,
};
const parameters = {};
for await (const page of (0, client_dynamodb_1.paginateQuery)(paginationOptions, sdkOptions)) {
for (const item of page.Items || []) {
const unmarshalledItem = (0, util_dynamodb_1.unmarshall)(item);
parameters[unmarshalledItem[this.sortAttr]] =
unmarshalledItem[this.valueAttr];
}
}
return parameters;
}
}
exports.DynamoDBProvider = DynamoDBProvider;
;