Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# options
## Purpose
Zod schema validating `SsePluginOptions` at the factory boundary. `createSsePlugin` calls `SsePluginOptionsSchema.safeParse(options)` and raises `SseError(SSE_INVALID_INPUT)` with the `ZodError` as `cause` on failure. The schema also encodes the canonical defaults so the plugin descriptor's resolved config reflects every documented default value without the implementation hand-coding them.
## Features
- Strict object validation rejects unknown keys to catch typos like `heartBeatInterval`.
- Defaults applied via Zod's `.default()` so the resolved type has every field non-optional.
- Numeric fields constrained: positive integers for time/cap fields; non-negative integer for retention (zero disables replay).
- `routePrefix` regex matches `/`, `/sse`, `/v1/sse`, rejecting trailing-slash and missing-leading-slash forms.
- Runtime objects (`idGenerator`, `clock`, `logger`) validated structurally via `z.custom` so duck-typed implementations are accepted.
## Usage: Basic
```ts
import { SsePluginOptionsSchema } from "@suaveplan/api-plugin-sse/schemas/options";
const parsed = SsePluginOptionsSchema.parse({
heartbeatIntervalMs: 15_000,
maxConnectionsPerPrincipal: 4,
});
console.log(parsed.routePrefix); // "/sse" (defaulted)
```
## Usage: Advanced
```ts
import { SsePluginOptionsSchema } from "@suaveplan/api-plugin-sse/schemas/options";
import { SSE_CODES, SseError } from "@suaveplan/api-plugin-sse/error-codes/error-codes";
function validateOrThrow(input: unknown) {
const result = SsePluginOptionsSchema.safeParse(input);
if (!result.success) {
throw new SseError(SSE_CODES.INVALID_INPUT, "invalid SSE config", {
cause: result.error,
});
}
return result.data;
}
// User-supplied logger duck-typed against LoggerLike — accepted.
validateOrThrow({
logger: {
debug: console.debug,
info: console.info,
warn: console.warn,
error: console.error,
},
});
```
## API Reference
- `SsePluginOptionsSchema` — Zod object schema. Fields and defaults:
- `heartbeatIntervalMs` — positive integer (default `30_000`).
- `routePrefix` — string matching `^/[A-Za-z0-9\-_/]*[A-Za-z0-9\-_]$|^/$` (default `"/sse"`).
- `attachDefaultRoute` — boolean (default `true`).
- `retentionPerChannel` — non-negative integer (default `100`).
- `maxConnectionsPerPrincipal` — positive integer (default `16`).
- `maxTotalConnections` — positive integer (default `10_000`).
- `queueHighWaterMark` — positive integer (default `256`).
- `overflowPolicy` — `"drop-oldest" | "drop-newest"` (default `"drop-oldest"`).
- `idGenerator` — optional `() => string`.
- `clock` — optional `Clock` from `@suaveplan/types`.
- `logger` — optional `LoggerLike` from `@suaveplan/types`.
- `type SsePluginOptionsInput` — `z.input<typeof SsePluginOptionsSchema>` (caller-facing shape).
- `type SsePluginOptionsResolved` — `z.output<typeof SsePluginOptionsSchema>` (post-default shape).
## Implementation Notes
- The schema is `.strict()` — unknown keys produce a `ZodIssueCode.unrecognized_keys` issue. Intentionally strict so a typo doesn't silently fall back to a default.
- The runtime-object validators do not require structural typing of every method — they sniff the presence of one canonical method (`logger.info`, `clock.now`) so callers can pass extended objects without rewriting them.
- Defaults are intentionally generous for production use; tighten them in your `createSsePlugin` call if you run behind aggressive proxies or with constrained memory budgets.