Browse Source

Use an object to register a validator - fixes #2 (#6)

iss58
Sam Verschueren 7 years ago
committed by Sindre Sorhus
parent
commit
df7b6774ec
  1. 28
      source/lib/predicates/predicate.ts
  2. 20
      source/lib/predicates/string.ts
  3. 11
      source/ow.ts

28
source/lib/predicates/predicate.ts

@ -1,20 +1,32 @@
import * as is from '@sindresorhus/is';
export type Validator = (value: any) => string | undefined;
export interface Validator<T> {
message: (value: T) => string;
validator: (value: T) => boolean;
}
export interface Context {
validators: Validator[];
validators: Validator<any>[];
}
export class Predicate {
export class Predicate<T = any> {
constructor(
type: string,
public context: Context = { validators: [] }
private context: Context = { validators: [] }
) {
this.context.validators.push(value => {
if (!is[type](value)) {
return `Expected argument to be of type \`${type}\` but received type \`${is(value)}\``;
}
this.addValidator({
message: value => `Expected argument to be of type \`${type}\` but received type \`${is(value)}\``,
validator: value => is[type](value)
});
}
get validators() {
return this.context.validators;
}
protected addValidator(validator: Validator<T>) {
this.context.validators.push(validator);
return this;
}
}

20
source/lib/predicates/string.ts

@ -1,6 +1,6 @@
import { Predicate, Context } from './predicate';
export class StringPredicate extends Predicate {
export class StringPredicate extends Predicate<string> {
constructor(context?: Context) {
super('string', context);
@ -12,25 +12,19 @@ export class StringPredicate extends Predicate {
* @param number The minimum length of the string.
*/
minLength(number: number) {
this.context.validators.push(value => {
if (value.length < number) {
return `Expected string length to be minimum ${number}`;
}
return this.addValidator({
message: () => `Expected string length to be minimum ${number}`,
validator: value => value.length >= number
});
return this;
}
/**
* Test a string to be alphanumeric.
*/
get alphanumeric() {
this.context.validators.push(value => {
if (!/^[a-z\d]+$/i.test(value)) {
return `Expected string to contain only alphanumeric characters but received \`${value}\``;
}
return this.addValidator({
message: value => `Expected string to contain only alphanumeric characters but received \`${value}\``,
validator: value => /^[a-z\d]+$/i.test(value)
});
return this;
}
}

11
source/ow.ts

@ -12,13 +12,14 @@ export interface Ow {
}
export const ow: Ow = (value: any, predicate: Predicate) => {
for (const validator of predicate.context.validators) {
const result = validator(value);
if (result) {
for (const { validator, message } of predicate.validators) {
if (!validator(value)) {
// TODO: Modify the stack output to show the original `ow()` call instead of this `throw` statement
throw new ArgumentError(result, ow);
throw new ArgumentError(message(value), ow);
}
}
};
ow.string = new StringPredicate();
Object.defineProperty(ow, 'string', {
get: () => new StringPredicate()
});

Loading…
Cancel
Save