@nifrajs/core
v3.1.0
Published
Bun-native, contract-first HTTP framework - the router, server, and route descriptor.
Maintainers
Readme
@nifrajs/core
The Bun-native, contract-first HTTP framework at the heart of nifra: a radix router, a fully type-inferred server, versionable contracts, lifecycle middleware, and production hardening.
The Web-standard app can be wrapped for Vercel Edge with toVercelHandler, Netlify Functions with
toNetlifyHandler, or API Gateway v1/v2 with toLambdaHandler from @nifrajs/core/server. These are
thin event-envelope adapters; application policy, persistence, and platform credentials stay outside
the core.
bun add @nifrajs/coreimport { server } from "@nifrajs/core/server"
const app = server()
.get("/users/:id", (c) => ({ id: c.params.id }))
.post("/users", { body: nameSchema }, (c) => ({ created: c.body.name }))
.listen(3000)
export type App = typeof app // hand this to @nifrajs/client for end-to-end types@nifrajs/core and @nifrajs/core/server expose the same lean common runtime. Optional systems are
available only from their explicit subpaths, so an ordinary HTTP server never evaluates them:
import { defineContract, implement } from "@nifrajs/core/contract"
import { startCausality } from "@nifrajs/core/causality"
import { defineAssurancePolicy } from "@nifrajs/core/assurance"
import { createDataPort, defineDataContract, diffDataContract } from "@nifrajs/core/data"
import { defineChannel, memoryChannelHub } from "@nifrajs/core/channel"- Inline or contract-first. Write routes inline (types inferred from the
builder), or
defineContract(...)+implement(...)for a decoupled, versionable surface - handlers lift over unchanged. - Validation at the boundary. Per-route
body/queryis any Standard Schema (zod/valibot/arktype, or@nifrajs/schema'st); invalid input is rejected with a structured422before the handler runs. - Lifecycle middleware.
derive/decorateextend the typed context;onRequest/beforeHandle/afterHandle/onResponse/onErrorrun around handlers;use(middleware)applies a bundle. - Portable response observation. The header/body/raw observer methods are opt-in so ordinary
servers stay lean: add
responseObserver()from@nifrajs/core/response-observerbefore callingonResponseHeaders,onResponseBody, oronResponseRaw. Official middleware that uses these tiers installs the compatibility runtime automatically. - Hardening built in.
stop({ drainMs })graceful shutdown (+ opt-in SIGTERM/ SIGINT),requestTimeoutMs(+ctx.signalandctx.budget), a streaming body-size cap, and a redacting structuredLogger. - One request budget.
ctx.budgetcarries the admitted absolute deadline and monotonicremaining()time. An inboundx-nifra-deadlinecan only shortenrequestTimeoutMs/maxInboundDeadlineMs; malformed and expired values fail before the handler.ctx.signalremains the cancellation primitive and aborts at that same effective deadline. - Route assurance. Official auth, CSRF, body-limit, rate-limit, idempotency,
IP-restriction, and security-header modules publish reflection-safe enforcement evidence.
An ordered
AssurancePolicyclassifies every route and fails closed on missing or forbidden evidence without adding work to the request path. - Owned effect execution.
executeCapability()correlates intent and terminal evidence with an opaqueeffectId, records outcomes automatically, and forwards request cancellation. Add order-scopedaroundCapability()policies for async approval/admission; they receive token-only metadata, have bounded timeouts, and must callnext()exactly once before the effect can run. - Durable workflows (opt in).
@nifrajs/core/durable-executionprovides tenant/principal-bound, signed single-use approval resumes; a durable effect journal + reconciliation scanner; and a typed saga state machine with reverse compensation, retry/backoff, and ambiguous-crash detection. Production constructors reject stores that do not declaredurability: "durable". Operational scans use bounded cursor pages throughreconcileEffectsPage()/reconcileSagasPage(). Provider-confirmed manual review uses effect-ID-boundresolveAmbiguity(), followed byresume()orcompensate(). - Production durable adapters.
@nifrajs/core/durable-adapterssuppliesPostgresDurableExecutionAdapter,SQLiteDurableExecutionAdapter, andDurableObjectExecutionAdapter. Each exposes compatibleeffects,approvals,sagas, andleasesstores. RunrunDurableExecutionAdapterConformance()against the deployment backend. - Bounded reconciliation workers.
@nifrajs/core/reconciliation-workerruns effect or saga scans under an atomic lease with durable cursor checkpoints, a finite page budget, bounded handler concurrency, filters, cancellation, and token-only metrics. A worker invocation always terminates. - Rich wire values (opt in).
@nifrajs/core/wireround-trips dates, bigints, maps, sets, binary, shared references, and cycles through JSON transports. Decoding validates every reachable shape, preserves owned__proto__keys without prototype mutation, and enforces configurable node, depth, collection-entry, and decoded-byte limits. - Versioned transport codecs (opt in). Add
.use(transportCodecs(registry))from@nifrajs/core/transport-pluginand configure the typed client'stransportoption with the same registry.@nifrajs/core/transport-codecnegotiates bounded HTTP representations and supplies the same frame/loader adapters for WebSockets and deferred data. ImportrichWireCodec()from@nifrajs/core/transport-codec-rich; the separate subpath keeps rich-wire code out of plain JSON bundles. - Typed data seam (opt in).
@nifrajs/core/datadefines token-only operation contracts,db.read/db.writecapability names, an opaque request-localRlsScope, typed adapter requests, drift snapshots, andcreateDataPort(contract, adapter, { beacon: useCapability }), which emits the operation's capability evidence - derived from the contract, never from the request - before the private adapter runs. It contains no database driver, tenant identity, policy, row values, or durable store; those belong in the adapter layer. - Typed channels (opt in).
@nifrajs/core/channeldefines typed message contracts, bounded subscriptions, cancellation, per-channel resume cursors, bounded local replay, and a process-local in-memory hub for tests. Durable replay, presence, rooms, and multi-instance fan-out remain adapter concerns.
import { defineAssurancePolicy, evaluateRouteAssurance, NIFRA_ASSURANCE } from "@nifrajs/core/assurance"
const policy = defineAssurancePolicy({
rules: [
{ name: "health", match: { paths: ["/health"] }, require: [] },
{ name: "mutation", match: { methods: ["POST", "PUT", "PATCH", "DELETE"] },
require: [NIFRA_ASSURANCE.AUTHENTICATED, NIFRA_ASSURANCE.CSRF] },
{ name: "read", match: { methods: ["GET", "HEAD"] },
require: [NIFRA_ASSURANCE.AUTHENTICATED] },
],
})
evaluateRouteAssurance(app, policy).ok // pure reflection-time evaluationESM-only; requires Bun at runtime. MIT.
For AI agents
Start with LLM.md - this package's contract card (the exports you call + its footguns),
one cheap read instead of the whole corpus. For the wider framework: the repo's
AGENTS.md is the copy-paste quick reference, and
llms-full.txt is the full machine-readable corpus. Run nifra check as the
done-gate, or nifra mcp to give the agent live project tools.
