@@ -222,7 +222,18 @@ class RouterObject extends MiddlewareChain {
222222 }
223223
224224 if ( isResponseMap ( schema . response ) ) {
225- ; ( context as any ) . error = createErrorHelper ( )
225+ ; ( context as any ) . error = createResponseHelper (
226+ schema . response ,
227+ request ,
228+ responsePlugins ,
229+ true
230+ )
231+ ; ( context as any ) . success = createResponseHelper (
232+ schema . response ,
233+ request ,
234+ responsePlugins ,
235+ false
236+ )
226237 }
227238
228239 const result = await handler ( context )
@@ -242,9 +253,14 @@ class RouterObject extends MiddlewareChain {
242253 } )
243254 }
244255 if ( isResponseMap ( schema . response ) ) {
245- // Success response from a response map — find the success status
246- const status = getSuccessStatus ( schema . response )
247- return Response . json ( result , { status } )
256+ const status = getDefaultSuccessStatus ( schema . response )
257+ return encodeResponseMapResult (
258+ schema . response ,
259+ status ,
260+ result ,
261+ request ,
262+ responsePlugins
263+ )
248264 }
249265 return Response . json ( result )
250266 }
@@ -350,9 +366,15 @@ function validateRouterResponsePlugins(
350366 plugins : Map < string , RouterResponsePlugin >
351367) {
352368 for ( const route of routes ) {
353- const pluginId = getResponsePluginMarkerId ( route . schema . response )
354- if ( pluginId && ! plugins . has ( pluginId ) ) {
355- throw missingRouterResponsePlugin ( pluginId )
369+ const pluginIds = isResponseMap ( route . schema . response )
370+ ? getResponseMapPluginIds ( route . schema . response )
371+ : [ getResponsePluginMarkerId ( route . schema . response ) ] . filter (
372+ pluginId => pluginId !== undefined
373+ )
374+ for ( const pluginId of pluginIds ) {
375+ if ( ! plugins . has ( pluginId ) ) {
376+ throw missingRouterResponsePlugin ( pluginId )
377+ }
356378 }
357379 }
358380}
@@ -497,39 +519,28 @@ function createOriginPattern(origin: string) {
497519 return new ExactPattern ( origin )
498520}
499521
500- /** Return true when the response schema is a status-keyed response map. */
501- function isResponseMap (
502- response : RouteSchema [ 'response' ]
503- ) : response is RouteResponseMap {
504- return (
505- typeof response === 'object' &&
506- response !== null &&
507- ! ( responsePluginMarker in response )
508- )
509- }
510-
511- import { responsePluginMarker } from '../response.js'
512-
513- /** Create the `ctx.error(status, body)` helper for route handlers. */
514- function createErrorHelper ( ) {
515- return ( status : number , body : unknown ) : Response => {
516- return Response . json ( body , { status } )
517- }
518- }
519-
520- /**
521- * Find the first success status in a response map (a status whose marker is
522- * `$type<T>()` or a plugin marker, not `$error<T>()`).
523- */
524- function getSuccessStatus ( responseMap : RouteResponseMap ) : number {
525- for ( const key of Object . keys ( responseMap ) ) {
526- const status = Number ( key )
527- const marker = ( responseMap as any ) [ status ]
528- if ( ! isErrorMarker ( marker ) ) {
529- return status
522+ /** Create `ctx.error(status, body)` or `ctx.success(status, body)`. */
523+ function createResponseHelper (
524+ responseMap : RouteResponseMap ,
525+ request : Request ,
526+ responsePlugins : Map < string , RouterResponsePlugin > ,
527+ error : boolean
528+ ) {
529+ return ( status : number , body : unknown ) : Promise < Response > | Response => {
530+ const marker = responseMap [ status ]
531+ if ( ! marker || isErrorMarker ( marker ) !== error ) {
532+ throw new Error (
533+ `Undeclared ${ error ? 'error' : 'success' } response status: ${ status } `
534+ )
530535 }
536+ return encodeResponseMapResult (
537+ responseMap ,
538+ status ,
539+ body ,
540+ request ,
541+ responsePlugins
542+ )
531543 }
532- return 200
533544}
534545
535546async function encodeResponseMapResult (
0 commit comments