UNPKG

@blueleader07/typeorm

Version:

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

256 lines (254 loc) 9.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addGlobalSecondaryIndex = exports.deleteGlobalSecondaryIndex = exports.updateGlobalSecondaryIndexes = exports.waitUntilActive = exports.buildGlobalSecondaryIndexes = exports.buildAttributeDefinitions = exports.populateGeneratedColumns = exports.indexedColumns = exports.buildPartitionKey = void 0; const uuid_1 = require("uuid"); const PlatformTools_1 = require("../../../platform/PlatformTools"); const buildPartitionKey = (columns) => { return columns .map((column) => { return column.propertyName; }) .join("#"); }; exports.buildPartitionKey = buildPartitionKey; const partitionKeyColumns = (columns, doc) => { if (columns.length > 1) { const partitionKey = (0, exports.buildPartitionKey)(columns); doc[partitionKey] = columns .map((column) => { return doc[column.propertyName]; }) .join("#"); } }; const sortKeyColumns = (sortKey, doc) => { const columns = sortKey.split("#"); if (columns.length > 1) { doc[sortKey] = columns .map((column) => { return doc[column]; }) .join("#"); } }; const indexedColumns = (metadata, doc) => { const indices = metadata.indices || []; for (let i = 0; i < indices.length; i += 1) { const index = indices[i]; const columns = index.columns || []; partitionKeyColumns(columns, doc); sortKeyColumns(index.where || "", doc); } }; exports.indexedColumns = indexedColumns; const populateGeneratedColumns = (metadata, doc) => { const generatedColumns = metadata.generatedColumns || []; for (let i = 0; i < generatedColumns.length; i += 1) { const generatedColumn = generatedColumns[i]; const value = generatedColumn.generationStrategy === "uuid" ? (0, uuid_1.v4)() : 1; if (generatedColumn.generationStrategy !== "uuid") { console.warn(`generationStrategy is not supported by dynamodb: ${generatedColumn.generationStrategy}`); } doc[generatedColumn.propertyName] = doc[generatedColumn.propertyName] || value; } }; exports.populateGeneratedColumns = populateGeneratedColumns; const primaryKeyAttributes = (metadata, driver, attributeMap) => { for (let i = 0; i < metadata.primaryColumns.length; i += 1) { const primaryColumn = metadata.primaryColumns[i]; attributeMap.set(primaryColumn.propertyName, { AttributeName: primaryColumn.propertyName, AttributeType: driver.normalizeDynamodbType(primaryColumn), }); } }; const keyAttributes = (metadata, driver, key, attributeMap) => { if (key.includes("#")) { attributeMap.set(key, { AttributeName: key, AttributeType: "S", }); } else { const column = metadata.columns.find((column) => { return column.propertyName === key; }); if (column) { attributeMap.set(key, { AttributeName: key, AttributeType: driver.normalizeDynamodbType(column), }); } } }; const partitionKeyAttributes = (metadata, driver, attributeMap) => { const indices = metadata.indices || []; for (let i = 0; i < indices.length; i += 1) { const index = indices[i]; const columns = index.columns || []; const partitionKey = (0, exports.buildPartitionKey)(columns); keyAttributes(metadata, driver, partitionKey, attributeMap); const sortKey = index.where || ""; keyAttributes(metadata, driver, sortKey, attributeMap); } }; const buildAttributeDefinitions = (metadata, driver) => { const attributeMap = new Map(); primaryKeyAttributes(metadata, driver, attributeMap); partitionKeyAttributes(metadata, driver, attributeMap); return Array.from(attributeMap.values()); }; exports.buildAttributeDefinitions = buildAttributeDefinitions; const buildGlobalSecondaryIndexes = (metadata) => { const globalSecondaryIndexes = []; const indices = metadata.indices || []; for (let i = 0; i < indices.length; i += 1) { const index = indices[i]; const globalSecondaryIndex = {}; globalSecondaryIndex.IndexName = index.name; globalSecondaryIndex.KeySchema = []; const columns = index.columns || []; const partitionKey = (0, exports.buildPartitionKey)(columns); globalSecondaryIndex.KeySchema.push({ AttributeName: partitionKey, KeyType: "HASH", }); const sortKey = index.where || ""; if (sortKey) { globalSecondaryIndex.KeySchema.push({ AttributeName: sortKey, KeyType: "RANGE", }); } globalSecondaryIndex.Projection = { ProjectionType: "ALL", }; globalSecondaryIndexes.push(globalSecondaryIndex); } return globalSecondaryIndexes.length > 0 ? globalSecondaryIndexes : undefined; }; exports.buildGlobalSecondaryIndexes = buildGlobalSecondaryIndexes; const wait = (seconds) => { return new Promise((resolve) => { setTimeout(function () { resolve(); }, seconds); }); }; const waitUntilActive = async (db, tableName) => { let retries = 10; while (retries > 0) { try { const result = await db .describeTable({ TableName: tableName, }) .promise(); const status = result.Table.TableStatus; if (status === "ACTIVE") { break; } await wait(10); } catch (error) { const _error = error; PlatformTools_1.PlatformTools.logError(`failed to describe table: ${tableName}`, _error); } retries -= 1; } }; exports.waitUntilActive = waitUntilActive; const updateGlobalSecondaryIndexes = async (db, tableName, attributeDefinitions, globalSecondaryIndexes) => { try { const existing = await db .describeTable({ TableName: tableName, }) .promise(); const existingGlobalSecondaryIndexes = existing.Table.GlobalSecondaryIndexes || []; const map = new Map(); existingGlobalSecondaryIndexes.forEach((existingGlobalSecondaryIndex) => { map.set(existingGlobalSecondaryIndex.IndexName, existingGlobalSecondaryIndex); }); for (let i = 0; i < globalSecondaryIndexes.length; i += 1) { const globalSecondaryIndex = globalSecondaryIndexes[i]; const existing = map.get(globalSecondaryIndex.IndexName); if (existing) { // has anything changed? const keySchemaChanged = JSON.stringify(existing.KeySchema) !== JSON.stringify(globalSecondaryIndex.KeySchema); const projectionChanged = JSON.stringify(existing.Projection) !== JSON.stringify(globalSecondaryIndex.Projection); if (keySchemaChanged || projectionChanged) { await (0, exports.deleteGlobalSecondaryIndex)(db, tableName, globalSecondaryIndex.IndexName); await (0, exports.addGlobalSecondaryIndex)(db, tableName, attributeDefinitions, globalSecondaryIndex); } } else { await (0, exports.addGlobalSecondaryIndex)(db, tableName, attributeDefinitions, globalSecondaryIndex); } map.delete(globalSecondaryIndex.IndexName); } const deletedIndexes = Array.from(map.values()); for (let i = 0; i < deletedIndexes.length; i += 1) { const deletedIndex = deletedIndexes[i]; await (0, exports.deleteGlobalSecondaryIndex)(db, tableName, deletedIndex.IndexName); } } catch (error) { const _error = error; PlatformTools_1.PlatformTools.logError("failed to update table indexes.", _error); } }; exports.updateGlobalSecondaryIndexes = updateGlobalSecondaryIndexes; const deleteGlobalSecondaryIndex = async (db, tableName, indexName) => { try { PlatformTools_1.PlatformTools.logInfo("deleting index:", indexName); await db .updateTable({ TableName: tableName, GlobalSecondaryIndexUpdates: [ { Delete: { IndexName: indexName }, }, ], }) .promise(); await (0, exports.waitUntilActive)(db, tableName); } catch (error) { const _error = error; PlatformTools_1.PlatformTools.logError(`failed to update table: ${tableName}`, _error); } }; exports.deleteGlobalSecondaryIndex = deleteGlobalSecondaryIndex; const addGlobalSecondaryIndex = async (db, tableName, attributeDefinitions, globalSecondaryIndex) => { try { PlatformTools_1.PlatformTools.logInfo("creating index:", globalSecondaryIndex.IndexName); await db .updateTable({ TableName: tableName, AttributeDefinitions: attributeDefinitions, GlobalSecondaryIndexUpdates: [ { Create: { KeySchema: globalSecondaryIndex.KeySchema, Projection: globalSecondaryIndex.Projection, IndexName: globalSecondaryIndex.IndexName, }, }, ], }) .promise(); await (0, exports.waitUntilActive)(db, tableName); } catch (error) { const _error = error; PlatformTools_1.PlatformTools.logError(`failed to create index: ${globalSecondaryIndex.IndexName}`, _error); } }; exports.addGlobalSecondaryIndex = addGlobalSecondaryIndex; //# sourceMappingURL=DynamoGlobalSecondaryIndexHelper.js.map