Skip to content

Instantly share code, notes, and snippets.

@mtimbs
Last active October 5, 2021 02:10
Show Gist options
  • Save mtimbs/bcd3b58ef719409b374d17c7b7033cf4 to your computer and use it in GitHub Desktop.
Save mtimbs/bcd3b58ef719409b374d17c7b7033cf4 to your computer and use it in GitHub Desktop.
Recursive Dynamic Update DynamoDB (WIP)
import { NativeAttributeValue } from '@aws-sdk/util-dynamodb/src/models';
import { AttributeValue } from '@aws-sdk/client-dynamodb';
import { marshall } from '@aws-sdk/util-dynamodb';
interface DynamoUpdateParams {
UpdateExpression: string;
ExpressionAttributeNames: Record<string, string>;
ExpressionAttributeValues: Record<string, AttributeValue>;
}
const attributeExtractor = (item: Record<string, unknown>) => Object.entries(item).reduce((previous, [key, value]): Record<string, string> =>
({
...previous,
...{ [`#${key}`]: key },
...(typeof value === 'object' && value !== null && Object.keys(item).length > 0) && attributeExtractor(value as Record<string, unknown>)
}),
{});
const valueExtractor = (item: Record<string, NativeAttributeValue>) => Object.entries(item).reduce((previous, [key, value]): Record<string, string> =>
({
...previous,
...(typeof value !== 'object') && marshall({ [`:${key}`]: value }),
...(typeof value === 'object' && value !== null && Object.keys(item).length > 0) && valueExtractor(value as Record<string, unknown>)
}),
{});
const expressionCreator = (item: Record<string, unknown>, prefix: string|null) =>
Object.entries(item).reduce<string>((carry, [key, value]): string => {
const prefixedKey = prefix ? `${prefix}.#${key}` : `#${key}`;
if (typeof value === 'object' && value !== null && Object.keys(item).length > 0) {
return `${carry}${expressionCreator(value as Record<string, unknown>, prefixedKey)}`;
}
return `${carry} ${prefixedKey} = :${key},`;
}, '');
export const dynamicUpdateExpressionFromObject = <T extends { [K in keyof T]: NativeAttributeValue }>(item: T): DynamoUpdateParams => {
const ExpressionAttributeNames: Record<string, string> = attributeExtractor(item);
const ExpressionAttributeValues: Record<string, AttributeValue> = valueExtractor(item);
const UpdateExpression = `SET${expressionCreator(item, null).slice(0, -1)}`;
return {
UpdateExpression,
ExpressionAttributeNames,
ExpressionAttributeValues,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment