Standard libraries that lift up your code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.0 KiB

import {Container, Injectable, InjectParam} from '../di'
import {Request} from '../http/lifecycle/Request'
import {Valid, ValidationRules} from './rules/types'
import {Validator} from './Validator'
import {AppClass} from '../lifecycle/AppClass'
import {DataContainer} from '../http/lifecycle/Request'
* Base class for defining reusable validators for request routes.
* If instantiated with a container, it must be a request-level container,
* but the type interface allows any data-container to be used when creating
* manually.
* You should mark implementations of this class as singleton to avoid
* re-validating the input data every time it is accessed.
* @example
* ```ts
* // Instantiate with the request:
* const data = <MyFormRequest> request.make(MyFormRequest)
* // Instantiate with some container:
* const data = new MyFormRequest(someDataContainer)
* ```
export abstract class FormRequest<T> extends AppClass {
/** The cached validation result. */
protected cachedResult?: Valid<T>
protected readonly data: DataContainer,
) {
protected container(): Container {
return ( as unknown) as Container
* The validation rules that should be applied to the request to guarantee
* that it contains the given data type.
* @protected
protected abstract getRules(): ValidationRules | Promise<ValidationRules>
* Validate and get the request input. Throws a validation error on fail.
* Internally, caches the result after the first validation. So, singleton
* validators will avoid re-processing their rules every time.
public async get(): Promise<Valid<T>> {
if ( !this.cachedResult ) {
const validator = <Validator<T>> this.make(Validator, await this.getRules())
this.cachedResult = await validator.validate(
return this.cachedResult