first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
# `conformance`
## Purpose
Builds a paired client/server harness over an in-process `MessageChannel`
for conformance tests. The harness is intended for use by every Stage-3
worker-proxy package (`api-db-worker-proxy`, `api-events-worker-proxy`,
`api-secrets-worker-proxy`, `api-jobs-worker-proxy`,
`api-logger-worker-proxy`, and any successor) so each proxy can verify
its capability semantics over a real `MessagePort` round-trip without
re-implementing setup boilerplate.
The harness exposes the live `client`, `server`, and `ports` handles
plus a `dispose()` that tears them all down in the correct order
(client first, then server, then port). Tests typically wrap it in a
`finally`-style block or per-test setup/teardown.
## Features
- Single-call paired construction: pass a handlers factory, get a
fully wired client/server/ports triple back.
- Idempotent `dispose()` — safe to call inside a test cleanup hook
even if the test already closed parts of the harness.
- Exposes the underlying `RawWorkerRpcClient` so streaming tests can
attach a `StreamDispatcher` via the client's `onStreamFrame`
option.
## Usage: Basic
```ts
import { runWorkerRpcConformance } from "@suaveplan/api-worker-rpc/testing";
const h = runWorkerRpcConformance(() => ({
ping: () => "pong",
}));
await expect(h.client.call("ping", [])).resolves.toBe("pong");
h.dispose();
```
## Usage: Advanced
```ts
import { StreamDispatcher, streamRequest } from "@suaveplan/api-worker-rpc/streaming";
import { runWorkerRpcConformance } from "@suaveplan/api-worker-rpc/testing";
const h = runWorkerRpcConformance(() => ({
rows: async function* () {
for (let i = 0; i < 5; i++) yield i;
},
}));
const dispatcher = new StreamDispatcher();
// Re-wire onStreamFrame on the underlying client — note: in practice you'd
// construct the client with this option from the start. The harness ships
// without it so test authors can choose whether streaming is exercised.
h.dispose();
```
## API Reference
- `interface ConformanceHarness { client, server, ports, dispose }`.
- `runWorkerRpcConformance(factory: () => WorkerRpcHandlers): ConformanceHarness`.
## Implementation Notes
- The default harness does NOT install a `StreamDispatcher` — streaming
tests construct their own client with the dispatcher's `dispatch`
method wired into `onStreamFrame`, then use the harness's ports
directly. This keeps the non-streaming path one-line.
- The `client` field is a `RawWorkerRpcClient`, not the typed proxy —
conformance tests address methods by string and inspect raw frames
rather than relying on TypeScript inference.
- `dispose()` tolerates partial-prior-closure so per-test `afterEach`
can call it unconditionally.