opentui icon indicating copy to clipboard operation
opentui copied to clipboard

Support Node/Deno (NAPI instead of bun:ffi)

Open remorses opened this issue 4 months ago • 14 comments

Have you thought about using NAPI to make the project run both in Bun and Node?

There is this package to create automatic NAPI bindings from Zig code https://github.com/cztomsik/napigen

remorses avatar Jul 29 '25 18:07 remorses

I am open to it. FFI was just really convenient and is faster than NAPI, but yes I gave it some thought already. Might happen at some point, just not priority for now on my side. A lot to be figured out for the actual API and then probably some stabilization needed.

kommander avatar Jul 29 '25 18:07 kommander

wasm (free standing or wasi) can be considered too?

jlucaso1 avatar Jul 29 '25 19:07 jlucaso1

@jlucaso1 I considered it in the beginning, but it being a lib for terminal UIs it's not a blocker to load native libs and wasm has some overhead with its vm.

kommander avatar Jul 29 '25 20:07 kommander

I've only just stumbled onto this project and rather excited by its goals. But, I am confused as to the target run time. Does this only run on bun?

esatterwhite avatar Nov 12 '25 12:11 esatterwhite

Deno also has an FFI interface as well for what its worth.

esatterwhite avatar Nov 12 '25 12:11 esatterwhite

It currently only runs on bun exclusively. There are no plans to support other runtimes, though I am open to it.

kommander avatar Nov 12 '25 12:11 kommander

It currently only runs on bun exclusively. There are no plans to support other runtimes, though I am open to it.

Can we make plans? 😃

esatterwhite avatar Nov 13 '25 14:11 esatterwhite

Sure, the zig.ts exports a RenderLib interface and a resolveRenderLib function, both is used throughout the codebase. It also eagerly loads the native lib to reduce startup time.

So to provide a NAPI module one Just™ would have to solve this incomplete list:

  • wrap the native lib.zig c abi to build .node modules, using the static libs from then next step
    • expose a RenderLib compatible interface
    • in resolveRenderLib and for the eager loading if !bun return the napi lib
    • Note: the module level ffi native path resolution at the top of zig.ts needs to be conditional and for non-bun dynamically import the RenderLibcompatible .node module instead of the native ffi lib
  • extend the build.zig to also build static versions
  • in core/scripts/build.ts
    • also build the .node modules as a step
    • add the .node modules to the respective binary npm packages
    • add the .node modules to artifacts
    • add tha t to the pipeline build.yml
    • in release.yml
      • bundle the static libs from artifacts in the zips with the dynamic ones
  • extend the "build & test" workflows to run a matrix, also running the tests on napi supported runtimes

And the napi needs to be maintained to stay in sync with the native interface, which is far from stable and changes almost daily, so something generated would work best if possible, so it can be regenerated when the native interface changes.

Note: this does not consider the whole 3D part which currently also uses an FFI lib, which needs to be switched out to some napi webgpu module as well. Deno has its own webgpu bindings. All of the webgpu interfaces should be mostly compatible though.

kommander avatar Nov 13 '25 19:11 kommander

It would be easier to wait for Node.js to add something like Bun ffi into core: https://github.com/nodejs/node/pull/57761

remorses avatar Nov 13 '25 20:11 remorses

Probably, would have to check how compatible the interfaces are, as ffi != ffi, so it likely still needs a compat layer for different runtimes.

kommander avatar Nov 14 '25 21:11 kommander

Maybe support for deno first, node later when the playing field is a bit more level?

esatterwhite avatar Nov 15 '25 06:11 esatterwhite

That could be more realistic than NAPI I think

kommander avatar Nov 15 '25 18:11 kommander

Out of curiosity, Why does this project need access to the gpu? Wouldn't it make more sense to leave that up to user to install gpu accelerated terminals if that is what they want?

It seems a bit outside the scope of what a tui framework should care about. But 🤷 I don't have a leg to stand on here.

esatterwhite avatar Nov 16 '25 13:11 esatterwhite

It doesn't need it for anything non-3D, the threejs stuff is completely optional for the core, just a fun gimmick currently. It doesn't load the 3D module if it's Not explicitly imported, so it could be made a separate package. I was just mentioning it for completeness.

kommander avatar Nov 16 '25 17:11 kommander