@cxai/yapi
v0.3.0
Published
Content-negotiated Y.Map server — Hono middleware with Mustache templates, path param filters, JSON/HTML/SSE handlers.
Downloads
213
Maintainers
Readme
@cxai/yapi
Content-negotiated Y.Map server built on Hono. Define routes declaratively — get JSON, HTML (Mustache), and SSE endpoints automatically from Yjs documents. Supports path-param filtering and dynamic collection resolution via templates.
Install
npm install @cxai/yapiUsage
Standalone
import * as Y from "yjs";
import { createApp } from "@cxai/yapi";
const doc = new Y.Doc();
const app = createApp(doc, {
routes: {
"/users": {
collection: "users",
json: { template: { data: "{{list}}", total: "{{count}}" } },
html: { template: "<ul>{{#list}}<li>{{name}}</li>{{/list}}</ul>" },
sse: { event: "user-update" },
post: { key: "id" },
},
"/users/:userId": {
collection: { template: "users" }, // dynamic collection resolution
select: "first",
},
},
});
// Content negotiation via Accept header or ?format= query
// GET /users → JSON (Accept: application/json)
// GET /users?format=html → HTML
// GET /users?format=sse → SSE stream
// POST /users → write to Y.MapCombined with @cxai/faker
import { createFakerJob } from "@cxai/faker";
import { createApp } from "@cxai/yapi";
const doc = new Y.Doc();
// Faker pushes items into doc
createFakerJob(doc, "events", {
id: "{{string.uuid}}",
type: "{{helpers.arrayElement(['click','scroll','submit'])}}",
timestamp: "{{date.recent}}",
}, { count: 100, interval: [500, 1000], autoStart: true });
// yapi serves them in real-time
const api = createApp(doc, {
routes: {
"/events": { collection: "events", sse: { event: "{{type}}" } },
"/events/:type": { collection: "events" }, // filtered by path param
},
});Combined with @cxai/job
import { createJob } from "@cxai/job";
import { createApp } from "@cxai/yapi";
const job = createJob({ doc, path: "discoveries", iterable: appDiscoverySource });
const api = createApp(doc, {
routes: { "/discoveries": { collection: "discoveries", sse: {} } },
});
job.trigger(); // SSE clients see items arrive in real-timeCLI
npx cxai-yapi --config routes.yaml --port 3000API Reference
createApp(doc, config): Hono
Creates the full content-negotiated app. Routes are prefixed by format internally (/json/*, /html/*, /sse/*) and selected via getPath content negotiation.
YapiConfig
interface YapiConfig {
routes: Record<string, RouteDef | string>; // string shorthand = collection name
}RouteDef
interface RouteDef {
collection: string | { template: string }; // Mustache template for dynamic resolution
select?: "list" | "first" | "last";
json?: { template?: Record<string, any> };
html?: { template: string }; // Mustache template
sse?: { event?: string; template?: string | Record<string, any> };
post?: PostDef | boolean;
}
interface PostDef {
key?: string; // body field to use as Y.Map key (default: "id")
template?: Record<string, any>; // response template
}createYapiMiddleware(doc, config)
Standalone middleware that resolves context variables:
| Variable | Type | Description |
|----------|------|-------------|
| c.get("doc") | Y.Doc | The document |
| c.get("source") | Y.Map | Raw collection |
| c.get("collection") | Y.Map | Filtered + synced collection |
| c.get("config") | RouteDef | Matched route definition |
getPath(req): string
Content negotiation helper — prefixes path with /json, /html, or /sse based on Accept header or ?format= query param.
Sub-app factories
| Function | Description |
|----------|-------------|
| createJsonApp(config) | JSON GET + POST routes |
| createHtmlApp(config) | Mustache-rendered HTML |
| createSseApp(config) | SSE via @cxai/stream yMapIterate |
Helpers
renderObject(template, ctx)— recursive Mustache object renderingrenderValue(value, ctx)— single value render (preserves raw types for exact{{key}}matches)findMatchingRoute(path, routes)— path-param route matching
Examples
@cxai/example-yapi-standalone— Standalone yapi server@cxai/example-faker-yapi-combined— Faker + yapi streaming@cxai/example-faker-standalone— Faker standalone (pairs with yapi)@cxai/example-job-app-discovery— Job engine + yapi
See Also
@cxai/job— Async iterable job engine@cxai/faker— Template-based fake data generator@cxai/stream— yMapIterate + stream utilities
