UNPKG

@blueleader07/typeorm

Version:

Data-Mapper ORM for TypeScript, ES7, ES6, ES5. Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, MongoDB databases.

288 lines (286 loc) 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DynamoEntityManager = void 0; /** * Entity manager supposed to work with any entity, automatically find its repository and call its methods, * whatever entity type are you passing. * * This implementation is used for DynamoDB driver which has some specifics in its EntityManager. */ const EntityManager_1 = require("./EntityManager"); const FindOptionsUtils_1 = require("../find-options/FindOptionsUtils"); const DynamoParamHelper_1 = require("../driver/dynamo/helpers/DynamoParamHelper"); const DynamoGlobalSecondaryIndexHelper_1 = require("../driver/dynamo/helpers/DynamoGlobalSecondaryIndexHelper"); const DynamoFindOptions_1 = require("../driver/dynamo/models/DynamoFindOptions"); const DynamoBatchHelper_1 = require("../driver/dynamo/helpers/DynamoBatchHelper"); const DynamoObjectHelper_1 = require("../driver/dynamo/helpers/DynamoObjectHelper"); const DynamoClient_1 = require("../driver/dynamo/DynamoClient"); // todo: we should look at the @PrimaryKey on the entity const DEFAULT_KEY_MAPPER = (item) => { return { id: item.id, }; }; class DynamoEntityManager extends EntityManager_1.EntityManager { get dynamodbQueryRunner() { return this.connection.driver .queryRunner; } // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- constructor(connection) { super(connection); } // ------------------------------------------------------------------------- // Overridden Methods // ------------------------------------------------------------------------- createDefaultKeyMapper(target) { const metadata = this.connection.getMetadata(target); return (entity) => { const keys = {}; for (let i = 0; i < metadata.primaryColumns.length; i++) { const primaryColumn = metadata.primaryColumns[i]; const propertyName = primaryColumn.propertyName; keys[propertyName] = entity[propertyName]; } return keys; }; } async update(entityClassOrName, options) { const metadata = this.connection.getMetadata(entityClassOrName); const changedValues = (0, DynamoObjectHelper_1.mixin)(options.setValues || {}, options.where); (0, DynamoGlobalSecondaryIndexHelper_1.indexedColumns)(metadata, changedValues); (0, DynamoObjectHelper_1.mixin)(options.setValues, changedValues); delete options.setValues.id; const params = DynamoParamHelper_1.dynamoParamHelper.update(metadata.tablePath, options); return (0, DynamoClient_1.getDocumentClient)().update(params).promise(); } /** * Finds entities that match given find options or conditions. */ async find(entityClassOrName, options) { if (options) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClassOrName); const params = DynamoParamHelper_1.dynamoParamHelper.find(metadata.tablePath, options, metadata.indices); const results = (0, DynamoObjectHelper_1.isEmpty)(options.where) ? await dbClient.scan(params).promise() : await dbClient.query(params).promise(); const items = results.Items || []; items.lastEvaluatedKey = results.LastEvaluatedKey; return items; } return []; } /** * Finds entities that match given find options or conditions. */ async findAll(entityClassOrName, options) { delete options.limit; const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClassOrName); const params = DynamoParamHelper_1.dynamoParamHelper.find(metadata.tablePath, options, metadata.indices); let items = []; let results = await dbClient.query(params).promise(); items = items.concat(results.Items || []); while (results.LastEvaluatedKey) { params.ExclusiveStartKey = results.LastEvaluatedKey; results = await dbClient.query(params).promise(); items = items.concat(results.Items || []); } return items; } async scan(entityClassOrName, options) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClassOrName); const params = { TableName: metadata.tablePath, // IndexName: findOptions.index, // KeyConditionExpression: FindOptions.toKeyConditionExpression(findOptions.where), // ExpressionAttributeValues: FindOptions.toExpressionAttributeValues(findOptions.where) }; if (options.limit) { params.Limit = options.limit; } if (options.exclusiveStartKey) { params.ExclusiveStartKey = options.exclusiveStartKey; } const results = await dbClient.scan(params).promise(); const items = results.Items || []; items.LastEvaluatedKey = results.LastEvaluatedKey; return items; } /** * Finds first entity that matches given conditions and/or find options. */ async findOne(entityClass, options) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClass); const id = typeof options === "string" ? options : undefined; const findOneOptionsOrConditions = options; let findOptions; if (FindOptionsUtils_1.FindOptionsUtils.isFindOneOptions(findOneOptionsOrConditions)) { findOptions = new DynamoFindOptions_1.DynamoFindOptions(); findOptions.where = findOneOptionsOrConditions.where; findOptions.limit = 1; } else { findOptions = new DynamoFindOptions_1.DynamoFindOptions(); findOptions.where = { id }; findOptions.limit = 1; } const params = DynamoParamHelper_1.dynamoParamHelper.find(metadata.tablePath, findOptions, metadata.indices); const results = await dbClient.query(params).promise(); const items = results.Items || []; return items.length > 0 ? items[0] : undefined; } /** * Finds first entity that matches given conditions and/or find options. */ async findOneBy(entityClass, options) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClass); const findOptions = new DynamoFindOptions_1.DynamoFindOptions(); findOptions.where = options; findOptions.limit = 1; const params = DynamoParamHelper_1.dynamoParamHelper.find(metadata.tablePath, findOptions, metadata.indices); const results = await dbClient.query(params).promise(); const items = results.Items || []; return items.length > 0 ? items[0] : undefined; } /** * Put a given entity into the database. * Unlike save method executes a primitive operation without cascades, relations and other operations included. * Executes fast and efficient INSERT query. * Does not check if entity exist in the database, so query will fail if duplicate entity is being inserted. * You can execute bulk inserts using this method. */ async put(target, entity) { if (Array.isArray(entity)) { return this.putMany(target, entity); } else { return this.putOne(target, entity); } } async delete(targetOrEntity, criteria) { if (Array.isArray(criteria)) { await this.deleteMany(targetOrEntity, criteria); } else { await this.deleteOne(targetOrEntity, criteria); } return { raw: {}, }; } async deleteAll(target, options, keyMapper) { let items = await this.scan(target, { limit: 500 }); while (items.length > 0) { const itemIds = items.map(keyMapper || this.createDefaultKeyMapper(target)); await this.deleteMany(target, itemIds); await this.deleteAll(target, keyMapper); items = await this.scan(target, { limit: 500 }); } } deleteAllBy(target, options, keyMapper) { options.limit = options.limit || 500; return this.deleteQueryBatch(target, options, keyMapper); } async deleteQueryBatch(target, options, keyMapper) { const items = await this.find(target, options); if (items.length > 0) { const metadata = this.connection.getMetadata(target); keyMapper = keyMapper || DEFAULT_KEY_MAPPER; const keys = items.map(keyMapper); await this.deleteMany(metadata.tablePath, keys); await this.deleteQueryBatch(target, options, keyMapper); } } /** * Delete multiple documents on DynamoDB. */ deleteMany(entityClassOrName, keys) { const metadata = this.connection.getMetadata(entityClassOrName); return this.dynamodbQueryRunner.deleteMany(metadata.tablePath, keys); } /** * Delete a document on DynamoDB. */ deleteOne(entityClassOrName, key) { const metadata = this.connection.getMetadata(entityClassOrName); return this.dynamodbQueryRunner.deleteOne(metadata.tablePath, key); } /** * Put an array of documents into DynamoDB. */ putMany(entityClassOrName, docs) { const metadata = this.connection.getMetadata(entityClassOrName); docs.forEach((doc) => { (0, DynamoGlobalSecondaryIndexHelper_1.indexedColumns)(metadata, doc); }); return this.dynamodbQueryRunner.putMany(metadata.tablePath, docs); } /** * Put a single document into DynamoDB. */ putOne(entityClassOrName, doc) { const metadata = this.connection.getMetadata(entityClassOrName); (0, DynamoGlobalSecondaryIndexHelper_1.indexedColumns)(metadata, doc); (0, DynamoGlobalSecondaryIndexHelper_1.populateGeneratedColumns)(metadata, doc); return this.dynamodbQueryRunner.putOne(metadata.tablePath, doc); } /** * Read from DynamoDB in batches. */ async batchRead(entityClassOrName, keys) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClassOrName); const batches = DynamoBatchHelper_1.dynamoBatchHelper.batch(keys, 100); let items = []; for (let i = 0; i < batches.length; i++) { const batch = batches[i]; const requestItems = {}; requestItems[metadata.tablePath] = { Keys: batch, }; const response = await dbClient .batchGet({ RequestItems: requestItems, }) .promise(); if (response.Responses !== undefined) { items = items.concat(response.Responses[metadata.tablePath]); } } return items; } /** * Put an array of documents into DynamoDB in batches. */ // TODO: ... how do we update the indexColumn values here ... ? async batchWrite(entityClassOrName, writes) { const dbClient = (0, DynamoClient_1.getDocumentClient)(); const metadata = this.connection.getMetadata(entityClassOrName); const batches = DynamoBatchHelper_1.dynamoBatchHelper.batch(writes, 25); for (let i = 0; i < batches.length; i++) { const batch = batches[i]; const requestItems = {}; requestItems[metadata.tablePath] = batch.map((write) => { const request = {}; request[write.type] = { Item: write.item, }; return request; }); await dbClient .batchWrite({ RequestItems: requestItems, }) .promise(); } } } exports.DynamoEntityManager = DynamoEntityManager; //# sourceMappingURL=DynamoEntityManager.js.map