// Import Mongo import MongoDB, { MongoClient } from 'mongodb'; // Import dotenv import * as dotenv from 'dotenv'; // Import state import dbState from './dbState'; /*------------------------------------------------------------------------*/ /* Initialization */ /*------------------------------------------------------------------------*/ /** * Get a copy of the db collection class with * Mongo/Amazon DocDB wrapper with functions that are * equally compatible with both * @author Gabe Abrams * @param [opts] object containing all arguments * @param [opts.schemaVersion=1] the version of the schema. Whenever you * change your schema, increment this number and dce-mango will automatically * re-build and re-provision your collections * @param [dbName=env.DB_NAME ?? 'mango-store'] the name of the database * to set up/use * @param [dbInfo=env vars] either include an object * with a mongo-style url: { url } or include an object * with pieces of a mongo-style url: * { user, pass, host, [options] } where options * is optional. * Otherwise, dce-mango will use environment variables instead: * either env.DB_URL or env.DB_USER + DB_PASS + DB_HOST must * be included, optionally with an included DB_OPTIONS. You can also use * mongo env vars: env.MONGO_URL or env.MONGO_USER + MONGO_PASS + MONGO_HOST * and optionally MONGO_OPTIONS * @returns collection class that references the given database */ const initMango = ( opts: { schemaVersion: number, dbName?: string, dbInfo?: ( | { url: string, } | { user: string, pass: string, host: string, options?: string, } ), }, ) => { // Pull environment variables from .env file dotenv.config(); // TODO: should we have overwrite functionality? if (dbState.isInitialized) { return; } dbState.isInitialized = true; // Get opts and set defaults const { schemaVersion } = opts; const dbName = (opts.dbName ?? (process.env.DB_NAME ?? 'mango-store')); const dbInfo = (opts.dbInfo ?? process.env) as any; // Get db info as parts const url = (dbInfo.url ?? dbInfo.DB_URL ?? dbInfo.MONGO_URL); const user = (dbInfo.user ?? dbInfo.DB_USER ?? dbInfo.MONGO_USER); const pass = (dbInfo.pass ?? dbInfo.DB_PASS ?? dbInfo.MONGO_PASS); const host = (dbInfo.host ?? dbInfo.DB_HOST ?? dbInfo.MONGO_HOST); const options = (dbInfo.options ?? dbInfo.DB_OPTIONS ?? dbInfo.MONGO_OPTIONS); // Make sure we have enough info to get a db url if ( !url && (!user || !pass || !host) ) { // eslint-disable-next-line no-console console.log('DCE-MANGO: No database information included. Either include a database url or include all of the following: user, pass, host. Fatal error. Now exiting.'); process.exit(1); } // Get db url const dbURL = ( url ?? `mongodb://${user}:${pass}@${host}/${dbName}${(options) ? '?' : ''}${(options) ?? ''}` ); // Create a schema version tag dbState.schemaVersionTag = `version_${schemaVersion}`; // Promise that resolves with collection names dbState.initDB = (async () => { // Connect the mongo client let client: MongoDB.MongoClient; try { const potentialClient = await MongoClient.connect(dbURL); // Make sure the client is defined if (!potentialClient) { throw new Error('Database returned an empty client'); } // Save the client client = potentialClient; } catch (err) { // This is a fatal error // eslint-disable-next-line no-console console.log('We could not connect to the database. This is a fatal error! Now exiting.'); // eslint-disable-next-line no-console console.log(err); process.exit(1); } // Get the database and its collections let collections; try { // Use client to get database dbState.db = client.db(dbName); dbState.client = client; // Get the list of collections collections = await dbState.db.listCollections().toArray(); } catch (err) { // This is a fatal error // eslint-disable-next-line no-console console.log('We could not list the collections in the database. This is a fatal error! Now exiting.'); // eslint-disable-next-line no-console console.log(err); process.exit(1); } // Return the list of collection names return collections.map((collection: { name: string }) => { return collection.name; }); })(); }; export default initMango;