Skip to content

BaldrVivaldelli/brass-runtime

Repository files navigation

๐Ÿ› ๏ธ brass-runtime โ€” Mini ZIO-like runtime in TypeScript

A small experimental runtime inspired by ZIO 2, implemented in vanilla TypeScript and intentionally built without using Promise / async/await as the primary semantic primitive.

brass-runtime is the foundation: it provides an effect system, fibers, scheduler, scopes, and streams. Higher-level modules (HTTP, streaming utilities, integrations) are built on top of the runtime, not baked into it.

You can still interop with the outside world (timers, fetch, Node APIs) via explicit, cancellable bridges such as fromPromiseAbortable.


Philosophy

  • Effects are values โ€” lazy, composable, referentially transparent
  • Async is explicit โ€” no hidden Promise semantics
  • Concurrency is structured โ€” fibers, scopes, finalizers
  • Side effects are interpreted โ€” not executed eagerly
  • Higher-level APIs are libraries, not magic

If you like ZIOโ€™s separation between zio-core, zio-streams, and zio-http, this project follows the same spirit.


Core concepts

  • Sync core effect: Effect<R, E, A> and Exit<E, A>
  • Algebraic async representation: Async<R, E, A>
  • Cooperative Scheduler (observable / testable)
  • Lightweight Fibers with interruption & finalizers
  • Structured Scopes for resource safety
  • ZStream-style streams with backpressure

Install

npm i brass-runtime

Quick start

Run an effect

import { succeed } from "brass-runtime";
import { Runtime, toPromise } from "brass-runtime/runtime";

const runtime = new Runtime({ env: {} });

const value = await toPromise(succeed(123), runtime.env);
console.log(value); // 123

Structured concurrency with Scope

import { withScope } from "brass-runtime/scope";
import { Runtime } from "brass-runtime/runtime";

const runtime = new Runtime({ env: {} });

withScope(runtime, (scope) => {
  const f = scope.fork(/* Async effect */);
  // later...
  scope.close(); // interrupts child fibers + runs finalizers
});

toPromise is just a convenience bridge for examples/DX. The runtime semantics remain explicit.


Modules built on top of brass-runtime

These are optional layers, implemented using the runtime primitives.

๐ŸŒ HTTP client (brass-http layer)

A ZIO-style HTTP client built on top of fibers and Async.

  • Lazy & cancelable HTTP requests
  • Explicit wire/content separation
  • Middleware-friendly (logging, retry, timeout, etc.)
  • Integrated with fiber interruption via AbortController

๐Ÿ‘‰ Docs: HTTP module

Example:

import { httpClientStream } from "brass-runtime/http";
import { toPromise, Runtime } from "brass-runtime/runtime";

type Post = { id: number; title: string; body: string };

const runtime = new Runtime({ env: {} });

const client = httpClientStream({ baseUrl: "https://jsonplaceholder.typicode.com" });

const res = await toPromise(client.getJson<Post>("/posts/1"), runtime.env);
console.log(res.status, res.value.title);

๐ŸŒŠ Streams (ZStream-like)

Pull-based, resource-aware streams with backpressure.

  • ZStream<R, E, A>
  • Pull semantics
  • Bounded buffers
  • Deterministic resource cleanup

Examples:

  • src/examples/fromPromise.ts
  • src/examples/mergeStreamSync.ts

Docs


Whatโ€™s new (recent changes)

  • Stream buffering with backpressure (buffer)
  • Abortable async integration (fromPromiseAbortable)
  • Fiber-safe toPromise for examples & DX
  • HTTP client module built on top of the runtime

Features (status)

Runtime (core)

  • Sync core: Effect
  • Async algebra: Async
  • Cooperative Scheduler
  • Fibers with interruption & finalizers
  • Structured Scope
  • Resource safety (acquireRelease)

Concurrency & Streams

  • race, zipPar, collectAllPar
  • ZStream-like core
  • Bounded buffers & backpressure
  • Stream merge / zip
  • Hubs / Broadcast
  • Pipelines (ZPipeline-style)

Libraries

  • HTTP client
  • Retry / timeout middleware
  • Logging / metrics layers

Design notes

  • No hidden Promises: async is always modeled explicitly
  • Deterministic execution: scheduler is observable & testable
  • Resource safety is structural: scopes guarantee cleanup
  • Libraries compose via functions: middleware, not inheritance

Contributing

  • Runtime invariants matter โ€” avoid sneaking Promises into semantics
  • Prefer libraries on top of the runtime over changes in the core
  • Small, focused PRs are welcome (your repo may enforce PR-only changes)

License

MIT License ยฉ 2025

About

A Fiber Typescript engine

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors