Skip to content

Commit 9eb42c6

Browse files
committed
[added] refs!
1 parent 78f84c3 commit 9eb42c6

16 files changed

+330
-132
lines changed

README.md

+65-13
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,25 @@ Thrown on failed validations, with the following properties
185185
validation chain. When the `abortEarly` option is `false` this is where you can inspect each error thrown,
186186
alternatively `errors` will have all the of the messages from each inner error.
187187

188+
#### `ref(String path, Object options)`
189+
190+
Creates a reference to another sibling or sibling descendant field. Ref's are resolved
191+
at _run time_ and supported where specified. Ref's are evaluated in in the proper order so that
192+
the ref value is resolved before the field using the ref (be careful of circular dependencies!).
193+
194+
```js
195+
var schema = object({
196+
baz: ref('foo.bar'),
197+
foo: object({
198+
bar: string()
199+
})
200+
x: ref('$x')
201+
})
202+
203+
inst.cast({ foo: { bar: 'boom' } }, { context: { x: 5 } })
204+
// { baz: 'boom', x: 5, { foo: { bar: 'boom' } }, }
205+
```
206+
188207

189208
### mixed
190209

@@ -365,7 +384,7 @@ schema.isValid(42) //=> false
365384
schema.isValid(new Date) //=> true
366385
```
367386

368-
#### `mixed.when(String key, Object options | Function func)`
387+
#### `mixed.when(String|Array<String> keys, Object options | Function func)`
369388

370389
Adjust the schema based on a sibling or sibling children fields. You can provide an object
371390
literal where the key `is` is value or a matcher function, `then` provides the true schema and/or
@@ -374,11 +393,8 @@ literal where the key `is` is value or a matcher function, `then` provides the t
374393
`is` conditions are strictly compared (`===`) if you want to use a different form of equality you
375394
can provide a function like: `is: (value) => value == true`.
376395

377-
Alternatively you can provide a function the returns a schema (called with the value of the key
378-
and the current schema). `when` conditions are additive.
379-
380396
Like joi you can also prefix properties with `$` to specify a property that is dependent
381-
on `context` passed in by `validate()` or `isValid`.
397+
on `context` passed in by `validate()` or `isValid`. `when` conditions are additive.
382398

383399
```javascript
384400
var inst = yup.object({
@@ -397,6 +413,42 @@ var inst = yup.object({
397413
inst.validate(value, { context: { other: 4 }})
398414
```
399415

416+
You can also specify more than one dependent key, in which case each value will be spread as an argument.
417+
418+
```javascript
419+
var inst = yup.object({
420+
isSpecial: yup.bool()
421+
isBig: yup.bool(),
422+
count: yup.number()
423+
.when(['isBig', 'isSpecial'], {
424+
is: true, // alternatively: (isBig, isSpecial) => isBig && isSpecial
425+
then: yup.number().min(5),
426+
otherwise: yup.number().min(0)
427+
})
428+
})
429+
430+
inst.validate({
431+
isBig: true,
432+
isSpecial: true,
433+
count: 10
434+
})
435+
```
436+
437+
Alternatively you can provide a function the returns a schema
438+
(called with the value of the key and the current schema).
439+
440+
```js
441+
var inst = yup.object({
442+
isBig: yup.boolean(),
443+
count: yup.number()
444+
.when('isBig', (isBig, schema) => {
445+
return isBig ? schema.min(5) : schema.min(0)
446+
})
447+
})
448+
449+
inst.validate({ isBig: false, count: 4 })
450+
```
451+
400452

401453
#### `mixed.test(String name, String message, Function fn, [Bool callbackStyleAsync])`
402454

@@ -539,11 +591,11 @@ schema.isValid('hello') //=> true
539591
The same as the `mixed()` schema required, except that empty strings are also considered 'missing' values.
540592
To allow empty strings but fail on `undefined` values use: `string().required().min(0)`
541593

542-
#### `string.min(Number limit, [String message])`
594+
#### `string.min(Number|Ref limit, [String message])`
543595

544596
Set an minimum length limit for the string value. The `${min}` interpolation can be used in the `message` argument
545597

546-
#### `string.max(Number limit, [String message])`
598+
#### `string.max(Number|Ref limit, [String message])`
547599

548600
Set an maximum length limit for the string value. The `${max}` interpolation can be used in the `message` argument
549601

@@ -588,12 +640,12 @@ var schema = yup.number();
588640
schema.isValid(10) //=> true
589641
```
590642

591-
#### `number.min(Number limit, [String message])`
643+
#### `number.min(Number|Ref limit, [String message])`
592644

593645
Set the minimum value allowed. The `${min}` interpolation can be used in the
594646
`message` argument.
595647

596-
#### `number.max(Number limit, [String message])`
648+
#### `number.max(Number|Ref limit, [String message])`
597649

598650
Set the maximum value allowed. The `${max}` interpolation can be used in the
599651
`message` argument.
@@ -636,11 +688,11 @@ var schema = yup.date();
636688
schema.isValid(new Date) //=> true
637689
```
638690

639-
#### `date.min(Date|String limit, [String message])`
691+
#### `date.min(Date|String|Ref limit, [String message])`
640692

641693
Set the minimum date allowed.
642694

643-
#### `date.max(Date|String limit, [String message])`
695+
#### `date.max(Date|String|Ref limit, [String message])`
644696

645697
Set the maximum date allowed.
646698

@@ -668,11 +720,11 @@ not validate its contents.
668720
The same as the `mixed()` schema required, except that empty arrays are also considered 'missing' values.
669721
To allow empty arrays but fail on `undefined` values use: `array().required().min(0)`
670722

671-
#### `array.min(Number limit, [String message])`
723+
#### `array.min(Number|Ref limit, [String message])`
672724

673725
Set an minimum length limit for the array. The `${min}` interpolation can be used in the `message` argument.
674726

675-
#### `array.max(Number limit, [String message])`
727+
#### `array.max(Number|Ref limit, [String message])`
676728

677729
Set an maximum length limit for the array. The `${max}` interpolation can be used in the `message` argument.
678730

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
"karma-jsdom-launcher": "^1.0.0",
3737
"karma-mocha": "^0.2.0",
3838
"karma-mocha-reporter": "^1.0.2",
39-
"karma-phantomjs-launcher": "^0.2.0",
4039
"karma-sourcemap-loader": "^0.3.5",
4140
"karma-webpack": "^1.7.0",
4241
"mocha": "^1.21.4",

src/array.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ inherits(ArraySchema, MixedSchema, {
109109
name: 'min',
110110
exclusive: true,
111111
params: { min },
112-
test: value => isAbsent(value) || value.length >= min
112+
test(value) {
113+
return isAbsent(value) || value.length >= this.resolve(min)
114+
}
113115
})
114116
},
115117

@@ -120,7 +122,9 @@ inherits(ArraySchema, MixedSchema, {
120122
name: 'max',
121123
exclusive: true,
122124
params: { max },
123-
test: value => isAbsent(value) || value.length <= max
125+
test(value) {
126+
return isAbsent(value) || value.length <= this.resolve(max)
127+
}
124128
})
125129
},
126130

src/date.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ inherits(DateSchema, MixedSchema, {
4242
exclusive: true,
4343
message: msg || locale.min,
4444
params: { min: min },
45-
test: value => isAbsent(value) || (value >= limit)
45+
test(value) {
46+
return isAbsent(value) || value >= this.resolve(limit)
47+
}
4648
})
4749
},
4850

@@ -57,7 +59,9 @@ inherits(DateSchema, MixedSchema, {
5759
exclusive: true,
5860
message: msg || locale.max,
5961
params: { max: max },
60-
test: value => isAbsent(value) || (value <= limit)
62+
test(value) {
63+
return isAbsent(value) || value <= this.resolve(limit)
64+
}
6165
})
6266
}
6367

src/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
var mixed = require('./mixed')
3-
, bool = require('./boolean');
3+
, bool = require('./boolean')
4+
, Ref = require('./util/reference');
45

56
var isSchema = schema => schema && !!schema.__isYupSchema__;
67

@@ -17,6 +18,7 @@ module.exports = {
1718
reach: require('./util/reach'),
1819

1920
ValidationError: require('./util/validation-error'),
21+
ref: (key, options) => new Ref(key, options),
2022

2123
isSchema,
2224

src/mixed.js

+31-15
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
var Promise = require('promise/lib/es6-extensions')
44
, Condition = require('./util/condition')
5-
, ValidationError = require('./util/validation-error')
65
, locale = require('./locale.js').mixed
76
, _ = require('./util/_')
87
, isAbsent = require('./util/isAbsent')
98
, cloneDeep = require('./util/clone')
109
, createValidation = require('./util/createValidation')
11-
, BadSet = require('./util/set');
10+
, BadSet = require('./util/set')
11+
, Ref = require('./util/reference');
1212

1313
let notEmpty = value => !isAbsent(value);
1414

@@ -25,6 +25,7 @@ function SchemaType(options = {}){
2525
return new SchemaType()
2626

2727
this._deps = []
28+
this._conditions = []
2829
this._options = { abortEarly: true, recursive: true }
2930
this._exclusive = Object.create(null)
3031
this._whitelist = new BadSet()
@@ -100,9 +101,9 @@ SchemaType.prototype = {
100101
return !this._typeCheck || this._typeCheck(v)
101102
},
102103

103-
cast(_value, _opts) {
104-
var schema = this._resolve((_opts || {}).context)
105-
return schema._cast(_value, _opts)
104+
cast(value, opts = {}) {
105+
var schema = this._resolve(opts.context, opts.parent)
106+
return schema._cast(value, opts)
106107
},
107108

108109
_cast(_value) {
@@ -116,9 +117,9 @@ SchemaType.prototype = {
116117
return value
117118
},
118119

119-
_resolve(context, parent){
120-
if (this._deps.length) {
121-
return this._deps.reduce((schema, match) =>
120+
_resolve(context, parent) {
121+
if (this._conditions.length) {
122+
return this._conditions.reduce((schema, match) =>
122123
match.resolve(schema, match.getValue(parent, context)), this)
123124
}
124125

@@ -186,7 +187,7 @@ SchemaType.prototype = {
186187
},
187188

188189
default(def) {
189-
if( arguments.length === 0){
190+
if (arguments.length === 0) {
190191
var dflt = _.has(this, '_default') ? this._default : this._defaultDefault
191192
return typeof dflt === 'function'
192193
? dflt.call(this) : cloneDeep(dflt)
@@ -277,11 +278,16 @@ SchemaType.prototype = {
277278
return next
278279
},
279280

280-
when(key, options){
281+
when(keys, options) {
281282
var next = this.clone()
282-
, dep = new Condition(key, next._type, options);
283+
, deps = [].concat(keys).map(key => new Ref(key));
283284

284-
next._deps.push(dep)
285+
deps.forEach(dep => {
286+
if (!dep.isContext)
287+
next._deps.push(dep.key)
288+
})
289+
290+
next._conditions.push(new Condition(deps, options))
285291

286292
return next
287293
},
@@ -295,7 +301,9 @@ SchemaType.prototype = {
295301
test(value) {
296302
if (value !== undefined && !this.schema.isType(value))
297303
return this.createError({
298-
params: { type: this.schema._type }
304+
params: {
305+
type: this.schema._type
306+
}
299307
})
300308
return true
301309
}
@@ -320,7 +328,11 @@ SchemaType.prototype = {
320328
test(value) {
321329
let valids = this.schema._whitelist
322330
if (valids.length && !(valids.has(value) || isAbsent(value)))
323-
return this.createError({ params: { values: valids.values().join(', ') }})
331+
return this.createError({
332+
params: {
333+
values: valids.values().join(', ')
334+
}
335+
})
324336
return true
325337
}
326338
})
@@ -342,7 +354,11 @@ SchemaType.prototype = {
342354
test(value) {
343355
let invalids = this.schema._blacklist
344356
if (invalids.length && invalids.has(value))
345-
return this.createError({ params: { values: invalids.values().join(', ') }})
357+
return this.createError({
358+
params: {
359+
values: invalids.values().join(', ')
360+
}
361+
})
346362
return true
347363
}
348364
})

src/number.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ inherits(NumberSchema, SchemaObject, {
3939
exclusive: true,
4040
params: { min },
4141
message: msg || locale.min,
42-
test: value => isAbsent(value) || value >= min
42+
test(value) {
43+
return isAbsent(value) || value >= this.resolve(min)
44+
}
4345
})
4446
},
4547

@@ -49,7 +51,9 @@ inherits(NumberSchema, SchemaObject, {
4951
exclusive: true,
5052
params: { max },
5153
message: msg || locale.max,
52-
test: value => isAbsent(value) || value <= max
54+
test(value) {
55+
return isAbsent(value) || value <= this.resolve(max)
56+
}
5357
})
5458
},
5559

0 commit comments

Comments
 (0)