npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zero.sc/bridge

v0.1.2

Published

Call Python, Rust, Go and Swift from Next.js over a warm worker pool — typed, with binary framing, no process per call.

Readme


The problem this solves

Some work does not belong in Node. Embeddings, image decoding, numerical code, anything with a mature library in another language. The usual answers are to stand up a microservice — HTTP server, health check, deployment, another thing that can be down — or to spawn a process per call and pay start-up cost every time. Python costs tens of milliseconds to boot before it has done anything.

There is a third option that people write badly by hand: keep the process alive and talk to it over stdio. It is badly written because the naive version delimits messages with newlines, and the first payload containing a newline desynchronises the stream permanently. The symptom appears three calls later, in an unrelated function.

This package is that third option, written once and carefully. Frames carry their length, so a partial write cannot desynchronise anything.

Install

npm install @zero.sc/bridge

No runtime dependencies. The language runtimes you actually call need to exist on the machine — this package does not install Python for you.

Sixty seconds

import { defineBridge, pythonWorker } from '@zero.sc/bridge';

interface Contract {
  embed(text: string): number[];
  slugify(text: string): string;
  countdown(n: number): AsyncGenerator<{ tick: number }>;
}

const py = defineBridge<Contract>({
  worker: pythonWorker({ cwd: './workers/embed' }),
  functions: ['embed', 'slugify', 'countdown'],
  streams: ['countdown'],
  workers: 4,
  timeoutMs: 20_000,
});

const vector = await py.embed('hello');

for await (const tick of py.countdown(3)) {
  console.log(tick);
}

await py.$close();

The Python side is a small worker script; a ready-made one ships in the package for each runtime, so the first call works before you have written any protocol code.

What's inside

| Piece | What it does | |-------|--------------| | defineBridge | Turns a TypeScript interface into a callable client | | defineSharedBridge | One pool shared across modules instead of one per import | | BridgePool | Warm workers, queueing, restart on death | | protocol | Length-prefixed frames, version, size ceiling, corruption detection | | presets | pythonWorker, rustWorker, goWorker, swiftWorker, nodeWorker | | next | Helpers for calling from route handlers without leaking pools on reload | | zero-bridge | A CLI for scaffolding and inspecting a worker |

Presets do the obvious local thing: Python prefers a .venv if one exists; Rust prefers a release binary and warns when it falls back to a debug build, because a debug build can be an order of magnitude slower and that difference gets misread as the bridge being slow.

Failure has six names

A single BridgeError would be easy to write and useless to handle. These are separate because the correct response differs:

| Error | Means | You should | |-------|-------|------------| | BridgeTimeoutError | Deadline passed — carries which phase | Retry, maybe with a longer deadline | | BridgeCallError | The worker raised | Fix the input; do not retry | | BridgeContractError | Shape did not match the declared type | Fix the contract | | BridgeOverloadError | Queue is full | Shed load or add workers | | BridgeUnavailableError | No worker could start | Check the toolchain | | BridgeProtocolError | The frame was malformed | Version mismatch |

The contract it keeps

  • Frames carry their length. Not newline-delimited, so binary payloads and multi-line strings are ordinary data.
  • Workers stay warm. Start-up is paid at pool creation, not per call.
  • A dead worker does not take the pool with it. It is replaced; queued calls proceed.
  • Streams are first class. A generator on the far side is an async generator here, so a long result arrives incrementally instead of as one large buffer.
  • The tests spawn real processes. Mocking the boundary would leave nothing verified, since the boundary is the entire product.

Honest limits

  • The toolchain has to be there. Calling Rust needs cargo, calling Go needs go, calling Swift needs a Swift toolchain. Missing ones surface as BridgeUnavailableError rather than something mysterious, but they still fail.
  • Local processes only. There is no remote transport. A pool is on this machine.
  • Payloads are JSON, plus binary as byte arrays. No shared memory, no zero-copy — a large array is serialised, and above some size a real IPC mechanism would beat this.
  • The pool is per process. Several Node workers mean several pools, and workers: 4 means four per Node process.
  • Swift support is the least exercised. It works and it is tested; it has seen the least real use of the five.
  • This is 0.1.x. The protocol is versioned and a mismatch is detected rather than misparsed, but the version can still move.

Around it

| | | |---|---| | Docs | kit.zero.sc | | Events | @zero.sc/events | | Calling services | @zero.sc/sdk | | Everything | @zero.sc |

License

MIT OR Zero License v1.0 — take whichever you prefer. Choosing MIT is enough; nothing further is required of you.

The Zero name, marks and logos are not covered — build anything you like with this code, just don't present it as a Zero product.

Copyright (c) 2026 Zero. Source Code begins at Zero.