UNPKG

dynolink

Version:
186 lines (185 loc) 6.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseRepository = void 0; const client_dynamodb_1 = require("@aws-sdk/client-dynamodb"); const util_dynamodb_1 = require("@aws-sdk/util-dynamodb"); const decorators_1 = require("./decorators"); const query_builder_1 = require("./query-builder"); const uuid_1 = require("uuid"); /** * BaseRepository class for managing DynamoDB entities. */ class BaseRepository { constructor(client) { this.client = client; this.metadata = (0, decorators_1.getEntityMetadata)(this.getEntityType()); this.tableName = this.metadata.tableName; } /** * Applies default values and auto-generated IDs to the entity. * @param entity * @protected */ applyDefaultsAndAutoId(entity) { for (const [key, attr] of this.metadata.attributes.entries()) { const val = entity[key]; if (attr.autoId && !val) entity[key] = (0, uuid_1.v4)(); else if ((val === undefined || val === null) && attr.defaultValue !== undefined) entity[key] = typeof attr.defaultValue === 'function' ? attr.defaultValue() : attr.defaultValue; } return entity; } /** * Transforms the entity using the defined transformers. * @param entity * @param dir * @protected */ transform(entity, dir) { for (const [key, attr] of this.metadata.attributes.entries()) { const transformer = attr.transformer; if (transformer) entity[key] = transformer(entity[key], dir); } return entity; } /** * Saves the entity to DynamoDB. * @param entity */ async save(entity) { this.applyDefaultsAndAutoId(entity); const data = (0, util_dynamodb_1.marshall)(this.transform(entity, 'toDb'), { removeUndefinedValues: true, convertClassInstanceToMap: true }); await this.client.send(new client_dynamodb_1.PutItemCommand({ TableName: this.tableName, Item: data })); } /** * Updates an entity in DynamoDB. * @param key * @param updatedEntity */ async update(key, updatedEntity) { const fullItem = { ...key, ...updatedEntity }; const data = (0, util_dynamodb_1.marshall)(this.transform(fullItem, 'toDb'), { removeUndefinedValues: true, convertClassInstanceToMap: true }); await this.client.send(new client_dynamodb_1.PutItemCommand({ TableName: this.tableName, Item: data })); } /** * Updates partial fields of an entity in DynamoDB. * @param key * @param updates */ async updatePartial(key, updates) { const pk = this.getKey(key); const expressions = []; const names = {}; const values = {}; Object.entries(updates).forEach(([k, v], i) => { const attr = `#attr${i}`; const val = `:val${i}`; expressions.push(`${attr} = ${val}`); names[attr] = k; values[val] = v; }); await this.client.send(new client_dynamodb_1.UpdateItemCommand({ TableName: this.tableName, Key: (0, util_dynamodb_1.marshall)(pk), UpdateExpression: `SET ${expressions.join(', ')}`, ExpressionAttributeNames: names, ExpressionAttributeValues: (0, util_dynamodb_1.marshall)(values), })); } /** * Deletes an entity from DynamoDB. * @param key */ async delete(key) { const pk = this.getKey(key); await this.client.send(new client_dynamodb_1.DeleteItemCommand({ TableName: this.tableName, Key: (0, util_dynamodb_1.marshall)(pk), })); } /** * Finds an entity by its primary key. * @param key */ async findOne(key) { const pk = this.getKey(key); const res = await this.client.send(new client_dynamodb_1.GetItemCommand({ TableName: this.tableName, Key: (0, util_dynamodb_1.marshall)(pk) })); if (!res.Item) return null; const entity = (0, util_dynamodb_1.unmarshall)(res.Item); return this.transform(entity, 'fromDb'); } /** * Batch retrieves entities from DynamoDB. * @param keys */ async batchGet(keys) { const requestKeys = keys.map((key) => (0, util_dynamodb_1.marshall)(this.getKey(key))); const command = new client_dynamodb_1.BatchGetItemCommand({ RequestItems: { [this.tableName]: { Keys: requestKeys, }, }, }); const result = await this.client.send(command); const items = result.Responses?.[this.tableName] ?? []; return items.map((item) => this.transform((0, util_dynamodb_1.unmarshall)(item), 'fromDb')); } /** * Batch writes entities to DynamoDB. * @param entities * @param action */ async batchWrite(entities, action = 'put') { const requestItems = entities.map((entity) => { if (action === 'put') { const transformed = (0, util_dynamodb_1.marshall)(this.transform(entity, 'toDb'), { removeUndefinedValues: true, convertClassInstanceToMap: true, }); return { PutRequest: { Item: transformed } }; } else { return { DeleteRequest: { Key: (0, util_dynamodb_1.marshall)(this.getKey(entity)) } }; } }); await this.client.send(new client_dynamodb_1.BatchWriteItemCommand({ RequestItems: { [this.tableName]: requestItems, }, })); } /** * Queries the table using the provided filters. * @param filters */ async query(filters) { const builder = new query_builder_1.QueryBuilder(this.metadata); const params = builder.build(filters); const res = await this.client.send(new client_dynamodb_1.QueryCommand({ TableName: this.tableName, ...params, })); return (res.Items || []).map((item) => this.transform((0, util_dynamodb_1.unmarshall)(item), 'fromDb')); } /** * Generates the key for the entity based on its partition and sort keys. * @param input * @protected */ getKey(input) { const keys = {}; for (const [key, attr] of this.metadata.attributes.entries()) { if (attr.isPartitionKey || attr.isSortKey) { keys[key] = input[key]; } } return keys; } } exports.BaseRepository = BaseRepository;