import { DynamoDB } from "aws-sdk"; import { compose, curry, flatten, join, map, mergeAll, pluck, splitEvery, toPairs } from "ramda"; import * as P from "~/shared/promise"; const DYNAMO_DB_MAX_BATCH_SIZE = 25; const splitBatches = splitEvery(DYNAMO_DB_MAX_BATCH_SIZE); export function createEnhancedClient() { const params = process.env.IS_LOCAL ? { region: "localhost", endpoint: "http://localhost:8000", } : {}; const client = new DynamoDB.DocumentClient(params); const writeSingleBatch = curry(function _writeSingleBatch(tableName, batch) { return client .batchWrite({ RequestItems: { [tableName]: batch, }, }) .promise(); }); const writeAllBatches = function _writeAllBatches(tableName, items) { return compose(map(writeSingleBatch(tableName)), splitBatches)(items); }; const batchWrite = curry(async function _batchWrite(tableName, items) { return flatten(await P.all(writeAllBatches(tableName, items))); }); return { client, batchWrite, }; } const buildGenericConditionExpression = curry(function _buildGenericConditionExpression(exprAttr, obj) { const buildDescriptors = compose( map(([key, value]) => ({ expr: `#${key} = :${key}`, name: { [`#${key}`]: key }, value: { [`:${key}`]: value }, })), toPairs ); const descriptors = buildDescriptors(obj); const buildExpression = compose(join(" and "), pluck("expr")); const buildAttrNames = compose(mergeAll, pluck("name")); const buildAttrValues = compose(mergeAll, pluck("value")); const expression = buildExpression(descriptors); const attrNames = buildAttrNames(descriptors); const attrValues = buildAttrValues(descriptors); return { [exprAttr]: expression, ExpressionAttributeNames: attrNames, ExpressionAttributeValues: attrValues, }; }); export const buildKeyConditionExpression = buildGenericConditionExpression("KeyConditionExpression"); export const buildConditionExpression = buildGenericConditionExpression("ConditionExpression"); export function buildSetUpdateExpression(obj) { const buildDescriptors = compose( map(([key, value]) => ({ expr: `#${key} = :${key}`, name: { [`#${key}`]: key }, value: { [`:${key}`]: value }, })), toPairs ); const descriptors = buildDescriptors(obj); const buildExpression = compose((expr) => `SET ${expr}`, join(", "), pluck("expr")); const buildAttrNames = compose(mergeAll, pluck("name")); const buildAttrValues = compose(mergeAll, pluck("value")); const expression = buildExpression(descriptors); const attrNames = buildAttrNames(descriptors); const attrValues = buildAttrValues(descriptors); return { UpdateExpression: expression, ExpressionAttributeNames: attrNames, ExpressionAttributeValues: attrValues, }; }