印 hanko
Hanko判子
Everything that stamps onto an inkan app: what comes in the core, the official middleware, the integrations, a few recipes, and the plugins other people publish.
The inkan is the seal. A hanko is the everyday word for the stamp you press it with.
41 of 41 · press / to search, esc to clear
built-in 21
In the core. Nothing to install, nothing to keep in step.
cors
built-inLets pages on other origins call the API: preflights and the access-control headers.
import { cors } from "@vxnsin/inkan"docs →sourcerateLimit
built-inAt most so many requests per client and window, keyed on ctx.ip.
import { rateLimit } from "@vxnsin/inkan"docs →sourcecompress
built-inBrotli or gzip, as the client takes it.
import { compress } from "@vxnsin/inkan"docs →sourceserveStatic
built-inThe built frontend next to the API, with the fallback a single-page app needs.
import { serveStatic } from "@vxnsin/inkan"docs →sourceopenapi + /docs
built-inOpenAPI 3.1 at /openapi.json and a docs page at /docs, from the same schemas. Every example gets a send button.
in the core · nothing to import
docs →sourceresponse
built-inOnly what the contract lists leaves the server. In development, an answer that breaks it is a 500 that says which field.
in the core · nothing to import
docs →sourceclient
built-inA client typed from the app itself, without code generation.
import { client } from "@vxnsin/inkan/client"docs →sourceinkan check
built-inExamples show up in the docs and run as tests: in-process, no port. Routes without one are listed.
in the core · nothing to import
docs →sourceinkan seal
built-inEvery contract's check stamped into plain code ahead of time, in a file you can read and commit. No eval.
in the core · nothing to import
docs →sourcesse · streams · uploads
built-inStreams out, server-sent events with a schema per event, multipart uploads and forms in.
import { sse, t } from "@vxnsin/inkan"docs →sourceapp.job
built-inWork that takes longer than a request: a queue, progress over SSE, and the result.
in the core · nothing to import
app.ws
built-inWebSockets with a contract both ways, a typed client, origins checked against hijacking. No dependency.
in the core · nothing to import
schedule
built-inJobs on a cron schedule: five fields, names, Vixie's day rule, UTC or local, one worker runs them.
in the core · nothing to import
env
built-inEnvironment variables checked with a t.object schema at startup: typed, frozen, every problem in one error.
import { env } from "@vxnsin/inkan"pressure
built-inOverload protection: a 503 with retry-after while the event loop lags or memory runs high.
in the core · nothing to import
currentContext()
built-inThe request's context anywhere, through AsyncLocalStorage: in a logger, in a database helper.
import { currentContext } from "@vxnsin/inkan"memoryStore
built-inThe Store inkan has built in: TTLs, atomic add, take and increment, LRU-bounded. One process.
import { memoryStore } from "@vxnsin/inkan"cache
built-inKeeps a route's answers for a while. Requests that arrive meanwhile wait for that one answer.
in the core · nothing to import
docs →sourcehtml · render
built-inHTML from a tagged template that escapes every value, in the layout of the route's scope.
import { html } from "@vxnsin/inkan"docs →sourceproblem
built-inEvery error in one shape: RFC 9457 problem documents with a stable type to switch on.
import { problem } from "@vxnsin/inkan"docs →source/_inkan
built-inA live log of the last 200 requests and what broke the contract. Development only, loopback only.
in the core · nothing to import
docs →source
middleware 8
Official packages under @inkanjs, each a shared plugin.
@inkanjs/auth
middlewareSessions, JWTs, API keys and basic auth, roles, CSRF, 2FA, OAuth and refresh tokens, on node:crypto alone.
$ npm i @inkanjs/auth@inkanjs/session
middlewareCookie sessions: signed, encrypted, or a random id in front of a store. Typed on ctx.session.
$ npm i @inkanjs/session@inkanjs/secure-headers
middlewareA strict Content-Security-Policy with nonces, HSTS, and the rest.
$ npm i @inkanjs/secure-headers@inkanjs/etag
middlewareETags and 304 Not Modified, hashed before compression.
$ npm i @inkanjs/etag@inkanjs/idempotency
middlewareIdempotency-Key: a POST sent twice runs once.
$ npm i @inkanjs/idempotency@inkanjs/proxy
middlewareA prefix of the app, or one route, handed on to a server behind it. Streamed both ways, no SSRF by construction.
$ npm i @inkanjs/proxy@inkanjs/circuit-breaker
middlewareStop calling what keeps failing: around an outgoing call, or a circuit per route.
$ npm i @inkanjs/circuit-breaker@inkanjs/otel
middlewareOpenTelemetry tracing: a SERVER span per request, named by its route, continued from traceparent.
$ npm i @inkanjs/otel
stores 4
One Store for jobs, rate limits, logins and sessions, shared by every process. On your own client.
@inkanjs/redis
storeA Store in Redis on your node-redis or ioredis client: SET NX, GETDEL, Pub/Sub for jobs.
$ npm i @inkanjs/redis@inkanjs/postgres
storeA Store in one PostgreSQL table on your pg or postgres.js: the database's clock, LISTEN/NOTIFY for jobs.
$ npm i @inkanjs/postgres@inkanjs/mongo
storeA Store on MongoDB with your own client: atomic commands, a TTL index, change streams or polling.
$ npm i @inkanjs/mongo@inkanjs/mysql
storeA Store on MySQL 8 with your mysql2 pool: exact binary keys, prepared statements, the database's clock.
$ npm i @inkanjs/mysql
integrations 4
inkan where you already are. One package each.
@inkanjs/next
integrationAn inkan app in Next.js: route handlers, the Pages Router, a typed client for Server Components.
$ npm i @inkanjs/nextdocs →source@inkanjs/vite
integrationYour inkan API inside the Vite dev server: one port, reloaded on every save.
$ npm i @inkanjs/vitedocs →source@inkanjs/query
integrationThe typed client for TanStack Query: keys and data from the contract, problems as errors.
$ npm i @inkanjs/querydocs →source@inkanjs/uws
integrationuWebSockets.js instead of node:http: the fastest way to run inkan.
$ npm i @inkanjs/uwsdocs →source
recipes 4
Not packages: a few lines of your own, on the driver you already use.
postgres
recipeA pg Pool on ctx.db: checked at start, closed after the last request, a transaction per request when you need one.
app.decorate("db", new pg.Pool())docs →redis
recipeioredis on ctx.redis: connected in onListen, quit in onClose, multi() for commands that belong together.
app.decorate("redis", new Redis(url))docs →mongodb
recipeThe official driver's Db on ctx.db, typed collections, and transactions on a replica set.
app.decorate("db", mongo.db("shop"))docs →prisma
recipeA Prisma client on ctx.db, typed from the schema, with $transaction for work that succeeds or fails as one.
app.decorate("db", new PrismaClient())docs →
community 0
Written by others, listed here, maintained by their authors.
Be the first stamp here.
No community plugins yet. Publish yours as inkan-<name> with the npm keyword inkan-plugin, and it shows up here next to the official ones within a day.
Stamp your own
A plugin is a function that gets a scope and its options. Publish it on npm as inkan-<name> with the keyword inkan-plugin, and it is on this page within a day. No form, no pull request.
Community packages are listed as npm has them, not reviewed or maintained by inkan: the README, the issues and the releases stay with their authors. A pull request to the list is only for a better line, tags or a link to docs.
// package.json
{
"name": "inkan-tenant",
"description": "One line: what it does.",
"keywords": ["inkan", "inkan-plugin"],
"peerDependencies": {
"@vxnsin/inkan": ">=0.8.0 <1.0.0"
}
}