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,78 @@
<!-- markdownlint-disable MD024 -->
# Capability Spec Delta: api-router-in-memory (api-router-in-memory)
**Package**: `@suaveplan/api-router-in-memory`
**Status**: PROPOSED
## ADDED Requirements
### Requirement: Dispatch without a socket
The package SHALL implement `Router` such that `dispatch(request)` runs the full request pipeline in-process and returns a `Response`-shaped value. No socket, port, or HTTP listener is bound.
#### Scenario: dispatch returns Response without network I/O
- **WHEN** a route is registered AND `router.dispatch(new Request("/x"))` is called
- **THEN** the result is a `Response` AND no network socket is opened (sanity-checked by asserting `Bun.listen`/`net` modules were not invoked)
**Verified by:** `src/factory/create-in-memory-router.test.ts::"dispatches without opening any network socket"`
---
### Requirement: host.fetch entry point matches design doc
The package SHALL expose `host.fetch(method, path, init?)` returning a `Promise<Response>`. The signature MUST be compatible with the `createTestHost` ergonomics example in §13.2.
#### Scenario: host.fetch dispatches a POST with body
- **WHEN** `host.fetch("POST", "/billing/invoices", { body: { amountCents: 10000, currency: "USD" } })` is called against a registered handler
- **THEN** the result has `status === 201` AND the body parses to the expected JSON
**Verified by:** `src/fetch-shape/fetch-shape.test.ts::"host.fetch POST returns 201 with parsed JSON body"`
---
### Requirement: Request recording supports assertions
The router SHALL maintain a `requests` history when `trackRequests: true`. Each entry records method, path, and request-id. `router.reset()` MUST clear the history.
#### Scenario: history captures every dispatched request
- **WHEN** three dispatches happen
- **THEN** `router.requests` has length 3 AND each entry records the correct method+path
#### Scenario: reset clears history
- **WHEN** `router.reset()` is called after dispatches
- **THEN** `router.requests` has length 0
**Verified by:** `src/recording/request-log.test.ts::"captures every dispatched request"` AND `src/recording/request-log.test.ts::"reset clears history"`
---
### Requirement: Conforms to Router contract
The factory SHALL pass `runRouterConformance` from `@suaveplan/api-router/testing` end-to-end.
#### Scenario: every Router invariant passes
- **WHEN** `runRouterConformance("in-memory-direct", createInMemoryRouter)` runs
- **THEN** every invariant reports passing
**Verified by:** `src/factory/create-in-memory-router.spec-conformance.test.ts::"in-memory-direct conforms to Router contract"`
---
### Requirement: Registered in `api-host/testing` adapter table
This adapter SHALL be reachable from `createTestHost({ adapters: { router: "in-memory" } })`. The lookup table in `@suaveplan/api-host/testing` SHALL recognize the `"in-memory"` string sentinel and instantiate this factory.
#### Scenario: createTestHost resolves the in-memory router
- **WHEN** a test calls `createTestHost({ adapters: { router: "in-memory" } })`
- **THEN** `host.router` is an instance of the factory produced by this package
**Verified by:** `tests/integration/integration.test.ts::"createTestHost resolves router:\"in-memory\" to this adapter"`
<!-- markdownlint-enable MD024 -->