summaryrefslogtreecommitdiff
path: root/src/api
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2017-03-02 21:54:46 +0900
committersyuilo <syuilotan@yahoo.co.jp>2017-03-02 21:54:46 +0900
commit789deecfe96a32adfd98ebede749380f81520402 (patch)
treec4c54343697c30ea5b95f76b84208f54ea80ad00 /src/api
parentwip (diff)
downloadsharkey-789deecfe96a32adfd98ebede749380f81520402.tar.gz
sharkey-789deecfe96a32adfd98ebede749380f81520402.tar.bz2
sharkey-789deecfe96a32adfd98ebede749380f81520402.zip
wip
Diffstat (limited to 'src/api')
-rw-r--r--src/api/endpoints/posts/create.ts18
-rw-r--r--src/api/it.ts518
-rw-r--r--src/api/validator.ts87
-rw-r--r--src/api/validator2.ts385
4 files changed, 526 insertions, 482 deletions
diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts
index 0ecce4e9ad..f707c81b1d 100644
--- a/src/api/endpoints/posts/create.ts
+++ b/src/api/endpoints/posts/create.ts
@@ -3,7 +3,7 @@
/**
* Module dependencies
*/
-import validate from '../../validator';
+import it from '../../it';
import parse from '../../../common/text';
import Post from '../../models/post';
import { isValidText } from '../../models/post';
@@ -27,13 +27,11 @@ module.exports = (params, user, app) =>
new Promise(async (res, rej) =>
{
// Get 'text' parameter
- const [text, textErr] = validate(params.text, 'string', false, isValidText);
+ const [text, textErr] = it(params.text).must.be.a.string().validate(isValidText).get();
if (textErr) return rej('invalid text');
// Get 'media_ids' parameter
- const [mediaIds, mediaIdsErr] = validate(params.media_ids, 'set', false,
- x => x.length > 4 ? 'too many media' : true
- );
+ const [mediaIds, mediaIdsErr] = it(params.media_ids).must.be.an.array().unique().range(1, 4).get();
if (mediaIdsErr) return rej('invalid media_ids');
let files = [];
@@ -42,7 +40,7 @@ module.exports = (params, user, app) =>
// forEach だと途中でエラーなどがあっても return できないので
// 敢えて for を使っています。
for (let i = 0; i < mediaIds.length; i++) {
- const [mediaId, mediaIdErr] = validate(mediaIds[i], 'id', true);
+ const [mediaId, mediaIdErr] = it(mediaIds[i]).must.be.an.id().required().get();
if (mediaIdErr) return rej('invalid media id');
// Fetch file
@@ -65,7 +63,7 @@ module.exports = (params, user, app) =>
}
// Get 'repost_id' parameter
- const [repostId, repostIdErr] = validate(params.repost_id, 'id');
+ const [repostId, repostIdErr] = it(params.repost_id).must.be.an.id().get();
if (repostIdErr) return rej('invalid repost_id');
let repost = null;
@@ -107,7 +105,7 @@ module.exports = (params, user, app) =>
}
// Get 'in_reply_to_post_id' parameter
- const [inReplyToPostId, inReplyToPostIdErr] = validate(params.reply_to_id, 'id');
+ const [inReplyToPostId, inReplyToPostIdErr] = it(params.reply_to_id, 'id');
if (inReplyToPostIdErr) return rej('invalid in_reply_to_post_id');
let inReplyToPost = null;
@@ -128,12 +126,12 @@ module.exports = (params, user, app) =>
}
// Get 'poll' parameter
- const [_poll, pollErr] = validate(params.poll, 'object');
+ const [_poll, pollErr] = it(params.poll, 'object');
if (pollErr) return rej('invalid poll');
let poll = null;
if (_poll !== null) {
- const [pollChoices, pollChoicesErr] = validate(params.poll, 'set', false, [
+ const [pollChoices, pollChoicesErr] = it(params.poll, 'set', false, [
choices => {
const shouldReject = choices.some(choice => {
if (typeof choice != 'string') return true;
diff --git a/src/api/it.ts b/src/api/it.ts
new file mode 100644
index 0000000000..1aff99c9e7
--- /dev/null
+++ b/src/api/it.ts
@@ -0,0 +1,518 @@
+import * as mongo from 'mongodb';
+import hasDuplicates from '../common/has-duplicates';
+
+type Validator<T> = (value: T) => boolean | Error;
+type Modifier<T> = (value: T) => T;
+
+interface Factory {
+ get: () => [any, Error];
+
+ required: () => Factory;
+
+ validate: (validator: Validator<any>) => Factory;
+
+ modify: (modifier: Modifier<any>) => Factory;
+}
+
+class FactoryCore implements Factory {
+ value: any;
+ error: Error;
+
+ constructor() {
+ this.value = null;
+ this.error = null;
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ if (this.error === null && this.value === null) {
+ this.error = new Error('required');
+ }
+ return this;
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [any, Error] {
+ return [this.value, this.error];
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<any>) {
+ if (this.error || this.value === null) return this;
+ const result = validator(this.value);
+ if (result === false) {
+ this.error = new Error('invalid-format');
+ } else if (result instanceof Error) {
+ this.error = result;
+ }
+ 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 BooleanFactory extends FactoryCore {
+ value: boolean;
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (typeof value != 'boolean') {
+ this.error = new Error('must-be-a-boolean');
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [boolean, Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<boolean>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<boolean>) {
+ return super.modify(modifier);
+ }
+}
+
+class NumberFactory extends FactoryCore {
+ value: number;
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (!Number.isFinite(value)) {
+ this.error = new Error('must-be-a-number');
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * 値が指定された範囲内にない場合エラーにします
+ * @param min 下限
+ * @param max 上限
+ */
+ range(min: number, max: number) {
+ if (this.error || this.value === null) return this;
+ if (this.value < min || this.value > max) {
+ this.error = new Error('invalid-range');
+ }
+ return this;
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [number, Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<number>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<number>) {
+ return super.modify(modifier);
+ }
+}
+
+class StringFactory extends FactoryCore {
+ value: string;
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (typeof value != 'string') {
+ this.error = new 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 = new Error('invalid-range');
+ }
+ return this;
+ }
+
+ trim() {
+ if (this.error || this.value === null) return this;
+ this.value = this.value.trim();
+ return this;
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [string, Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<string>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<string>) {
+ return super.modify(modifier);
+ }
+}
+
+class ArrayFactory extends FactoryCore {
+ value: any[];
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (!Array.isArray(value)) {
+ this.error = new Error('must-be-an-array');
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * 配列の値がユニークでない場合(=重複した項目がある場合)エラーにします
+ */
+ unique() {
+ if (this.error || this.value === null) return this;
+ if (hasDuplicates(this.value)) {
+ this.error = new 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 = new Error('invalid-range');
+ }
+ return this;
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [any[], Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<any[]>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<any[]>) {
+ return super.modify(modifier);
+ }
+}
+
+class IdFactory extends FactoryCore {
+ value: mongo.ObjectID;
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (typeof value != 'string' || !mongo.ObjectID.isValid(value)) {
+ this.error = new Error('must-be-an-id');
+ } else {
+ this.value = new mongo.ObjectID(value);
+ }
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [any[], Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<any[]>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<any[]>) {
+ return super.modify(modifier);
+ }
+}
+
+class ObjectFactory extends FactoryCore {
+ value: any;
+ error: Error;
+
+ constructor(value) {
+ super();
+ if (value === undefined || value === null) {
+ this.value = null;
+ } else if (typeof value != 'object') {
+ this.error = new Error('must-be-an-object');
+ } else {
+ this.value = value;
+ }
+ }
+
+ /**
+ * このインスタンスの値が undefined または null の場合エラーにします
+ */
+ required() {
+ return super.required();
+ }
+
+ /**
+ * このインスタンスの値およびエラーを取得します
+ */
+ get(): [any, Error] {
+ return super.get();
+ }
+
+ /**
+ * このインスタンスの値に対して妥当性を検証します
+ * バリデータが false またはエラーを返した場合エラーにします
+ * @param validator バリデータ
+ */
+ validate(validator: Validator<any>) {
+ return super.validate(validator);
+ }
+
+ modify(modifier: Modifier<any>) {
+ return super.modify(modifier);
+ }
+}
+
+type MustBe = {
+ must: {
+ be: {
+ a: {
+ string: () => StringFactory;
+ number: () => NumberFactory;
+ boolean: () => BooleanFactory;
+ };
+ an: {
+ id: () => IdFactory;
+ array: () => ArrayFactory;
+ object: () => ObjectFactory;
+ };
+ };
+ };
+};
+
+const mustBe = (value: any) => ({
+ must: {
+ be: {
+ a: {
+ string: () => new StringFactory(value),
+ number: () => new NumberFactory(value),
+ boolean: () => new BooleanFactory(value)
+ },
+ an: {
+ id: () => new IdFactory(value),
+ array: () => new ArrayFactory(value),
+ object: () => new ObjectFactory(value)
+ }
+ }
+ }
+});
+
+type Type = 'id' | 'string' | 'number' | 'boolean' | 'array' | 'set' | 'object';
+type Pipe<T> = (x: T) => T | boolean | Error;
+
+function validate(value: any, type: 'id', isRequired?: boolean, pipe?: Pipe<mongo.ObjectID> | Pipe<mongo.ObjectID>[]): [mongo.ObjectID, Error];
+function validate(value: any, type: 'string', isRequired?: boolean, pipe?: Pipe<string> | Pipe<string>[]): [string, Error];
+function validate(value: any, type: 'number', isRequired?: boolean, pipe?: Pipe<number> | Pipe<number>[]): [number, Error];
+function validate(value: any, type: 'boolean', isRequired?: boolean): [boolean, Error];
+function validate(value: any, type: 'array', isRequired?: boolean, pipe?: Pipe<any[]> | Pipe<any[]>[]): [any[], Error];
+function validate(value: any, type: 'set', isRequired?: boolean, pipe?: Pipe<any[]> | Pipe<any[]>[]): [any[], Error];
+function validate(value: any, type: 'object', isRequired?: boolean, pipe?: Pipe<any> | Pipe<any>[]): [any, Error];
+function validate(value: any, type: Type, isRequired?: boolean, pipe?: Pipe<any> | Pipe<any>[]): [any, Error] {
+ if (value === undefined || value === null) {
+ if (isRequired) {
+ return [null, new Error('is-required')]
+ } else {
+ return [null, null]
+ }
+ }
+
+ switch (type) {
+ case 'id':
+ if (typeof value != 'string' || !mongo.ObjectID.isValid(value)) {
+ return [null, new Error('incorrect-id')];
+ }
+ break;
+
+ case 'string':
+ if (typeof value != 'string') {
+ return [null, new Error('must-be-a-string')];
+ }
+ break;
+
+ case 'number':
+ if (!Number.isFinite(value)) {
+ return [null, new Error('must-be-a-number')];
+ }
+ break;
+
+ case 'boolean':
+ if (typeof value != 'boolean') {
+ return [null, new Error('must-be-a-boolean')];
+ }
+ break;
+
+ case 'array':
+ if (!Array.isArray(value)) {
+ return [null, new Error('must-be-an-array')];
+ }
+ break;
+
+ case 'set':
+ if (!Array.isArray(value)) {
+ return [null, new Error('must-be-an-array')];
+ } else if (hasDuplicates(value)) {
+ return [null, new Error('duplicated-contents')];
+ }
+ break;
+
+ case 'object':
+ if (typeof value != 'object') {
+ return [null, new Error('must-be-an-object')];
+ }
+ break;
+ }
+
+ if (type == 'id') value = new mongo.ObjectID(value);
+
+ if (pipe) {
+ const pipes = Array.isArray(pipe) ? pipe : [pipe];
+ for (let i = 0; i < pipes.length; i++) {
+ const result = pipes[i](value);
+ if (result === false) {
+ return [null, new Error('invalid-format')];
+ } else if (result instanceof Error) {
+ return [null, result];
+ } else if (result !== true) {
+ value = result;
+ }
+ }
+ }
+
+ return [value, null];
+}
+
+function it(value: any): MustBe;
+function it(value: any, type: 'id', isRequired?: boolean, pipe?: Pipe<mongo.ObjectID> | Pipe<mongo.ObjectID>[]): [mongo.ObjectID, Error];
+function it(value: any, type: 'string', isRequired?: boolean, pipe?: Pipe<string> | Pipe<string>[]): [string, Error];
+function it(value: any, type: 'number', isRequired?: boolean, pipe?: Pipe<number> | Pipe<number>[]): [number, Error];
+function it(value: any, type: 'boolean', isRequired?: boolean): [boolean, Error];
+function it(value: any, type: 'array', isRequired?: boolean, pipe?: Pipe<any[]> | Pipe<any[]>[]): [any[], Error];
+function it(value: any, type: 'set', isRequired?: boolean, pipe?: Pipe<any[]> | Pipe<any[]>[]): [any[], Error];
+function it(value: any, type: 'object', isRequired?: boolean, pipe?: Pipe<any> | Pipe<any>[]): [any, Error];
+function it(value: any, type?: any, isRequired?: boolean, pipe?: Pipe<any> | Pipe<any>[]): any {
+ if (typeof type === 'undefined') {
+ return mustBe(value);
+ } else {
+ return validate(value, type, isRequired, pipe);
+ }
+}
+
+export default it;
diff --git a/src/api/validator.ts b/src/api/validator.ts
deleted file mode 100644
index 3f1678e35d..0000000000
--- a/src/api/validator.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import * as mongo from 'mongodb';
-import hasDuplicates from '../common/has-duplicates';
-
-type Type = 'id' | 'string' | 'number' | 'boolean' | 'array' | 'set' | 'object';
-
-type Validator<T> = ((x: T) => boolean | string) | ((x: T) => boolean | string)[];
-
-function validate(value: any, type: 'id', isRequired?: boolean): [mongo.ObjectID, string];
-function validate(value: any, type: 'string', isRequired?: boolean, validator?: Validator<string>): [string, string];
-function validate(value: any, type: 'number', isRequired?: boolean, validator?: Validator<number>): [number, string];
-function validate(value: any, type: 'boolean', isRequired?: boolean): [boolean, string];
-function validate(value: any, type: 'array', isRequired?: boolean, validator?: Validator<any[]>): [any[], string];
-function validate(value: any, type: 'set', isRequired?: boolean, validator?: Validator<any[]>): [any[], string];
-function validate(value: any, type: 'object', isRequired?: boolean, validator?: Validator<any>): [any, string];
-function validate<T>(value: any, type: Type, isRequired?: boolean, validator?: Validator<T>): [T, string] {
- if (value === undefined || value === null) {
- if (isRequired) {
- return [null, 'is-required']
- } else {
- return [null, null]
- }
- }
-
- switch (type) {
- case 'id':
- if (typeof value != 'string' || !mongo.ObjectID.isValid(value)) {
- return [null, 'incorrect-id'];
- }
- break;
-
- case 'string':
- if (typeof value != 'string') {
- return [null, 'must-be-a-string'];
- }
- break;
-
- case 'number':
- if (!Number.isFinite(value)) {
- return [null, 'must-be-a-number'];
- }
- break;
-
- case 'boolean':
- if (typeof value != 'boolean') {
- return [null, 'must-be-a-boolean'];
- }
- break;
-
- case 'array':
- if (!Array.isArray(value)) {
- return [null, 'must-be-an-array'];
- }
- break;
-
- case 'set':
- if (!Array.isArray(value)) {
- return [null, 'must-be-an-array'];
- } else if (hasDuplicates(value)) {
- return [null, 'duplicated-contents'];
- }
- break;
-
- case 'object':
- if (typeof value != 'object') {
- return [null, 'must-be-an-object'];
- }
- break;
- }
-
- if (type == 'id') value = new mongo.ObjectID(value);
-
- if (validator) {
- const validators = Array.isArray(validator) ? validator : [validator];
- for (let i = 0; i < validators.length; i++) {
- const result = validators[i](value);
- if (result === false) {
- return [null, 'invalid-format'];
- } else if (typeof result == 'string') {
- return [null, result];
- }
- }
- }
-
- return [value, null];
-}
-
-export default validate;
diff --git a/src/api/validator2.ts b/src/api/validator2.ts
deleted file mode 100644
index 04dff59aac..0000000000
--- a/src/api/validator2.ts
+++ /dev/null
@@ -1,385 +0,0 @@
-import * as mongo from 'mongodb';
-import hasDuplicates from '../common/has-duplicates';
-
-type Validator<T> = (value: T) => boolean | string;
-type Modifier<T> = (value: T) => T;
-
-interface Fuctory {
- get: () => [any, string];
-
- required: () => Fuctory;
-
- validate: (validator: Validator<any>) => Fuctory;
-
- modify: (modifier: Modifier<any>) => Fuctory;
-}
-
-class FuctoryCore implements Fuctory {
- value: any;
- error: string;
-
- constructor() {
- this.value = null;
- this.error = null;
- }
-
- /**
- * この値が undefined または null の場合エラーにします
- */
- required() {
- if (this.error === null && this.value === null) {
- this.error = 'required';
- }
- return this;
- }
-
- /**
- * このインスタンスの値およびエラーを取得します
- */
- get(): [any, string] {
- return [this.value, this.error];
- }
-
- /**
- * このインスタンスの値に対して妥当性を検証します
- * バリデータが false または(エラーを表す)文字列を返した場合エラーにします
- * @param validator バリデータ
- */
- validate(validator: Validator<any>) {
- if (this.error || this.value === null) return this;
- const result = validator(this.value);
- if (result === false) {
- this.error = 'invalid-format';
- } else if (typeof result == 'string') {
- this.error = result;
- }
- 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 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;
- error: string;
-
- constructor(value) {
- super();
- if (value === undefined || value === null) {
- this.value = null;
- } else if (!Number.isFinite(value)) {
- this.error = 'must-be-a-number';
- } else {
- this.value = value;
- }
- }
-
- /**
- * 値が指定された範囲内にない場合エラーにします
- * @param min 下限
- * @param max 上限
- */
- range(min: number, max: number) {
- if (this.error || this.value === null) return this;
- if (this.value < min || this.value > max) {
- this.error = 'invalid-range';
- }
- return this;
- }
-
- required() {
- return super.required();
- }
-
- /**
- * このインスタンスの値およびエラーを取得します
- */
- get(): [number, string] {
- return super.get();
- }
-
- /**
- * このインスタンスの値に対して妥当性を検証します
- * バリデータが false または(エラーを表す)文字列を返した場合エラーにします
- * @param validator バリデータ
- */
- validate(validator: Validator<number>) {
- 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) => ({
- must: {
- be: {
- a: {
- string: () => new StringFuctory(value),
- number: () => new NumberFuctory(value),
- boolean: () => new BooleanFuctory(value)
- },
- an: {
- id: () => new IdFuctory(value),
- array: () => new ArrayFuctory(value),
- object: () => new ObjectFuctory(value)
- }
- }
- }
-});
-
-export default it;
-
-const [n, e] = it(42).must.be.a.number().required().range(10, 70).validate(x => x != 21).get();