Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to run validations asynchronously #227

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { Joiful } from './joiful';
export const DEFAULT_INSTANCE = new Joiful();

const DEFAULT_VALIDATOR = new Validator();
const { validate, validateAsClass, validateArrayAsClass } = DEFAULT_VALIDATOR;
const { validate, validateAsClass, validateArrayAsClass, validateAsClassAsync, validateAsync } = DEFAULT_VALIDATOR;

const {
any,
Expand Down Expand Up @@ -37,7 +37,9 @@ export {
object,
string,
validate,
validateAsync,
validateAsClass,
validateAsClassAsync,
validateArrayAsClass,
validateParams,
getSchema,
Expand Down
50 changes: 50 additions & 0 deletions src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ export class Validator {
return this.validateAsClass(target, target.constructor as AnyClass, options);
}

/**
* Validates an instance of a decorated class asynchronously.
* @param target Instance of decorated class to validate.
* @param options Optional validation options to use. These override any default options.
*/
validateAsync = <T extends {} | null | undefined>(target: T, options?: ValidationOptions)
: Promise<ValidationResult<T>> => {
if (target === null || target === undefined) {
throw new InvalidValidationTarget();
}
return this.validateAsClassAsync(target, target.constructor as AnyClass, options);
}

/**
* Validates a plain old javascript object against a decorated class.
* @param target Object to validate.
Expand Down Expand Up @@ -153,6 +166,43 @@ export class Validator {
} as ValidationResult<TInstance>;
}

/**
* Validates a plain old javascript object against a decorated class asynchronously.
* @param target Object to validate.
* @param clz Decorated class to validate against.
* @param options Optional validation options to use. These override any default options.
*/
validateAsClassAsync = async <
TClass extends Constructor<any>,
TInstance = TClass extends Constructor<infer TInstance> ? TInstance : never
>(
target: Partial<TInstance> | null | undefined,
Class: TClass,
options: ValidationOptions | undefined = this.defaultOptions,
): Promise<ValidationResult<TInstance>> => {
if (target === null || target === undefined) {
throw new InvalidValidationTarget();
}

const {joi, joiOptions} = this.extractOptions(options);
const classSchema = getJoiSchema(Class, joi);

if (!classSchema) {
throw new NoValidationSchemaForClassError(Class);
}

const result = joiOptions ?
await classSchema.validateAsync(target, joiOptions) :
await classSchema.validateAsync(target);

return {
error: (result.error ? result.error : null),
errors: null,
warning: null,
value: result.value as TInstance,
} as ValidationResult<TInstance>;
}

/**
* Validates an array of plain old javascript objects against a decorated class.
* @param target Objects to validate.
Expand Down