How to bind to the methods of the MongoClient if you use a Promise (not callback)? Help

I am trying to connect to a MongoDB database using the new @ryyppy Promises. The earlier solution with a callback, solved earlier by @eWert-Online and @yawaramin doesn’t work when you create a new instance of the MongoClient so you can use it with the new promises.

What needs binding:

const { MongoClient } = require('mongodb')
// or as an es module:
// import { MongoClient } from 'mongodb'

// Connection URL
const url = 'mongodb://localhost:27017'
const client = new MongoClient(url)

// Database Name
const dbName = 'myProject'

async function main() {
  // Use connect method to connect to the server
  await client.connect()
  console.log('Connected successfully to server')
  const db = client.db(dbName)
  const collection = db.collection('documents')

  // the following code examples can be pasted here...

  return 'done.'
}

main()
  .then(console.log)
  .catch(console.error)
  .finally(() => client.close())

I started with

type t
@module("mongodb") @new external createMongoClient: string => t = "MongoClient"
let client = createMongoClient("someUri")

That works, but to associate the connect with that client … doesn’t.

@send external connect: t => unit = "connect"

client.connect() // doesn't work
client->connect // doesn't work

What I want to achieve is to be able to connect to a MongoDB database and use connect, db, collection,… commands. If I understand how to bind the connect I can go from there. Help would be greatly appreciated.

Here’s a basic structure that might help get you started:

module Collection = {
  type t
}

module Db = {
  type t

  @send
  external collection: (t, string) => Collection.t = "collection"
}

module ClientInstance = {
  type t

  @send
  external db: (t, string) => Db.t = "db"
}

module Client = {
  type t

  @module("mongodb") @new
  external create: string => t = "MongoClient"

  @send
  external connect: t => Js.Promise.t<ClientInstance.t> = "connect"
}

let onSuccess = (instance: ClientInstance.t) => {
  let db = instance->ClientInstance.db("myProject")
  let collection = db->Db.collection("documents")
  Js.log(collection)
  Js.Promise.resolve()
}

let onError = (error: Js.Promise.error) => {
  Js.log(error)
  Js.Promise.resolve()
}

Client.create("someUri")
->Client.connect
->Js.Promise.then_(onSuccess, _)
->Js.Promise.catch(onError, _)
->ignore

Not tested, but hopefully is helpful.

This uses the built in Promise lib, but would be worth switching to rescript-promise for nicer promise handling.

1 Like

I suppose that you will have problem with types by key of collection.
Look at there for decision – How can get keys of object in generic - #15 by snatvb

2 Likes