deno fmt
This commit is contained in:
@@ -1,15 +1,20 @@
|
|||||||
import { assertEquals, assertNotEquals } from "https://deno.land/std@0.53.0/testing/asserts.ts";
|
|
||||||
import {
|
import {
|
||||||
validate, Validatable, ArraySymbol,
|
assertEquals,
|
||||||
isString
|
assertNotEquals,
|
||||||
|
} from "https://deno.land/std@0.53.0/testing/asserts.ts";
|
||||||
|
import {
|
||||||
|
validate,
|
||||||
|
Validatable,
|
||||||
|
ArraySymbol,
|
||||||
|
isString,
|
||||||
} from "./mod.ts";
|
} from "./mod.ts";
|
||||||
|
|
||||||
Deno.test("validate schema (match)", async () => {
|
Deno.test("validate schema (match)", async () => {
|
||||||
const values: [any, Validatable][] = [
|
const values: [any, Validatable][] = [
|
||||||
["string", isString],
|
["string", isString],
|
||||||
["string", [isString]],
|
["string", [isString]],
|
||||||
[["arr", "ay"], {[ArraySymbol]: isString}],
|
[["arr", "ay"], { [ArraySymbol]: isString }],
|
||||||
[{foo: "bar", lorem: "ipsum"}, {foo: isString, lorem: [isString]}],
|
[{ foo: "bar", lorem: "ipsum" }, { foo: isString, lorem: [isString] }],
|
||||||
];
|
];
|
||||||
for (const [value, constraints] of values) {
|
for (const [value, constraints] of values) {
|
||||||
assertEquals([], await validate(value, constraints));
|
assertEquals([], await validate(value, constraints));
|
||||||
@@ -20,8 +25,8 @@ Deno.test("validate schema (no match)", async () => {
|
|||||||
const values: [any, Validatable][] = [
|
const values: [any, Validatable][] = [
|
||||||
[6, isString],
|
[6, isString],
|
||||||
[false, [isString]],
|
[false, [isString]],
|
||||||
[["arr", ["ay"]], {[ArraySymbol]: isString}],
|
[["arr", ["ay"]], { [ArraySymbol]: isString }],
|
||||||
[{foo: {}, lorem: "ipsum"}, {foo: isString, lorem: [isString]}],
|
[{ foo: {}, lorem: "ipsum" }, { foo: isString, lorem: [isString] }],
|
||||||
];
|
];
|
||||||
for (const [value, constraints] of values) {
|
for (const [value, constraints] of values) {
|
||||||
assertNotEquals([], await validate(value, constraints));
|
assertNotEquals([], await validate(value, constraints));
|
||||||
|
|||||||
56
Validator.ts
56
Validator.ts
@@ -1,24 +1,32 @@
|
|||||||
export type Args = {[_: string]: any};
|
export type Args = { [_: string]: any };
|
||||||
|
|
||||||
export interface Validator {
|
export interface Validator {
|
||||||
type: string;
|
type: string;
|
||||||
check: (value: any) => Promise<Args|undefined>|Args|undefined;
|
check: (value: any) => Promise<Args | undefined> | Args | undefined;
|
||||||
message: (value: any, args?: Args) => Promise<string|undefined>|string|undefined;
|
message: (
|
||||||
|
value: any,
|
||||||
|
args?: Args,
|
||||||
|
) => Promise<string | undefined> | string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ValidationError {
|
export interface ValidationError {
|
||||||
type: string;
|
type: string;
|
||||||
param?: string[];
|
param?: string[];
|
||||||
message?: string|null;
|
message?: string | null;
|
||||||
args?: Args;
|
args?: Args;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Validatable = Schema|Validator|Validator[];
|
export type Validatable = Schema | Validator | Validator[];
|
||||||
|
|
||||||
export const ArraySymbol: unique symbol = Symbol("ArraySymbol");
|
export const ArraySymbol: unique symbol = Symbol("ArraySymbol");
|
||||||
export type Schema = {[key: string]: Validatable}|{[ArraySymbol]: Validatable};
|
export type Schema = { [key: string]: Validatable } | {
|
||||||
|
[ArraySymbol]: Validatable;
|
||||||
|
};
|
||||||
|
|
||||||
export async function validate(value: any, validators: Validatable): Promise<ValidationError[]|undefined> {
|
export async function validate(
|
||||||
|
value: any,
|
||||||
|
validators: Validatable,
|
||||||
|
): Promise<ValidationError[] | undefined> {
|
||||||
if (instanceofValidatorArray(validators) || instanceofValidator(validators)) {
|
if (instanceofValidatorArray(validators) || instanceofValidator(validators)) {
|
||||||
return validateValue(value, validators);
|
return validateValue(value, validators);
|
||||||
} else {
|
} else {
|
||||||
@@ -34,10 +42,13 @@ function instanceofValidator(value: any): value is Validator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function instanceofValidatorArray(value: any): value is Validator[] {
|
function instanceofValidatorArray(value: any): value is Validator[] {
|
||||||
return Array.isArray(value) && value.every(x => instanceofValidator(x));
|
return Array.isArray(value) && value.every((x) => instanceofValidator(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateValue(value: any, validators: Validator|Validator[]): Promise<ValidationError[]> {
|
async function validateValue(
|
||||||
|
value: any,
|
||||||
|
validators: Validator | Validator[],
|
||||||
|
): Promise<ValidationError[]> {
|
||||||
if (!Array.isArray(validators)) {
|
if (!Array.isArray(validators)) {
|
||||||
validators = [validators];
|
validators = [validators];
|
||||||
}
|
}
|
||||||
@@ -49,33 +60,40 @@ async function validateValue(value: any, validators: Validator|Validator[]): Pro
|
|||||||
result.push({
|
result.push({
|
||||||
type: validator.type,
|
type: validator.type,
|
||||||
args,
|
args,
|
||||||
message
|
message,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function validateSchema(value: any, validators: Schema): Promise<ValidationError[]> {
|
async function validateSchema(
|
||||||
|
value: any,
|
||||||
|
validators: Schema,
|
||||||
|
): Promise<ValidationError[]> {
|
||||||
if (validators.hasOwnProperty(ArraySymbol)) {
|
if (validators.hasOwnProperty(ArraySymbol)) {
|
||||||
const v = validators as {[ArraySymbol]: Validatable};
|
const v = validators as { [ArraySymbol]: Validatable };
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const arr = await Promise.all(value.map(val => validate(val, v[ArraySymbol])));
|
const arr = await Promise.all(
|
||||||
const errors = arr.flatMap((val, idx) => (val ?? []).map(error => ({
|
value.map((val) => validate(val, v[ArraySymbol])),
|
||||||
|
);
|
||||||
|
const errors = arr.flatMap((val, idx) =>
|
||||||
|
(val ?? []).map((error) => ({
|
||||||
...error,
|
...error,
|
||||||
param: [`[${idx}]`, ...(error.param || [])]
|
param: [`[${idx}]`, ...(error.param || [])],
|
||||||
})));
|
}))
|
||||||
|
);
|
||||||
return errors;
|
return errors;
|
||||||
} else {
|
} else {
|
||||||
return [{
|
return [{
|
||||||
type: "array",
|
type: "array",
|
||||||
param: ["[]"],
|
param: ["[]"],
|
||||||
message: "Array expected!",
|
message: "Array expected!",
|
||||||
args: {}
|
args: {},
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const v = validators as {[key: string]: Validatable};
|
const v = validators as { [key: string]: Validatable };
|
||||||
const valErrors: ValidationError[] = [];
|
const valErrors: ValidationError[] = [];
|
||||||
for (const prop in validators) {
|
for (const prop in validators) {
|
||||||
if (!validators.hasOwnProperty(prop)) {
|
if (!validators.hasOwnProperty(prop)) {
|
||||||
@@ -89,7 +107,7 @@ async function validateSchema(value: any, validators: Schema): Promise<Validatio
|
|||||||
type: "property",
|
type: "property",
|
||||||
param: [prop],
|
param: [prop],
|
||||||
message: `Property '${prop}' expected but not found!`,
|
message: `Property '${prop}' expected but not found!`,
|
||||||
args: {property: prop}
|
args: { property: prop },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
mod.ts
9
mod.ts
@@ -1,2 +1,9 @@
|
|||||||
export { Args, Validator, ValidationError, validate, Validatable, ArraySymbol } from "./Validator.ts";
|
export {
|
||||||
|
Args,
|
||||||
|
Validator,
|
||||||
|
ValidationError,
|
||||||
|
validate,
|
||||||
|
Validatable,
|
||||||
|
ArraySymbol,
|
||||||
|
} from "./Validator.ts";
|
||||||
export * from "./validators/string.ts";
|
export * from "./validators/string.ts";
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
import { isString } from "./string.ts";
|
import { isString } from "./string.ts";
|
||||||
import { validate } from "../mod.ts";
|
import { validate } from "../mod.ts";
|
||||||
import { assertEquals, assertNotEquals } from "https://deno.land/std@0.53.0/testing/asserts.ts";
|
import {
|
||||||
|
assertEquals,
|
||||||
|
assertNotEquals,
|
||||||
|
} from "https://deno.land/std@0.53.0/testing/asserts.ts";
|
||||||
|
|
||||||
Deno.test("isString (match)", async () => {
|
Deno.test("isString (match)", async () => {
|
||||||
const values = [
|
const values = [
|
||||||
"",
|
"",
|
||||||
"foo",
|
"foo",
|
||||||
new String(),
|
new String(),
|
||||||
new String("bar")
|
new String("bar"),
|
||||||
];
|
];
|
||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
assertEquals([], await validate(value, isString));
|
assertEquals([], await validate(value, isString));
|
||||||
@@ -25,7 +28,7 @@ Deno.test("isString (no match)", async () => {
|
|||||||
() => {},
|
() => {},
|
||||||
function named() {},
|
function named() {},
|
||||||
new Object(),
|
new Object(),
|
||||||
Symbol()
|
Symbol(),
|
||||||
];
|
];
|
||||||
for (const value of values) {
|
for (const value of values) {
|
||||||
assertNotEquals([], await validate(value, isString));
|
assertNotEquals([], await validate(value, isString));
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { Validator, Args } from "../mod.ts";
|
|||||||
export const isString: Validator = {
|
export const isString: Validator = {
|
||||||
type: "isString",
|
type: "isString",
|
||||||
check: (value: any) => {
|
check: (value: any) => {
|
||||||
if (typeof value !== 'string' && !(value instanceof String)) {
|
if (typeof value !== "string" && !(value instanceof String)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
message: (value: any, args?: Args) => {
|
message: (value: any, args?: Args) => {
|
||||||
return `The value '${value && value.toString()}' has to be a string.`
|
return `The value '${value && value.toString()}' has to be a string.`;
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user