Changed to constructor functions
This commit is contained in:
@@ -14,15 +14,42 @@ import {
|
||||
|
||||
Deno.test("validate schema (match)", async () => {
|
||||
const values: [any, Validatable][] = [
|
||||
["string", isString],
|
||||
["string", [isString]],
|
||||
[["arr", "ay"], { [ArraySymbol]: isString }],
|
||||
[{ foo: 3.1415, lorem: "ipsum" }, { foo: isNumber, lorem: [isString] }],
|
||||
[{}, { optional: [isString] }],
|
||||
[{ foo: { bar: "" } }, { foo: { bar: [isRequired, isString] } }],
|
||||
[{ foo: { bar: "" } }, { foo: { bar: [isString] } }],
|
||||
[{ foo: {} }, { foo: { bar: [isString] } }],
|
||||
[{}, { foo: { bar: [isString] } }],
|
||||
[
|
||||
"string",
|
||||
isString(),
|
||||
],
|
||||
[
|
||||
"string",
|
||||
[isString()],
|
||||
],
|
||||
[
|
||||
["arr", "ay"],
|
||||
{ [ArraySymbol]: isString() },
|
||||
],
|
||||
[
|
||||
{ foo: 3.1415, lorem: "ipsum" },
|
||||
{ foo: isNumber(), lorem: [isString()] },
|
||||
],
|
||||
[
|
||||
{},
|
||||
{ optional: [isString()] },
|
||||
],
|
||||
[
|
||||
{ foo: { bar: "" } },
|
||||
{ foo: { bar: [isRequired(), isString()] } },
|
||||
],
|
||||
[
|
||||
{ foo: { bar: "" } },
|
||||
{ foo: { bar: [isString()] } },
|
||||
],
|
||||
[
|
||||
{ foo: {} },
|
||||
{ foo: { bar: [isString()] } },
|
||||
],
|
||||
[
|
||||
{},
|
||||
{ foo: { bar: [isString()] } },
|
||||
],
|
||||
];
|
||||
for (const [value, constraints] of values) {
|
||||
assertEquals([], await validate(value, constraints));
|
||||
@@ -31,14 +58,38 @@ Deno.test("validate schema (match)", async () => {
|
||||
|
||||
Deno.test("validate schema (no match)", async () => {
|
||||
const values: [any, Validatable][] = [
|
||||
[6, isString],
|
||||
[false, [isString]],
|
||||
[["arr", ["ay"]], { [ArraySymbol]: isString }],
|
||||
[{ foo: 3.1415, lorem: "ipsum" }, { foo: isInteger, lorem: [isString] }],
|
||||
[{}, { required: [isRequired, isString] }],
|
||||
[{ foo: { bar: 1 } }, { foo: { bar: [isRequired, isString] } }],
|
||||
[{ foo: {} }, { foo: { bar: [isRequired, isString] } }],
|
||||
[{}, { foo: { bar: [isRequired, isString] } }],
|
||||
[
|
||||
6,
|
||||
isString(),
|
||||
],
|
||||
[
|
||||
false,
|
||||
[isString()],
|
||||
],
|
||||
[
|
||||
["arr", ["ay"]],
|
||||
{ [ArraySymbol]: isString() },
|
||||
],
|
||||
[
|
||||
{ foo: 3.1415, lorem: "ipsum" },
|
||||
{ foo: isInteger(), lorem: [isString()] },
|
||||
],
|
||||
[
|
||||
{},
|
||||
{ required: [isRequired(), isString()] },
|
||||
],
|
||||
[
|
||||
{ foo: { bar: 1 } },
|
||||
{ foo: { bar: [isRequired(), isString()] } },
|
||||
],
|
||||
[
|
||||
{ foo: {} },
|
||||
{ foo: { bar: [isRequired(), isString()] } },
|
||||
],
|
||||
[
|
||||
{},
|
||||
{ foo: { bar: [isRequired(), isString()] } },
|
||||
],
|
||||
];
|
||||
for (const [value, constraints] of values) {
|
||||
assertNotEquals([], await validate(value, constraints));
|
||||
|
||||
@@ -2,6 +2,7 @@ export type Args = { [_: string]: any };
|
||||
|
||||
export interface Validator {
|
||||
type: string;
|
||||
extends?: Validator[];
|
||||
check: (value: any) => Promise<Args | undefined> | Args | undefined;
|
||||
message: (
|
||||
value: any,
|
||||
@@ -54,6 +55,13 @@ async function validateValue(
|
||||
}
|
||||
const result: ValidationError[] = [];
|
||||
for (const validator of validators) {
|
||||
if (validator.extends) {
|
||||
const prerequisites = await validate(value, validator.extends);
|
||||
if (prerequisites.length > 0) {
|
||||
result.push(...prerequisites);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const args = await validator.check(value);
|
||||
if (args !== undefined) {
|
||||
const message = await validator.message(value, args);
|
||||
|
||||
@@ -13,7 +13,7 @@ Deno.test("isArray (match)", async () => {
|
||||
["foo"],
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isArray), []);
|
||||
assertEquals(await validate(value, isArray()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,6 +33,6 @@ Deno.test("isArray (no match)", async () => {
|
||||
Symbol(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isArray), []);
|
||||
assertNotEquals(await validate(value, isArray()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { Validator, Args } from "../mod.ts";
|
||||
|
||||
export const isArray: Validator = {
|
||||
type: "isArray",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be an array.`;
|
||||
},
|
||||
};
|
||||
export function isArray(): Validator {
|
||||
return {
|
||||
type: "isArray",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be an array.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ Deno.test("isBoolean (match)", async () => {
|
||||
false,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isBoolean), []);
|
||||
assertEquals(await validate(value, isBoolean()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,6 @@ Deno.test("isBoolean (no match)", async () => {
|
||||
Symbol(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isBoolean), []);
|
||||
assertNotEquals(await validate(value, isBoolean()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { Validator, Args } from "../mod.ts";
|
||||
|
||||
export const isBoolean: Validator = {
|
||||
type: "isBoolean",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (value !== true && value !== false) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a boolean.`;
|
||||
},
|
||||
};
|
||||
export function isBoolean(): Validator {
|
||||
return {
|
||||
type: "isBoolean",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (value !== true && value !== false) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a boolean.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ Deno.test("isRequired (match)", async () => {
|
||||
Symbol("foo"),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isRequired), []);
|
||||
assertEquals(await validate(value, isRequired()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ Deno.test("isRequired (no match)", async () => {
|
||||
null,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isRequired), []);
|
||||
assertNotEquals(await validate(value, isRequired()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ Deno.test("isDefined (match)", async () => {
|
||||
Symbol("foo"),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isDefined), []);
|
||||
assertEquals(await validate(value, isDefined()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -63,7 +63,7 @@ Deno.test("isDefined (no match)", async () => {
|
||||
undefined,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isDefined), []);
|
||||
assertNotEquals(await validate(value, isDefined()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ Deno.test("isNotEmpty (match)", async () => {
|
||||
Symbol("foo"),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isNotEmpty), []);
|
||||
assertEquals(await validate(value, isNotEmpty()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -94,6 +94,6 @@ Deno.test("isNotEmpty (no match)", async () => {
|
||||
[],
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isNotEmpty), []);
|
||||
assertNotEquals(await validate(value, isNotEmpty()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,63 +8,71 @@ import {
|
||||
isBoolean,
|
||||
} from "../mod.ts";
|
||||
|
||||
export const isRequired: Validator = {
|
||||
type: "isRequired",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value is required.`;
|
||||
},
|
||||
};
|
||||
|
||||
export const isDefined: Validator = {
|
||||
type: "isDefined",
|
||||
check: (value: any) => {
|
||||
if (value === undefined) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be defined.`;
|
||||
},
|
||||
};
|
||||
|
||||
export const isNotEmpty: Validator = {
|
||||
type: "isNotEmpty",
|
||||
check: async (value: any) => {
|
||||
if (value === null || value === undefined) {
|
||||
return {};
|
||||
}
|
||||
if ((await isString.check(value)) === undefined) {
|
||||
if (/^\s*$/.test(value)) {
|
||||
export function isRequired(): Validator {
|
||||
return {
|
||||
type: "isRequired",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) {
|
||||
return {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((await isNumber.check(value)) === undefined || Number.isNaN(value)) {
|
||||
return;
|
||||
}
|
||||
if (await isSymbol.check(value) === undefined) {
|
||||
return;
|
||||
}
|
||||
if (await isBoolean.check(value) === undefined) {
|
||||
return;
|
||||
}
|
||||
if ((await isArray.check(value)) === undefined) {
|
||||
if (value.length > 0) {
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value is required.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isDefined(): Validator {
|
||||
return {
|
||||
type: "isDefined",
|
||||
check: (value: any) => {
|
||||
if (value === undefined) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be defined.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isNotEmpty(): Validator {
|
||||
return {
|
||||
type: "isNotEmpty",
|
||||
check: async (value: any) => {
|
||||
if (value === null || value === undefined) {
|
||||
return {};
|
||||
}
|
||||
if ((await isString().check(value)) === undefined) {
|
||||
if (/^\s*$/.test(value)) {
|
||||
return {};
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (
|
||||
(await isNumber().check(value)) === undefined || Number.isNaN(value)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (await isSymbol().check(value) === undefined) {
|
||||
return;
|
||||
}
|
||||
if (await isBoolean().check(value) === undefined) {
|
||||
return;
|
||||
}
|
||||
if ((await isArray().check(value)) === undefined) {
|
||||
if (value.length > 0) {
|
||||
return;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
for (const key in value) {
|
||||
return;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
for (const key in value) {
|
||||
return;
|
||||
}
|
||||
return {};
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be non-empty.`;
|
||||
},
|
||||
};
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be non-empty.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
|
||||
Deno.test("or (match)", async () => {
|
||||
const values: [any, Validator[]][] = [
|
||||
["", [isString, isInteger]],
|
||||
[1, [isString, isInteger]],
|
||||
["", [isString(), isInteger()]],
|
||||
[1, [isString(), isInteger()]],
|
||||
];
|
||||
for (const [value, validators] of values) {
|
||||
assertEquals(await validate(value, or(...validators)), []);
|
||||
@@ -17,9 +17,9 @@ Deno.test("or (match)", async () => {
|
||||
|
||||
Deno.test("or (no match)", async () => {
|
||||
const values: [any, Validator[]][] = [
|
||||
[true, [isString, isInteger]],
|
||||
[3.1415, [isString, isInteger]],
|
||||
[1, [isString]],
|
||||
[true, [isString(), isInteger()]],
|
||||
[3.1415, [isString(), isInteger()]],
|
||||
[1, [isString()]],
|
||||
];
|
||||
for (const [value, validators] of values) {
|
||||
assertNotEquals(await validate(value, or(...validators)), []);
|
||||
|
||||
@@ -17,7 +17,7 @@ Deno.test("isNumber (match)", async () => {
|
||||
Math.PI,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isNumber), []);
|
||||
assertEquals(await validate(value, isNumber()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,7 +33,7 @@ Deno.test("isNumber (no match)", async () => {
|
||||
Symbol(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isNumber), []);
|
||||
assertNotEquals(await validate(value, isNumber()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,7 +47,7 @@ Deno.test("isInteger (match)", async () => {
|
||||
-1,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isInteger), []);
|
||||
assertEquals(await validate(value, isInteger()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -64,6 +64,6 @@ Deno.test("isInteger (no match)", async () => {
|
||||
0.1,
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isInteger), []);
|
||||
assertNotEquals(await validate(value, isInteger()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
import { Validator, Args } from "../mod.ts";
|
||||
|
||||
export const isNumber: Validator = {
|
||||
type: "isNumber",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Number.isFinite(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a number.`;
|
||||
},
|
||||
};
|
||||
export function isNumber(): Validator {
|
||||
return {
|
||||
type: "isNumber",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Number.isFinite(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a number.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const isInteger: Validator = {
|
||||
type: "isInteger",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Number.isInteger(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be an integer.`;
|
||||
},
|
||||
};
|
||||
export function isInteger(): Validator {
|
||||
return {
|
||||
type: "isInteger",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (!Number.isInteger(value)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be an integer.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isString } from "./string.ts";
|
||||
import { isString, isURL } from "./string.ts";
|
||||
import { validate } from "../mod.ts";
|
||||
import {
|
||||
assertEquals,
|
||||
@@ -15,7 +15,7 @@ Deno.test("isString (match)", async () => {
|
||||
new String("bar"),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isString), []);
|
||||
assertEquals(await validate(value, isString()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,24 @@ Deno.test("isString (no match)", async () => {
|
||||
Symbol(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isString), []);
|
||||
assertNotEquals(await validate(value, isString()), []);
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("isURL (match)", async () => {
|
||||
const values = [
|
||||
"http://google.com",
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isURL()), []);
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("isURL (no match)", async () => {
|
||||
const values = [
|
||||
"invalid",
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isURL()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,14 +1,32 @@
|
||||
import { Validator, Args } from "../mod.ts";
|
||||
|
||||
export const isString: Validator = {
|
||||
type: "isString",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (typeof value !== "string" && !(value instanceof String)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a string.`;
|
||||
},
|
||||
};
|
||||
export function isString(): Validator {
|
||||
return {
|
||||
type: "isString",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (typeof value !== "string" && !(value instanceof String)) {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a string.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function isURL(): Validator {
|
||||
return {
|
||||
type: "isURL",
|
||||
extends: [isString()],
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (value !== "http://google.com") {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value is not a valid URL.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ Deno.test("isSymbol (match)", async () => {
|
||||
Symbol(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertEquals(await validate(value, isSymbol), []);
|
||||
assertEquals(await validate(value, isSymbol()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,6 @@ Deno.test("isSymbol (no match)", async () => {
|
||||
new Object(),
|
||||
];
|
||||
for (const value of values) {
|
||||
assertNotEquals(await validate(value, isSymbol), []);
|
||||
assertNotEquals(await validate(value, isSymbol()), []);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { Validator, Args } from "../mod.ts";
|
||||
|
||||
export const isSymbol: Validator = {
|
||||
type: "isSymbol",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (typeof value !== "symbol") {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a symbol.`;
|
||||
},
|
||||
};
|
||||
export function isSymbol(): Validator {
|
||||
return {
|
||||
type: "isSymbol",
|
||||
check: (value: any) => {
|
||||
if (value === null || value === undefined) return;
|
||||
if (typeof value !== "symbol") {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
message: (value: any, args?: Args) => {
|
||||
return `This value has to be a symbol.`;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user