@rotorsoft/act-http 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/hono/index.d.ts +109 -0
- package/dist/@types/hono/index.d.ts.map +1 -0
- package/dist/hono/index.cjs +192 -0
- package/dist/hono/index.cjs.map +1 -0
- package/dist/hono/index.js +116 -0
- package/dist/hono/index.js.map +1 -0
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -171,6 +171,45 @@ const authed = t.procedure.use(authenticated(myExtractor));
|
|
|
171
171
|
// procedures alongside the generated ones.
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
+
### `hono` — auto-generated REST surface
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { hono } from "@rotorsoft/act-http/hono";
|
|
178
|
+
import { serve } from "@hono/node-server";
|
|
179
|
+
|
|
180
|
+
const api = hono(app, {
|
|
181
|
+
// ActorExtractor from `@rotorsoft/act-http/api` — host's auth seam.
|
|
182
|
+
actor: (c) => resolveActorFromJwt(c),
|
|
183
|
+
// Resolve the target stream per call; singleton aggregates return a constant.
|
|
184
|
+
stream: (action, input, c) => `tenant-${c.req.header("x-tenant")}`,
|
|
185
|
+
// Optional optimistic concurrency — return `undefined` to skip the check.
|
|
186
|
+
expectedVersion: (action, input, c) => {
|
|
187
|
+
const v = c.req.header("if-match");
|
|
188
|
+
return v ? Number.parseInt(v, 10) : undefined;
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
serve({ fetch: api.fetch, port: 4000 });
|
|
193
|
+
// POST /api/actions/OpenTicket body: { title }
|
|
194
|
+
// → 200 [Snapshot] | 4xx ApiError envelope
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The generator walks `app.registry.actions` once and registers one `POST /actions/<actionName>` per action under the configured `basePath` (default `/api`). Bodies are validated with `@hono/zod-validator` against the action's registered Zod schema; failures short-circuit with `400`. The internal `authenticated(extractor)` middleware runs `options.actor` once per request and stashes the resolved `Actor` under `c.get("actor")`, available to any downstream middleware (logging, tracing, hand-written routes mounted on the same Hono instance). `Idempotency-Key` is read from the request header by default; `keyFrom` overrides for hosts that prefer a custom convention.
|
|
198
|
+
|
|
199
|
+
Errors map through the shared `toApiError(...)` table at `@rotorsoft/act-http/api`: `ConcurrencyError → 412 / CONCURRENCY`, `InvariantError → 409 / INVARIANT`, `ValidationError → 422 / VALIDATION`, `StreamClosedError → 410 / STREAM_CLOSED`, `NonRetryableError → 400 / NON_RETRYABLE`. The envelope (`{ error, detail?, code? }`) is the same shape every other act-http transport ships so a client speaking REST plus tRPC never sees two formats for the same framework error.
|
|
200
|
+
|
|
201
|
+
Edge-runtime ready — Hono runs unchanged on Node, Bun, Cloudflare Workers, Vercel Edge, and AWS Lambda. Operators wiring `idempotency` on edge runtimes should verify the `IdempotencyStore` is edge-compatible (in-memory works per worker; cross-worker requires a distributed store).
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
// Compose the auth middleware into your own Hono chain instead:
|
|
205
|
+
import { Hono } from "hono";
|
|
206
|
+
import { authenticated, type ActMiddlewareVariables } from "@rotorsoft/act-http/hono";
|
|
207
|
+
|
|
208
|
+
const api = new Hono<{ Variables: ActMiddlewareVariables }>();
|
|
209
|
+
api.use("*", authenticated((c) => resolveActorFromJwt(c)));
|
|
210
|
+
// Hand-written routes alongside the generated ones now see c.get("actor") typed.
|
|
211
|
+
```
|
|
212
|
+
|
|
174
213
|
### `sse` — live state broadcast
|
|
175
214
|
|
|
176
215
|
```ts
|
|
@@ -244,6 +283,15 @@ Auto-generated tRPC router for the act-http-api epic (#835).
|
|
|
244
283
|
- **`authenticated(extractor) → middleware`** — standalone export of the auth middleware the generator uses internally. Hosts composing their own procedure chain (logging + tracing + custom auth flavors) use `t.procedure.use(authenticated(extractor))` to inject `ctx.actor` without going through the generator. The middleware is structurally-typed so any host `t` instance accepts it.
|
|
245
284
|
- **`TrpcOptions<Ctx>`** — `{ actor, stream, expectedVersion?, idempotency? }`. `actor` is the `ActorExtractor` from `@rotorsoft/act-http/api`. `stream` returns the target stream per call. `expectedVersion` is optional — `(action, input, ctx) => number | undefined` — when set, the procedure threads the resolved value through `Target.expectedVersion` so `app.do` enforces optimistic concurrency; hosts typically read it from an `If-Match` header or the client's last-known snapshot, and returning `undefined` skips the check for that call. `idempotency` is optional — `{ store: IdempotencyStore; keyFrom: (ctx) => string | undefined }` — when set, the procedure honors `Idempotency-Key` via `withIdempotency`. Duplicate claims throw `CONFLICT` (the contract intentionally doesn't cache the original handler's result).
|
|
246
285
|
|
|
286
|
+
### `/hono` subpath
|
|
287
|
+
|
|
288
|
+
Auto-generated REST surface for the act-http-api epic (#835).
|
|
289
|
+
|
|
290
|
+
- **`hono(app, options) → Hono`** — generator function. Walks `app.registry.actions` once and registers a `POST /actions/<actionName>` per action under `basePath` (default `/api`). Body is validated with `@hono/zod-validator` against the action's Zod schema; failures short-circuit with `400`. The internal `authenticated(options.actor)` middleware stashes the resolved `Actor` under `c.get("actor")`. Routes return `200 Snapshot[]` on success, `4xx ApiError` envelope (with the conventional HTTP status) on framework errors, `500 / INTERNAL` on unknown throws.
|
|
291
|
+
- **`authenticated(extractor) → MiddlewareHandler`** — standalone export of the auth middleware the generator uses internally. Hosts composing their own Hono chain wire `api.use("*", authenticated(extractor))` and downstream routes read `c.get("actor"): Actor`. Errors thrown by the extractor surface as `401 / UNAUTHORIZED`.
|
|
292
|
+
- **`HonoOptions`** — `{ actor, stream, expectedVersion?, idempotency?, basePath? }`. `actor` is the `ActorExtractor`. `stream` returns the target stream per call. `expectedVersion` threads `Target.expectedVersion` for optimistic concurrency — returning `undefined` skips the check. `idempotency` is optional — `{ store: IdempotencyStore; keyFrom?: (c) => string | undefined }` — when set, the route honors `Idempotency-Key` via `withIdempotency`; default `keyFrom` reads the `Idempotency-Key` header. Duplicate claims return `409 / CONFLICT`. `basePath` defaults to `/api`.
|
|
293
|
+
- **`ActMiddlewareVariables`** — `{ actor: Actor }`. Use as the `Variables` generic on a host Hono instance to get `c.get("actor")` typed downstream of `authenticated`.
|
|
294
|
+
|
|
247
295
|
### `/sse` subpath
|
|
248
296
|
|
|
249
297
|
- **`BroadcastChannel<S>`** — server-side broadcast manager with per-stream subscriber sets and an LRU state cache.
|