Skip to content

Commit e79c9d4

Browse files
authored
fix: async rule with schema (#162)
fix: async rule with schema
2 parents d60fd4d + 63e422f commit e79c9d4

3 files changed

Lines changed: 63 additions & 17 deletions

File tree

src/Rule.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,17 @@ class Rule {
5151
}
5252
}
5353

54+
function pickFn(fn, variant = "simple") {
55+
return typeof fn === "object" ? fn[variant] : fn;
56+
}
57+
5458
function testAux(modifiers, fn) {
5559
if (modifiers.length) {
5660
const modifier = modifiers.shift();
5761
const nextFn = testAux(modifiers, fn);
5862
return modifier.perform(nextFn);
5963
} else {
60-
return fn;
64+
return pickFn(fn);
6165
}
6266
}
6367

@@ -67,7 +71,7 @@ function testAsyncAux(modifiers, fn) {
6771
const nextFn = testAsyncAux(modifiers, fn);
6872
return modifier.performAsync(nextFn);
6973
} else {
70-
return value => Promise.resolve(fn(value));
74+
return value => Promise.resolve(pickFn(fn, "async")(value));
7175
}
7276
}
7377

src/v8n.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ function proxyContext(context) {
4040
const availableModifiers = {
4141
not: {
4242
simple: fn => value => !fn(value),
43-
async: fn => value => Promise.resolve(fn(value)).then(result => !result)
43+
async: fn => value =>
44+
Promise.resolve(fn(value))
45+
.then(result => !result)
46+
.catch(e => true)
4447
},
4548

4649
some: {
@@ -57,7 +60,7 @@ const availableModifiers = {
5760
return Promise.all(
5861
split(value).map(item => {
5962
try {
60-
return fn(item);
63+
return fn(item).catch(e => false);
6164
} catch (ex) {
6265
return false;
6366
}
@@ -206,21 +209,40 @@ function isIntegerPolyfill(value) {
206209
}
207210

208211
function testSchema(schema) {
209-
return value => {
210-
const causes = [];
211-
Object.keys(schema).forEach(key => {
212-
const nestedValidation = schema[key];
213-
try {
214-
nestedValidation.check((value || {})[key]);
215-
} catch (ex) {
216-
ex.target = key;
217-
causes.push(ex);
212+
return {
213+
simple: value => {
214+
const causes = [];
215+
Object.keys(schema).forEach(key => {
216+
const nestedValidation = schema[key];
217+
try {
218+
nestedValidation.check((value || {})[key]);
219+
} catch (ex) {
220+
ex.target = key;
221+
causes.push(ex);
222+
}
223+
});
224+
if (causes.length > 0) {
225+
throw causes;
218226
}
219-
});
220-
if (causes.length > 0) {
221-
throw causes;
227+
return true;
228+
},
229+
async: value => {
230+
const causes = [];
231+
const nested = Object.keys(schema).map(key => {
232+
const nestedValidation = schema[key];
233+
return nestedValidation.testAsync((value || {})[key]).catch(ex => {
234+
ex.target = key;
235+
causes.push(ex);
236+
});
237+
});
238+
return Promise.all(nested).then(values => {
239+
if (causes.length > 0) {
240+
throw causes;
241+
}
242+
243+
return true;
244+
});
222245
}
223-
return true;
224246
};
225247
}
226248

src/v8n.test.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,26 @@ describe("execution functions", () => {
220220
});
221221
});
222222

223+
describe("working with schema's", () => {
224+
it("should handle async rule within a schema", async () => {
225+
v8n.extend({ asyncRule });
226+
227+
const validation = v8n().schema({
228+
item: v8n()
229+
.number()
230+
.asyncRule([10, 17, 20])
231+
});
232+
233+
await expect(
234+
validation.testAsync({ item: "10" })
235+
).rejects.toBeDefined();
236+
await expect(validation.testAsync({ item: 11 })).rejects.toBeDefined();
237+
await expect(validation.testAsync({ item: 17 })).resolves.toEqual({
238+
item: 17
239+
});
240+
});
241+
});
242+
223243
describe("the returned Promise", () => {
224244
it("should resolves when valid", async () => {
225245
const validation = v8n()

0 commit comments

Comments
 (0)