Skip to content

Instantly share code, notes, and snippets.

@Saghen
Created September 5, 2022 19:03
Show Gist options
  • Save Saghen/176c7c8179f22260afe99bfe9fa85941 to your computer and use it in GitHub Desktop.
Save Saghen/176c7c8179f22260afe99bfe9fa85941 to your computer and use it in GitHub Desktop.
MongoDB FP-TS Utilities
// WARN: Please note the error types may be incorrect
// WARN: Non-null assertions are used to avoid having to deal with overload typing but lead to unsafe typing
// NOTE: Unfortunately, due to the typing of the client, you must pass the type of the document during the call
// such as `insertOne<YourDocumentType>({ foo: 'bar' })
import { UnknownError } from '@shared/errors'
import { safeTask } from '@utils/fp'
import * as M from 'mongodb'
export const findOne =
<T extends M.Document>(filter: M.Filter<T>, options?: M.FindOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, Option<M.WithId<T>>> =>
safeTask(() => client.findOne(filter, options!).then(O.fromNullable))
export const find =
<T extends M.Document>(filter: M.Filter<T>, options?: M.FindOptions) =>
(client: M.Collection<T>): M.FindCursor<M.WithId<T>> =>
client.find(filter, options)
export const insertOne =
<T extends M.Document>(filter: M.OptionalUnlessRequiredId<T>, options?: M.InsertOneOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.InsertOneResult<T>> =>
safeTask(() => client.insertOne(filter, options!))
export const insertMany =
<T extends M.Document>(filter: M.OptionalUnlessRequiredId<T>[], options?: M.BulkWriteOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.InsertManyResult<T>> =>
safeTask(() => client.insertMany(filter, options!))
export const bulkWrite =
<T extends M.Document>(filter: M.AnyBulkWriteOperation<T>[], options?: M.BulkWriteOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.BulkWriteResult> =>
safeTask(() => client.bulkWrite(filter, options!))
export const countDocuments =
<T extends M.Document>(filter?: M.Filter<T>, options?: M.CountDocumentsOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, number> =>
safeTask(() => client.countDocuments(filter!, options!))
export const createIndex =
<T extends M.Document>(filter: M.IndexSpecification, options?: M.CreateIndexesOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, string> =>
safeTask(() => client.createIndex(filter, options!))
export const createIndexes =
<T extends M.Document>(filter: M.IndexDescription[], options?: M.CreateIndexesOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, string[]> =>
safeTask(() => client.createIndexes(filter, options!))
export const updateOne =
<T extends M.Document>(
filter: M.Filter<T>,
update: M.UpdateFilter<T> | Partial<T>,
options?: M.UpdateOptions,
) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.UpdateResult> =>
safeTask(() => client.updateOne(filter, update, options!))
export const updateMany =
<T extends M.Document>(
filter: M.Filter<T>,
update: M.UpdateFilter<T> | Partial<T>,
options?: M.UpdateOptions,
) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.Document | M.UpdateResult> =>
safeTask(() => client.updateMany(filter, update, options!))
export const deleteOne =
<T extends M.Document>(filter: M.Filter<T>, options?: M.DeleteOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.Document | M.UpdateResult> =>
safeTask(() => client.deleteOne(filter, options!))
export const deleteMany =
<T extends M.Document>(filter: M.Filter<T>, options?: M.DeleteOptions) =>
(client: M.Collection<T>): TaskEither<UnknownError, M.Document | M.UpdateResult> =>
safeTask(() => client.deleteMany(filter, options!))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment