0.21

Every published okengine release, newest first.

all series · 0.20

v0.21.0

✨ Added

Runtime

  • Built-in fx.fail helpers (notFound, forbidden, conflict, foreignKey, unauthorized, rateLimited, serviceUnavailable, database, internal) are always on — no errors: { NotFound } bag required. Domain codes (OutOfStock, FlightFull, keel Duplicate) still go on errors:.
  • okengine/client/explainmatch / matchError / explain collapse unknown flow and transport errors into a UX kind (auth, missing, invalid, …). Dispatch: named code → kind arm → required _. match takes the whole { data, error } envelope (ok + those arms). ValidationError issues type as { message, path }[] (explain.fields for forms).
  • fx.store SQL unique / FK / NOT NULL / CHECK / invalid / too_long / out_of_range / connection failures become typed fail values (same family as ValidationError). Serialization / deadlock / lock-busy (40001 / 40P01 / 55P03, SQLite BUSY) stay thrown so flow.retry can run, then ServiceUnavailable. Redis connection / CLUSTERDOWN / READONLY map to ServiceUnavailable; BUSY / TRYAGAIN follow the same retry-then-503 path. WRONGTYPE stays InternalError. Files fs / s3 AccessDenied and path-escape keys map to Forbidden; SlowDown / EBUSY follow retry-then-503; NoSuchBucket / ENOSPC are ServiceUnavailable.
  • Boot fatals print cause + fix (formatFatalError). VaultBootError is **OKE1510**. No TTY stack unless OKE_DEBUG=1. Request-line chips include error.code (409 Conflict).

Docs

  • Site header adds a Discord square before npm (blurple tile, invite https://discord.gg/j2hkZZbnp), matching npm’s flush square cell and Clyde glyph height to the npm “n”, including the mobile menu.
  • Flow / HTTP / Store / Errors / Vault / Try It document always-on helpers, honest 404/409/503 tables, SQL / KV / files auto-fail, and the OKE1510 TTY dump.
  • Errors reference catalogs fx.fail helpers, always-on vs domain errors:, HTTP statuses, and SQL / KV / files store auto-map.
  • Calling documents match / matchError / explain (kind arms, required _, dispatch order) and JSON NotFound vs a plain-text router 404. Errors smallest example uses match.

💥 Breaking Changes

Runtime

  • Built-in HTTP statuses: NotFound **404** (was 400), Conflict / ForeignKey **409**, AuthRateLimited **429** (was 400), ServiceUnavailable **503**. Domain codes stay **400**. Router miss remains plain-text 404.
  • SQL unique violations are Conflict **409**, not 500 InternalError.
  • InternalError uses the catalog message only — it no longer copies the thrown Error.message.
  • Typed client ContractErrors always includes built-in codes; a declared key still wins (shorter { code } tightening).
  • store.resource no longer stamps Manifest errors: { NotFound } by default.

♻️ Changed

Runtime

  • Export gzip regression baselines refreshed in budgets.json after always-on fx.fail helpers, store SQL/KV/files auto-map, and i18n catalog strings (kernel edge 16.99 kB and client 4.99 kB still under the 17 kB / 5 kB absolute caps).

Docs

  • Try It is a first-app walkthrough: scaffold file map, GET / POST /users in one routes file, persist, then Signal + Channel, then split files / http.resource and short Gate · Clock · Vault · AI explainers.
  • Try It Create explains why Bun ≥ 1.4.2 and Docker Compose (host app, production-shaped data plane) and links the install pages.
  • Try It puts **The files** before First HTTP — roles (Flow, Store, root, boot), not the blank tree as the only layout.
  • Try It HTTP contracts can live in the router file or in shapes.ts.
  • Try It First HTTP explains the { data, error } envelope (success vs ValidationError / fx.fail).
  • Try It First HTTP explains .public() — required posture, open with no session.
  • Try It First Signal declares in src/signals/, binds a worker in src/flows/workers/, and emits from create ({ key } for once). Code samples on the page focus the lines that change; earlier context dims.

Dev, Keel & create-oke

  • Compose default RustFS pin: 1.0.0-rc.51.0.0 (stable, no v prefix).
  • create-oke shorter and examples/keel use fail.notFound / fail.forbidden / fail.conflict helpers. Keel drops redundant errors: { NotFound } bags and keeps domain Duplicate / Unavailable. Shorter keeps { code } tightening on NotFound / Forbidden / Conflict.

🐛 Fixed

Runtime

  • Untriggered RPC flows (POST /_oke/...) returning unhandled throws now serialize to 500 InternalError (or store auto-mapped failure) instead of empty 204 No Content.
  • fx.call() and app.call() rethrow unhandled exceptions across flow boundaries instead of returning undefined.

Client

  • TransportError runtime instances now consistently populate error.message matching error.data.message. The type requires message (same string as data.message).
  • SSE handshake failure decoding prioritizes top-level error.message while preserving fallback to error.data.message and error.code.
  • Typed client ContractErrors treats a missing errors bag as the built-in map — a phantom Record<string, unknown> no longer wipes NotFound.id.
  • match success ok data is the success type, not O | null.

Docs

  • Calling / Errors document TransportError.message === error.data.message. Flow / fx note that fx.call / app.call rethrow unhandled throws (not silent undefined).