3.3 KiB
Spec delta: api-router-hono
ADDED Requirements
Requirement: HonoRouter pipeline facet satisfies the host's PipelineRouter contract
The package SHALL extend HonoRouter with a second, additive facet that produces values structurally assignable to @suaveplan/api-host's PipelineRoute interface. The facet SHALL expose:
registerPipelineRoute(reg: HonoPipelineRegistration): void— stores(plugin, method, path, handler, options?, statusMap?).unregisterPipelineRoute(method: string, path: string): void— no-op when absent.unregisterPipelinePlugin(plugin: string): void— removes every entry owned byplugin(hot-reload teardown).listPipelineRoutes(): readonly HonoPipelineRoute[]— snapshot for admin tooling.matchPipeline(method: string, url: string): HonoPipelineRoute | null— resolves(method, url)to aHonoPipelineRoutecarryingplugin,path,options,handler,params,statusMap.
The facet SHALL preserve the existing abstract Router surface verbatim. Registering the same (method, path-shape) under a DIFFERENT plugin SHALL throw ROUTER_HONO.PIPELINE_ROUTE_COLLISION. Re-registering the same (plugin, method, path) SHALL overwrite. Parameter names SHALL be erased in the collision key so :id and :other clash.
Scenario: facet satisfies the host's PipelineRouter conformance suite
- WHEN
runPipelineRouterConformance(from@suaveplan/api-host/testing) is invoked with a factory that returns{ router: { match: (m, u) => r.matchPipeline(m, u) }, register: (reg) => r.registerPipelineRoute(reg) } - THEN every harness case passes (register → match round-trip, 404, statusMap propagation, plugin ownership across reload, param parsing, collision detection)
Scenario: collision detection throws ROUTER_HONO.PIPELINE_ROUTE_COLLISION
- WHEN two plugins register the same
(method, path-shape)on oneHonoRouter - THEN the second call throws
RouterHonoErrorwithcode === "ROUTER_HONO.PIPELINE_ROUTE_COLLISION"
Scenario: hot-reload teardown removes plugin-owned entries
- WHEN
unregisterPipelinePlugin("billing")is called afterbillingregistered two pipeline routes - THEN subsequent
matchPipeline(...)calls against either route returnnullANDlistPipelineRoutes()no longer contains a"billing"-owned entry
Verified by: src/pipeline/pipeline.test.ts AND src/pipeline/pipeline.conformance.test.ts AND src/adapter/adapter.test.ts::"pipeline facet — register/match/list/unregister/unregisterPlugin"
MODIFIED Requirements
Requirement: ROUTER_HONO error-code registry
The package SHALL expose ROUTER_HONO_CODES (defineCodes("ROUTER_HONO", [...])) and a RouterHonoError extending SuaveplanError. The registry MUST contain HONO_INTERNAL_ERROR, INVALID_HONO_PEER, AND PIPELINE_ROUTE_COLLISION. Every code MUST be thrown by at least one production path in this package.
Scenario: registry shape
- WHEN
Object.keys(ROUTER_HONO_CODES)is inspected - THEN the keys are exactly
["HONO_INTERNAL_ERROR", "INVALID_HONO_PEER", "PIPELINE_ROUTE_COLLISION"]AND each value isROUTER_HONO.<name>
Verified by: src/error-codes/error-codes.test.ts::"enumerates the three declared codes" AND src/error-codes/error-codes.test.ts::"namespaces each entry under ROUTER_HONO.*"