Support server-side Node/Bun clients: exit status, @blit-sh/core/node, nodejs wasm#65
Merged
Merged
Conversation
…s wasm
Addresses gaps that force a server-side consumer (a Node/Bun client driving
a local `blit server` over a unix socket) to re-implement library internals.
@blit-sh/core:
- Parse `exit_status` from S2C_EXITED (was discarded) and expose it as
`BlitSession.exitStatus`. Export `exitCodeFromStatus`/`formatExitStatus`/
`EXIT_STATUS_UNKNOWN`, ported from crates/cli/src/agent.rs so JS consumers
no longer re-derive the `128 + signal` convention.
- Add a non-browser `@blit-sh/core/node` subpath re-exporting the existing
Node/Bun/Deno unix-socket transports plus `loadBlitWasm()`, a helper that
initializes @blit-sh/browser off-browser (reads the colocated
blit_browser_bg.wasm and feeds init({module_or_path})) so consumers never
touch raw wasm bytes. Kept out of the package root so node:net never leaks
into browser bundles.
@blit-sh/browser (nix):
- Build a self-initializing wasm-bindgen `--target nodejs` artifact and
publish it under the `@blit-sh/browser/node` subpath (CommonJS, reads its
.wasm from disk on import). The root `.` export keeps the `--target web`
build, so existing browser consumers and the `.wasm` deep-import are
unchanged.
Docs:
- EMBEDDING.md gains a server-side Node/Bun section covering the unix
transport, loadBlitWasm, exitStatus and nullLogger.
All @blit-sh/core typechecks + 332 tests pass; the nodejs wasm artifact and
loadBlitWasm are validated end-to-end (Node + Bun) against the published
@blit-sh/browser@0.34.0.
|
🔗 Preview: https://blit-4m40bj8z3-indent.vercel.app |
Coverage
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
These changes come from a downstream consumer that runs a
@blit-sh/coreclient server-side (Node/Bun) to drive a localblit serverover a unix socket. They had to re-implement several things that are really library internals. This PR moves that work upstream. Observed against@blit-sh/browser@0.34.0/@blit-sh/coreBlitWorkspace.Note: a few of the original asks were already in-tree and just needed a release + discoverability:
c577adb) — but only under@blit-sh/core/transportswith anode/browserexport condition, not discoverable from the root. This PR adds an explicit@blit-sh/core/nodeentry + docs.nullLoggerand theBlitWorkspaceroot export already exist. Documented in EMBEDDING.md.What this PR does
1. Exit status in the JS client (
@blit-sh/core)The client received
S2C_EXITEDbut discarded theexit_statusfield, so a JS consumer could not get an exit code without re-decoding the frame. Now:S2C_EXITEDparsesexit_status([0x08][pty_id:2][exit_status:4], i32 LE; tolerates legacy 3-byte frames →EXIT_STATUS_UNKNOWN).BlitSession.exitStatus: number | null.exitCodeFromStatus,formatExitStatus,EXIT_STATUS_UNKNOWN— direct ports offormat_exit_status/exit_code_from_statusincrates/cli/src/agent.rs(unknown → 1, normal → code, signalled →128 + signal), so the convention lives in one place.2.
@blit-sh/core/nodeentryA non-browser subpath that re-exports
NodeUnixSocketTransport/BunUnixSocketTransport/DenoUnixSocketTransportplus a newloadBlitWasm()helper. Deliberately not re-exported from the package root —transports/unix.tsimportsnode:netat module top, which would poison browser bundles (the same reasontransports/browser.tsomits them).loadBlitWasm()initializes@blit-sh/browseroff-browser: the published package is a--target webbuild whoseinit()assumes a browserfetch(new URL(...wasm, import.meta.url)); under Node/Bun that rejects with an opaque, stackless error. The helper resolves the colocatedblit_browser_bg.wasm, reads its bytes and callsinit({ module_or_path }), so consumers never touch raw wasm bytes and a bad asset throws a real filesystem error. It also transparently passes through a self-initializing build (see #3).3. Self-initializing
--target nodejswasm (@blit-sh/browser/node)New nix derivation
browserWasmNodebuilds the crate withwasm-pack --target nodejsand publishes it under the@blit-sh/browser/nodesubpath. This build reads its.wasmfrom disk and instantiates synchronously on import — nofetch, noinit()dance. The package root.export stays the--target webbuild, so existing browser consumers and the./blit_browser_bg.wasmdeep-import are unchanged.The
--target nodejsoutput has a wasm-bindgen quirk: it emits CommonJS glue but copies the inline canvas snippets verbatim as ES modules, so the generatedrequire()throws. The derivation rewrites those snippets to CommonJS and marks the subtree{"type":"commonjs"}.Validation
@blit-sh/core:tsc --noEmitclean; 332 tests pass (9 new inexit-status.test.ts, plus apushExitedmock helper). Fullpnpm -r build+pnpm -r typecheckgreen across core/react/solid/ui/website.browserWasmNodebuilds vianix buildand the realized artifact self-initializes headless under bothrequire()andimport(new Terminal()works).loadBlitWasm()validated end-to-end (Node + Bun) against the real published@blit-sh/browser@0.34.0web build (resolve → readFile 84KB → init →new Terminal()).exportsmap validated in a cleannpm install: root.→ web build (init is a function),./node→ self-init build (ESM + CJS),./blit_browser_bg.wasmdeep-import preserved, under both default andbrowserconditions.Notes for reviewers
crates/browser/pkgis gitignored (fetched/built), so it's not in the diff.exportsmap keeps.= web build specifically so existing browser consumers (and the consumer's currentimport initflow) are unaffected;./nodeis purely additive.