Forma
@xndrjs/forma is an intent-oriented composition library for TypeScript. It gives applications a
small vocabulary for making architectural ownership, dependencies, public entry points, and
resource lifetimes explicit.
Forma starts by making architectural ownership explicit:
- a Boundary owns a local architectural language and its contracts;
- an Intent names something that Boundary promises, independently of its implementation;
- a Provider says how that Intent is realized;
- a Composition decides which realizations form one executable graph.
Ordinary dependency injection can connect implementations without preserving those distinctions. Forma makes them part of the graph. Implementations can then change without turning the meaning of the system into moving infrastructure, and the graph can be validated before the application begins executing it.
Install
Section titled “Install”pnpm add @xndrjs/formaThe current alpha targets Node.js >=24 <26.
A minimal composition
Section titled “A minimal composition”import { boundary, compose } from "@xndrjs/forma";
type OrderId = string;type Order = { readonly id: string; readonly total: number };type GetOrderDetailsError = { readonly code: "not_found" };
const Orders = boundary("orders");
const GetOrderDetailsUseCase = Orders.intent("getOrderDetailsUseCase").contract< OrderId, Order, GetOrderDetailsError>();
const GetOrderDetailsProvider = GetOrderDetailsUseCase.provide.with(({ out }) => { return function getOrderDetails(id) { return id === "42" ? out.success({ id: "42", total: 100 }) : out.expectedError({ code: "not_found" }); };});
const root = compose({ entryBoundaries: [Orders], surface: { getOrderDetails: GetOrderDetailsProvider },});
const outcome = await root.withExecutionContext((surface) => { return surface.getOrderDetails("42");});
switch (outcome.kind) { case "success": console.log(outcome.value); break; case "expectedError": console.log(outcome.error.code); break; case "unexpectedFailure": console.error("Unexpected failure", outcome.failure.id); break; case "cancelled": console.log("Cancelled"); break;}
await root.dispose();This small graph already establishes several properties:
Ordersowns the Intent and its Contract;- the Provider realizes that Contract but does not redefine it;
- only
getOrderDetailsis public; - the public traversal starts from the declared
OrdersEntry Boundary; - the execution context is disposed after the callback;
- every Intent exit uses the typed
InvocationOutcomeprotocol.
What Forma owns
Section titled “What Forma owns”| Concern | Forma’s role |
|---|---|
| Architectural identity | Names Intents inside explicit Boundaries |
| Realization | Associates Intent, dependencies, lifetime policy, and implementation in a Provider |
| Cross-Boundary integration | Gives semantic translation an explicit Adapter identity |
| Graph closure | Rejects missing providers, cycles, competing realizations, and incompatible edges |
| Public API | Publishes only the aliases selected by the Composition Surface |
| Lifecycle | Lazily materializes Providers and disposes their resources through owned scopes |
| Failure protocol | Keeps expected errors typed and censors unexpected causes at Boundary exits |
| Streaming | Owns cold stream invocations, cancellation, and cleanup |
Forma is not a general-purpose IoC container, a service locator, a domain-modeling language, or an application framework. It does not require a directory hierarchy and does not turn every function into an Intent.
Where to continue
Section titled “Where to continue”- Mental model defines the vocabulary and the relationships between its concepts.
- Your first Composition builds a runnable graph step by step.
- Providers and dependencies covers lazy materialization, Params, and lifetimes.
- Adapters and evolution shows how Boundaries collaborate and how ownership can move over time.
- Composition and execution explains Surface direction, Entry Boundaries, execution contexts, and disposal.
- Errors and outcomes documents the total Boundary-exit protocol.
- Streaming covers cold pull-based streams and their ownership model.
- Inspection and testing covers
describePlan(), validation boundaries, package checks, and current non-goals.
Forma is currently alpha. The public model is implemented and tested, but breaking API changes may still occur while the vocabulary and ergonomics are being validated in real applications.