Firebase modular bindings

Hi folks,

I’m new to ReScript and I want to use Firebase with ReScript and I started to learn how to create bindings:

So far I have:

module App = {
  type app

  type appConfig = {
    apiKey: string,
    authDomain: string,
    projectId: string,
    storageBucket: string,
    messagingSenderId: string,
    appId: string,
  }

  @module("firebase/app")
  external initializeApp: appConfig => app = "initializeApp"
}

module Firestore = {
  type firestore

  @module("firebase/firestore")
  external getFirestore: App.app => firestore = "getFirestore"

  type collectionReference<'documentdata, 'metadata>

  @module("firebase/firestore") @variadic
  external collection: (
    firestore,
    string,
    array<string>,
  ) => collectionReference<'documentdata, 'metadata> = "collection"

  type query<'documentdata, 'metadata>

  type querySnapshot<'documentdata, 'metadata>

  @module("firebase/firestore")
  external getDocs: query<'documentdata, 'metadata> => Js.Promise.t<
    querySnapshot<'documentdata, 'metadata>,
  > = "getDocs"

  external collectionReferenceToQuery: collectionReference<'documentdata, 'metadata> => query<
    'documentdata,
    'metadata,
  > = "%identity"

  type queryDocumentSnapshot<'documentdata, 'metadata>

  @get
  external docs: querySnapshot<'documentdata, 'metadata> => array<
    queryDocumentSnapshot<'documentdata, 'metadata>,
  > = "docs"

  @send
  external _data: (queryDocumentSnapshot<'documentdata, 'metadata>, unit) => 'documentdata = "data"

  let data = qds => _data(qds, ()) 
}

Usage:

open Firebase.Firestore

let firebaseConfig: Firebase.App.appConfig = {
  apiKey:....
}

type entry = {content: string}

@react.component
let make = () => {
  React.useEffect0(() => {
    let app = Firebase.App.initializeApp(firebaseConfig)
    let store = getFirestore(app)
    collection(store, "entries", [])
    ->collectionReferenceToQuery
    ->getDocs
    ->Promise.thenResolve(querySnapshot => {
      let snapshots = querySnapshot->docs
      Belt.Array.forEach(
        snapshots,
        snapshot => {
            let data = snapshot->data
          Js.Console.log(data.content)
        },
      )
    })
    ->Promise.done
    None
  })

  <h1> {React.string("Thunder")} </h1>
}

This works, but goodness, writing these bindings is a pain. Are there any existing bindings available? Or perhaps there’s a way to generate them automatically?

Any feedback on my work so far is also appreciated.

Cheers!

1 Like

I have continued my project with Firebase and ReScript.
The project itself is private but I’m putting my bindings over on GitHub - nojaf/rescript-firebase
It is only a subset for now but eventually I wish to port everything and add some more examples.

1 Like

There seems to be an error in your repo, Firebase.res looks like a broken symlink.

Hmm, it is a symlink to my project file in private project. I’ll look into it.

1 Like

Ok, thanks for open sourcing it :slight_smile:

Sure thing, fixed rescript-firebase/src/Firebase.res at main · nojaf/rescript-firebase · GitHub
If anyone in the future is playing with Rescript & Firebase, feel free to reach out here.

3 Likes