@inkly/core
v0.0.0
Published
The inkly server core: typed app, router, rooms/presence, RPC, and resumable streams. Runtime-agnostic.
Readme
@inkly/core
The runtime-agnostic server engine for inkly — typed contracts, actions, events, rooms, lifecycle hooks, and resumable streams without importing any Node, Bun, Deno, or Cloudflare runtime APIs.
This package is the server app layer. Pair it with a runtime adapter such as
@inkly/node; adapters consumeapp.handlerswhile your app code stays portable.
Why it exists
@inkly/core turns one shared contract() into a server that validates every input/output, injects an authorized peer.context, routes typed actions and streams, and buffers recent events/chunks for reconnect resume. Keeping the engine runtime-free means the same app can run behind the Node reference adapter today and another adapter tomorrow with no handler rewrites.
Install
pnpm add @inkly/core zodQuickstart
import { inkly, contract } from "@inkly/core";
import { z } from "zod";
const chat = contract({
actions: {
joinRoom: { input: z.object({ room: z.string() }), output: z.object({ ok: z.boolean() }) },
sendMessage: {
input: z.object({ room: z.string(), text: z.string().min(1) }),
output: z.object({ id: z.string(), at: z.number() }),
},
},
events: {
message: z.object({ id: z.string(), room: z.string(), user: z.string(), text: z.string(), at: z.number() }),
},
streams: {},
});
export const app = inkly(chat, {
async authorize(_request, params) {
const token = (params as { token?: string } | undefined)?.token;
if (token !== "demo-token") throw new inkly.Unauthorized("bad token");
return { user: "daryl" };
},
});
app.defineAction("joinRoom", (peer, input) => {
peer.join(input.room);
return { ok: true };
});
app.defineAction("sendMessage", (peer, input) => {
const message = { id: crypto.randomUUID(), room: input.room, user: peer.context.user, text: input.text, at: Date.now() };
app.to(input.room).emit("message", message);
return { id: message.id, at: message.at };
});API reference
| API | Purpose |
| --- | --- |
| contract({ actions, events, streams }) | Declares Standard Schema validators for typed RPC, server events, and streams. |
| inkly(contract, options) | Creates an app. options include authorize, codec, heartbeat, resume, resumeWindow, backpressure, exposeErrors, and the security options allowedOrigins, reauthorize, and authExpiry. |
| inkly.Unauthorized / Forbidden / NotFound / TimeoutError | Static error classes for rejecting auth, hooks, actions, and streams with typed wire errors. |
| app.defineAction(name, (peer, input) => output) | Registers a request/response handler. The peer argument is first. |
| app.defineStream(name, async function* (peer, input) { ... }, options?) | Registers a server-push stream; pass { resumable, window } to keep chunks replayable. |
| app.on("open" | "close" | "error", listener) | Observes connection lifecycle. |
| app.use(hook) | Runs per-message authorization; returning false rejects with FORBIDDEN. |
| app.emit(event, payload) / app.to(room).emit(event, payload) | Broadcasts typed events to every peer or one room. |
| app.room(room).members() / .size() | Inspects room presence. |
| app.namespace(name) | Creates a namespaced app surface over the same engine. |
| app.authorizeConnection(request, params?) | Lets adapters pre-authorize an upgrade and attach context before hello. |
| app.checkOrigin(request) | Adapter-facing CSWSH guard: returns false when allowedOrigins rejects the request's Origin so adapters can answer 403 before the socket opens. |
| app.handlers | Adapter-facing open / message / close / error handlers. |
| app.shutdown() | Stops the app and releases sessions. |
| peer.id, peer.context, peer.request, peer.remoteAddress, peer.rooms | Per-connection identity, auth context, request metadata, and room set. |
| peer.send(...), peer.close(...), peer.join(...rooms), peer.leave(...rooms) | Low-level peer operations and room membership helpers. |
Docs
- docs/overview.md — the server engine model.
- docs/auth-and-context.md — connection auth, context, and per-message hooks.
- docs/rooms-and-events.md — broadcast and presence patterns.
- docs/streams-and-resume.md — resumable stream behavior and windows.
Examples
- examples/chat-server.ts — actions, rooms, lifecycle, and events.
- examples/token-stream.ts — a resumable
defineStream().
License
Dazza Public License 1.0 (LicenseRef-Dazza-1.0).
