Bindings: to create or reuse

I’ve recently started writing some bindings for a project. Specifically, I’m targeting the popular TanStack Query. Since it’s quite popular, there are already some existing bindings on GitHub.

I’m often conflicted about this. Reusing something out there can feel like a gamble. If something doesn’t work, you might end up copying or forking the project. Sending a PR could end up unnoticed, which makes it tempting to just write your own bindings. The advantage is that you only write bindings for what you use, and there’s a level of muscle memory from having written them yourself.

However, this mindset doesn’t typically lead to high-quality community bindings. I’m curious about everyone’s opinions on this. Do you prefer reusing bindings or do you usually create them yourself?

1 Like

I usually reuse them, copy paste some base and tailor them for my use case. Copilot generates correct bindings 95% of the time anyway and this allows to have simpler bindings.

But yeah, this prevents us from having a nice equivalent of definitely typed for example.

2 Likes

Outside of rescript react and core, I don’t think we’ve ever installed any other community bindings. We just write our own bindings when we need them.

Few reasons I can think of:

  1. Always worried that the bindings I find on someone’s github has partial coverage and may be missing something we need. Without the ability to extend, you end up with like Express2.res files that have one function in them

  2. For some bindings that I was interested in, the bindings took a custom implementation approach – like reductive or bs-jest for redux and jest, when most the time I’m looking for zero cost

  3. There’s a bit of friction with finding, installing the library, installing the rescript version of it, and adding it again to rescript.json that makes just feel easier to copy paste into a new file

2 Likes

I generally just write my own bindings for most things. I usually just need a function or two, plus I am doing stuff with Deno these days so I prefix stuff with jsr: or npm:.

1 Like

I’m targeting the popular TanStack Query

Interesting you mention that, I vendor’d the rescriptbr ones because they had a few mistakes in them. I’d recently started working on binding them for v5 using some of the rescript v11 features:

type fetchStatus = | @as("fetching") Fetching | @as("paused") Paused | @as("idle") Idle

@tag("status")
type queryResult<'data> =
  | @as("pending")
  Pending({
      data: unit,
      dataUpdatedAt: int,
      errorUpdateCount: int,
      failureCount: int,
      failureReason: Null.t<Error.t>,
      fetchStatus: fetchStatus,
      isFetched: bool,
      isFetchedAfterMount: bool,
      isPlaceholderData: bool,
      isRefetchError: bool,
      isStale: bool,
    })
  | @as("success")
  Success({
      data: 'data,
      dataUpdatedAt: int,
      error: unit,
      errorUpdateCount: int,
      failureReason: unit,
      fetchStatus: fetchStatus,
      isFetched: bool,
      isFetchedAfterMount: bool,
      isPlaceholderData: bool,
      isRefetchError: bool,
      isStale: bool,
    })
  | @as("error")
  Error({
      data: Nullable.t<'data>,
      dataUpdatedAt: int,
      error: Error.t,
      errorUpdateCount: int,
      failureCount: int,
      failureReason: Null.t<Error.t>,
      fetchStatus: fetchStatus,
      isFetched: bool,
      isFetchedAfterMount: bool,
      isPlaceholderData: bool,
      isRefetchError: bool,
      isStale: bool,
    })

Do you prefer reusing bindings or do you usually create them yourself?

Personally I try to contribute to any available bindings if at all feasible. The lack of OSS bindings is a huge barrier to entry to the Rescript community in my opinion, and learning to write the bindings is a skill unto itself when newcomers used to the JS ecosystem generally will not be as familiar with many of the patterns and concepts in FP languages. Trying to learn the type system, how to interpret the compiler, and also how to mentally translate what you are learning back into the javascript APIs, which often are at odds with how you would write Rescript code, is extraordinarily difficult for someone new.

1 Like

Always worried that the bindings I find on someone’s github has partial coverage and may be missing something we need. Without the ability to extend, you end up with like Express2.res files that have one function in them

I always thought yarn’s patch protocol was a super useful feature for avoiding this problem: yarn patch | Yarn

There’s a bit of friction with finding, installing the library, installing the rescript version of it, and adding it again to rescript.json that makes just feel easier to copy paste into a new file

That’s definitely easier, and what I’d been doing until pretty recently. Our compilation times had started to creep up a bit, and breaking these vendored bindings into separate packages in our monorepo yielded a pretty significant reduction in incremental and “warm” (bs-dependencies already compiled) compilation times.

That said, it’d be pretty convenient if the compiler could pick up some metadata from package.json of installed packages instead of relying on manually syncing these

2 Likes

That said, it’d be pretty convenient if the compiler could pick up some metadata from package.json of installed packages instead of relying on manually syncing these

Honestly, this can actually be done pretty easily in userland; Run a small script on prepare that checks package.json dependencies for anything that matches rescript-* or @*/rescript-* and automatically append it to rescript.json.

Can manually add some exceptions to package.json to include or exclude certain matches. Might take a whack at this for my project