Add support for parameter middleware classes

This commit is contained in:
Garrett Mills 2022-04-05 09:55:20 -05:00
parent f6a7cac05c
commit 8b9f393405
3 changed files with 35 additions and 6 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@extollo/lib", "name": "@extollo/lib",
"version": "0.9.23", "version": "0.9.24",
"description": "The framework library that lifts up your code.", "description": "The framework library that lifts up your code.",
"main": "lib/index.js", "main": "lib/index.js",
"types": "lib/index.d.ts", "types": "lib/index.d.ts",

View File

@ -2,6 +2,7 @@ import {Request} from '../lifecycle/Request'
import {ResponseObject} from './Route' import {ResponseObject} from './Route'
import {Container} from '../../di' import {Container} from '../../di'
import {CanonicalItemClass} from '../../support/CanonicalReceiver' import {CanonicalItemClass} from '../../support/CanonicalReceiver'
import {Awaitable, Either, Left, left, Right, right} from '../../util'
/** /**
* Base class representing a middleware handler that can be applied to routes. * Base class representing a middleware handler that can be applied to routes.
@ -31,3 +32,26 @@ export abstract class Middleware extends CanonicalItemClass {
*/ */
public abstract apply(): ResponseObject public abstract apply(): ResponseObject
} }
/**
* A type of Middleware that produces a parameter that is passed to later handlers.
* Can be used to do common look-ups, &c before routes.
*/
export abstract class ParameterMiddleware<T> extends Middleware {
/** Look up the value. */
public abstract handle(): Awaitable<Either<ResponseObject, T>>
apply(): ResponseObject {
return this.handle()
}
/** Alias for an error response return. */
left(what: T): Left<T> {
return left(what)
}
/** Alias for a good value return. */
right(what: T): Right<T> {
return right(what)
}
}

View File

@ -1,8 +1,8 @@
import {Collection, Either, ErrorWithContext, Maybe, Pipeline, PrefixTypeArray, right} from '../../util' import {Awaitable, Collection, Either, ErrorWithContext, Maybe, Pipeline, PrefixTypeArray, right} from '../../util'
import {ResponseFactory} from '../response/ResponseFactory' import {ResponseFactory} from '../response/ResponseFactory'
import {HTTPMethod, Request} from '../lifecycle/Request' import {HTTPMethod, Request} from '../lifecycle/Request'
import {constructable, Constructable, Container, Instantiable, isInstantiableOf, TypedDependencyKey} from '../../di' import {constructable, Constructable, Container, Instantiable, isInstantiableOf, TypedDependencyKey} from '../../di'
import {Middleware} from './Middleware' import {Middleware, ParameterMiddleware} from './Middleware'
import {Valid, Validator, ValidatorFactory} from '../../validation/Validator' import {Valid, Validator, ValidatorFactory} from '../../validation/Validator'
import {validateMiddleware} from '../../validation/middleware' import {validateMiddleware} from '../../validation/middleware'
import {RouteGroup} from './RouteGroup' import {RouteGroup} from './RouteGroup'
@ -20,7 +20,7 @@ export type ResponseObject = ResponseFactory | string | number | void | any | Pr
*/ */
export type ResolvedRouteHandler = (request: Request) => ResponseObject export type ResolvedRouteHandler = (request: Request) => ResponseObject
export type ParameterProvidingMiddleware<T> = (request: Request) => Either<ResponseObject, T> export type ParameterProvidingMiddleware<T> = (request: Request) => Awaitable<Either<ResponseObject, T>>
export interface HandledRoute<TReturn extends ResponseObject, THandlerParams extends unknown[] = []> { export interface HandledRoute<TReturn extends ResponseObject, THandlerParams extends unknown[] = []> {
handler: Constructable<(...x: THandlerParams) => TReturn> handler: Constructable<(...x: THandlerParams) => TReturn>
@ -311,7 +311,7 @@ export class Route<TReturn extends ResponseObject, THandlerParams extends unknow
} }
public parameterMiddleware<T>( public parameterMiddleware<T>(
handler: ParameterProvidingMiddleware<T>, handler: ParameterProvidingMiddleware<T> | Instantiable<ParameterMiddleware<T>>,
): Route<TReturn, PrefixTypeArray<T, THandlerParams>> { ): Route<TReturn, PrefixTypeArray<T, THandlerParams>> {
const route = new Route<TReturn, PrefixTypeArray<T, THandlerParams>>( const route = new Route<TReturn, PrefixTypeArray<T, THandlerParams>>(
this.method, this.method,
@ -319,7 +319,12 @@ export class Route<TReturn extends ResponseObject, THandlerParams extends unknow
) )
route.copyFrom(this) route.copyFrom(this)
route.parameters.push(handler)
if ( handler.prototype instanceof ParameterMiddleware ) {
route.parameters.push(req => req.make<ParameterMiddleware<T>>(handler).handle())
}
route.parameters.push(handler as ParameterProvidingMiddleware<T>)
return route return route
} }