dce-mango
Version:
Harvard DCE's Non-relational DB Wrapper.
143 lines (125 loc) • 4.61 kB
text/typescript
// 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;