import dotenv from "dotenv" ; import { Db as Database , MongoClient , Cursor , FindAndModifyWriteOpResultObject , } from "mongodb" ; import { encode as encodeQueryString } from "querystring" ; import { ObjectLiteral } from "./utils" ; import path from "path" ; import { Person } from "./person" ; dotenv . config ( ) ; const log = console . log . bind ( console ) ; const ONLY_DESTROY_DATABASES_WITH_THIS_STRING_INCLUDED = "test" ; function getMongoConnectionString ( username , password , host , database , options ) { let connectionString = `mongodb://localhost/${ database }?` ; connectionString += encodeQueryString ( options ) ; return connectionString ; } export function getDatabasenameForTests ( ) { if ( ! ( global as any ) . expect ) { return null ; } const testPathFull = expect ?. getState ( ) . testPath ; return path . parse ( testPathFull ) . name . replace ( "." , "-" ) ; } const USERNAME = process . env . MONGODB_USER ; const PASSWORD = process . env . MONGODB_PASSWORD ; const DATABASE = getDatabasenameForTests ( ) || process . env . MONGODB_DATABASE ; if ( ! USERNAME ) { throw new Error ( `Missing MONGODB_USER in .env file` ) ; } if ( ! PASSWORD ) { throw new Error ( `Missing MONGODB_PASSWORD in .env file` ) ; } if ( ! DATABASE ) { throw new Error ( `Missing MONGODB_DATABASE in .env file` ) ; } export async function dbOperation < T > ( work ) { let client ; let result ; const uri = getMongoConnectionString ( USERNAME , PASSWORD , "localhost" , DATABASE , { retryWrites : true , w : "majority" , } ) ; try { client = new MongoClient ( uri , { useUnifiedTopology : true } ) ; await client . connect ( ) ; const database = client . db ( DATABASE ) ; result = await work ( database ) ; } finally { await client . close ( ) ; } return result ; } export async function destroyDatabase ( ) { await dbOperation ( async function ( database ) { const databaseName = database . databaseName ; if ( ! databaseName . includes ( ONLY_DESTROY_DATABASES_WITH_THIS_STRING_INCLUDED ) ) { throw new Error ( `Refusing to delete database '${ databaseName }' as it does not include '${ ONLY_DESTROY_DATABASES_WITH_THIS_STRING_INCLUDED }'` ) ; } await database . dropDatabase ( ) ; } ) ; } async function cursorToDocuments ( cursor ) { const documents = [ ] ; await cursor . forEach ( function ( document ) { if ( ! document ) { return ; } documents . push ( document ) ; } ) ; return documents ; } export async function addOrUpdate ( database , collection , document ) { const result = await database . collection ( collection ) . findOneAndUpdate ( { _id : document . _id , } , { $set : document } , { returnOriginal : false , upsert : true , } ) ; return result . value ; } export async function getAllDocuments ( database , collection ) { const cursor = await database . collection ( collection ) . find ( ) ; return cursorToDocuments ( cursor ) ; }