// Import MongoDB import MongoDB from 'mongodb'; // Import dbState import dbState from '../dbState'; // Import types import CollectionOpts from '../types/CollectionOpts'; /** * Initialize a collection. * @author Gabe Abrams * @param collectionName the name of the collection * @param options the options tied to the collection * @returns a Promise which resolves to the Mongo collection */ const initCollection = async ( collectionName: string, options: CollectionOpts, ): Promise> => { // Get the collection names const collectionNames = await dbState.initDB; // Variable for the collection let collection: MongoDB.Collection; // Create collection if it doesn't exist if (collectionNames.indexOf(collectionName) < 0) { // Collection doesn't exist. Create it try { // Create collection await dbState.db.createCollection(collectionName); // Get the collection collection = dbState.db.collection(collectionName); } catch (err) { // eslint-disable-next-line no-console console.log('DCE-MANGO: An error occurred while creating collections. Fatal error. Now exiting.'); // eslint-disable-next-line no-console console.log(err); process.exit(1); } } else { // Collection exists. Get it collection = dbState.db.collection(collectionName); } // Get the indexes const existingIndexes = await collection.indexes(); // If any of the indexes are old, drop them all const dropAllIndexes = ( existingIndexes .some((index: { name?: string }) => { // Ignore invalid indexes if (!index || !index.name || typeof index.name !== 'string') { return false; } // Ignore ttl index if (index.name === 'ttl-index') { return false; } // Ignore default index if (index.name.startsWith('_')) { return false; } // Check if this index is from a previous version return (!index.name.includes(dbState.schemaVersionTag)); }) ); // Drop all indexes if need be if (dropAllIndexes) { try { // eslint-disable-next-line no-console console.log(`DCE-MANGO: Found old schema for collection ${collectionName}! Dropping all indexes and re-creating them.`); await collection.dropIndexes(); } catch (err) { // eslint-disable-next-line no-console console.log('DCE-MANGO: An error occurred while dropping old indexes. Fatal error. Now exiting.'); // eslint-disable-next-line no-console console.log(err); process.exit(1); } } // Gather a list of indexes that need to be created const indexesToCreate = []; // Add unique index to the list if (options.uniqueIndexKey) { // Create index options const indexOpts = { key: { [options.uniqueIndexKey]: 1, }, name: `main-${options.uniqueIndexKey}-unique-index-${dbState.schemaVersionTag}`, unique: true, background: false, } as any; // Add expiry if (options.expireAfterSeconds) { indexOpts.expireAfterSeconds = options.expireAfterSeconds; } // Add the index to the list indexesToCreate.push(indexOpts); } // Add TTL for DocDB if (options.expireAfterSeconds) { indexesToCreate.push({ key: { lastUpdatedForTTL: 1, }, name: `ttl-index-${dbState.schemaVersionTag}`, expireAfterSeconds: options.expireAfterSeconds, background: false, unique: false, }); } // Add secondary indexes to the list (options.indexKeys || []).forEach((secondaryIndexKey: any) => { indexesToCreate.push({ key: { [secondaryIndexKey]: 1, }, name: `secondary-${secondaryIndexKey}-index-${dbState.schemaVersionTag}`, unique: false, background: false, }); }); // Create the indexes try { await collection.createIndexes(indexesToCreate); if ((process.env.MANGO_LOG_LEVEL ?? '').toLowerCase() === 'info') { // eslint-disable-next-line no-console console.log('DCE-MANGO: Created indexes. ', indexesToCreate); } } catch (err) { // eslint-disable-next-line no-console console.log('DCE-MANGO: An error occurred while creating indexes. Fatal error. Now exiting.'); // eslint-disable-next-line no-console console.log(err); process.exit(1); } // Return the collection return collection; }; export default initCollection;