Skip to content

Commit 8f00d50

Browse files
committedApr 20, 2020
feat: make schema.type and array.innerType public API's
Also simplify reach/getIn logic
1 parent 81e4058 commit 8f00d50

File tree

4 files changed

+37
-51
lines changed

4 files changed

+37
-51
lines changed
 

‎src/array.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function ArraySchema(type) {
1717
// `undefined` specifically means uninitialized, as opposed to
1818
// "no subtype"
1919
this._subType = undefined;
20+
this.innerType = undefined;
2021

2122
this.withMutation(() => {
2223
this.transform(function(values) {
@@ -43,11 +44,11 @@ inherits(ArraySchema, MixedSchema, {
4344
const value = MixedSchema.prototype._cast.call(this, _value, _opts);
4445

4546
//should ignore nulls here
46-
if (!this._typeCheck(value) || !this._subType) return value;
47+
if (!this._typeCheck(value) || !this.innerType) return value;
4748

4849
let isChanged = false;
4950
const castArray = value.map((v, idx) => {
50-
const castElement = this._subType.cast(v, {
51+
const castElement = this.innerType.cast(v, {
5152
..._opts,
5253
path: makePath`${_opts.path}[${idx}]`,
5354
});
@@ -65,7 +66,7 @@ inherits(ArraySchema, MixedSchema, {
6566
let errors = [];
6667
let sync = options.sync;
6768
let path = options.path;
68-
let subType = this._subType;
69+
let innerType = this.innerType;
6970
let endEarly = this._option('abortEarly', options);
7071
let recursive = this._option('recursive', options);
7172

@@ -76,7 +77,7 @@ inherits(ArraySchema, MixedSchema, {
7677
.call(this, _value, options)
7778
.catch(propagateErrors(endEarly, errors))
7879
.then(value => {
79-
if (!recursive || !subType || !this._typeCheck(value)) {
80+
if (!recursive || !innerType || !this._typeCheck(value)) {
8081
if (errors.length) throw errors[0];
8182
return value;
8283
}
@@ -95,7 +96,7 @@ inherits(ArraySchema, MixedSchema, {
9596
originalValue: originalValue[idx],
9697
};
9798

98-
if (subType.validate) return subType.validate(item, innerOptions);
99+
if (innerType.validate) return innerType.validate(item, innerOptions);
99100

100101
return true;
101102
});
@@ -126,6 +127,7 @@ inherits(ArraySchema, MixedSchema, {
126127
);
127128

128129
next._subType = schema;
130+
next.innerType = schema;
129131

130132
return next;
131133
},
@@ -175,7 +177,7 @@ inherits(ArraySchema, MixedSchema, {
175177

176178
describe() {
177179
let base = MixedSchema.prototype.describe.call(this);
178-
if (this._subType) base.innerType = this._subType.describe();
180+
if (this.innerType) base.innerType = this.innerType.describe();
179181
return base;
180182
},
181183
});

‎src/mixed.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ export default function SchemaType(options = {}) {
7272

7373
if (has(options, 'default')) this._defaultDefault = options.default;
7474

75+
this.type = options.type || 'mixed';
76+
// TODO: remove
7577
this._type = options.type || 'mixed';
7678
}
7779

@@ -117,9 +119,7 @@ const proto = (SchemaType.prototype = {
117119

118120
if (schema._type !== this._type && this._type !== 'mixed')
119121
throw new TypeError(
120-
`You cannot \`concat()\` schema's of different types: ${
121-
this._type
122-
} and ${schema._type}`,
122+
`You cannot \`concat()\` schema's of different types: ${this._type} and ${schema._type}`,
123123
);
124124

125125
var next = prependDeep(schema.clone(), this);

‎src/util/reach.js

+24-39
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,50 @@
11
import { forEach } from 'property-expr';
2-
import has from 'lodash/has';
32

43
let trim = part => part.substr(0, part.length - 1).substr(1);
54

6-
export function getIn(schema, path, value, context) {
5+
export function getIn(schema, path, value, context = value) {
76
let parent, lastPart, lastPartDebug;
87

9-
// if only one "value" arg then use it for both
10-
context = context || value;
8+
// root path: ''
9+
if (!path) return { parent, parentPath: path, schema };
1110

12-
if (!path)
13-
return {
14-
parent,
15-
parentPath: path,
16-
schema,
17-
};
18-
19-
// I no longer remember why this is so complicated
20-
forEach(path, (_part, isBracket, isArray, partIdx, parts) => {
21-
let isLast = partIdx === parts.length - 1;
11+
forEach(path, (_part, isBracket, isArray) => {
2212
let part = isBracket ? trim(_part) : _part;
2313

24-
if (isArray || has(schema, '_subType')) {
25-
// we skipped an array: foo[].bar
26-
let idx = isArray ? parseInt(part, 10) : 0;
27-
28-
schema = schema.resolve({ context, parent, value })._subType;
14+
schema = schema.resolve({ context, parent, value });
2915

30-
if (value) {
31-
if (isArray && idx >= value.length) {
32-
throw new Error(
33-
`Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. ` +
34-
`because there is no value at that index. `,
35-
);
36-
}
16+
if (schema.innerType) {
17+
let idx = isArray ? parseInt(part, 10) : 0;
3718

38-
if (isLast) {
39-
parent = value;
40-
lastPart = part;
41-
lastPartDebug = isBracket ? '[' + _part + ']' : '.' + _part;
42-
}
43-
value = value[idx];
19+
if (value && idx >= value.length) {
20+
throw new Error(
21+
`Yup.reach cannot resolve an array item at index: ${_part}, in the path: ${path}. ` +
22+
`because there is no value at that index. `,
23+
);
4424
}
25+
parent = value;
26+
value = value && value[idx];
27+
schema = schema.innerType;
4528
}
4629

30+
// sometimes the array index part of a path doesn't exist: "nested.arr.child"
31+
// in these cases the current part is the next schema and should be processed
32+
// in this iteration. For cases where the index signature is included this
33+
// check will fail and we'll handle the `child` part on the next iteration like normal
4734
if (!isArray) {
48-
schema = schema.resolve({ context, parent, value });
49-
50-
if (!has(schema, 'fields') || !has(schema.fields, part))
35+
if (!schema.fields || !schema.fields[part])
5136
throw new Error(
5237
`The schema does not contain the path: ${path}. ` +
5338
`(failed at: ${lastPartDebug} which is a type: "${schema._type}")`,
5439
);
5540

56-
schema = schema.fields[part];
57-
5841
parent = value;
5942
value = value && value[part];
60-
lastPart = part;
61-
lastPartDebug = isBracket ? '[' + _part + ']' : '.' + _part;
43+
schema = schema.fields[part];
6244
}
45+
46+
lastPart = part;
47+
lastPartDebug = isBracket ? '[' + _part + ']' : '.' + _part;
6348
});
6449

6550
return { schema, parent, parentPath: lastPart };

‎test/yup.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ describe('Yup', function() {
107107

108108
const { schema, parent, parentPath } = getIn(inst, 'nested.arr[1]', value);
109109

110-
console.log(parentPath);
111110
expect(schema).to.equal(shape);
112111
expect(parentPath).to.equal('1');
113112
expect(parent).to.equal(value.nested.arr);
@@ -127,14 +126,14 @@ describe('Yup', function() {
127126

128127
reach(inst, '').should.equal(inst);
129128

130-
reach(inst, 'nested.arr.num').should.equal(num);
129+
reach(inst, 'nested.arr[0].num').should.equal(num);
131130
reach(inst, 'nested.arr[].num').should.equal(num);
132131
reach(inst, 'nested.arr[1].num').should.equal(num);
133132
reach(inst, 'nested.arr[1]').should.equal(shape);
134133

135134
reach(inst, 'nested["arr"][1].num').should.not.equal(number());
136135

137-
let valid = await reach(inst, 'nested.arr[].num').isValid(5);
136+
let valid = await reach(inst, 'nested.arr[0].num').isValid(5);
138137
valid.should.equal(true);
139138
});
140139

0 commit comments

Comments
 (0)
Please sign in to comment.