印 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

built-in 21

In the core. Nothing to install, nothing to keep in step.

  • cors

    built-in

    Lets pages on other origins call the API: preflights and the access-control headers.

    import { cors } from "@vxnsin/inkan"
    docs →source
  • rateLimit

    built-in

    At most so many requests per client and window, keyed on ctx.ip.

    import { rateLimit } from "@vxnsin/inkan"
    docs →source
  • compress

    built-in

    Brotli or gzip, as the client takes it.

    import { compress } from "@vxnsin/inkan"
    docs →source
  • serveStatic

    built-in

    The built frontend next to the API, with the fallback a single-page app needs.

    import { serveStatic } from "@vxnsin/inkan"
    docs →source
  • OpenAPI 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 →source
  • response

    built-in

    Only 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 →source
  • client

    built-in

    A client typed from the app itself, without code generation.

    import { client } from "@vxnsin/inkan/client"
    docs →source
  • inkan check

    built-in

    Examples 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 →source
  • inkan seal

    built-in

    Every 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 →source
  • Streams out, server-sent events with a schema per event, multipart uploads and forms in.

    import { sse, t } from "@vxnsin/inkan"
    docs →source
  • app.job

    built-in

    Work that takes longer than a request: a queue, progress over SSE, and the result.

    in the core · nothing to import

    docs →needs 0.7.0source
  • app.ws

    built-in

    WebSockets with a contract both ways, a typed client, origins checked against hijacking. No dependency.

    in the core · nothing to import

    docs →needs 0.7.0source
  • schedule

    built-in

    Jobs on a cron schedule: five fields, names, Vixie's day rule, UTC or local, one worker runs them.

    in the core · nothing to import

    docs →needs 0.7.0source
  • env

    built-in

    Environment variables checked with a t.object schema at startup: typed, frozen, every problem in one error.

    import { env } from "@vxnsin/inkan"
    docs →needs 0.7.0source
  • pressure

    built-in

    Overload protection: a 503 with retry-after while the event loop lags or memory runs high.

    in the core · nothing to import

    docs →needs 0.7.0source
  • The request's context anywhere, through AsyncLocalStorage: in a logger, in a database helper.

    import { currentContext } from "@vxnsin/inkan"
    docs →needs 0.7.0source
  • memoryStore

    built-in

    The Store inkan has built in: TTLs, atomic add, take and increment, LRU-bounded. One process.

    import { memoryStore } from "@vxnsin/inkan"
    docs →needs 0.8.0source
  • cache

    built-in

    Keeps a route's answers for a while. Requests that arrive meanwhile wait for that one answer.

    in the core · nothing to import

    docs →source
  • HTML from a tagged template that escapes every value, in the layout of the route's scope.

    import { html } from "@vxnsin/inkan"
    docs →source
  • problem

    built-in

    Every error in one shape: RFC 9457 problem documents with a stable type to switch on.

    import { problem } from "@vxnsin/inkan"
    docs →source
  • /_inkan

    built-in

    A 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

    middleware

    Sessions, JWTs, API keys and basic auth, roles, CSRF, 2FA, OAuth and refresh tokens, on node:crypto alone.

    $ npm i @inkanjs/auth
    docs →needs 0.7.0source
  • Cookie sessions: signed, encrypted, or a random id in front of a store. Typed on ctx.session.

    $ npm i @inkanjs/session
    docs →needs 0.7.0source
  • A strict Content-Security-Policy with nonces, HSTS, and the rest.

    $ npm i @inkanjs/secure-headers
    docs →needs 0.7.0source
  • @inkanjs/etag

    middleware

    ETags and 304 Not Modified, hashed before compression.

    $ npm i @inkanjs/etag
    docs →needs 0.7.0source
  • Idempotency-Key: a POST sent twice runs once.

    $ npm i @inkanjs/idempotency
    docs →needs 0.7.0source
  • @inkanjs/proxy

    middleware

    A 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
    docs →needs 0.7.0source
  • Stop calling what keeps failing: around an outgoing call, or a circuit per route.

    $ npm i @inkanjs/circuit-breaker
    docs →needs 0.7.0source
  • @inkanjs/otel

    middleware

    OpenTelemetry tracing: a SERVER span per request, named by its route, continued from traceparent.

    $ npm i @inkanjs/otel
    docs →needs 0.7.0source

stores 4

One Store for jobs, rate limits, logins and sessions, shared by every process. On your own client.

  • A Store in Redis on your node-redis or ioredis client: SET NX, GETDEL, Pub/Sub for jobs.

    $ npm i @inkanjs/redis
    docs →needs 0.8.0source
  • A Store in one PostgreSQL table on your pg or postgres.js: the database's clock, LISTEN/NOTIFY for jobs.

    $ npm i @inkanjs/postgres
    docs →needs 0.8.0source
  • A Store on MongoDB with your own client: atomic commands, a TTL index, change streams or polling.

    $ npm i @inkanjs/mongo
    docs →needs 0.8.0source
  • A Store on MySQL 8 with your mysql2 pool: exact binary keys, prepared statements, the database's clock.

    $ npm i @inkanjs/mysql
    docs →needs 0.8.0source

integrations 4

inkan where you already are. One package each.

  • @inkanjs/next

    integration

    An inkan app in Next.js: route handlers, the Pages Router, a typed client for Server Components.

    $ npm i @inkanjs/next
    docs →source
  • @inkanjs/vite

    integration

    Your inkan API inside the Vite dev server: one port, reloaded on every save.

    $ npm i @inkanjs/vite
    docs →source
  • @inkanjs/query

    integration

    The typed client for TanStack Query: keys and data from the contract, problems as errors.

    $ npm i @inkanjs/query
    docs →source
  • @inkanjs/uws

    integration

    uWebSockets.js instead of node:http: the fastest way to run inkan.

    $ npm i @inkanjs/uws
    docs →source

recipes 4

Not packages: a few lines of your own, on the driver you already use.

  • postgres

    recipe

    A 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

    recipe

    ioredis on ctx.redis: connected in onListen, quit in onClose, multi() for commands that belong together.

    app.decorate("redis", new Redis(url))
    docs →
  • mongodb

    recipe

    The official driver's Db on ctx.db, typed collections, and transactions on a replica set.

    app.decorate("db", mongo.db("shop"))
    docs →
  • prisma

    recipe

    A 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.

publish a plugin →

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.

the keyword is enough
// package.json
{
  "name": "inkan-tenant",
  "description": "One line: what it does.",
  "keywords": ["inkan", "inkan-plugin"],
  "peerDependencies": {
    "@vxnsin/inkan": ">=0.8.0 <1.0.0"
  }
}