XYOracleNetwork/clients

View on GitHub
packages/mongo/src/Base.ts

Summary

Maintainability
B
6 hrs
Test Coverage
import { assertEx } from '@xylabs/assert'
import type {
  Collection, DeleteResult, Document, Filter, FindCursor, MongoClient, OptionalUnlessRequiredId, UpdateFilter, WithId,
} from 'mongodb'

import type { BaseMongoSdkConfig } from './Config.js'
import { MongoClientWrapper } from './Wrapper.js'

export class BaseMongoSdk<T extends Document> {
  config: BaseMongoSdkConfig

  constructor(config: BaseMongoSdkConfig) {
    this.config = config
  }

  get uri() {
    return (
      this.config.dbConnectionString
      // eslint-disable-next-line @stylistic/max-len
      ?? `mongodb+srv://${this.config.dbUserName}:${this.config.dbPassword}@${this.config.dbDomain}.mongodb.net/${this.config.dbName}?retryWrites=true&w=majority`
    )
  }

  async deleteOne(filter: Filter<T>) {
    return await this.useCollection<DeleteResult>(async (collection: Collection<T>) => {
      return await collection.deleteOne(filter)
    })
  }

  async find(filter: Filter<T>) {
    return await this.useCollection<FindCursor<WithId<T>>>((collection: Collection<T>) => {
      return collection.find(filter)
    })
  }

  async findOne(filter: Filter<T>) {
    return await this.useCollection<WithId<T> | null>(async (collection: Collection<T>) => {
      return await collection.findOne(filter)
    })
  }

  async insertMany(items: OptionalUnlessRequiredId<T>[]) {
    return await this.useCollection(async (collection: Collection<T>) => {
      return await collection.insertMany(items)
    })
  }

  async insertOne(item: OptionalUnlessRequiredId<T>) {
    return await this.useCollection(async (collection: Collection<T>) => {
      return await collection.insertOne(item)
    })
  }

  async updateOne(filter: Filter<T>, fields: UpdateFilter<T>) {
    return await this.useCollection(async (collection: Collection<T>) => {
      return await collection.updateOne(filter, fields, { upsert: false })
    })
  }

  async upsertOne(filter: Filter<T>, fields: UpdateFilter<T>) {
    return await this.useCollection(async (collection: Collection<T>) => {
      return await collection.updateOne(filter, fields, { upsert: true })
    })
  }

  async useCollection<R>(func: (collection: Collection<T>) => Promise<R> | R) {
    return await this.useMongo<R>(async (client: MongoClient) => {
      return await func(client.db(this.config.dbName).collection<T>(this.config.collection))
    })
  }

  async useMongo<R>(func: (client: MongoClient) => Promise<R> | R) {
    const wrapper = MongoClientWrapper.get(this.uri, this.config.maxPoolSize, this.config.closeDelay)
    const connection = await wrapper.connect()
    assertEx(connection, () => 'Connection failed')
    try {
      return await func(connection)
    } finally {
      await wrapper.disconnect()
    }
  }
}