# All files database.ts

94% Statements 94/100
86.95% Branches 20/23
100% Functions 5/5
94% Lines 94/100

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    1011x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    30x
    30x
    30x
    30x
    30x
    30x
    30x
    30x
    30x
    30x
    30x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    29x
    29x
    29x
    29x
    30x

    29x
    30x
    1x
    1x
    29x
    30x
    30x
    30x
    28x
    28x
    28x
    2x
    2x
    2x
    2x
    2x
    2x

    2x
    2x
    2x
    2x
    2x
    30x
    29x
    30x
    1x
    1x
    1x
    1x
    1x

    30x
    1x
    2x
    2x
    2x
    1x
    1x
    32x
    28x
    28x
    28x
    28x
    28x
    32x
    1x
    2x
    2x
    1x
    1x
    1x
    1x
    1x
    287x
    287x
    1x
    1x
    286x
    286x
     import { readFileSync } from 'fs'

    import { Db, MongoClient, MongoClientOptions, MongoError } from 'mongodb'

    let dbInstance: Db | null
    let mongoClient: MongoClient | null
    let _connectionStatus = false

    export async function connect(
      mongoUri: string,
      isProduction = false,
      connectionRetryWait = 5,
      connectionRetryMax = 10,
      certFileUri?: string,
      overrideOptions?: MongoClientOptions
    ) {
      let mongoOptions: MongoClientOptions = {}
      console.log(`Connecting to database... Prod mode: ${isProduction}.`)

      if (certFileUri) {
        const certFileBuf = [readFileSync(certFileUri)]

        //TODO: Replace ssl prefixed options with tls and store certs in SecureContext
        // https://www.mongodb.com/docs/drivers/node/current/fundamentals/connection/tls/#std-label-node-connect-tls
        mongoOptions = Object.assign(mongoOptions, {
          ssl: true,
          sslValidate: true,
          sslCA: certFileBuf,
          poolSize: 1,
        })
      }

      let retryAttempt = 0
      let lastException: MongoError | null = null

      if (!connectionRetryMax) {
        connectionRetryMax = 1
      }

      if (overrideOptions) {
        Object.assign(mongoOptions, overrideOptions)
      }

      while (retryAttempt < connectionRetryMax && !dbInstance) {
        try {
          mongoClient = await MongoClient.connect(mongoUri, mongoOptions)
          dbInstance = mongoClient.db()
          _connectionStatus = true
        } catch (ex: unknown) {
          _connectionStatus = false
          retryAttempt++
          if (ex instanceof Error) {
            console.log(ex.message)
          }
          if (ex instanceof MongoError) {
            lastException = ex
          }
          if (connectionRetryWait) {
            console.log(`${retryAttempt}: Retrying in ${connectionRetryWait}s...`)
            await sleep(connectionRetryWait)
          }
        }
      }

      if (!dbInstance) {
        if (!lastException) {
          throw new Error(
            'Unable to connect to the database, please verify that your configuration is correct'
          )
        }
        throw lastException
      }
    }

    function sleep(seconds: number) {
      return new Promise((resolve) => setTimeout(resolve, seconds * 1000))
    }

    export async function close(force = false) {
      if (mongoClient) {
        await mongoClient.close(force)
        dbInstance = null
        mongoClient = null
        _connectionStatus = false
      }
    }

    export function connectionStatus() {
      if (mongoClient) {
        return _connectionStatus
      }
      return false
    }

    export function getDbInstance(): Db {
      if (!dbInstance) {
        throw new Error('Database is not yet instantiated')
      }
      return dbInstance
    }