UNPKG

dynamodb-toolbox

Version:

Lightweight and type-safe query builder for DynamoDB and TypeScript.

118 lines (117 loc) 5.6 kB
import { BatchGetCommand as _BatchGetCommand } from '@aws-sdk/lib-dynamodb'; import { EntityFormatter } from '../../../entity/actions/format/index.js'; import { DynamoDBToolboxError } from '../../../errors/index.js'; import { parseCapacityOption } from '../../../options/capacity.js'; import { isEmpty } from '../../../utils/isEmpty.js'; import { BatchGetCommand } from './batchGetCommand.js'; import { $options, $requests } from './constants.js'; export const execute = async (..._commands) => { const [headCommandOrOptions = {}, ...tailCommands] = _commands; const commands = tailCommands; let options = {}; if (headCommandOrOptions instanceof BatchGetCommand) { commands.unshift(headCommandOrOptions); } else { options = headCommandOrOptions; } const firstCommand = commands[0]; if (firstCommand === undefined) { throw new DynamoDBToolboxError('actions.incompleteAction', { message: 'batchGet incomplete: No BatchGetCommand supplied' }); } const { maxAttempts = 1, documentClient, capacity, ...documentClientOptions } = options; const docClient = documentClient !== null && documentClient !== void 0 ? documentClient : firstCommand.table.getDocumentClient(); const { RequestItems: initialRequestItems, ...commandOptions } = getCommandInput(commands, { capacity }); let attemptCount = 0; let requestItems = initialRequestItems; let responses = undefined; let unprocessedKeys = {}; let consumedCapacity = undefined; let responseMetadata = {}; do { attemptCount += 1; const { Responses: attemptResponses, UnprocessedKeys: attemptUnprocessedKeys = {}, ConsumedCapacity: attemptConsumedCapacity, $metadata: attemptMetadata } = await docClient.send(new _BatchGetCommand({ RequestItems: requestItems, ...commandOptions }), documentClientOptions); if (attemptResponses !== undefined) { if (responses === undefined) { responses = {}; } for (const [tableName, attemptTableResponses] of Object.entries(attemptResponses)) { const tableResponses = responses[tableName]; if (tableResponses === undefined) { responses[tableName] = attemptTableResponses; } else { tableResponses.push(...attemptTableResponses); } } } requestItems = attemptUnprocessedKeys; unprocessedKeys = attemptUnprocessedKeys; consumedCapacity = attemptConsumedCapacity; responseMetadata = attemptMetadata; } while (attemptCount < maxAttempts && !isEmpty(unprocessedKeys)); let formattedResponses = undefined; if (responses !== undefined) { formattedResponses = commands.map(command => { const tableName = command.table.getName(); const requests = command[$requests]; const { attributes } = command[$options]; return requests === null || requests === void 0 ? void 0 : requests.map((request, index) => { const entity = request.entity; // We know responses is defined // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const tableResponses = responses[tableName]; if (tableResponses === undefined) { return undefined; } // We know RequestItems & Keys exist // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const itemKey = initialRequestItems[tableName].Keys[index]; const savedItem = tableResponses.find(tableResponse => Object.entries(itemKey).every(([key, value]) => tableResponse[key] === value)); if (savedItem === undefined) { return undefined; } return entity.build(EntityFormatter).format(savedItem, { attributes }); }); }); } return { ...(formattedResponses !== undefined ? { Responses: formattedResponses } : {}), ...(unprocessedKeys !== undefined ? { UnprocessedKeys: unprocessedKeys } : {}), // return ConsumedCapacity & $metadata only if one attempt has been tried ...(attemptCount === 1 ? { ...(consumedCapacity !== undefined ? { ConsumedCapacity: consumedCapacity } : {}), ...(responseMetadata !== undefined ? { $metadata: responseMetadata } : {}) } : {}) }; }; export const getCommandInput = (commands, options = {}) => { const requestItems = {}; if (commands.length === 0) { throw new DynamoDBToolboxError('actions.incompleteAction', { message: 'Unable to execute BatchGetCommands: No BatchGetCommand supplied' }); } for (const command of commands) { const commandParams = command.params(); for (const tableName of Object.keys(commandParams)) { if (tableName in requestItems) { throw new DynamoDBToolboxError('actions.invalidAction', { message: `Two BatchGetCommands detected for table: ${tableName}. Please provide only one BatchGetCommand per table` }); } } Object.assign(requestItems, commandParams); } const { capacity } = options; return { RequestItems: requestItems, ...(capacity !== undefined ? { ReturnConsumedCapacity: parseCapacityOption(capacity) } : {}) }; };