read-excel-file 8.0.3 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +26 -10
- package/browser/index.d.ts +2 -1
- package/commonjs/parseData/parseData.js +423 -206
- package/commonjs/parseData/parseData.js.map +1 -1
- package/commonjs/parseData/parseData.test.js.map +1 -1
- package/commonjs/xml/xml.js +1 -1
- package/commonjs/xml/xml.js.map +1 -1
- package/modules/parseData/parseData.js +422 -206
- package/modules/parseData/parseData.js.map +1 -1
- package/modules/parseData/parseData.test.js.map +1 -1
- package/modules/xml/xml.js +1 -1
- package/modules/xml/xml.js.map +1 -1
- package/node/index.d.ts +2 -1
- package/package.json +2 -2
- package/types/parseData/parseDataError.d.ts +11 -0
- package/types/types.d.ts +4 -2
- package/universal/index.d.ts +2 -1
- package/web-worker/index.d.ts +2 -1
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports["default"] = parseData;
|
|
7
7
|
exports.getNextSubstring = getNextSubstring;
|
|
8
|
+
exports.parseDataWithPerRowErrors = parseDataWithPerRowErrors;
|
|
8
9
|
exports.parseSeparatedSubstrings = parseSeparatedSubstrings;
|
|
9
10
|
exports.parseValue = parseValue;
|
|
10
11
|
var _Number = _interopRequireDefault(require("./types/Number.js"));
|
|
@@ -12,20 +13,21 @@ var _String = _interopRequireDefault(require("./types/String.js"));
|
|
|
12
13
|
var _Boolean = _interopRequireDefault(require("./types/Boolean.js"));
|
|
13
14
|
var _Date = _interopRequireDefault(require("./types/Date.js"));
|
|
14
15
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
16
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
17
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
18
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
15
19
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
16
20
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
17
21
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
18
22
|
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
19
23
|
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
20
|
-
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
21
|
-
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
22
|
-
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
23
24
|
function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }
|
|
24
25
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
25
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
26
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
27
26
|
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
28
27
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
28
|
+
function _createForOfIteratorHelperLoose(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (it) return (it = it.call(o)).next.bind(it); if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
29
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
30
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
29
31
|
/**
|
|
30
32
|
* Converts spreadsheet-alike data structure into an array of JSON objects.
|
|
31
33
|
*
|
|
@@ -39,7 +41,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
39
41
|
* // * `shouldSkipRequiredValidationWhenColumnIsMissing: (column: string, { object }) => boolean` — By default, it does apply `required` validation to `schema` properties for which columns are missing in the input `data`. One could pass a custom `shouldSkipRequiredValidationWhenColumnIsMissing(column, { object })` to disable `required` validation for missing columns in some or all cases.
|
|
40
42
|
* * `transformEmptyObject(object, { path? })` — By default, it returns `null` for "empty" objects. One could override that value using `transformEmptyObject(object, { path })` parameter. The value applies to both top-level object and any nested sub-objects in case of a nested schema, hence the additional (optional) `path?: string` parameter.
|
|
41
43
|
* * `transformEmptyArray(array, { path })` — By default, it returns `null` for an "empty" array value. One could override that value using `transformEmptyArray(array, { path })` parameter.
|
|
42
|
-
* * `
|
|
44
|
+
* * `separatorCharacter` — By default, it splits array-type cell values by a comma character.
|
|
43
45
|
*
|
|
44
46
|
* When parsing a property value, in case of an error, the value of that property is gonna be `undefined`.
|
|
45
47
|
*
|
|
@@ -51,301 +53,398 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
|
51
53
|
* // @param {boolean} [options.shouldSkipRequiredValidationWhenColumnIsMissing(column: string, { object })] — By default, it does apply `required` validation to `schema` properties for which columns are missing in the input `data`. One could pass a custom `shouldSkipRequiredValidationWhenColumnIsMissing(column, { object })` to disable `required` validation for missing columns in some or all cases.
|
|
52
54
|
* @param {function} [options.transformEmptyObject(object, { path })] — By default, it returns `null` for an "empty" resulting object. One could override that value using `transformEmptyObject(object, { path })` parameter. The value applies to both top-level object and any nested sub-objects in case of a nested schema, hence the additional `path?: string` parameter.
|
|
53
55
|
* @param {function} [options.transformEmptyArray(array, { path })] — By default, it returns `null` for an "empty" array value. One could override that value using `transformEmptyArray(array, { path })` parameter.
|
|
54
|
-
* @param {string} [options.
|
|
55
|
-
* @return {object
|
|
56
|
+
* @param {string} [options.separatorCharacter] — When specified, string values will be split by this separator to get the array.
|
|
57
|
+
* @return {object} — An object of shape `{ objects, errors }`. Either `objects` or `errors` is going to be `undefined`.
|
|
56
58
|
*/
|
|
57
59
|
function parseData(data, schema, optionsCustom) {
|
|
60
|
+
var objects = [];
|
|
61
|
+
var errors = [];
|
|
62
|
+
var parsedRows = parseDataWithPerRowErrors(data, schema, optionsCustom);
|
|
63
|
+
for (var _iterator = _createForOfIteratorHelperLoose(parsedRows), _step; !(_step = _iterator()).done;) {
|
|
64
|
+
var _step$value = _step.value,
|
|
65
|
+
object = _step$value.object,
|
|
66
|
+
rowErrors = _step$value.errors;
|
|
67
|
+
if (rowErrors) {
|
|
68
|
+
errors = errors.concat(rowErrors);
|
|
69
|
+
} else {
|
|
70
|
+
objects.push(object);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (errors.length > 0) {
|
|
74
|
+
return {
|
|
75
|
+
errors: errors
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
objects: objects
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// This one is only used in tests.
|
|
84
|
+
function parseDataWithPerRowErrors(data, schema, optionsCustom) {
|
|
58
85
|
validateSchema(schema);
|
|
59
86
|
var options = applyDefaultOptions(optionsCustom);
|
|
60
87
|
var _data = _toArray(data),
|
|
61
88
|
columns = _data[0],
|
|
62
89
|
dataRows = _data.slice(1);
|
|
63
|
-
return dataRows.map(function (
|
|
64
|
-
return parseDataRow(
|
|
90
|
+
return dataRows.map(function (row) {
|
|
91
|
+
return parseDataRow(row, schema, columns, options);
|
|
65
92
|
});
|
|
66
93
|
}
|
|
67
|
-
function parseDataRow(
|
|
94
|
+
function parseDataRow(dataRow, schema, columns, options) {
|
|
95
|
+
// Create a `schemaEntry` for the top-level object.
|
|
96
|
+
var schemaEntry = {
|
|
97
|
+
schema: schema
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Parse the values in the given data row into an object.
|
|
101
|
+
var _parseProperty = parseProperty(dataRow, schemaEntry, undefined, columns, options),
|
|
102
|
+
value = _parseProperty.value,
|
|
103
|
+
isEmptyValue = _parseProperty.isEmptyValue,
|
|
104
|
+
errors = _parseProperty.errors,
|
|
105
|
+
children = _parseProperty.children;
|
|
106
|
+
|
|
107
|
+
// Simulate a "dummy" parent object for the top-level object.
|
|
108
|
+
// It will be used when running `required` validations.
|
|
109
|
+
var dummyParentObject = {
|
|
110
|
+
// The "dummy" parent object has a "dummy" value.
|
|
111
|
+
// This value is irrelevant because it won't be read anywhere.
|
|
112
|
+
value: PARSED_OBJECT_TREE_START,
|
|
113
|
+
// The "dummy" parent object is empty if the parsed row is empty.
|
|
114
|
+
isEmptyValue: isEmptyValue,
|
|
115
|
+
// The "dummy" object has the same errors as the parsed row.
|
|
116
|
+
errors: errors,
|
|
117
|
+
// The parsed object by default is not required to have any data
|
|
118
|
+
// so the "dummy" object is not required.
|
|
119
|
+
isRequired: undefined
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Run any `required` validations.
|
|
123
|
+
//
|
|
124
|
+
// `required` validations should be run after the entire data row has been parsed,
|
|
125
|
+
// i.e. when the entire object structure has been parsed.
|
|
126
|
+
// The reason is that a `required` validation could be either a simple boolean or a "complex" function.
|
|
127
|
+
// In the latter case, the result of a `required()` function may depend on any other property of the object,
|
|
128
|
+
// hence the actual `required` flag value could only be obtained after the entire data row has been parsed.
|
|
129
|
+
//
|
|
130
|
+
// For example, consider a top-level object:
|
|
131
|
+
//
|
|
132
|
+
// {
|
|
133
|
+
// firstName: string,
|
|
134
|
+
// lastName: string,
|
|
135
|
+
// pet?: { name: string }
|
|
136
|
+
// }
|
|
137
|
+
//
|
|
138
|
+
// A corresponding schema would be:
|
|
139
|
+
//
|
|
140
|
+
// {
|
|
141
|
+
// firstName: {
|
|
142
|
+
// required: true
|
|
143
|
+
// },
|
|
144
|
+
// lastName: {
|
|
145
|
+
// required: true
|
|
146
|
+
// },
|
|
147
|
+
// pet: {
|
|
148
|
+
// required: false,
|
|
149
|
+
// schema: {
|
|
150
|
+
// name: {
|
|
151
|
+
// required: true
|
|
152
|
+
// }
|
|
153
|
+
// }
|
|
154
|
+
// }
|
|
155
|
+
// }
|
|
156
|
+
//
|
|
157
|
+
// I.e. when a `pet` exists, it must have a `name`.
|
|
158
|
+
//
|
|
159
|
+
// In such case, the `required: true` check of the `pet`'s `name` property
|
|
160
|
+
// should not be performed if the `pet` is not present, because the `pet` nested object
|
|
161
|
+
// is marked as `required: false`, meaning that `pet` data is not required to be present.
|
|
162
|
+
//
|
|
163
|
+
var requiredErrors = runPendingRequiredValidations(schemaEntry, value, isEmptyValue, errors, children,
|
|
164
|
+
// Simulate a "dummy" parent object for the top-level object.
|
|
165
|
+
dummyParentObject.isRequired, dummyParentObject.value, dummyParentObject.isEmptyValue, dummyParentObject.errors);
|
|
166
|
+
|
|
167
|
+
// If there were any errors, whether caused by `required`
|
|
168
|
+
// or occured while parsing the values, return those errors.
|
|
169
|
+
if (errors || requiredErrors) {
|
|
170
|
+
return {
|
|
171
|
+
errors: (errors || []).concat(requiredErrors || [])
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Return the parsed object.
|
|
176
|
+
return {
|
|
177
|
+
object: transformValue(value, isEmptyValue, undefined, options)
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function parseObject(row, schema, path, columns, options) {
|
|
68
181
|
var object = {};
|
|
69
|
-
var errors = [];
|
|
70
182
|
var isEmptyObject = true;
|
|
71
|
-
var
|
|
183
|
+
var errors = [];
|
|
184
|
+
var children = [];
|
|
72
185
|
|
|
73
186
|
// For each property of the object.
|
|
74
187
|
for (var _i = 0, _Object$keys = Object.keys(schema); _i < _Object$keys.length; _i++) {
|
|
75
188
|
var key = _Object$keys[_i];
|
|
76
|
-
var
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
value = _parseProperty.value;
|
|
80
|
-
if (propertyErrors) {
|
|
81
|
-
errors = errors.concat(propertyErrors);
|
|
189
|
+
var child = parseProperty(row, schema[key], getPropertyPath(key, path), columns, options);
|
|
190
|
+
if (child.errors) {
|
|
191
|
+
errors = errors.concat(child.errors);
|
|
82
192
|
} else {
|
|
83
|
-
object[key] = value;
|
|
84
|
-
// Will perform `required` validation later, when all properties have been parsed.
|
|
85
|
-
if (pendingRequiredValidation) {
|
|
86
|
-
pendingRequiredValidations.push(pendingRequiredValidation);
|
|
87
|
-
}
|
|
193
|
+
object[key] = transformValue(child.value, child.isEmptyValue, getPropertyPath(key, path), options);
|
|
88
194
|
// Potentially unmark the object as "empty".
|
|
89
|
-
if (isEmptyObject && !isEmptyValue
|
|
195
|
+
if (isEmptyObject && !child.isEmptyValue) {
|
|
90
196
|
isEmptyObject = false;
|
|
91
197
|
}
|
|
92
198
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
var _pendingRequiredValid2 = _pendingRequiredValid[_i2],
|
|
98
|
-
required = _pendingRequiredValid2.required,
|
|
99
|
-
schemaEntry = _pendingRequiredValid2.schemaEntry,
|
|
100
|
-
_value = _pendingRequiredValid2.value;
|
|
101
|
-
if (required === true) {
|
|
102
|
-
errors.push(createError({
|
|
103
|
-
error: 'required',
|
|
104
|
-
schemaEntry: schemaEntry,
|
|
105
|
-
value: _value
|
|
106
|
-
}));
|
|
107
|
-
}
|
|
199
|
+
children.push(_objectSpread(_objectSpread({}, child), {}, {
|
|
200
|
+
// `schemaEntry` will be used when running `required` validation of this property (later),
|
|
201
|
+
schemaEntry: schema[key]
|
|
202
|
+
}));
|
|
108
203
|
}
|
|
109
204
|
|
|
110
205
|
// If there were any errors, return them.
|
|
111
206
|
if (errors.length > 0) {
|
|
112
207
|
return {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// Perform "complex" `required` validations (i.e. when `required` property is a function).
|
|
118
|
-
// These "complex" `required` validations should only be performed when all properties
|
|
119
|
-
// of an object have been parsed correctly because these validations rely on the values
|
|
120
|
-
// of other properties.
|
|
121
|
-
for (var _i3 = 0, _pendingRequiredValid3 = pendingRequiredValidations; _i3 < _pendingRequiredValid3.length; _i3++) {
|
|
122
|
-
var _pendingRequiredValid4 = _pendingRequiredValid3[_i3],
|
|
123
|
-
_required = _pendingRequiredValid4.required,
|
|
124
|
-
_schemaEntry = _pendingRequiredValid4.schemaEntry,
|
|
125
|
-
_value2 = _pendingRequiredValid4.value;
|
|
126
|
-
if (typeof _required !== 'boolean' && _required(object)) {
|
|
127
|
-
errors.push(createError({
|
|
128
|
-
error: 'required',
|
|
129
|
-
schemaEntry: _schemaEntry,
|
|
130
|
-
value: _value2
|
|
131
|
-
}));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// If there were any "complex" `required` errors, return them.
|
|
136
|
-
if (errors.length > 0) {
|
|
137
|
-
return {
|
|
138
|
-
errors: errors
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// Return `null` for an "empty" mapped object.
|
|
143
|
-
if (isEmptyObject) {
|
|
144
|
-
return {
|
|
145
|
-
object: options.transformEmptyObject(object, {
|
|
146
|
-
path: path
|
|
147
|
-
})
|
|
208
|
+
// Return the errors.
|
|
209
|
+
errors: errors,
|
|
210
|
+
// Return the `children` because `required` validations still have to be run (later).
|
|
211
|
+
children: children
|
|
148
212
|
};
|
|
149
213
|
}
|
|
150
214
|
return {
|
|
151
|
-
|
|
215
|
+
value: object,
|
|
216
|
+
isEmptyValue: isEmptyObject,
|
|
217
|
+
// Return the `children` because `required` validations still have to be run (later).
|
|
218
|
+
children: children
|
|
152
219
|
};
|
|
153
220
|
}
|
|
154
|
-
function parseProperty(
|
|
155
|
-
var schemaEntry = schema[key];
|
|
221
|
+
function parseProperty(row, schemaEntry, path, columns, options) {
|
|
156
222
|
var columnIndex = schemaEntry.column ? columns.indexOf(schemaEntry.column) : undefined;
|
|
157
|
-
var isMissingColumn = columnIndex < 0;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
223
|
+
var isMissingColumn = schemaEntry.column ? columnIndex < 0 : undefined;
|
|
224
|
+
var _ref = schemaEntry.column ? isMissingColumn ? {
|
|
225
|
+
value: options.propertyValueWhenColumnIsMissing,
|
|
226
|
+
isEmptyValue: true
|
|
227
|
+
} : parseCellValueWithPossibleErrors(row[columnIndex], schemaEntry, options) : parseObject(row, schemaEntry.schema, path, columns, options),
|
|
228
|
+
value = _ref.value,
|
|
229
|
+
isEmptyValue = _ref.isEmptyValue,
|
|
164
230
|
errors = _ref.errors,
|
|
165
|
-
|
|
231
|
+
children = _ref.children;
|
|
232
|
+
|
|
233
|
+
// If there were any errors, return them.
|
|
166
234
|
if (errors) {
|
|
167
235
|
return {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
// Should apply `required` validation if the value is "empty".
|
|
173
|
-
var pendingRequiredValidation;
|
|
174
|
-
if (schemaEntry.required && isEmptyValue(value)) {
|
|
175
|
-
// // Can optionally skip `required` validation for certain missing columns.
|
|
176
|
-
// const skipRequiredValidation = isMissingColumn && options.shouldSkipRequiredValidationWhenColumnIsMissing(schemaEntry.column, { object: ... })
|
|
177
|
-
// if (!skipRequiredValidation) { ... }
|
|
178
|
-
|
|
179
|
-
// Will perform `required` validation in the end,
|
|
180
|
-
// when all properties of the object have been parsed.
|
|
181
|
-
// This is because `required` could also be a function of `object`.
|
|
182
|
-
pendingRequiredValidation = {
|
|
183
|
-
required: schemaEntry.required,
|
|
184
|
-
schemaEntry: schemaEntry,
|
|
185
|
-
value: value
|
|
236
|
+
// Return the errors.
|
|
237
|
+
errors: errors,
|
|
238
|
+
// Return the `children` because `required` validations still have to be run (later).
|
|
239
|
+
children: children
|
|
186
240
|
};
|
|
187
241
|
}
|
|
188
242
|
return {
|
|
189
243
|
value: value,
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
function parseNestedObject(row, schema, propertyPath, columns, options) {
|
|
194
|
-
var _parseDataRow = parseDataRow(row, schema, propertyPath, columns, options),
|
|
195
|
-
object = _parseDataRow.object,
|
|
196
|
-
errors = _parseDataRow.errors;
|
|
197
|
-
return {
|
|
198
|
-
value: object,
|
|
199
|
-
errors: errors
|
|
244
|
+
isEmptyValue: isEmptyValue,
|
|
245
|
+
// Return the `children` because `required` validations still have to be run (later).
|
|
246
|
+
children: children
|
|
200
247
|
};
|
|
201
248
|
}
|
|
202
|
-
function
|
|
203
|
-
var
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
249
|
+
function parseCellValueWithPossibleErrors(cellValue, schemaEntry, options) {
|
|
250
|
+
var _parseCellValue = parseCellValue(cellValue, schemaEntry, options),
|
|
251
|
+
value = _parseCellValue.value,
|
|
252
|
+
isEmptyValue = _parseCellValue.isEmptyValue,
|
|
253
|
+
errorMessage = _parseCellValue.error,
|
|
254
|
+
errorReason = _parseCellValue.reason;
|
|
207
255
|
if (errorMessage) {
|
|
208
256
|
var error = createError({
|
|
209
|
-
schemaEntry: schemaEntry,
|
|
210
|
-
value: cellValue,
|
|
211
257
|
error: errorMessage,
|
|
212
|
-
reason:
|
|
258
|
+
reason: errorReason,
|
|
259
|
+
column: schemaEntry.column,
|
|
260
|
+
valueType: schemaEntry.type,
|
|
261
|
+
value: cellValue
|
|
213
262
|
});
|
|
214
263
|
return {
|
|
215
264
|
errors: [error]
|
|
216
265
|
};
|
|
217
|
-
} else {
|
|
218
|
-
return {
|
|
219
|
-
value: propertyValue
|
|
220
|
-
};
|
|
221
266
|
}
|
|
267
|
+
return {
|
|
268
|
+
value: value,
|
|
269
|
+
isEmptyValue: isEmptyValue
|
|
270
|
+
};
|
|
222
271
|
}
|
|
223
272
|
|
|
224
273
|
/**
|
|
225
274
|
* Converts a cell value value to a javascript typed value.
|
|
226
|
-
* @param {any}
|
|
275
|
+
* @param {any} cellValue
|
|
227
276
|
* @param {object} schemaEntry
|
|
228
277
|
* @param {string} propertyPath
|
|
229
278
|
* @param {object} options
|
|
230
|
-
* @return {{ value?: any, error
|
|
279
|
+
* @return {{ value?: any, isEmptyValue: boolean } | { error: string, reason?: string }}
|
|
231
280
|
*/
|
|
232
|
-
function
|
|
281
|
+
function parseCellValue(cellValue, schemaEntry, options) {
|
|
233
282
|
if (cellValue === undefined) {
|
|
234
283
|
// This isn't supposed to be possible when reading spreadsheet data:
|
|
235
284
|
// cell values are always read as `null` when those cells are empty.
|
|
236
285
|
// It's currently impossible for `read-excel-file` to return `undefined` cell value.
|
|
237
286
|
// Here it uses some "sensible default" fallback by treating `undefined` as "column missing".
|
|
238
287
|
return {
|
|
239
|
-
value: options.propertyValueWhenColumnIsMissing
|
|
288
|
+
value: options.propertyValueWhenColumnIsMissing,
|
|
289
|
+
isEmptyValue: true
|
|
240
290
|
};
|
|
241
291
|
}
|
|
242
292
|
if (cellValue === null) {
|
|
243
293
|
return {
|
|
244
|
-
value: options.propertyValueWhenCellIsEmpty
|
|
294
|
+
value: options.propertyValueWhenCellIsEmpty,
|
|
295
|
+
isEmptyValue: true
|
|
245
296
|
};
|
|
246
297
|
}
|
|
298
|
+
|
|
299
|
+
// Parse comma-separated cell value.
|
|
247
300
|
if (Array.isArray(schemaEntry.type)) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
301
|
+
return parseArrayValue(cellValue, schemaEntry, options);
|
|
302
|
+
}
|
|
303
|
+
return parseValue(cellValue, schemaEntry, options);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Converts textual value to a javascript typed array value.
|
|
308
|
+
* @param {any} value
|
|
309
|
+
* @param {object} schemaEntry
|
|
310
|
+
* @param {object} options
|
|
311
|
+
* @return {{ value?: any, isEmptyValue: boolean } | { error: string, reason?: string }}
|
|
312
|
+
*/
|
|
313
|
+
function parseArrayValue(value, schemaEntry, options) {
|
|
314
|
+
// If the cell value is not a string — i.e. a number, a boolean, a Date —
|
|
315
|
+
// then throw an error.
|
|
316
|
+
if (typeof value !== 'string') {
|
|
317
|
+
return {
|
|
318
|
+
error: 'not_a_string'
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
var isEmptyArray = true;
|
|
322
|
+
var errors = [];
|
|
323
|
+
var reasons = [];
|
|
324
|
+
var values = parseSeparatedSubstrings(value, options.separatorCharacter).map(function (substring) {
|
|
325
|
+
// If any substring was already detected to be invalid
|
|
326
|
+
// don't attempt to parse any other substrings.
|
|
273
327
|
if (errors.length > 0) {
|
|
274
|
-
return
|
|
275
|
-
error: errors[0],
|
|
276
|
-
reason: reasons[0]
|
|
277
|
-
};
|
|
328
|
+
return;
|
|
278
329
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
330
|
+
|
|
331
|
+
// If an empty substring was extracted, it means that there was an out-of-place separator.
|
|
332
|
+
if (!substring) {
|
|
333
|
+
errors.push('invalid');
|
|
334
|
+
reasons.push('syntax');
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
var _parseValue = parseValue(substring, schemaEntry, options),
|
|
338
|
+
value = _parseValue.value,
|
|
339
|
+
isEmptyValue = _parseValue.isEmptyValue,
|
|
340
|
+
error = _parseValue.error,
|
|
341
|
+
reason = _parseValue.reason;
|
|
342
|
+
if (error) {
|
|
343
|
+
errors.push(error);
|
|
344
|
+
reasons.push(reason);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
if (isEmptyArray && !isEmptyValue) {
|
|
348
|
+
isEmptyArray = false;
|
|
286
349
|
}
|
|
350
|
+
return value;
|
|
351
|
+
});
|
|
352
|
+
if (errors.length > 0) {
|
|
287
353
|
return {
|
|
288
|
-
|
|
354
|
+
error: errors[0],
|
|
355
|
+
reason: reasons[0]
|
|
289
356
|
};
|
|
290
357
|
}
|
|
291
|
-
return
|
|
358
|
+
return {
|
|
359
|
+
value: values,
|
|
360
|
+
isEmptyValue: isEmptyArray
|
|
361
|
+
};
|
|
292
362
|
}
|
|
293
363
|
|
|
294
364
|
/**
|
|
295
365
|
* Converts textual value to a javascript typed value.
|
|
296
366
|
* @param {any} value
|
|
297
367
|
* @param {object} schemaEntry
|
|
298
|
-
* @
|
|
368
|
+
* @param {object} options
|
|
369
|
+
* @return {{ value?: any, isEmptyValue: boolean } | { error: string }}
|
|
299
370
|
*/
|
|
300
371
|
function parseValue(value, schemaEntry, options) {
|
|
372
|
+
// `null` values (i.e. empty cells) don't get parsed.
|
|
301
373
|
if (value === null) {
|
|
302
374
|
return {
|
|
303
|
-
value: null
|
|
375
|
+
value: null,
|
|
376
|
+
isEmptyValue: true
|
|
304
377
|
};
|
|
305
378
|
}
|
|
379
|
+
|
|
380
|
+
// Parse the value according to the `type` that is specified in the schema entry.
|
|
306
381
|
var result;
|
|
307
382
|
if (schemaEntry.type) {
|
|
308
383
|
result = parseValueOfType(value,
|
|
309
|
-
//
|
|
310
|
-
//
|
|
384
|
+
// Get the type of the value.
|
|
385
|
+
//
|
|
386
|
+
// Handle the case if it's a comma-separated value.
|
|
311
387
|
// Example `type`: String[]
|
|
312
|
-
// Input: 'Barack Obama, "String, with, colons", Donald Trump'
|
|
313
|
-
//
|
|
388
|
+
// Example Input Value: 'Barack Obama, "String, with, colons", Donald Trump'
|
|
389
|
+
// Example Parsed Value: ['Barack Obama', 'String, with, colons', 'Donald Trump']
|
|
390
|
+
//
|
|
314
391
|
Array.isArray(schemaEntry.type) ? schemaEntry.type[0] : schemaEntry.type, options);
|
|
315
392
|
} else {
|
|
316
|
-
//
|
|
393
|
+
// If the `type` is not specified for a given schema entry, the default one is `String`.
|
|
317
394
|
result = {
|
|
318
395
|
value: value
|
|
319
396
|
};
|
|
320
397
|
// throw new Error('Invalid schema entry: no `type` specified:\n\n' + JSON.stringify(schemaEntry, null, 2))
|
|
321
398
|
}
|
|
322
399
|
|
|
323
|
-
// If
|
|
400
|
+
// If there was an error when parsing the value then return the error.
|
|
324
401
|
if (result.error) {
|
|
325
402
|
return result;
|
|
326
403
|
}
|
|
327
404
|
|
|
328
|
-
//
|
|
329
|
-
if (
|
|
330
|
-
|
|
331
|
-
|
|
405
|
+
// If the parsed value is empty, return it.
|
|
406
|
+
if (value === null) {
|
|
407
|
+
return {
|
|
408
|
+
value: null,
|
|
409
|
+
isEmptyValue: true
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Value is not empty.
|
|
414
|
+
// Validate it and return.
|
|
415
|
+
|
|
416
|
+
// Perform `oneOf` validation.
|
|
417
|
+
if (schemaEntry.oneOf) {
|
|
418
|
+
var errorAndReason = validateOneOf(result.value, schemaEntry.oneOf);
|
|
419
|
+
if (errorAndReason) {
|
|
420
|
+
return errorAndReason;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Perform `validate()` validation.
|
|
425
|
+
if (schemaEntry.validate) {
|
|
426
|
+
try {
|
|
427
|
+
schemaEntry.validate(result.value);
|
|
428
|
+
} catch (error) {
|
|
332
429
|
return {
|
|
333
|
-
error:
|
|
334
|
-
reason: 'unknown'
|
|
430
|
+
error: error.message
|
|
335
431
|
};
|
|
336
432
|
}
|
|
337
|
-
// Perform `validate()` validation.
|
|
338
|
-
if (schemaEntry.validate) {
|
|
339
|
-
try {
|
|
340
|
-
schemaEntry.validate(result.value);
|
|
341
|
-
} catch (error) {
|
|
342
|
-
return {
|
|
343
|
-
error: error.message
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
433
|
}
|
|
348
|
-
|
|
434
|
+
|
|
435
|
+
// Return the value.
|
|
436
|
+
return {
|
|
437
|
+
value: result.value,
|
|
438
|
+
isEmptyValue: isEmptyValue(result.value)
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
function validateOneOf(value, oneOf) {
|
|
442
|
+
if (oneOf.indexOf(value) < 0) {
|
|
443
|
+
return {
|
|
444
|
+
error: 'invalid',
|
|
445
|
+
reason: 'unknown'
|
|
446
|
+
};
|
|
447
|
+
}
|
|
349
448
|
}
|
|
350
449
|
|
|
351
450
|
/**
|
|
@@ -395,18 +494,22 @@ function parseValueUsingTypeParser(value, type) {
|
|
|
395
494
|
var result = {
|
|
396
495
|
error: error.message
|
|
397
496
|
};
|
|
497
|
+
// Built-in types such as `Number` or `Date` may also report
|
|
498
|
+
// a specific `reason` of the error.
|
|
398
499
|
if (error.reason) {
|
|
399
500
|
result.reason = error.reason;
|
|
400
501
|
}
|
|
401
502
|
return result;
|
|
402
503
|
}
|
|
403
504
|
}
|
|
404
|
-
|
|
505
|
+
|
|
506
|
+
// Extracts a substring from a string.
|
|
507
|
+
function getNextSubstring(string, separatorCharacter, startIndex) {
|
|
405
508
|
var i = 0;
|
|
406
509
|
var substring = '';
|
|
407
510
|
while (startIndex + i < string.length) {
|
|
408
511
|
var character = string[startIndex + i];
|
|
409
|
-
if (character ===
|
|
512
|
+
if (character === separatorCharacter) {
|
|
410
513
|
return [substring, i];
|
|
411
514
|
}
|
|
412
515
|
// Previously, it used to treat `"` character similar to how it's treated in `.csv` files:
|
|
@@ -433,27 +536,110 @@ function getNextSubstring(string, endCharacter, startIndex) {
|
|
|
433
536
|
* @param {string} string — A string of comma-separated substrings.
|
|
434
537
|
* @return {string[]} An array of substrings.
|
|
435
538
|
*/
|
|
436
|
-
function parseSeparatedSubstrings(string,
|
|
539
|
+
function parseSeparatedSubstrings(string, separatorCharacter) {
|
|
437
540
|
var elements = [];
|
|
438
541
|
var index = 0;
|
|
439
542
|
while (index < string.length) {
|
|
440
|
-
var _getNextSubstring = getNextSubstring(string,
|
|
543
|
+
var _getNextSubstring = getNextSubstring(string, separatorCharacter, index),
|
|
441
544
|
_getNextSubstring2 = _slicedToArray(_getNextSubstring, 2),
|
|
442
545
|
substring = _getNextSubstring2[0],
|
|
443
546
|
length = _getNextSubstring2[1];
|
|
444
|
-
index += length +
|
|
547
|
+
index += length + separatorCharacter.length;
|
|
445
548
|
elements.push(substring.trim());
|
|
446
549
|
}
|
|
447
550
|
return elements;
|
|
448
551
|
}
|
|
552
|
+
function transformValue(value, isEmptyValue, path, options) {
|
|
553
|
+
if (isEmptyValue) {
|
|
554
|
+
if (isObject(value)) {
|
|
555
|
+
return options.transformEmptyObject(value, {
|
|
556
|
+
path: path
|
|
557
|
+
});
|
|
558
|
+
} else if (Array.isArray(value)) {
|
|
559
|
+
return options.transformEmptyArray(value, {
|
|
560
|
+
path: path
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return value;
|
|
565
|
+
}
|
|
566
|
+
function getPropertyPath(propertyName, parentObjectPath) {
|
|
567
|
+
return "".concat(parentObjectPath ? parentObjectPath + '.' : '').concat(propertyName);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Recursively runs `required` validations for the parsed data row tree.
|
|
571
|
+
function runPendingRequiredValidations(schemaEntry, value, isEmptyValue, errors, children, parentObjectIsRequired, parentObjectValue, parentObjectValueIsEmpty, parentObjectErrors) {
|
|
572
|
+
var requiredErrors = [];
|
|
573
|
+
|
|
574
|
+
// See if this property is required.
|
|
575
|
+
var isRequired = isPropertyRequired(schemaEntry, parentObjectIsRequired, parentObjectValue, parentObjectValueIsEmpty, parentObjectErrors);
|
|
576
|
+
|
|
577
|
+
// If this property is required and empty, create a "required" error.
|
|
578
|
+
if (isRequired && isEmptyValue) {
|
|
579
|
+
requiredErrors.push(createError({
|
|
580
|
+
error: 'required',
|
|
581
|
+
column: schemaEntry.column,
|
|
582
|
+
valueType: schemaEntry.type,
|
|
583
|
+
value: value
|
|
584
|
+
}));
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Run `required` validations of the children.
|
|
588
|
+
if (children) {
|
|
589
|
+
for (var _iterator2 = _createForOfIteratorHelperLoose(children), _step2; !(_step2 = _iterator2()).done;) {
|
|
590
|
+
var child = _step2.value;
|
|
591
|
+
var requiredErrorsOfChild = runPendingRequiredValidations(child.schemaEntry, child.value, child.isEmptyValue, child.errors, child.children,
|
|
592
|
+
// The following properties describe the parent object of the `child`,
|
|
593
|
+
// i.e. the current (iterated) object.
|
|
594
|
+
isRequired, value, isEmptyValue, errors);
|
|
595
|
+
if (requiredErrorsOfChild) {
|
|
596
|
+
requiredErrors = requiredErrors.concat(requiredErrorsOfChild);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (requiredErrors.length > 0) {
|
|
601
|
+
return requiredErrors;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function isPropertyRequired(schemaEntry, parentObjectIsRequired, parentObjectValue, parentObjectValueIsEmpty, parentObjectErrors) {
|
|
605
|
+
// If the parent object is marked as `required: false` then it's allowed
|
|
606
|
+
// to be absent entirely from the input data. If that's the case,
|
|
607
|
+
// i.e. if the parent object is absent entirely from the input data,
|
|
608
|
+
// then any descendant properties of such object are allowed to be absent too,
|
|
609
|
+
// which means that they should also be considered being `required: false`.
|
|
610
|
+
//
|
|
611
|
+
// Also, if the parent object couldn't be parsed due to some non-`required` errors,
|
|
612
|
+
// it can't be known whether it's actually empty or not. In case of such uncertainty,
|
|
613
|
+
// the code shouldn't attempt to be overly smart and do things that might not be necessary,
|
|
614
|
+
// so such parent object is just assumed to be empty in order to not falsly trigger
|
|
615
|
+
// any `required` validations that otherwise wouldn't have been run.
|
|
616
|
+
// In other words, skipping some `required` validations is better than
|
|
617
|
+
// running `required` validations that shouldn't have been run.
|
|
618
|
+
//
|
|
619
|
+
if (parentObjectIsRequired === false && (parentObjectValueIsEmpty || parentObjectErrors)) {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
return schemaEntry.required && (typeof schemaEntry.required === 'boolean' ? schemaEntry.required :
|
|
623
|
+
// If there were any non-`required` errors when parsing the parent object,
|
|
624
|
+
// the `parentObject` will be `undefined`. In that case, "complex" `required()`
|
|
625
|
+
// validations — the ones where `required` is a function — can't really be run
|
|
626
|
+
// because those validations assume a fully and correctly parsed parent object
|
|
627
|
+
// be passed as an argument, and the thing is that the `parentObject` is unknown.
|
|
628
|
+
// As a result, only "basic" `required` validations could be run,
|
|
629
|
+
// i.e. the ones where `required` is just a boolean, and "complex" `required`
|
|
630
|
+
// validations, i.e. the ones where `required` is a functions, should be skipped,
|
|
631
|
+
// because it's better to skip some `required` errors than to trigger falsy ones.
|
|
632
|
+
parentObjectErrors ? false : schemaEntry.required(parentObjectValue));
|
|
633
|
+
}
|
|
449
634
|
function createError(_ref2) {
|
|
450
|
-
var
|
|
635
|
+
var column = _ref2.column,
|
|
636
|
+
valueType = _ref2.valueType,
|
|
451
637
|
value = _ref2.value,
|
|
452
638
|
errorMessage = _ref2.error,
|
|
453
639
|
reason = _ref2.reason;
|
|
454
640
|
var error = {
|
|
455
641
|
error: errorMessage,
|
|
456
|
-
column:
|
|
642
|
+
column: column,
|
|
457
643
|
value: value
|
|
458
644
|
};
|
|
459
645
|
if (reason) {
|
|
@@ -461,14 +647,14 @@ function createError(_ref2) {
|
|
|
461
647
|
}
|
|
462
648
|
// * Regular values specify a `type?` property, which is included in the `error` object.
|
|
463
649
|
// * Nested objects specify a `schema` property, which is not included in the `error` object.
|
|
464
|
-
if (
|
|
465
|
-
error.type =
|
|
650
|
+
if (valueType) {
|
|
651
|
+
error.type = valueType;
|
|
466
652
|
}
|
|
467
653
|
return error;
|
|
468
654
|
}
|
|
469
655
|
function validateSchema(schema) {
|
|
470
|
-
for (var
|
|
471
|
-
var key = _Object$keys2[
|
|
656
|
+
for (var _i2 = 0, _Object$keys2 = Object.keys(schema); _i2 < _Object$keys2.length; _i2++) {
|
|
657
|
+
var key = _Object$keys2[_i2];
|
|
472
658
|
var schemaEntry = schema[key];
|
|
473
659
|
// Validate that the `schema` is not using a deprecated `type: nestedSchema` format.
|
|
474
660
|
if (_typeof(schemaEntry.type) === 'object' && !Array.isArray(schemaEntry.type)) {
|
|
@@ -481,6 +667,30 @@ function validateSchema(schema) {
|
|
|
481
667
|
}
|
|
482
668
|
}
|
|
483
669
|
}
|
|
670
|
+
|
|
671
|
+
// A nested object could have a `required` property but the only allowed value is `false`.
|
|
672
|
+
// The reason why `true` value is not allowed is because in case of a "required" error
|
|
673
|
+
// there's no single column title corresponding to such nested object, and column title
|
|
674
|
+
// is required to create a "required" error.
|
|
675
|
+
validateObjectSchemaRequiredProperty(schema, undefined);
|
|
676
|
+
}
|
|
677
|
+
function validateObjectSchemaRequiredProperty(schema, required) {
|
|
678
|
+
if (required !== undefined && required !== false) {
|
|
679
|
+
throw new Error("In a schema, a nested object can have a `required` property but the only allowed value is `undefined` or `false`. Otherwise, a \"required\" error for a nested object would have to include a specific `column` title and a nested object doesn't have one. You've specified the following `required`: ".concat(required));
|
|
680
|
+
}
|
|
681
|
+
// For each property of the described object.
|
|
682
|
+
for (var _i3 = 0, _Object$keys3 = Object.keys(schema); _i3 < _Object$keys3.length; _i3++) {
|
|
683
|
+
var key = _Object$keys3[_i3];
|
|
684
|
+
// If this property is itself an object.
|
|
685
|
+
if (isObject(schema[key].schema)) {
|
|
686
|
+
// Validate that a `column` property can't coexist with a `schema` property.
|
|
687
|
+
if (schema[key].column) {
|
|
688
|
+
throw new Error("In a schema, `column` property is only allowed when describing a property value rather than a nested object. Key: ".concat(key, ". Schema:\n").concat(JSON.stringify(schema[key], null, 2)));
|
|
689
|
+
}
|
|
690
|
+
// Recurse into the child object.
|
|
691
|
+
validateObjectSchemaRequiredProperty(schema[key].schema, schema[key].required);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
484
694
|
}
|
|
485
695
|
function isEmptyValue(value) {
|
|
486
696
|
return value === undefined || value === null;
|
|
@@ -497,7 +707,7 @@ var DEFAULT_OPTIONS = {
|
|
|
497
707
|
transformEmptyArray: function transformEmptyArray() {
|
|
498
708
|
return null;
|
|
499
709
|
},
|
|
500
|
-
|
|
710
|
+
separatorCharacter: ','
|
|
501
711
|
};
|
|
502
712
|
function applyDefaultOptions(options) {
|
|
503
713
|
if (options) {
|
|
@@ -506,4 +716,11 @@ function applyDefaultOptions(options) {
|
|
|
506
716
|
return DEFAULT_OPTIONS;
|
|
507
717
|
}
|
|
508
718
|
}
|
|
719
|
+
|
|
720
|
+
// This `value` marks the start of a tree structure that is parsed from a given data row.
|
|
721
|
+
var PARSED_OBJECT_TREE_START = {};
|
|
722
|
+
var objectConstructor = {}.constructor;
|
|
723
|
+
function isObject(object) {
|
|
724
|
+
return object !== undefined && object !== null && object.constructor === objectConstructor;
|
|
725
|
+
}
|
|
509
726
|
//# sourceMappingURL=parseData.js.map
|