@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
JavaScript
;
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