wip
This commit is contained in:
parent
a26de4fda5
commit
f6c4f13b57
1 changed files with 298 additions and 15 deletions
|
@ -1,17 +1,20 @@
|
||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import hasDuplicates from '../common/has-duplicates';
|
import hasDuplicates from '../common/has-duplicates';
|
||||||
|
|
||||||
type CustomValidator<T> = (value: T) => boolean | string;
|
type Validator<T> = (value: T) => boolean | string;
|
||||||
|
type Modifier<T> = (value: T) => T;
|
||||||
|
|
||||||
interface Validator {
|
interface Fuctory {
|
||||||
get: () => [any, string];
|
get: () => [any, string];
|
||||||
|
|
||||||
required: () => Validator;
|
required: () => Fuctory;
|
||||||
|
|
||||||
validate: (validator: CustomValidator<any>) => Validator;
|
validate: (validator: Validator<any>) => Fuctory;
|
||||||
|
|
||||||
|
modify: (modifier: Modifier<any>) => Fuctory;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ValidatorCore implements Validator {
|
class FuctoryCore implements Fuctory {
|
||||||
value: any;
|
value: any;
|
||||||
error: string;
|
error: string;
|
||||||
|
|
||||||
|
@ -20,6 +23,9 @@ class ValidatorCore implements Validator {
|
||||||
this.error = null;
|
this.error = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* この値が undefined または null の場合エラーにします
|
||||||
|
*/
|
||||||
required() {
|
required() {
|
||||||
if (this.error === null && this.value === null) {
|
if (this.error === null && this.value === null) {
|
||||||
this.error = 'required';
|
this.error = 'required';
|
||||||
|
@ -27,11 +33,19 @@ class ValidatorCore implements Validator {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
get(): [any, string] {
|
get(): [any, string] {
|
||||||
return [this.value, this.error];
|
return [this.value, this.error];
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(validator: CustomValidator<any>) {
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<any>) {
|
||||||
if (this.error || this.value === null) return this;
|
if (this.error || this.value === null) return this;
|
||||||
const result = validator(this.value);
|
const result = validator(this.value);
|
||||||
if (result === false) {
|
if (result === false) {
|
||||||
|
@ -41,9 +55,59 @@ class ValidatorCore implements Validator {
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<any>) {
|
||||||
|
if (this.error || this.value === null) return this;
|
||||||
|
try {
|
||||||
|
this.value = modifier(this.value);
|
||||||
|
} catch (e) {
|
||||||
|
this.error = e;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NumberValidator extends ValidatorCore {
|
class BooleanFuctory extends FuctoryCore {
|
||||||
|
value: boolean;
|
||||||
|
error: string;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
this.value = null;
|
||||||
|
} else if (typeof value != 'boolean') {
|
||||||
|
this.error = 'must-be-a-boolean';
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required() {
|
||||||
|
return super.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
|
get(): [boolean, string] {
|
||||||
|
return super.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<boolean>) {
|
||||||
|
return super.validate(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<boolean>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NumberFuctory extends FuctoryCore {
|
||||||
value: number;
|
value: number;
|
||||||
error: string;
|
error: string;
|
||||||
|
|
||||||
|
@ -58,6 +122,11 @@ class NumberValidator extends ValidatorCore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 値が指定された範囲内にない場合エラーにします
|
||||||
|
* @param min 下限
|
||||||
|
* @param max 上限
|
||||||
|
*/
|
||||||
range(min: number, max: number) {
|
range(min: number, max: number) {
|
||||||
if (this.error || this.value === null) return this;
|
if (this.error || this.value === null) return this;
|
||||||
if (this.value < min || this.value > max) {
|
if (this.value < min || this.value > max) {
|
||||||
|
@ -70,28 +139,242 @@ class NumberValidator extends ValidatorCore {
|
||||||
return super.required();
|
return super.required();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
get(): [number, string] {
|
get(): [number, string] {
|
||||||
return super.get();
|
return super.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(validator: CustomValidator<number>) {
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<number>) {
|
||||||
return super.validate(validator);
|
return super.validate(validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<number>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringFuctory extends FuctoryCore {
|
||||||
|
value: string;
|
||||||
|
error: string;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
this.value = null;
|
||||||
|
} else if (typeof value != 'string') {
|
||||||
|
this.error = 'must-be-a-string';
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文字数が指定された範囲内にない場合エラーにします
|
||||||
|
* @param min 下限
|
||||||
|
* @param max 上限
|
||||||
|
*/
|
||||||
|
range(min: number, max: number) {
|
||||||
|
if (this.error || this.value === null) return this;
|
||||||
|
if (this.value.length < min || this.value.length > max) {
|
||||||
|
this.error = 'invalid-range';
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
trim() {
|
||||||
|
if (this.error || this.value === null) return this;
|
||||||
|
this.value = this.value.trim();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
required() {
|
||||||
|
return super.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
|
get(): [string, string] {
|
||||||
|
return super.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<string>) {
|
||||||
|
return super.validate(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<string>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArrayFuctory extends FuctoryCore {
|
||||||
|
value: any[];
|
||||||
|
error: string;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
this.value = null;
|
||||||
|
} else if (!Array.isArray(value)) {
|
||||||
|
this.error = 'must-be-an-array';
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配列の値がユニークでない場合(=重複した項目がある場合)エラーにします
|
||||||
|
*/
|
||||||
|
unique() {
|
||||||
|
if (this.error || this.value === null) return this;
|
||||||
|
if (hasDuplicates(this.value)) {
|
||||||
|
this.error = 'must-be-unique';
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配列の長さが指定された範囲内にない場合エラーにします
|
||||||
|
* @param min 下限
|
||||||
|
* @param max 上限
|
||||||
|
*/
|
||||||
|
range(min: number, max: number) {
|
||||||
|
if (this.error || this.value === null) return this;
|
||||||
|
if (this.value.length < min || this.value.length > max) {
|
||||||
|
this.error = 'invalid-range';
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
required() {
|
||||||
|
return super.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
|
get(): [any[], string] {
|
||||||
|
return super.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<any[]>) {
|
||||||
|
return super.validate(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<any[]>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IdFuctory extends FuctoryCore {
|
||||||
|
value: mongo.ObjectID;
|
||||||
|
error: string;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
this.value = null;
|
||||||
|
} else if (typeof value != 'string' || !mongo.ObjectID.isValid(value)) {
|
||||||
|
this.error = 'must-be-an-id';
|
||||||
|
} else {
|
||||||
|
this.value = new mongo.ObjectID(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required() {
|
||||||
|
return super.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
|
get(): [any[], string] {
|
||||||
|
return super.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<any[]>) {
|
||||||
|
return super.validate(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<any[]>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectFuctory extends FuctoryCore {
|
||||||
|
value: any;
|
||||||
|
error: string;
|
||||||
|
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
if (value === undefined || value === null) {
|
||||||
|
this.value = null;
|
||||||
|
} else if (typeof value != 'object') {
|
||||||
|
this.error = 'must-be-an-object';
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
required() {
|
||||||
|
return super.required();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値およびエラーを取得します
|
||||||
|
*/
|
||||||
|
get(): [any, string] {
|
||||||
|
return super.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* このインスタンスの値に対して妥当性を検証します
|
||||||
|
* バリデータが false または(エラーを表す)文字列を返した場合エラーにします
|
||||||
|
* @param validator バリデータ
|
||||||
|
*/
|
||||||
|
validate(validator: Validator<any>) {
|
||||||
|
return super.validate(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
modify(modifier: Modifier<any>) {
|
||||||
|
return super.modify(modifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const it = (value: any) => ({
|
const it = (value: any) => ({
|
||||||
must: {
|
must: {
|
||||||
be: {
|
be: {
|
||||||
a: {
|
a: {
|
||||||
string: 0,
|
string: () => new StringFuctory(value),
|
||||||
number: () => new NumberValidator(value),
|
number: () => new NumberFuctory(value),
|
||||||
boolean: 0,
|
boolean: () => new BooleanFuctory(value)
|
||||||
set: 0
|
|
||||||
},
|
},
|
||||||
an: {
|
an: {
|
||||||
id: 0,
|
id: () => new IdFuctory(value),
|
||||||
array: 0,
|
array: () => new ArrayFuctory(value),
|
||||||
object: 0
|
object: () => new ObjectFuctory(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue