API Reference
Every reusable framework capability is exposed through one import — the facade at @/framework/facade.js. You never reach into framework internals; if it is not on this page, it is not part of the public API.
import {
createRouter, // router builder
createRoute, // OpenAPI route declaration
group, // middleware grouping shorthand
z, // Zod + .openapi() schemas
jsonContent, // JSON media-type wrapper
HttpStatusCodes, // status constants
validate, // schema validation outside routes
database, // init/access the Drizzle instance
db, // global query proxy
paginate, // request-driven pagination
paginateModel, // eager-loading pagination
paginateQuery, // custom count/data pagination
paginateTable, // single-table pagination
cache, // Redis key-value cache
command, // register in-process handler
dispatchCommand, // run an in-process handler
dispatchEvent, // broadcast and/or enqueue an event
queue, // access a BullMQ queue
queueJob, // enqueue a background job
shouldQueue, // register a job handler
broadcast, // Socket.IO broadcast
defineSchedule, // named cron schedules
session, // server-side sessions
storage, // file storage
notify, // persisted + realtime notifications
password, // bcrypt hashing
jwt, // token generation/verification
cookie, // auth cookie helpers
mail, // SMTP transport
logger, // structured logging
urls, // absolute URL building
lodash, // full Lodash library
} from "@/framework/facade.js";import {
createRouter, // router builder
createRoute, // OpenAPI route declaration
group, // middleware grouping shorthand
z, // Zod + .openapi() schemas
jsonContent, // JSON media-type wrapper
HttpStatusCodes, // status constants (curated subset)
validate, // schema validation outside routes
database, // init/access the Drizzle instance
db, // global query proxy
paginate, // request-driven pagination
paginateModel, // eager-loading pagination
paginateQuery, // custom count/data pagination
paginateTable, // single-table pagination
cache, // Redis key-value cache
command, // register in-process handler
dispatchCommand, // run an in-process handler
dispatchEvent, // broadcast and/or enqueue an event
queue, // access a BullMQ queue
queueJob, // enqueue a background job
shouldQueue, // register a job handler
broadcast, // Socket.IO broadcast
defineSchedule, // named cron schedules
session, // server-side sessions
storage, // file storage
notify, // persisted + realtime notifications
password, // bcrypt hashing
jwt, // token generation/verification
cookie, // auth cookie helpers
mail, // SMTP transport
logger, // structured logging
urls, // absolute URL building
lodash, // full Lodash library
fields, // multer-driven multipart fields
upload, // multer-driven file upload middleware
} from "@/framework/facade.js";The difference between engines is only upload/fields — the Hono engine parses multipart natively via c.req.parseBody(), so it has no multer helpers. See Upload and the Upload guide.
Express engine additionally exports
uploadandfields— multipart parsing middleware built onmulter. See Upload and the Upload guide. The Hono engine parses multipart natively viac.req.parseBody().
Function reference
Each facade function has its own page. Every export below is a documented part of the public API.
| Function | Purpose | Guide |
|---|---|---|
createRouter | Router with group/route/api helpers | Routing · OpenAPI |
createRoute | Declare a documented OpenAPI route | Routing · OpenAPI |
group | createRouter().group() shorthand + role middleware | Routing |
z | Extended Zod with .openapi() | OpenAPI |
jsonContent | Wrap a schema as application/json | OpenAPI |
HttpStatusCodes | Numeric HTTP status constants | OpenAPI |
validate | Run a Zod schema → throws 422 on mismatch | OpenAPI |
database | Returns the initialized Drizzle instance | Database |
db | Global Drizzle query proxy | Database |
paginate | Request-driven pagination (joins, aggregates) | Database |
paginateModel | Eager-loading pagination (db.query…findMany with) | Database |
paginateQuery | Manual total()/data() pagination | Database |
paginateTable | Single-table pagination, no request object | Database |
cache | Redis key-value cache (graceful fallback) | Cache |
command | Register an in-process synchronous handler | Events & Queue |
dispatchCommand | Run a registered command (async: enqueue) | Events & Queue |
dispatchEvent | Broadcast + enqueue a domain event | Events & Queue |
queue | Access a BullMQ queue instance | Events & Queue |
queueJob | Enqueue a background job | Events & Queue |
shouldQueue | Register a job handler (optionally durable) | Events & Queue |
broadcast | Socket.IO emit to targeted audiences | Realtime |
defineSchedule | Named cron tasks with distributed locking | Scheduler |
session | Redis-backed server-side sessions | Session |
storage | Local + S3-compatible file storage | Storage |
notify | Persist + broadcast + email notifications | Notifications |
password | bcrypt hash / verify | Password |
jwt | HS256 token generation / verification | JWT |
cookie | {name}_access / {name}_refresh cookie helpers | Cookie |
mail | SMTP sendMail transport | |
logger | Leveled structured logging + rotating files | Logger |
urls | Absolute URL building from APP_URL | URL |
upload | File upload middleware (Express only, multer) | Upload |
lodash | Full Lodash re-export | libraries |
When do I use which?
- HTTP & OpenAPI —
createRouter/groupbuild the router;createRoutedocuments a route;zwrites the schemas;jsonContent+HttpStatusCodesdescribe responses. - Input safety —
validateruns a schema anywhere (outside routes) and throws a structured422on failure. - Data -
dbis the Drizzle client;paginate/paginateModel/paginateQuery/paginateTablewrap queries into a single page of results (see the Which one? table). - Caching —
cachestores JSON with TTL and degrades to a no-op when Redis is off. - Background work —
command/dispatchCommandrun in-process handlers;dispatchEventfans out to sockets and/or queues;queueJob/shouldQueueare the raw BullMQ surface. - Realtime —
broadcastemits a Socket.IO event to targeted audiences. - Automation —
defineScheduleruns cron tasks with distributed locking. - State & files —
sessionkeeps server-side state;storagereads/writes files on local disk or S3. - User-visible events —
notifypersists a notification row and optionally broadcasts + emails it. - Support —
password,jwt,cookie,mailpower auth flows;loggeris the structured logger;urlsbuilds absolute links;lodashre-exports the full library.
Common recipes
Sign up a user with hashed password + realtime + email
The auth flow composes hashing, persistence, and dispatch:
import { db, password, dispatchEvent, notify } from "@/framework/facade.js";
import * as schema from "@/database/schema.js";
export const register = async (input: {
name: string;
email: string;
password: string;
}) => {
const user = await db.insert(schema.users).values({
name: input.name,
email: input.email,
password: await password.hashPassword(input.password),
});
await notify(user.id, {
type: "success",
title: "Welcome",
body: "Your account is ready.",
broadcast: true,
mail: { subject: "Welcome to nexwire" },
});
await dispatchEvent(
"user.registered",
{ userId: user.id },
{ broadcast: { roles: ["admin"] } },
);
return user;
};List a paginated resource
Route + controller compose routing, querying, and pagination:
import {
createRoute,
createRouter,
group,
HttpStatusCodes,
jsonContent,
db,
paginate,
z,
} from "@/framework/facade.js";
import { desc } from "drizzle-orm";
import { posts } from "@/modules/blog/database/models/post.js";
const listRoute = createRoute({
path: "/",
method: "get",
tags: ["Posts"],
responses: {
[HttpStatusCodes.OK]: jsonContent(z.array(PostSchema), "list of posts"),
},
});
export default createRouter()
.group()
.api(listRoute, async (c) => {
const query = db.select().from(posts).orderBy(desc(posts.id));
return c.json(await paginate(c, query, 15));
});import {
createRoute,
createRouter,
group,
HttpStatusCodes,
jsonContent,
db,
paginate,
z,
} from "@/framework/facade.js";
import type { Request, Response } from "express";
import { desc } from "drizzle-orm";
import { posts } from "@/modules/blog/database/models/post.js";
const listRoute = createRoute({
path: "/",
method: "get",
tags: ["Posts"],
responses: {
[HttpStatusCodes.OK]: jsonContent(z.array(PostSchema), "list of posts"),
},
});
export default createRouter()
.group()
.api(listRoute, async (req: Request, res: Response) => {
const query = db.select().from(posts).orderBy(desc(posts.id));
res.json(await paginate(req, query, 15));
});Throttle background work and broadcast the result
queueJob + shouldQueue handle heavy work; broadcast surfaces the outcome:
import { queueJob, shouldQueue, broadcast } from "@/framework/facade.js";
// Controller: queue it, respond fast
await queueJob("process-image", { path }, { queue: "images", delay: 5 });
// Worker: register handler, then notify the author
shouldQueue("process-image", "images", async (job) => {
const url = await processImage(job.data.path);
broadcast("image.processed", { url }, { users: [job.data.userId] });
});Rules of the facade
- One import — everything importable lives on
@/framework/facade.js; the facade only re-exports what is implemented. If a function is missing here, it does not exist yet. - Graceful degradation — Redis-backed features (
cache,session,queue,broadcastvia adapter) returnnull/false/fallbackwhen Redis is unavailable instead of throwing. - Namespaces over bare functions — grouped utilities (
cache,session,storage,jwt,cookie,password,mail,urls,lodash) keep call sites searchable and collide-proof. - Compose, don't re-implement — features are built by combining the exports above (see the pagination helpers, which all share one
PaginatedResultshape).
