import * as Either from 'fp-ts/lib/Either' ; import { pipe } from 'fp-ts/lib/function' ; import * as t from 'io-ts' ; import { PathReporter } from 'io-ts/lib/PathReporter' ; import * as Middleware from './middleware' ; import * as Response from './response' ; export const bodyP = < RequestBase > ( getBody ) => genericP ( getBody , 'body' ) ; export const body = < RequestBase > ( getBody ) => generic ( getBody , 'body' ) ; export const queryP = < RequestBase > ( getQuery ) => genericP ( getQuery , 'query' ) ; export const query = < RequestBase > ( getQuery ) => generic ( getQuery , 'query' ) ; export const headersP = < RequestBase > ( getHeaders ) => genericP ( getHeaders , 'headers' ) ; export const headers = < RequestBase > ( getHeaders ) => generic ( getHeaders , 'headers' ) ; export const cookiesP = < RequestBase > ( getCookies ) => genericP ( getCookies , 'cookies' ) ; export const cookies = < RequestBase > ( getCookies ) => generic ( getCookies , 'cookies' ) ; export type GetInput < RequestBase > = ( req : RequestBase ) => any ; export type ErrorHandler < ErrorResponse extends Response . Generic > = ( errors : t . Errors ) => ErrorResponse ; const genericP = < RequestBase , Key extends string > ( input , key ) => < T , ErrorResponse extends Response . Generic > ( codec , errorHandler ) : Middleware . Middleware < RequestBase , Record < Key , T > , ErrorResponse > => ( req ) => pipe ( codec . decode ( input ( req ) ) , Either . fold < t . Errors , T , Middleware . MiddlewareOutput < Record < Key , T > , ErrorResponse > > ( ( errors ) => Middleware . stop ( errorHandler ( errors ) ) , ( result ) => Middleware . next ( { [ key ] : result } as any ) ) ) ; const generic = < RequestBase , Key extends string > ( input , key ) => < T > ( codec ) : Middleware . Middleware < RequestBase , Record < Key , T > , Response . BadRequest < string > > => genericP ( input , key ) ( codec , ( err ) => Response . badRequest ( `Invalid ${ key }: ${ errorsToString ( err ) }` ) ) ; function errorsToString ( err ) { return PathReporter . report ( Either . left ( err ) ) ; }