From 0a04d6f1ce3a4c2786a38f128eb5797e1eef06af Mon Sep 17 00:00:00 2001 From: Giacomo Augello Date: Sun, 17 Mar 2024 18:22:33 +0100 Subject: [PATCH] fix: nested objects returned checkResult, execution of async rules on arrays --- src/ArrayType.ts | 31 +++++++++++++++++++++++++++---- src/ObjectType.ts | 8 ++++++-- test/ArrayTypeSpec.js | 29 +++++++++++++++++++++++++++++ test/ObjectTypeSpec.js | 1 + 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/ArrayType.ts b/src/ArrayType.ts index 158c566..1237877 100644 --- a/src/ArrayType.ts +++ b/src/ArrayType.ts @@ -68,11 +68,11 @@ export class ArrayType extends MixedType< of(type: MixedType) { super.pushRule({ - onValid: (items, data, filedName) => { + onValid: (items, data, fieldName) => { const checkResults = items.map((value, index) => { - const name = Array.isArray(filedName) - ? [...filedName, `[${index}]`] - : [filedName, `[${index}]`]; + const name = Array.isArray(fieldName) + ? [...fieldName, `[${index}]`] + : [fieldName, `[${index}]`]; return type.check(value, data, name as string[]); }); @@ -85,6 +85,29 @@ export class ArrayType extends MixedType< } }); + super.pushRule({ + onValid: (items, data, fieldName) => { + return new Promise(resolve => { + const checkAll: Promise>>[] = + items.map((value, index) => { + const name = Array.isArray(fieldName) + ? [...fieldName, `[${index}]`] + : [fieldName, `[${index}]`]; + + return type.checkAsync(value, data, name as string[]); + }); + + return Promise.all(checkAll).then(checkResults => { + resolve({ + hasError: !!checkResults.find(item => item?.hasError), + array: checkResults + }); + }); + }) + }, + isAsync: true + }); + return this; } } diff --git a/src/ObjectType.ts b/src/ObjectType.ts index 6c2957a..eb033b2 100644 --- a/src/ObjectType.ts +++ b/src/ObjectType.ts @@ -74,11 +74,15 @@ export class ObjectType extends MixedType< }); return Promise.all(checkAll).then(values => { - values.forEach((v, index) => { + let hasError = false; + values.forEach((v: any, index: number) => { + if (v?.hasError) { + hasError = true; + } checkResult[keys[index]] = v; }); - resolve({ object: checkResult }); + resolve({ hasError, object: checkResult }); }); } diff --git a/test/ArrayTypeSpec.js b/test/ArrayTypeSpec.js index 5d75b8f..d1526de 100644 --- a/test/ArrayTypeSpec.js +++ b/test/ArrayTypeSpec.js @@ -176,4 +176,33 @@ describe('#ArrayType', () => { .checkForField('data', { data: [1] }) .errorMessage.should.equal('data field must have at least 2 items'); }); + + it('Should call async check', done => { + const schema = new Schema({ + arr1: ArrayType().addAsyncRule(() => { + return new Promise(resolve => { + setTimeout(() => { + resolve(false); + }, 1000); + }); + }, 'error1'), + arr2: ArrayType().addAsyncRule(() => { + return new Promise(resolve => { + setTimeout(() => { + resolve(true); + }, 1000); + }); + }, 'error2'), + }); + + schema.checkAsync({ arr1: [1, 2, 3], arr2: [1, 2, 3] }).then(status => { + if ( + status.arr1.hasError && + status.arr1.errorMessage === 'error1' && + !status.arr2.hasError + ) { + done(); + } + }); + }); }); diff --git a/test/ObjectTypeSpec.js b/test/ObjectTypeSpec.js index dc029ea..edac4a4 100644 --- a/test/ObjectTypeSpec.js +++ b/test/ObjectTypeSpec.js @@ -124,6 +124,7 @@ describe('#ObjectType', () => { schema.checkAsync({ url: 'url', user: { email: 'a', age: '10' } }).then(status => { const user = status.user.object; if ( + status.user.hasError && user.age.hasError && user.age.errorMessage === 'error2' && user.email.hasError &&