@sanity/validation 3.0.0-v3-pkg-utils.54 → 3.0.0-v3-pkg-utils.59
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/lib/index.cjs +656 -378
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +646 -377
- package/lib/index.js.map +1 -1
- package/package.json +5 -4
- package/src/validateDocument.test.ts +6 -0
- package/src/validateDocument.ts +1 -0
package/lib/index.cjs
CHANGED
|
@@ -1,22 +1,44 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const _excluded = ["value", "type", "path", "parent"];
|
|
4
|
+
|
|
5
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
6
|
+
|
|
7
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
8
|
+
|
|
9
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
10
|
+
|
|
11
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
12
|
+
|
|
13
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
14
|
+
|
|
15
|
+
Object.defineProperty(exports, '__esModule', {
|
|
16
|
+
value: true
|
|
17
|
+
});
|
|
4
18
|
|
|
5
19
|
var lodash = require('lodash');
|
|
20
|
+
|
|
6
21
|
var types = require('@sanity/types');
|
|
22
|
+
|
|
7
23
|
var formatDate = require('date-fns/format');
|
|
8
24
|
|
|
9
|
-
function _interopDefaultLegacy
|
|
25
|
+
function _interopDefaultLegacy(e) {
|
|
26
|
+
return e && typeof e === 'object' && 'default' in e ? e : {
|
|
27
|
+
'default': e
|
|
28
|
+
};
|
|
29
|
+
}
|
|
10
30
|
|
|
11
31
|
var formatDate__default = /*#__PURE__*/_interopDefaultLegacy(formatDate);
|
|
12
32
|
|
|
13
33
|
const ValidationError = class ValidationError2 {
|
|
14
|
-
constructor(message
|
|
34
|
+
constructor(message) {
|
|
35
|
+
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
15
36
|
this.message = message;
|
|
16
37
|
this.paths = options.paths || [];
|
|
17
38
|
this.children = options.children;
|
|
18
39
|
this.operation = options.operation;
|
|
19
40
|
}
|
|
41
|
+
|
|
20
42
|
cloneWithMessage(msg) {
|
|
21
43
|
return new ValidationError2(msg, {
|
|
22
44
|
paths: this.paths,
|
|
@@ -24,94 +46,98 @@ const ValidationError = class ValidationError2 {
|
|
|
24
46
|
operation: this.operation
|
|
25
47
|
});
|
|
26
48
|
}
|
|
49
|
+
|
|
27
50
|
};
|
|
28
51
|
|
|
29
|
-
var escapeRegex =
|
|
52
|
+
var escapeRegex = string => {
|
|
30
53
|
return string.replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, "\\$&");
|
|
31
54
|
};
|
|
32
55
|
|
|
33
|
-
function pathToString(
|
|
56
|
+
function pathToString() {
|
|
57
|
+
let path = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
34
58
|
return path.reduce((target, segment, i) => {
|
|
35
59
|
const segmentType = typeof segment;
|
|
60
|
+
|
|
36
61
|
if (segmentType === "number") {
|
|
37
|
-
return
|
|
62
|
+
return "".concat(target, "[").concat(segment, "]");
|
|
38
63
|
}
|
|
64
|
+
|
|
39
65
|
if (segmentType === "string") {
|
|
40
66
|
const separator = i === 0 ? "" : ".";
|
|
41
|
-
return
|
|
67
|
+
return "".concat(target).concat(separator).concat(segment);
|
|
42
68
|
}
|
|
69
|
+
|
|
43
70
|
if (types.isKeyedObject(segment)) {
|
|
44
|
-
return
|
|
71
|
+
return "".concat(target, "[_key==\"").concat(segment._key, "\"]");
|
|
45
72
|
}
|
|
46
|
-
|
|
73
|
+
|
|
74
|
+
throw new Error("Unsupported path segment \"".concat(segment, "\""));
|
|
47
75
|
}, "");
|
|
48
76
|
}
|
|
49
77
|
|
|
50
78
|
function isNonNullable$1(t) {
|
|
51
79
|
return t !== null || t !== void 0;
|
|
52
80
|
}
|
|
81
|
+
|
|
53
82
|
function convertToValidationMarker(validatorResult, level, context) {
|
|
54
83
|
var _a;
|
|
84
|
+
|
|
55
85
|
if (!context) {
|
|
56
86
|
throw new Error("missing context");
|
|
57
87
|
}
|
|
58
|
-
|
|
59
|
-
|
|
88
|
+
|
|
89
|
+
if (validatorResult === true) return [];
|
|
90
|
+
|
|
60
91
|
if (Array.isArray(validatorResult)) {
|
|
61
|
-
return validatorResult.flatMap(
|
|
92
|
+
return validatorResult.flatMap(child => convertToValidationMarker(child, level, context)).filter(isNonNullable$1);
|
|
62
93
|
}
|
|
94
|
+
|
|
63
95
|
if (typeof validatorResult === "string") {
|
|
64
96
|
return convertToValidationMarker(new ValidationError(validatorResult), level, context);
|
|
65
97
|
}
|
|
98
|
+
|
|
66
99
|
if (!(validatorResult instanceof ValidationError)) {
|
|
67
100
|
if (typeof (validatorResult == null ? void 0 : validatorResult.message) !== "string") {
|
|
68
|
-
throw new Error(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
return convertToValidationMarker(
|
|
75
|
-
new ValidationError(validatorResult.message, validatorResult),
|
|
76
|
-
level,
|
|
77
|
-
context
|
|
78
|
-
);
|
|
101
|
+
throw new Error("".concat(pathToString(context.path), ": Validator must return 'true' if valid or an error message as a string on errors"));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return convertToValidationMarker(new ValidationError(validatorResult.message, validatorResult), level, context);
|
|
79
105
|
}
|
|
106
|
+
|
|
80
107
|
const results = [];
|
|
108
|
+
|
|
81
109
|
if (!((_a = validatorResult.paths) == null ? void 0 : _a.length)) {
|
|
82
|
-
return [
|
|
83
|
-
{
|
|
84
|
-
level: level || "error",
|
|
85
|
-
item: validatorResult,
|
|
86
|
-
path: context.path || []
|
|
87
|
-
}
|
|
88
|
-
];
|
|
89
|
-
}
|
|
90
|
-
return results.concat(
|
|
91
|
-
validatorResult.paths.map((path) => ({
|
|
92
|
-
path: (context.path || []).concat(path),
|
|
110
|
+
return [{
|
|
93
111
|
level: level || "error",
|
|
94
|
-
item: validatorResult
|
|
95
|
-
|
|
96
|
-
|
|
112
|
+
item: validatorResult,
|
|
113
|
+
path: context.path || []
|
|
114
|
+
}];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return results.concat(validatorResult.paths.map(path => ({
|
|
118
|
+
path: (context.path || []).concat(path),
|
|
119
|
+
level: level || "error",
|
|
120
|
+
item: validatorResult
|
|
121
|
+
})));
|
|
97
122
|
}
|
|
98
123
|
|
|
99
124
|
const _toString = {}.toString;
|
|
100
125
|
const builtIns = [Object, Function, Array, String, Boolean, Number, Date, RegExp, Error];
|
|
126
|
+
|
|
101
127
|
function isBuiltIn(_constructor) {
|
|
102
128
|
for (let i = 0; i < builtIns.length; i++) {
|
|
103
|
-
if (builtIns[i] === _constructor)
|
|
104
|
-
return true;
|
|
129
|
+
if (builtIns[i] === _constructor) return true;
|
|
105
130
|
}
|
|
131
|
+
|
|
106
132
|
return false;
|
|
107
133
|
}
|
|
134
|
+
|
|
108
135
|
function typeString(obj) {
|
|
109
136
|
const stringType = _toString.call(obj).slice(8, -1);
|
|
110
|
-
|
|
111
|
-
|
|
137
|
+
|
|
138
|
+
if (obj === null || obj === void 0) return stringType.toLowerCase();
|
|
112
139
|
const constructorType = obj.constructor;
|
|
113
|
-
if (constructorType && !isBuiltIn(constructorType))
|
|
114
|
-
return constructorType.name;
|
|
140
|
+
if (constructorType && !isBuiltIn(constructorType)) return constructorType.name;
|
|
115
141
|
return stringType;
|
|
116
142
|
}
|
|
117
143
|
|
|
@@ -119,93 +145,116 @@ function deepEquals(a, b) {
|
|
|
119
145
|
if (a === b) {
|
|
120
146
|
return true;
|
|
121
147
|
}
|
|
148
|
+
|
|
122
149
|
if (Array.isArray(a) && Array.isArray(b)) {
|
|
123
|
-
if (a.length != b.length)
|
|
124
|
-
|
|
150
|
+
if (a.length != b.length) return false;
|
|
151
|
+
|
|
125
152
|
for (let i = 0; i < a.length; i++) {
|
|
126
153
|
if (!deepEquals(a[i], b[i])) {
|
|
127
154
|
return false;
|
|
128
155
|
}
|
|
129
156
|
}
|
|
157
|
+
|
|
130
158
|
return true;
|
|
131
159
|
}
|
|
160
|
+
|
|
132
161
|
if (Array.isArray(a) != Array.isArray(b)) {
|
|
133
162
|
return false;
|
|
134
163
|
}
|
|
164
|
+
|
|
135
165
|
if (a && b && typeof a === "object" && typeof b === "object") {
|
|
136
166
|
const keys = Object.keys(a);
|
|
167
|
+
|
|
137
168
|
if (keys.length !== Object.keys(b).length) {
|
|
138
169
|
return false;
|
|
139
170
|
}
|
|
171
|
+
|
|
140
172
|
if (a instanceof Date && b instanceof Date) {
|
|
141
173
|
return a.getTime() === b.getTime();
|
|
142
174
|
}
|
|
175
|
+
|
|
143
176
|
if (a instanceof Date != b instanceof Date) {
|
|
144
177
|
return false;
|
|
145
178
|
}
|
|
179
|
+
|
|
146
180
|
if (a instanceof RegExp && b instanceof RegExp) {
|
|
147
181
|
return a.toString() == b.toString();
|
|
148
182
|
}
|
|
183
|
+
|
|
149
184
|
if (a instanceof RegExp != b instanceof RegExp) {
|
|
150
185
|
return false;
|
|
151
186
|
}
|
|
187
|
+
|
|
152
188
|
for (let i = 0; i < keys.length; i++) {
|
|
153
189
|
if (keys[i] === "_key") {
|
|
154
190
|
continue;
|
|
155
191
|
}
|
|
192
|
+
|
|
156
193
|
if (!Object.prototype.hasOwnProperty.call(b, keys[i])) {
|
|
157
194
|
return false;
|
|
158
195
|
}
|
|
159
196
|
}
|
|
197
|
+
|
|
160
198
|
for (let i = 0; i < keys.length; i++) {
|
|
161
199
|
const key = keys[i];
|
|
200
|
+
|
|
162
201
|
if (key === "_key") {
|
|
163
202
|
continue;
|
|
164
203
|
}
|
|
204
|
+
|
|
165
205
|
if (!deepEquals(a[key], b[key])) {
|
|
166
206
|
return false;
|
|
167
207
|
}
|
|
168
208
|
}
|
|
209
|
+
|
|
169
210
|
return true;
|
|
170
211
|
}
|
|
212
|
+
|
|
171
213
|
return false;
|
|
172
214
|
}
|
|
173
215
|
|
|
174
216
|
const SLOW_VALIDATOR_TIMEOUT = 5e3;
|
|
175
|
-
|
|
217
|
+
|
|
218
|
+
const formatValidationErrors = options => {
|
|
176
219
|
var _a;
|
|
220
|
+
|
|
177
221
|
let message;
|
|
222
|
+
|
|
178
223
|
if (options.message) {
|
|
179
224
|
message = options.message;
|
|
180
225
|
} else if (options.results.length === 1) {
|
|
181
226
|
message = (_a = options.results[0]) == null ? void 0 : _a.item.message;
|
|
182
227
|
} else {
|
|
183
|
-
message =
|
|
228
|
+
message = "[".concat(options.results.map(err => err.item.message).join(" - ".concat(options.operation, " - ")), "]");
|
|
184
229
|
}
|
|
230
|
+
|
|
185
231
|
return new ValidationError(message, {
|
|
186
232
|
children: options.results.length > 1 ? options.results : void 0,
|
|
187
233
|
operation: options.operation
|
|
188
234
|
});
|
|
189
235
|
};
|
|
236
|
+
|
|
190
237
|
const genericValidators = {
|
|
191
238
|
type: (expected, value, message) => {
|
|
192
239
|
const actualType = typeString(value);
|
|
240
|
+
|
|
193
241
|
if (actualType !== expected && actualType !== "undefined") {
|
|
194
|
-
return message ||
|
|
242
|
+
return message || "Expected type \"".concat(expected, "\", got \"").concat(actualType, "\"");
|
|
195
243
|
}
|
|
244
|
+
|
|
196
245
|
return true;
|
|
197
246
|
},
|
|
198
247
|
presence: (expected, value, message) => {
|
|
199
248
|
if (value === void 0 && expected === "required") {
|
|
200
249
|
return message || "Value is required";
|
|
201
250
|
}
|
|
251
|
+
|
|
202
252
|
return true;
|
|
203
253
|
},
|
|
204
254
|
all: async (children, value, message, context) => {
|
|
205
|
-
const resolved = await Promise.all(children.map(
|
|
255
|
+
const resolved = await Promise.all(children.map(child => child.validate(value, context)));
|
|
206
256
|
const results = resolved.flat();
|
|
207
|
-
if (!results.length)
|
|
208
|
-
return true;
|
|
257
|
+
if (!results.length) return true;
|
|
209
258
|
return formatValidationErrors({
|
|
210
259
|
message,
|
|
211
260
|
results,
|
|
@@ -213,10 +262,9 @@ const genericValidators = {
|
|
|
213
262
|
});
|
|
214
263
|
},
|
|
215
264
|
either: async (children, value, message, context) => {
|
|
216
|
-
const resolved = await Promise.all(children.map(
|
|
265
|
+
const resolved = await Promise.all(children.map(child => child.validate(value, context)));
|
|
217
266
|
const results = resolved.flat();
|
|
218
|
-
if (results.length < children.length)
|
|
219
|
-
return true;
|
|
267
|
+
if (results.length < children.length) return true;
|
|
220
268
|
return formatValidationErrors({
|
|
221
269
|
message,
|
|
222
270
|
results,
|
|
@@ -225,368 +273,461 @@ const genericValidators = {
|
|
|
225
273
|
},
|
|
226
274
|
valid: (allowedValues, actual, message) => {
|
|
227
275
|
const valueType = typeof actual;
|
|
276
|
+
|
|
228
277
|
if (valueType === "undefined") {
|
|
229
278
|
return true;
|
|
230
279
|
}
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
const
|
|
234
|
-
|
|
280
|
+
|
|
281
|
+
const value = (valueType === "number" || valueType === "string") && "".concat(actual);
|
|
282
|
+
const strValue = value && value.length > 30 ? "".concat(value.slice(0, 30), "\u2026") : value;
|
|
283
|
+
const defaultMessage = value ? "Value \"".concat(strValue, "\" did not match any allowed values") : "Value did not match any allowed values";
|
|
284
|
+
return allowedValues.some(expected => deepEquals(expected, actual)) ? true : message || defaultMessage;
|
|
235
285
|
},
|
|
236
286
|
custom: async (fn, value, message, context) => {
|
|
237
287
|
const slowTimer = setTimeout(() => {
|
|
238
|
-
console.warn(
|
|
239
|
-
`Custom validator at ${pathToString(
|
|
240
|
-
context.path
|
|
241
|
-
)} has taken more than ${SLOW_VALIDATOR_TIMEOUT}ms to respond`
|
|
242
|
-
);
|
|
288
|
+
console.warn("Custom validator at ".concat(pathToString(context.path), " has taken more than ").concat(SLOW_VALIDATOR_TIMEOUT, "ms to respond"));
|
|
243
289
|
}, SLOW_VALIDATOR_TIMEOUT);
|
|
244
290
|
let result;
|
|
291
|
+
|
|
245
292
|
try {
|
|
246
293
|
result = await fn(value, context);
|
|
247
294
|
} finally {
|
|
248
295
|
clearTimeout(slowTimer);
|
|
249
296
|
}
|
|
250
|
-
|
|
251
|
-
|
|
297
|
+
|
|
298
|
+
if (typeof result === "string") return message || result;
|
|
252
299
|
return result;
|
|
253
300
|
}
|
|
254
301
|
};
|
|
255
302
|
|
|
256
|
-
const booleanValidators = {
|
|
257
|
-
...genericValidators,
|
|
303
|
+
const booleanValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
258
304
|
presence: (flag, value, message) => {
|
|
259
305
|
if (flag === "required" && typeof value !== "boolean") {
|
|
260
306
|
return message || "Required";
|
|
261
307
|
}
|
|
308
|
+
|
|
262
309
|
return true;
|
|
263
310
|
}
|
|
264
|
-
};
|
|
311
|
+
});
|
|
265
312
|
|
|
266
313
|
const precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
|
|
267
|
-
|
|
268
|
-
|
|
314
|
+
|
|
315
|
+
const numberValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
269
316
|
integer: (_unused, value, message) => {
|
|
270
317
|
if (!Number.isInteger(value)) {
|
|
271
318
|
return message || "Must be an integer";
|
|
272
319
|
}
|
|
320
|
+
|
|
273
321
|
return true;
|
|
274
322
|
},
|
|
275
323
|
precision: (limit, value, message) => {
|
|
276
|
-
if (value === void 0)
|
|
277
|
-
return true;
|
|
324
|
+
if (value === void 0) return true;
|
|
278
325
|
const places = value.toString().match(precisionRx);
|
|
279
|
-
const decimals = Math.max(
|
|
280
|
-
|
|
281
|
-
0
|
|
282
|
-
);
|
|
326
|
+
const decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0);
|
|
327
|
+
|
|
283
328
|
if (decimals > limit) {
|
|
284
|
-
return message ||
|
|
329
|
+
return message || "Max precision is ".concat(limit);
|
|
285
330
|
}
|
|
331
|
+
|
|
286
332
|
return true;
|
|
287
333
|
},
|
|
288
334
|
min: (minNum, value, message) => {
|
|
289
335
|
if (value >= minNum) {
|
|
290
336
|
return true;
|
|
291
337
|
}
|
|
292
|
-
|
|
338
|
+
|
|
339
|
+
return message || "Must be greater than or equal ".concat(minNum);
|
|
293
340
|
},
|
|
294
341
|
max: (maxNum, value, message) => {
|
|
295
342
|
if (value <= maxNum) {
|
|
296
343
|
return true;
|
|
297
344
|
}
|
|
298
|
-
|
|
345
|
+
|
|
346
|
+
return message || "Must be less than or equal ".concat(maxNum);
|
|
299
347
|
},
|
|
300
348
|
greaterThan: (num, value, message) => {
|
|
301
349
|
if (value > num) {
|
|
302
350
|
return true;
|
|
303
351
|
}
|
|
304
|
-
|
|
352
|
+
|
|
353
|
+
return message || "Must be greater than ".concat(num);
|
|
305
354
|
},
|
|
306
355
|
lessThan: (maxNum, value, message) => {
|
|
307
356
|
if (value < maxNum) {
|
|
308
357
|
return true;
|
|
309
358
|
}
|
|
310
|
-
|
|
359
|
+
|
|
360
|
+
return message || "Must be less than ".concat(maxNum);
|
|
311
361
|
}
|
|
312
|
-
};
|
|
362
|
+
});
|
|
313
363
|
|
|
314
364
|
const DUMMY_ORIGIN = "http://sanity";
|
|
315
365
|
const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
366
|
+
|
|
367
|
+
const isRelativeUrl = url => /^\.*\//.test(url);
|
|
368
|
+
|
|
369
|
+
const stringValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
319
370
|
min: (minLength, value, message) => {
|
|
320
371
|
if (!value || value.length >= minLength) {
|
|
321
372
|
return true;
|
|
322
373
|
}
|
|
323
|
-
|
|
374
|
+
|
|
375
|
+
return message || "Must be at least ".concat(minLength, " characters long");
|
|
324
376
|
},
|
|
325
377
|
max: (maxLength, value, message) => {
|
|
326
378
|
if (!value || value.length <= maxLength) {
|
|
327
379
|
return true;
|
|
328
380
|
}
|
|
329
|
-
|
|
381
|
+
|
|
382
|
+
return message || "Must be at most ".concat(maxLength, " characters long");
|
|
330
383
|
},
|
|
331
384
|
length: (wantedLength, value, message) => {
|
|
332
385
|
const strValue = value || "";
|
|
386
|
+
|
|
333
387
|
if (strValue.length === wantedLength) {
|
|
334
388
|
return true;
|
|
335
389
|
}
|
|
336
|
-
|
|
390
|
+
|
|
391
|
+
return message || "Must be exactly ".concat(wantedLength, " characters long");
|
|
337
392
|
},
|
|
338
393
|
uri: (constraints, value, message) => {
|
|
339
394
|
const strValue = value || "";
|
|
340
|
-
const {
|
|
341
|
-
|
|
395
|
+
const {
|
|
396
|
+
options
|
|
397
|
+
} = constraints;
|
|
398
|
+
const {
|
|
399
|
+
allowCredentials,
|
|
400
|
+
relativeOnly
|
|
401
|
+
} = options;
|
|
342
402
|
const allowRelative = options.allowRelative || relativeOnly;
|
|
343
403
|
let url;
|
|
404
|
+
|
|
344
405
|
try {
|
|
345
406
|
url = allowRelative ? new URL(strValue, DUMMY_ORIGIN) : new URL(strValue);
|
|
346
407
|
} catch (err) {
|
|
347
408
|
return message || "Not a valid URL";
|
|
348
409
|
}
|
|
410
|
+
|
|
349
411
|
if (relativeOnly && url.origin !== DUMMY_ORIGIN) {
|
|
350
412
|
return message || "Only relative URLs are allowed";
|
|
351
413
|
}
|
|
414
|
+
|
|
352
415
|
if (!allowRelative && url.origin === DUMMY_ORIGIN && isRelativeUrl(strValue)) {
|
|
353
416
|
return message || "Relative URLs are not allowed";
|
|
354
417
|
}
|
|
418
|
+
|
|
355
419
|
if (!allowCredentials && (url.username || url.password)) {
|
|
356
|
-
return message ||
|
|
420
|
+
return message || "Username/password not allowed";
|
|
357
421
|
}
|
|
422
|
+
|
|
358
423
|
const urlScheme = url.protocol.replace(/:$/, "");
|
|
359
|
-
const matchesAllowedScheme = options.scheme.some(
|
|
424
|
+
const matchesAllowedScheme = options.scheme.some(scheme => scheme.test(urlScheme));
|
|
425
|
+
|
|
360
426
|
if (!matchesAllowedScheme) {
|
|
361
427
|
return message || "Does not match allowed protocols/schemes";
|
|
362
428
|
}
|
|
429
|
+
|
|
363
430
|
return true;
|
|
364
431
|
},
|
|
365
432
|
stringCasing: (casing, value, message) => {
|
|
366
433
|
const strValue = value || "";
|
|
434
|
+
|
|
367
435
|
if (casing === "uppercase" && strValue !== strValue.toLocaleUpperCase()) {
|
|
368
|
-
return message ||
|
|
436
|
+
return message || "Must be all uppercase letters";
|
|
369
437
|
}
|
|
438
|
+
|
|
370
439
|
if (casing === "lowercase" && strValue !== strValue.toLocaleLowerCase()) {
|
|
371
|
-
return message ||
|
|
440
|
+
return message || "Must be all lowercase letters";
|
|
372
441
|
}
|
|
442
|
+
|
|
373
443
|
return true;
|
|
374
444
|
},
|
|
375
445
|
presence: (flag, value, message) => {
|
|
376
446
|
if (flag === "required" && !value) {
|
|
377
447
|
return message || "Required";
|
|
378
448
|
}
|
|
449
|
+
|
|
379
450
|
return true;
|
|
380
451
|
},
|
|
381
452
|
regex: (options, value, message) => {
|
|
382
|
-
const {
|
|
383
|
-
|
|
453
|
+
const {
|
|
454
|
+
pattern,
|
|
455
|
+
name,
|
|
456
|
+
invert
|
|
457
|
+
} = options;
|
|
458
|
+
const regName = name || "\"".concat(pattern.toString(), "\"");
|
|
384
459
|
const strValue = value || "";
|
|
385
460
|
const matches = pattern.test(strValue);
|
|
461
|
+
|
|
386
462
|
if (!invert && !matches || invert && matches) {
|
|
387
|
-
const defaultMessage = invert ?
|
|
463
|
+
const defaultMessage = invert ? "Should not match ".concat(regName, "-pattern") : "Does not match ".concat(regName, "-pattern");
|
|
388
464
|
return message || defaultMessage;
|
|
389
465
|
}
|
|
466
|
+
|
|
390
467
|
return true;
|
|
391
468
|
},
|
|
392
469
|
email: (_unused, value, message) => {
|
|
393
|
-
const strValue =
|
|
470
|
+
const strValue = "".concat(value || "").trim();
|
|
471
|
+
|
|
394
472
|
if (!strValue || emailRegex.test(strValue)) {
|
|
395
473
|
return true;
|
|
396
474
|
}
|
|
475
|
+
|
|
397
476
|
return message || "Must be a valid email address";
|
|
398
477
|
}
|
|
399
|
-
};
|
|
478
|
+
});
|
|
400
479
|
|
|
401
|
-
const arrayValidators = {
|
|
402
|
-
...genericValidators,
|
|
480
|
+
const arrayValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
403
481
|
min: (minLength, value, message) => {
|
|
404
482
|
if (!value || value.length >= minLength) {
|
|
405
483
|
return true;
|
|
406
484
|
}
|
|
407
|
-
|
|
485
|
+
|
|
486
|
+
return message || "Must have at least ".concat(minLength, " items");
|
|
408
487
|
},
|
|
409
488
|
max: (maxLength, value, message) => {
|
|
410
489
|
if (!value || value.length <= maxLength) {
|
|
411
490
|
return true;
|
|
412
491
|
}
|
|
413
|
-
|
|
492
|
+
|
|
493
|
+
return message || "Must have at most ".concat(maxLength, " items");
|
|
414
494
|
},
|
|
415
495
|
length: (wantedLength, value, message) => {
|
|
416
496
|
if (!value || value.length === wantedLength) {
|
|
417
497
|
return true;
|
|
418
498
|
}
|
|
419
|
-
|
|
499
|
+
|
|
500
|
+
return message || "Must have exactly ".concat(wantedLength, " items");
|
|
420
501
|
},
|
|
421
502
|
presence: (flag, value, message) => {
|
|
422
503
|
if (flag === "required" && !value) {
|
|
423
504
|
return message || "Required";
|
|
424
505
|
}
|
|
506
|
+
|
|
425
507
|
return true;
|
|
426
508
|
},
|
|
427
509
|
valid: (allowedValues, values, message) => {
|
|
428
510
|
const valueType = typeof values;
|
|
511
|
+
|
|
429
512
|
if (valueType === "undefined") {
|
|
430
513
|
return true;
|
|
431
514
|
}
|
|
515
|
+
|
|
432
516
|
const paths = [];
|
|
517
|
+
|
|
433
518
|
for (let i = 0; i < values.length; i++) {
|
|
434
519
|
const value = values[i];
|
|
435
|
-
|
|
520
|
+
|
|
521
|
+
if (allowedValues.some(expected => deepEquals(expected, value))) {
|
|
436
522
|
continue;
|
|
437
523
|
}
|
|
438
|
-
|
|
524
|
+
|
|
525
|
+
const pathSegment = value && value._key ? {
|
|
526
|
+
_key: value._key
|
|
527
|
+
} : i;
|
|
439
528
|
paths.push([pathSegment]);
|
|
440
529
|
}
|
|
441
|
-
|
|
530
|
+
|
|
531
|
+
return paths.length === 0 ? true : new ValidationError(message || "Value did not match any allowed values", {
|
|
532
|
+
paths
|
|
533
|
+
});
|
|
442
534
|
},
|
|
443
535
|
unique: (_unused, value, message) => {
|
|
444
536
|
const dupeIndices = [];
|
|
537
|
+
|
|
445
538
|
if (!value) {
|
|
446
539
|
return true;
|
|
447
540
|
}
|
|
541
|
+
|
|
448
542
|
for (let x = 0; x < value.length; x++) {
|
|
449
543
|
for (let y = x + 1; y < value.length; y++) {
|
|
450
544
|
const itemA = value[x];
|
|
451
545
|
const itemB = value[y];
|
|
546
|
+
|
|
452
547
|
if (!deepEquals(itemA, itemB)) {
|
|
453
548
|
continue;
|
|
454
549
|
}
|
|
550
|
+
|
|
455
551
|
if (dupeIndices.indexOf(x) === -1) {
|
|
456
552
|
dupeIndices.push(x);
|
|
457
553
|
}
|
|
554
|
+
|
|
458
555
|
if (dupeIndices.indexOf(y) === -1) {
|
|
459
556
|
dupeIndices.push(y);
|
|
460
557
|
}
|
|
461
558
|
}
|
|
462
559
|
}
|
|
463
|
-
|
|
560
|
+
|
|
561
|
+
const paths = dupeIndices.map(idx => {
|
|
464
562
|
const item = value[idx];
|
|
465
|
-
const pathSegment = item && item._key ? {
|
|
563
|
+
const pathSegment = item && item._key ? {
|
|
564
|
+
_key: item._key
|
|
565
|
+
} : idx;
|
|
466
566
|
return [pathSegment];
|
|
467
567
|
});
|
|
468
|
-
return dupeIndices.length > 0 ? new ValidationError(message ||
|
|
568
|
+
return dupeIndices.length > 0 ? new ValidationError(message || "Can't be a duplicate", {
|
|
569
|
+
paths
|
|
570
|
+
}) : true;
|
|
469
571
|
}
|
|
470
|
-
};
|
|
572
|
+
});
|
|
471
573
|
|
|
472
574
|
const metaKeys = ["_key", "_type", "_weak"];
|
|
473
|
-
|
|
474
|
-
|
|
575
|
+
|
|
576
|
+
const objectValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
475
577
|
presence: (expected, value, message) => {
|
|
476
578
|
if (expected !== "required") {
|
|
477
579
|
return true;
|
|
478
580
|
}
|
|
479
|
-
|
|
581
|
+
|
|
582
|
+
const keys = value && Object.keys(value).filter(key => !metaKeys.includes(key));
|
|
583
|
+
|
|
480
584
|
if (value === void 0 || keys && keys.length === 0) {
|
|
481
585
|
return message || "Required";
|
|
482
586
|
}
|
|
587
|
+
|
|
483
588
|
return true;
|
|
484
589
|
},
|
|
485
590
|
reference: async (_unused, value, message, context) => {
|
|
486
591
|
if (!value) {
|
|
487
592
|
return true;
|
|
488
593
|
}
|
|
594
|
+
|
|
489
595
|
if (!types.isReference(value)) {
|
|
490
596
|
return message || true;
|
|
491
597
|
}
|
|
492
|
-
|
|
598
|
+
|
|
599
|
+
const {
|
|
600
|
+
type,
|
|
601
|
+
getDocumentExists
|
|
602
|
+
} = context;
|
|
603
|
+
|
|
493
604
|
if (!type) {
|
|
494
|
-
throw new Error(
|
|
605
|
+
throw new Error("`type` was not provided in validation context");
|
|
495
606
|
}
|
|
607
|
+
|
|
496
608
|
if ("weak" in type && type.weak) {
|
|
497
609
|
return true;
|
|
498
610
|
}
|
|
611
|
+
|
|
499
612
|
if (!getDocumentExists) {
|
|
500
|
-
throw new Error(
|
|
613
|
+
throw new Error("`getDocumentExists` was not provided in validation context");
|
|
501
614
|
}
|
|
502
|
-
|
|
615
|
+
|
|
616
|
+
const exists = await getDocumentExists({
|
|
617
|
+
id: value._ref
|
|
618
|
+
});
|
|
619
|
+
|
|
503
620
|
if (!exists) {
|
|
504
621
|
return "This reference must be published";
|
|
505
622
|
}
|
|
623
|
+
|
|
506
624
|
return true;
|
|
507
625
|
},
|
|
508
626
|
assetRequired: (flag, value, message) => {
|
|
509
627
|
if (!value || !value.asset || !value.asset._ref) {
|
|
510
628
|
const assetType = flag.assetType || "Asset";
|
|
511
|
-
return message ||
|
|
629
|
+
return message || "".concat(assetType, " required");
|
|
512
630
|
}
|
|
631
|
+
|
|
513
632
|
return true;
|
|
514
633
|
}
|
|
515
|
-
};
|
|
634
|
+
});
|
|
516
635
|
|
|
517
636
|
function isRecord$1(obj) {
|
|
518
637
|
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
519
638
|
}
|
|
639
|
+
|
|
520
640
|
const isoDate = /^(?:[-+]\d{2})?(?:\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?![T]$|[T][\d]+Z$)(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24:?00)(?:[.,]\d+(?!:))?)(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[Z]|(?:[+-])(?:[01]\d|2[0-3])(?::?[0-5]\d)?)?)?)?$/;
|
|
521
|
-
|
|
641
|
+
|
|
642
|
+
const getFormattedDate = function () {
|
|
643
|
+
let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "";
|
|
644
|
+
let value = arguments.length > 1 ? arguments[1] : undefined;
|
|
645
|
+
let options = arguments.length > 2 ? arguments[2] : undefined;
|
|
522
646
|
let format = "yyyy-MM-dd";
|
|
647
|
+
|
|
523
648
|
if (options && options.dateFormat) {
|
|
524
649
|
format = options.dateFormat;
|
|
525
650
|
}
|
|
651
|
+
|
|
526
652
|
if (type === "date") {
|
|
527
653
|
return formatDate__default["default"](new Date(value), format);
|
|
528
654
|
}
|
|
655
|
+
|
|
529
656
|
if (options && options.timeFormat) {
|
|
530
|
-
format +=
|
|
657
|
+
format += " ".concat(options.timeFormat);
|
|
531
658
|
} else {
|
|
532
659
|
format += " HH:mm";
|
|
533
660
|
}
|
|
661
|
+
|
|
534
662
|
return formatDate__default["default"](new Date(value), format);
|
|
535
663
|
};
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (date
|
|
540
|
-
|
|
664
|
+
|
|
665
|
+
function parseDate(date) {
|
|
666
|
+
let throwOnError = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
667
|
+
if (!date) return null;
|
|
668
|
+
if (date === "now") return new Date();
|
|
541
669
|
const parsed = new Date(date);
|
|
542
670
|
const isInvalid = isNaN(parsed.getTime());
|
|
671
|
+
|
|
543
672
|
if (isInvalid && throwOnError) {
|
|
544
|
-
throw new Error(
|
|
673
|
+
throw new Error("Unable to parse \"".concat(date, "\" to a date"));
|
|
545
674
|
}
|
|
675
|
+
|
|
546
676
|
return isInvalid ? null : parsed;
|
|
547
677
|
}
|
|
548
|
-
|
|
549
|
-
|
|
678
|
+
|
|
679
|
+
const dateValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
|
|
550
680
|
type: (_unused, value, message) => {
|
|
551
|
-
const strVal =
|
|
681
|
+
const strVal = "".concat(value);
|
|
682
|
+
|
|
552
683
|
if (!strVal || isoDate.test(value)) {
|
|
553
684
|
return true;
|
|
554
685
|
}
|
|
686
|
+
|
|
555
687
|
return message || "Must be a valid ISO-8601 formatted date string";
|
|
556
688
|
},
|
|
557
689
|
min: (minDate, value, message, context) => {
|
|
558
690
|
const dateVal = parseDate(value);
|
|
691
|
+
|
|
559
692
|
if (!dateVal) {
|
|
560
693
|
return true;
|
|
561
694
|
}
|
|
695
|
+
|
|
562
696
|
if (!value || dateVal >= parseDate(minDate, true)) {
|
|
563
697
|
return true;
|
|
564
698
|
}
|
|
699
|
+
|
|
565
700
|
if (!context.type) {
|
|
566
|
-
throw new Error(
|
|
701
|
+
throw new Error("`type` was not provided in validation context.");
|
|
567
702
|
}
|
|
703
|
+
|
|
568
704
|
const dateTimeOptions = isRecord$1(context.type.options) ? context.type.options : {};
|
|
569
705
|
const date = getFormattedDate(context.type.name, minDate, dateTimeOptions);
|
|
570
|
-
return message ||
|
|
706
|
+
return message || "Must be at or after ".concat(date);
|
|
571
707
|
},
|
|
572
708
|
max: (maxDate, value, message, context) => {
|
|
573
709
|
const dateVal = parseDate(value);
|
|
710
|
+
|
|
574
711
|
if (!dateVal) {
|
|
575
712
|
return true;
|
|
576
713
|
}
|
|
714
|
+
|
|
577
715
|
if (!value || dateVal <= parseDate(maxDate, true)) {
|
|
578
716
|
return true;
|
|
579
717
|
}
|
|
718
|
+
|
|
580
719
|
if (!context.type) {
|
|
581
|
-
throw new Error(
|
|
720
|
+
throw new Error("`type` was not provided in validation context.");
|
|
582
721
|
}
|
|
722
|
+
|
|
583
723
|
const dateTimeOptions = isRecord$1(context.type.options) ? context.type.options : {};
|
|
584
724
|
const date = getFormattedDate(context.type.name, maxDate, dateTimeOptions);
|
|
585
|
-
return message ||
|
|
725
|
+
return message || "Must be at or before ".concat(date);
|
|
586
726
|
}
|
|
587
|
-
};
|
|
727
|
+
});
|
|
588
728
|
|
|
589
729
|
var _a;
|
|
730
|
+
|
|
590
731
|
const typeValidators = {
|
|
591
732
|
Boolean: booleanValidators,
|
|
592
733
|
Number: numberValidators,
|
|
@@ -595,24 +736,19 @@ const typeValidators = {
|
|
|
595
736
|
Object: objectValidators,
|
|
596
737
|
Date: dateValidators
|
|
597
738
|
};
|
|
598
|
-
|
|
739
|
+
|
|
740
|
+
const getBaseType = type => {
|
|
599
741
|
return type && type.type ? getBaseType(type.type) : type;
|
|
600
742
|
};
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
743
|
+
|
|
744
|
+
const isFieldRef = constraint => {
|
|
745
|
+
if (typeof constraint !== "object" || !constraint) return false;
|
|
604
746
|
return constraint.type === Rule.FIELD_REF;
|
|
605
747
|
};
|
|
748
|
+
|
|
606
749
|
const EMPTY_ARRAY = [];
|
|
607
750
|
const FIELD_REF = Symbol("FIELD_REF");
|
|
608
|
-
const ruleConstraintTypes$1 = [
|
|
609
|
-
"Array",
|
|
610
|
-
"Boolean",
|
|
611
|
-
"Date",
|
|
612
|
-
"Number",
|
|
613
|
-
"Object",
|
|
614
|
-
"String"
|
|
615
|
-
];
|
|
751
|
+
const ruleConstraintTypes$1 = ["Array", "Boolean", "Date", "Number", "Object", "String"];
|
|
616
752
|
const Rule = (_a = class {
|
|
617
753
|
constructor(typeDef) {
|
|
618
754
|
this._type = void 0;
|
|
@@ -626,43 +762,48 @@ const Rule = (_a = class {
|
|
|
626
762
|
this._typeDef = typeDef;
|
|
627
763
|
this.reset();
|
|
628
764
|
}
|
|
765
|
+
|
|
629
766
|
_mergeRequired(next) {
|
|
630
|
-
if (this._required === "required" || next._required === "required")
|
|
631
|
-
|
|
632
|
-
if (this._required === "optional" || next._required === "optional")
|
|
633
|
-
return "optional";
|
|
767
|
+
if (this._required === "required" || next._required === "required") return "required";
|
|
768
|
+
if (this._required === "optional" || next._required === "optional") return "optional";
|
|
634
769
|
return void 0;
|
|
635
770
|
}
|
|
771
|
+
|
|
636
772
|
error(message) {
|
|
637
773
|
const rule = this.clone();
|
|
638
774
|
rule._level = "error";
|
|
639
775
|
rule._message = message || void 0;
|
|
640
776
|
return rule;
|
|
641
777
|
}
|
|
778
|
+
|
|
642
779
|
warning(message) {
|
|
643
780
|
const rule = this.clone();
|
|
644
781
|
rule._level = "warning";
|
|
645
782
|
rule._message = message || void 0;
|
|
646
783
|
return rule;
|
|
647
784
|
}
|
|
785
|
+
|
|
648
786
|
info(message) {
|
|
649
787
|
const rule = this.clone();
|
|
650
788
|
rule._level = "info";
|
|
651
789
|
rule._message = message || void 0;
|
|
652
790
|
return rule;
|
|
653
791
|
}
|
|
792
|
+
|
|
654
793
|
reset() {
|
|
655
794
|
this._type = this._type || void 0;
|
|
656
|
-
this._rules = (this._rules || []).filter(
|
|
795
|
+
this._rules = (this._rules || []).filter(rule => rule.flag === "type");
|
|
657
796
|
this._message = void 0;
|
|
658
797
|
this._required = void 0;
|
|
659
798
|
this._level = "error";
|
|
660
799
|
this._fieldRules = void 0;
|
|
661
800
|
return this;
|
|
662
801
|
}
|
|
802
|
+
|
|
663
803
|
isRequired() {
|
|
664
804
|
return this._required === "required";
|
|
665
805
|
}
|
|
806
|
+
|
|
666
807
|
clone() {
|
|
667
808
|
const rule = new _a();
|
|
668
809
|
rule._type = this._type;
|
|
@@ -674,26 +815,30 @@ const Rule = (_a = class {
|
|
|
674
815
|
rule._typeDef = this._typeDef;
|
|
675
816
|
return rule;
|
|
676
817
|
}
|
|
818
|
+
|
|
677
819
|
cloneWithRules(rules) {
|
|
678
820
|
const rule = this.clone();
|
|
679
|
-
const newRules = /* @__PURE__ */
|
|
680
|
-
rules.forEach(
|
|
821
|
+
const newRules = /* @__PURE__ */new Set();
|
|
822
|
+
rules.forEach(curr => {
|
|
681
823
|
if (curr.flag === "type") {
|
|
682
824
|
rule._type = curr.constraint;
|
|
683
825
|
}
|
|
826
|
+
|
|
684
827
|
newRules.add(curr.flag);
|
|
685
828
|
});
|
|
686
|
-
rule._rules = rule._rules.filter(
|
|
829
|
+
rule._rules = rule._rules.filter(curr => {
|
|
687
830
|
const disallowDuplicate = ["type", "uri", "email"].includes(curr.flag);
|
|
688
831
|
const isDuplicate = newRules.has(curr.flag);
|
|
689
832
|
return !(disallowDuplicate && isDuplicate);
|
|
690
833
|
}).concat(rules);
|
|
691
834
|
return rule;
|
|
692
835
|
}
|
|
836
|
+
|
|
693
837
|
merge(rule) {
|
|
694
838
|
if (this._type && rule._type && this._type !== rule._type) {
|
|
695
839
|
throw new Error("merge() failed: conflicting types");
|
|
696
840
|
}
|
|
841
|
+
|
|
697
842
|
const newRule = this.cloneWithRules(rule._rules);
|
|
698
843
|
newRule._type = this._type || rule._type;
|
|
699
844
|
newRule._message = this._message || rule._message;
|
|
@@ -701,76 +846,155 @@ const Rule = (_a = class {
|
|
|
701
846
|
newRule._level = this._level === "error" ? rule._level : this._level;
|
|
702
847
|
return newRule;
|
|
703
848
|
}
|
|
849
|
+
|
|
704
850
|
type(targetType) {
|
|
705
|
-
const type =
|
|
851
|
+
const type = "".concat(targetType.slice(0, 1).toUpperCase()).concat(targetType.slice(1));
|
|
852
|
+
|
|
706
853
|
if (!ruleConstraintTypes$1.includes(type)) {
|
|
707
|
-
throw new Error(
|
|
854
|
+
throw new Error("Unknown type \"".concat(targetType, "\""));
|
|
708
855
|
}
|
|
709
|
-
|
|
856
|
+
|
|
857
|
+
const rule = this.cloneWithRules([{
|
|
858
|
+
flag: "type",
|
|
859
|
+
constraint: type
|
|
860
|
+
}]);
|
|
710
861
|
rule._type = type;
|
|
711
862
|
return rule;
|
|
712
863
|
}
|
|
864
|
+
|
|
713
865
|
all(children) {
|
|
714
|
-
return this.cloneWithRules([{
|
|
866
|
+
return this.cloneWithRules([{
|
|
867
|
+
flag: "all",
|
|
868
|
+
constraint: children
|
|
869
|
+
}]);
|
|
715
870
|
}
|
|
871
|
+
|
|
716
872
|
either(children) {
|
|
717
|
-
return this.cloneWithRules([{
|
|
873
|
+
return this.cloneWithRules([{
|
|
874
|
+
flag: "either",
|
|
875
|
+
constraint: children
|
|
876
|
+
}]);
|
|
718
877
|
}
|
|
878
|
+
|
|
719
879
|
optional() {
|
|
720
|
-
const rule = this.cloneWithRules([{
|
|
880
|
+
const rule = this.cloneWithRules([{
|
|
881
|
+
flag: "presence",
|
|
882
|
+
constraint: "optional"
|
|
883
|
+
}]);
|
|
721
884
|
rule._required = "optional";
|
|
722
885
|
return rule;
|
|
723
886
|
}
|
|
887
|
+
|
|
724
888
|
required() {
|
|
725
|
-
const rule = this.cloneWithRules([{
|
|
889
|
+
const rule = this.cloneWithRules([{
|
|
890
|
+
flag: "presence",
|
|
891
|
+
constraint: "required"
|
|
892
|
+
}]);
|
|
726
893
|
rule._required = "required";
|
|
727
894
|
return rule;
|
|
728
895
|
}
|
|
896
|
+
|
|
729
897
|
custom(fn) {
|
|
730
|
-
return this.cloneWithRules([{
|
|
898
|
+
return this.cloneWithRules([{
|
|
899
|
+
flag: "custom",
|
|
900
|
+
constraint: fn
|
|
901
|
+
}]);
|
|
731
902
|
}
|
|
903
|
+
|
|
732
904
|
block(fn) {
|
|
733
|
-
return this.cloneWithRules([{
|
|
905
|
+
return this.cloneWithRules([{
|
|
906
|
+
flag: "custom",
|
|
907
|
+
constraint: fn
|
|
908
|
+
}]);
|
|
734
909
|
}
|
|
910
|
+
|
|
735
911
|
min(len) {
|
|
736
|
-
return this.cloneWithRules([{
|
|
912
|
+
return this.cloneWithRules([{
|
|
913
|
+
flag: "min",
|
|
914
|
+
constraint: len
|
|
915
|
+
}]);
|
|
737
916
|
}
|
|
917
|
+
|
|
738
918
|
max(len) {
|
|
739
|
-
return this.cloneWithRules([{
|
|
919
|
+
return this.cloneWithRules([{
|
|
920
|
+
flag: "max",
|
|
921
|
+
constraint: len
|
|
922
|
+
}]);
|
|
740
923
|
}
|
|
924
|
+
|
|
741
925
|
length(len) {
|
|
742
|
-
return this.cloneWithRules([{
|
|
926
|
+
return this.cloneWithRules([{
|
|
927
|
+
flag: "length",
|
|
928
|
+
constraint: len
|
|
929
|
+
}]);
|
|
743
930
|
}
|
|
931
|
+
|
|
744
932
|
valid(value) {
|
|
745
933
|
const values = Array.isArray(value) ? value : [value];
|
|
746
|
-
return this.cloneWithRules([{
|
|
934
|
+
return this.cloneWithRules([{
|
|
935
|
+
flag: "valid",
|
|
936
|
+
constraint: values
|
|
937
|
+
}]);
|
|
747
938
|
}
|
|
939
|
+
|
|
748
940
|
integer() {
|
|
749
|
-
return this.cloneWithRules([{
|
|
941
|
+
return this.cloneWithRules([{
|
|
942
|
+
flag: "integer"
|
|
943
|
+
}]);
|
|
750
944
|
}
|
|
945
|
+
|
|
751
946
|
precision(limit) {
|
|
752
|
-
return this.cloneWithRules([{
|
|
947
|
+
return this.cloneWithRules([{
|
|
948
|
+
flag: "precision",
|
|
949
|
+
constraint: limit
|
|
950
|
+
}]);
|
|
753
951
|
}
|
|
952
|
+
|
|
754
953
|
positive() {
|
|
755
|
-
return this.cloneWithRules([{
|
|
954
|
+
return this.cloneWithRules([{
|
|
955
|
+
flag: "min",
|
|
956
|
+
constraint: 0
|
|
957
|
+
}]);
|
|
756
958
|
}
|
|
959
|
+
|
|
757
960
|
negative() {
|
|
758
|
-
return this.cloneWithRules([{
|
|
961
|
+
return this.cloneWithRules([{
|
|
962
|
+
flag: "lessThan",
|
|
963
|
+
constraint: 0
|
|
964
|
+
}]);
|
|
759
965
|
}
|
|
966
|
+
|
|
760
967
|
greaterThan(num) {
|
|
761
|
-
return this.cloneWithRules([{
|
|
968
|
+
return this.cloneWithRules([{
|
|
969
|
+
flag: "greaterThan",
|
|
970
|
+
constraint: num
|
|
971
|
+
}]);
|
|
762
972
|
}
|
|
973
|
+
|
|
763
974
|
lessThan(num) {
|
|
764
|
-
return this.cloneWithRules([{
|
|
975
|
+
return this.cloneWithRules([{
|
|
976
|
+
flag: "lessThan",
|
|
977
|
+
constraint: num
|
|
978
|
+
}]);
|
|
765
979
|
}
|
|
980
|
+
|
|
766
981
|
uppercase() {
|
|
767
|
-
return this.cloneWithRules([{
|
|
982
|
+
return this.cloneWithRules([{
|
|
983
|
+
flag: "stringCasing",
|
|
984
|
+
constraint: "uppercase"
|
|
985
|
+
}]);
|
|
768
986
|
}
|
|
987
|
+
|
|
769
988
|
lowercase() {
|
|
770
|
-
return this.cloneWithRules([{
|
|
989
|
+
return this.cloneWithRules([{
|
|
990
|
+
flag: "stringCasing",
|
|
991
|
+
constraint: "lowercase"
|
|
992
|
+
}]);
|
|
771
993
|
}
|
|
994
|
+
|
|
772
995
|
regex(pattern, a, b) {
|
|
773
996
|
var _a2, _b;
|
|
997
|
+
|
|
774
998
|
const name = typeof a === "string" ? a : (_a2 = a == null ? void 0 : a.name) != null ? _a2 : b == null ? void 0 : b.name;
|
|
775
999
|
const invert = typeof a === "string" ? false : (_b = a == null ? void 0 : a.invert) != null ? _b : b == null ? void 0 : b.invert;
|
|
776
1000
|
const constraint = {
|
|
@@ -778,175 +1002,226 @@ const Rule = (_a = class {
|
|
|
778
1002
|
name,
|
|
779
1003
|
invert: invert || false
|
|
780
1004
|
};
|
|
781
|
-
return this.cloneWithRules([{
|
|
1005
|
+
return this.cloneWithRules([{
|
|
1006
|
+
flag: "regex",
|
|
1007
|
+
constraint
|
|
1008
|
+
}]);
|
|
782
1009
|
}
|
|
1010
|
+
|
|
783
1011
|
email() {
|
|
784
|
-
return this.cloneWithRules([{
|
|
1012
|
+
return this.cloneWithRules([{
|
|
1013
|
+
flag: "email"
|
|
1014
|
+
}]);
|
|
785
1015
|
}
|
|
1016
|
+
|
|
786
1017
|
uri(opts) {
|
|
787
1018
|
const optsScheme = (opts == null ? void 0 : opts.scheme) || ["http", "https"];
|
|
788
1019
|
const schemes = Array.isArray(optsScheme) ? optsScheme : [optsScheme];
|
|
1020
|
+
|
|
789
1021
|
if (!schemes.length) {
|
|
790
1022
|
throw new Error("scheme must have at least 1 scheme specified");
|
|
791
1023
|
}
|
|
1024
|
+
|
|
792
1025
|
const constraint = {
|
|
793
1026
|
options: {
|
|
794
|
-
scheme: schemes.map(
|
|
1027
|
+
scheme: schemes.map(scheme => {
|
|
795
1028
|
if (!(scheme instanceof RegExp) && typeof scheme !== "string") {
|
|
796
1029
|
throw new Error("scheme must be a RegExp or a String");
|
|
797
1030
|
}
|
|
798
|
-
|
|
1031
|
+
|
|
1032
|
+
return typeof scheme === "string" ? new RegExp("^".concat(escapeRegex(scheme), "$")) : scheme;
|
|
799
1033
|
}),
|
|
800
1034
|
allowRelative: (opts == null ? void 0 : opts.allowRelative) || false,
|
|
801
1035
|
relativeOnly: (opts == null ? void 0 : opts.relativeOnly) || false,
|
|
802
1036
|
allowCredentials: (opts == null ? void 0 : opts.allowCredentials) || false
|
|
803
1037
|
}
|
|
804
1038
|
};
|
|
805
|
-
return this.cloneWithRules([{
|
|
1039
|
+
return this.cloneWithRules([{
|
|
1040
|
+
flag: "uri",
|
|
1041
|
+
constraint
|
|
1042
|
+
}]);
|
|
806
1043
|
}
|
|
1044
|
+
|
|
807
1045
|
unique() {
|
|
808
|
-
return this.cloneWithRules([{
|
|
1046
|
+
return this.cloneWithRules([{
|
|
1047
|
+
flag: "unique"
|
|
1048
|
+
}]);
|
|
809
1049
|
}
|
|
1050
|
+
|
|
810
1051
|
reference() {
|
|
811
|
-
return this.cloneWithRules([{
|
|
1052
|
+
return this.cloneWithRules([{
|
|
1053
|
+
flag: "reference"
|
|
1054
|
+
}]);
|
|
812
1055
|
}
|
|
1056
|
+
|
|
813
1057
|
fields(rules) {
|
|
814
1058
|
if (this._type !== "Object") {
|
|
815
1059
|
throw new Error("fields() can only be called on an object type");
|
|
816
1060
|
}
|
|
1061
|
+
|
|
817
1062
|
const rule = this.cloneWithRules([]);
|
|
818
1063
|
rule._fieldRules = rules;
|
|
819
1064
|
return rule;
|
|
820
1065
|
}
|
|
1066
|
+
|
|
821
1067
|
assetRequired() {
|
|
822
1068
|
const base = getBaseType(this._typeDef);
|
|
823
1069
|
let assetType;
|
|
1070
|
+
|
|
824
1071
|
if (base && ["image", "file"].includes(base.name)) {
|
|
825
1072
|
assetType = base.name === "image" ? "Image" : "File";
|
|
826
1073
|
} else {
|
|
827
1074
|
assetType = "Asset";
|
|
828
1075
|
}
|
|
829
|
-
|
|
1076
|
+
|
|
1077
|
+
return this.cloneWithRules([{
|
|
1078
|
+
flag: "assetRequired",
|
|
1079
|
+
constraint: {
|
|
1080
|
+
assetType
|
|
1081
|
+
}
|
|
1082
|
+
}]);
|
|
830
1083
|
}
|
|
1084
|
+
|
|
831
1085
|
async validate(value, context) {
|
|
832
1086
|
if (!context) {
|
|
833
1087
|
throw new Error("missing context");
|
|
834
1088
|
}
|
|
1089
|
+
|
|
835
1090
|
const valueIsEmpty = value === null || value === void 0;
|
|
1091
|
+
|
|
836
1092
|
if (valueIsEmpty && this._required === "optional") {
|
|
837
1093
|
return EMPTY_ARRAY;
|
|
838
1094
|
}
|
|
839
|
-
|
|
1095
|
+
|
|
1096
|
+
const rules = this._required === void 0 && valueIsEmpty ? this._rules.filter(curr => curr.flag === "custom") : this._rules;
|
|
840
1097
|
const validators = this._type && typeValidators[this._type] || genericValidators;
|
|
841
|
-
const results = await Promise.all(
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1098
|
+
const results = await Promise.all(rules.map(async curr => {
|
|
1099
|
+
if (curr.flag === void 0) {
|
|
1100
|
+
throw new Error('Invalid rule, did not contain "flag"-property');
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
const validator = validators[curr.flag];
|
|
1104
|
+
|
|
1105
|
+
if (!validator) {
|
|
1106
|
+
const forType = this._type ? "type \"".concat(this._type, "\"") : "rule without declared type";
|
|
1107
|
+
throw new Error("Validator for flag \"".concat(curr.flag, "\" not found for ").concat(forType));
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
let specConstraint = "constraint" in curr ? curr.constraint : null;
|
|
1111
|
+
|
|
1112
|
+
if (isFieldRef(specConstraint)) {
|
|
1113
|
+
specConstraint = lodash.get(context.parent, specConstraint.path);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
let result;
|
|
1117
|
+
|
|
1118
|
+
try {
|
|
1119
|
+
result = await validator(specConstraint, value, this._message, context);
|
|
1120
|
+
} catch (err) {
|
|
1121
|
+
const errorFromException = new ValidationError("".concat(pathToString(context.path), ": Exception occurred while validating value: ").concat(err.message));
|
|
1122
|
+
return convertToValidationMarker(errorFromException, "error", context);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
return convertToValidationMarker(result, this._level, context);
|
|
1126
|
+
}));
|
|
867
1127
|
return results.flat();
|
|
868
1128
|
}
|
|
869
|
-
|
|
1129
|
+
|
|
1130
|
+
}, _a.FIELD_REF = FIELD_REF, _a.array = def => new _a(def).type("Array"), _a.object = def => new _a(def).type("Object"), _a.string = def => new _a(def).type("String"), _a.number = def => new _a(def).type("Number"), _a.boolean = def => new _a(def).type("Boolean"), _a.dateTime = def => new _a(def).type("Date"), _a.valueOfField = path => ({
|
|
870
1131
|
type: FIELD_REF,
|
|
871
1132
|
path
|
|
872
1133
|
}), _a);
|
|
873
|
-
|
|
874
1134
|
const memoizedWarnOnArraySlug = lodash.memoize(warnOnArraySlug);
|
|
1135
|
+
|
|
875
1136
|
function getDocumentIds(id) {
|
|
876
1137
|
const isDraft = id.indexOf("drafts.") === 0;
|
|
877
1138
|
return {
|
|
878
1139
|
published: isDraft ? id.slice("drafts.".length) : id,
|
|
879
|
-
draft: isDraft ? id :
|
|
1140
|
+
draft: isDraft ? id : "drafts.".concat(id)
|
|
880
1141
|
};
|
|
881
1142
|
}
|
|
1143
|
+
|
|
882
1144
|
function serializePath(path) {
|
|
883
1145
|
return path.reduce((target, part, i) => {
|
|
884
1146
|
const isIndex = typeof part === "number";
|
|
885
1147
|
const isKey = types.isKeyedObject(part);
|
|
886
1148
|
const separator = i === 0 ? "" : ".";
|
|
887
|
-
const add = isIndex || isKey ? "[]" :
|
|
888
|
-
return
|
|
1149
|
+
const add = isIndex || isKey ? "[]" : "".concat(separator).concat(part);
|
|
1150
|
+
return "".concat(target).concat(add);
|
|
889
1151
|
}, "");
|
|
890
1152
|
}
|
|
1153
|
+
|
|
891
1154
|
const defaultIsUnique = (slug, context) => {
|
|
892
|
-
const {
|
|
1155
|
+
const {
|
|
1156
|
+
client,
|
|
1157
|
+
document,
|
|
1158
|
+
path,
|
|
1159
|
+
type
|
|
1160
|
+
} = context;
|
|
893
1161
|
const schemaOptions = type == null ? void 0 : type.options;
|
|
1162
|
+
|
|
894
1163
|
if (!document) {
|
|
895
|
-
throw new Error(
|
|
1164
|
+
throw new Error("`document` was not provided in validation context.");
|
|
896
1165
|
}
|
|
1166
|
+
|
|
897
1167
|
if (!path) {
|
|
898
|
-
throw new Error(
|
|
1168
|
+
throw new Error("`path` was not provided in validation context.");
|
|
899
1169
|
}
|
|
1170
|
+
|
|
900
1171
|
const disableArrayWarning = (schemaOptions == null ? void 0 : schemaOptions.disableArrayWarning) || false;
|
|
901
|
-
const {
|
|
1172
|
+
const {
|
|
1173
|
+
published,
|
|
1174
|
+
draft
|
|
1175
|
+
} = getDocumentIds(document._id);
|
|
902
1176
|
const docType = document._type;
|
|
903
1177
|
const atPath = serializePath(path.concat("current"));
|
|
1178
|
+
|
|
904
1179
|
if (!disableArrayWarning && atPath.includes("[]")) {
|
|
905
1180
|
memoizedWarnOnArraySlug(serializePath(path));
|
|
906
1181
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
published,
|
|
918
|
-
slug
|
|
919
|
-
},
|
|
920
|
-
{ tag: "validation.slug-is-unique" }
|
|
921
|
-
);
|
|
1182
|
+
|
|
1183
|
+
const constraints = ["_type == $docType", "!(_id in [$draft, $published])", "".concat(atPath, " == $slug")].join(" && ");
|
|
1184
|
+
return client.fetch("!defined(*[".concat(constraints, "][0]._id)"), {
|
|
1185
|
+
docType,
|
|
1186
|
+
draft,
|
|
1187
|
+
published,
|
|
1188
|
+
slug
|
|
1189
|
+
}, {
|
|
1190
|
+
tag: "validation.slug-is-unique"
|
|
1191
|
+
});
|
|
922
1192
|
};
|
|
1193
|
+
|
|
923
1194
|
function warnOnArraySlug(serializedPath) {
|
|
924
|
-
console.warn(
|
|
925
|
-
[
|
|
926
|
-
`Slug field at path ${serializedPath} is within an array and cannot be automatically checked for uniqueness`,
|
|
927
|
-
`If you need to check for uniqueness, provide your own "isUnique" method`,
|
|
928
|
-
`To disable this message, set \`disableArrayWarning: true\` on the slug \`options\` field`
|
|
929
|
-
].join("\n")
|
|
930
|
-
);
|
|
1195
|
+
console.warn(["Slug field at path ".concat(serializedPath, " is within an array and cannot be automatically checked for uniqueness"), "If you need to check for uniqueness, provide your own \"isUnique\" method", "To disable this message, set `disableArrayWarning: true` on the slug `options` field"].join("\n"));
|
|
931
1196
|
}
|
|
1197
|
+
|
|
932
1198
|
const slugValidator = async (value, context) => {
|
|
933
1199
|
var _a;
|
|
1200
|
+
|
|
934
1201
|
if (!value) {
|
|
935
1202
|
return true;
|
|
936
1203
|
}
|
|
1204
|
+
|
|
937
1205
|
if (typeof value !== "object") {
|
|
938
1206
|
return "Slug must be an object";
|
|
939
1207
|
}
|
|
1208
|
+
|
|
940
1209
|
const slugValue = value.current;
|
|
1210
|
+
|
|
941
1211
|
if (!slugValue) {
|
|
942
1212
|
return "Slug must have a value";
|
|
943
1213
|
}
|
|
1214
|
+
|
|
944
1215
|
const options = (_a = context == null ? void 0 : context.type) == null ? void 0 : _a.options;
|
|
945
1216
|
const isUnique = (options == null ? void 0 : options.isUnique) || defaultIsUnique;
|
|
946
|
-
const wasUnique = await isUnique(slugValue, {
|
|
1217
|
+
const wasUnique = await isUnique(slugValue, _objectSpread(_objectSpread({}, context), {}, {
|
|
1218
|
+
defaultIsUnique
|
|
1219
|
+
}));
|
|
1220
|
+
|
|
947
1221
|
if (wasUnique) {
|
|
948
1222
|
return true;
|
|
949
1223
|
}
|
|
1224
|
+
|
|
950
1225
|
return "Slug is already in use";
|
|
951
1226
|
};
|
|
952
1227
|
|
|
@@ -958,112 +1233,117 @@ const ruleConstraintTypes = {
|
|
|
958
1233
|
object: true,
|
|
959
1234
|
string: true
|
|
960
1235
|
};
|
|
961
|
-
|
|
1236
|
+
|
|
1237
|
+
const isRuleConstraint = typeString => typeString in ruleConstraintTypes;
|
|
1238
|
+
|
|
962
1239
|
function getTypeChain(type, visited) {
|
|
963
|
-
if (!type)
|
|
964
|
-
|
|
965
|
-
if (visited.has(type))
|
|
966
|
-
return [];
|
|
1240
|
+
if (!type) return [];
|
|
1241
|
+
if (visited.has(type)) return [];
|
|
967
1242
|
visited.add(type);
|
|
968
1243
|
const next = type.type ? getTypeChain(type.type, visited) : [];
|
|
969
1244
|
return [...next, type];
|
|
970
1245
|
}
|
|
1246
|
+
|
|
971
1247
|
function baseRuleReducer(inputRule, type) {
|
|
972
1248
|
let baseRule = inputRule;
|
|
1249
|
+
|
|
973
1250
|
if (isRuleConstraint(type.jsonType)) {
|
|
974
1251
|
baseRule = baseRule.type(type.jsonType);
|
|
975
1252
|
}
|
|
1253
|
+
|
|
976
1254
|
const typeOptionsList = (type == null ? void 0 : type.options) && typeof type.options === "object" && "list" in type.options && type.options.list;
|
|
1255
|
+
|
|
977
1256
|
if (Array.isArray(typeOptionsList)) {
|
|
978
|
-
baseRule = baseRule.valid(
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
if (type.name === "
|
|
983
|
-
|
|
984
|
-
if (type.name === "
|
|
985
|
-
|
|
986
|
-
if (type.name === "
|
|
987
|
-
return baseRule.uri();
|
|
988
|
-
if (type.name === "slug")
|
|
989
|
-
return baseRule.custom(slugValidator);
|
|
990
|
-
if (type.name === "reference")
|
|
991
|
-
return baseRule.reference();
|
|
992
|
-
if (type.name === "email")
|
|
993
|
-
return baseRule.email();
|
|
1257
|
+
baseRule = baseRule.valid(typeOptionsList.map(option => extractValueFromListOption(option, type)));
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (type.name === "datetime") return baseRule.type("Date");
|
|
1261
|
+
if (type.name === "date") return baseRule.type("Date");
|
|
1262
|
+
if (type.name === "url") return baseRule.uri();
|
|
1263
|
+
if (type.name === "slug") return baseRule.custom(slugValidator);
|
|
1264
|
+
if (type.name === "reference") return baseRule.reference();
|
|
1265
|
+
if (type.name === "email") return baseRule.email();
|
|
994
1266
|
return baseRule;
|
|
995
1267
|
}
|
|
1268
|
+
|
|
996
1269
|
function hasValueField(typeDef) {
|
|
997
|
-
if (!typeDef)
|
|
998
|
-
|
|
999
|
-
if (!("fields" in typeDef)
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
return false;
|
|
1003
|
-
if (!Array.isArray(typeDef.fields))
|
|
1004
|
-
return false;
|
|
1005
|
-
return typeDef.fields.some((field) => field.name === "value");
|
|
1270
|
+
if (!typeDef) return false;
|
|
1271
|
+
if (!("fields" in typeDef) && typeDef.type) return hasValueField(typeDef.type);
|
|
1272
|
+
if (!("fields" in typeDef)) return false;
|
|
1273
|
+
if (!Array.isArray(typeDef.fields)) return false;
|
|
1274
|
+
return typeDef.fields.some(field => field.name === "value");
|
|
1006
1275
|
}
|
|
1276
|
+
|
|
1007
1277
|
function extractValueFromListOption(option, typeDef) {
|
|
1008
|
-
if (typeDef.jsonType === "object" && hasValueField(typeDef))
|
|
1009
|
-
return option;
|
|
1278
|
+
if (typeDef.jsonType === "object" && hasValueField(typeDef)) return option;
|
|
1010
1279
|
return option.value === void 0 ? option : option.value;
|
|
1011
1280
|
}
|
|
1281
|
+
|
|
1012
1282
|
function normalizeValidationRules(typeDef) {
|
|
1013
1283
|
if (!typeDef) {
|
|
1014
1284
|
return [];
|
|
1015
1285
|
}
|
|
1286
|
+
|
|
1016
1287
|
const validation = typeDef.validation;
|
|
1288
|
+
|
|
1017
1289
|
if (Array.isArray(validation)) {
|
|
1018
|
-
return validation.flatMap(
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
validation: i
|
|
1022
|
-
})
|
|
1023
|
-
);
|
|
1290
|
+
return validation.flatMap(i => normalizeValidationRules(_objectSpread(_objectSpread({}, typeDef), {}, {
|
|
1291
|
+
validation: i
|
|
1292
|
+
})));
|
|
1024
1293
|
}
|
|
1294
|
+
|
|
1025
1295
|
if (validation instanceof Rule) {
|
|
1026
1296
|
return [validation];
|
|
1027
1297
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1298
|
+
|
|
1299
|
+
const baseRule = Object.values(getTypeChain(typeDef, /* @__PURE__ */new Set()).reduce((acc, type) => {
|
|
1300
|
+
acc[type.name] = type;
|
|
1301
|
+
return acc;
|
|
1302
|
+
}, {})).reduce(baseRuleReducer, new Rule(typeDef));
|
|
1303
|
+
|
|
1034
1304
|
if (!validation) {
|
|
1035
1305
|
return [baseRule];
|
|
1036
1306
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1307
|
+
|
|
1308
|
+
return normalizeValidationRules(_objectSpread(_objectSpread({}, typeDef), {}, {
|
|
1039
1309
|
validation: validation(baseRule)
|
|
1040
|
-
});
|
|
1310
|
+
}));
|
|
1041
1311
|
}
|
|
1042
1312
|
|
|
1043
|
-
const isRecord =
|
|
1044
|
-
|
|
1313
|
+
const isRecord = maybeRecord => typeof maybeRecord === "object" && maybeRecord !== null && !Array.isArray(maybeRecord);
|
|
1314
|
+
|
|
1315
|
+
const isNonNullable = value => value !== null && value !== void 0;
|
|
1316
|
+
|
|
1045
1317
|
function resolveTypeForArrayItem(item, candidates) {
|
|
1046
|
-
if (candidates.length === 1)
|
|
1047
|
-
|
|
1318
|
+
if (candidates.length === 1) return candidates[0];
|
|
1319
|
+
|
|
1048
1320
|
const itemType = types.isTypedObject(item) && item._type;
|
|
1321
|
+
|
|
1049
1322
|
const primitive = item === void 0 || item === null || !itemType && typeString(item).toLowerCase();
|
|
1323
|
+
|
|
1050
1324
|
if (primitive && primitive !== "object") {
|
|
1051
|
-
return candidates.find(
|
|
1325
|
+
return candidates.find(candidate => candidate.jsonType === primitive);
|
|
1052
1326
|
}
|
|
1053
|
-
|
|
1327
|
+
|
|
1328
|
+
return candidates.find(candidate => {
|
|
1054
1329
|
var _a;
|
|
1330
|
+
|
|
1055
1331
|
return ((_a = candidate.type) == null ? void 0 : _a.name) === itemType;
|
|
1056
|
-
}) || candidates.find(
|
|
1332
|
+
}) || candidates.find(candidate => candidate.name === itemType) || candidates.find(candidate => candidate.name === "object" && primitive === "object");
|
|
1057
1333
|
}
|
|
1334
|
+
|
|
1058
1335
|
async function validateDocument(client, doc, schema, context) {
|
|
1059
1336
|
const documentType = schema.get(doc._type);
|
|
1337
|
+
|
|
1060
1338
|
if (!documentType) {
|
|
1061
1339
|
console.warn('Schema type for object type "%s" not found, skipping validation', doc._type);
|
|
1062
1340
|
return [];
|
|
1063
1341
|
}
|
|
1342
|
+
|
|
1064
1343
|
try {
|
|
1065
1344
|
return await validateItem({
|
|
1066
1345
|
client,
|
|
1346
|
+
schema,
|
|
1067
1347
|
parent: void 0,
|
|
1068
1348
|
value: doc,
|
|
1069
1349
|
path: [],
|
|
@@ -1073,106 +1353,98 @@ async function validateDocument(client, doc, schema, context) {
|
|
|
1073
1353
|
});
|
|
1074
1354
|
} catch (err) {
|
|
1075
1355
|
console.error(err);
|
|
1076
|
-
return [
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
}
|
|
1082
|
-
];
|
|
1356
|
+
return [{
|
|
1357
|
+
level: "error",
|
|
1358
|
+
path: [],
|
|
1359
|
+
item: new ValidationError(err == null ? void 0 : err.message)
|
|
1360
|
+
}];
|
|
1083
1361
|
}
|
|
1084
1362
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1363
|
+
|
|
1364
|
+
async function validateItem(_ref) {
|
|
1365
|
+
let {
|
|
1366
|
+
value,
|
|
1367
|
+
type,
|
|
1368
|
+
path = [],
|
|
1369
|
+
parent
|
|
1370
|
+
} = _ref,
|
|
1371
|
+
restOfContext = _objectWithoutProperties(_ref, _excluded);
|
|
1372
|
+
|
|
1092
1373
|
const rules = normalizeValidationRules(type);
|
|
1093
|
-
const selfChecks = rules.map(
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
type
|
|
1099
|
-
})
|
|
1100
|
-
);
|
|
1374
|
+
const selfChecks = rules.map(rule => rule.validate(value, _objectSpread(_objectSpread({}, restOfContext), {}, {
|
|
1375
|
+
parent,
|
|
1376
|
+
path,
|
|
1377
|
+
type
|
|
1378
|
+
})));
|
|
1101
1379
|
let nestedChecks = [];
|
|
1102
|
-
const selfIsRequired = rules.some(
|
|
1380
|
+
const selfIsRequired = rules.some(rule => rule.isRequired());
|
|
1103
1381
|
const shouldRunNestedObjectValidation = (type == null ? void 0 : type.jsonType) === "object" && (!!value || (value === null || value === void 0) && selfIsRequired);
|
|
1382
|
+
|
|
1104
1383
|
if (shouldRunNestedObjectValidation) {
|
|
1105
1384
|
const fieldTypes = type.fields.reduce((acc, field) => {
|
|
1106
1385
|
acc[field.name] = field.type;
|
|
1107
1386
|
return acc;
|
|
1108
1387
|
}, {});
|
|
1109
|
-
nestedChecks = nestedChecks.concat(
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
path: path.concat(name),
|
|
1118
|
-
type: fieldType
|
|
1119
|
-
});
|
|
1120
|
-
});
|
|
1121
|
-
})
|
|
1122
|
-
);
|
|
1123
|
-
nestedChecks = nestedChecks.concat(
|
|
1124
|
-
type.fields.map(
|
|
1125
|
-
(field) => validateItem({
|
|
1126
|
-
...restOfContext,
|
|
1388
|
+
nestedChecks = nestedChecks.concat(rules.map(rule => rule._fieldRules).filter(isNonNullable).flatMap(fieldResults => Object.entries(fieldResults)).flatMap(_ref2 => {
|
|
1389
|
+
let [name, validation] = _ref2;
|
|
1390
|
+
const fieldType = fieldTypes[name];
|
|
1391
|
+
return normalizeValidationRules(_objectSpread(_objectSpread({}, fieldType), {}, {
|
|
1392
|
+
validation
|
|
1393
|
+
})).map(subRule => {
|
|
1394
|
+
const nestedValue = isRecord(value) ? value[name] : void 0;
|
|
1395
|
+
return subRule.validate(nestedValue, _objectSpread(_objectSpread({}, restOfContext), {}, {
|
|
1127
1396
|
parent: value,
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
)
|
|
1397
|
+
path: path.concat(name),
|
|
1398
|
+
type: fieldType
|
|
1399
|
+
}));
|
|
1400
|
+
});
|
|
1401
|
+
}));
|
|
1402
|
+
nestedChecks = nestedChecks.concat(type.fields.map(field => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
|
|
1403
|
+
parent: value,
|
|
1404
|
+
value: isRecord(value) ? value[field.name] : void 0,
|
|
1405
|
+
path: path.concat(field.name),
|
|
1406
|
+
type: field.type
|
|
1407
|
+
}))));
|
|
1134
1408
|
}
|
|
1409
|
+
|
|
1135
1410
|
const shouldRunNestedValidationForArrays = (type == null ? void 0 : type.jsonType) === "array" && Array.isArray(value);
|
|
1411
|
+
|
|
1136
1412
|
if (shouldRunNestedValidationForArrays) {
|
|
1137
|
-
nestedChecks = nestedChecks.concat(
|
|
1138
|
-
value
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
})
|
|
1146
|
-
)
|
|
1147
|
-
);
|
|
1413
|
+
nestedChecks = nestedChecks.concat(value.map(item => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
|
|
1414
|
+
parent: value,
|
|
1415
|
+
value: item,
|
|
1416
|
+
path: path.concat(types.isKeyedObject(item) ? {
|
|
1417
|
+
_key: item._key
|
|
1418
|
+
} : value.indexOf(item)),
|
|
1419
|
+
type: resolveTypeForArrayItem(item, type.of)
|
|
1420
|
+
}))));
|
|
1148
1421
|
}
|
|
1422
|
+
|
|
1149
1423
|
const shouldRunNestedValidationForMarkDefs = types.isBlock(value) && value.markDefs.length && types.isBlockSchemaType(type);
|
|
1424
|
+
|
|
1150
1425
|
if (shouldRunNestedValidationForMarkDefs) {
|
|
1151
1426
|
const [spanChildrenField] = type.fields;
|
|
1152
1427
|
const spanType = spanChildrenField.type.of.find(types.isSpanSchemaType);
|
|
1153
|
-
const annotations = ((spanType == null ? void 0 : spanType.annotations) || []).reduce(
|
|
1154
|
-
(
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
value: markDef,
|
|
1166
|
-
path: path.concat(["markDefs", { _key: markDef._key }]),
|
|
1167
|
-
type: annotations.get(markDef._type)
|
|
1168
|
-
})
|
|
1169
|
-
)
|
|
1170
|
-
);
|
|
1428
|
+
const annotations = ((spanType == null ? void 0 : spanType.annotations) || []).reduce((map, annotationType) => {
|
|
1429
|
+
map.set(annotationType.name, annotationType);
|
|
1430
|
+
return map;
|
|
1431
|
+
}, /* @__PURE__ */new Map());
|
|
1432
|
+
nestedChecks = nestedChecks.concat(value.markDefs.map(markDef => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
|
|
1433
|
+
parent: value,
|
|
1434
|
+
value: markDef,
|
|
1435
|
+
path: path.concat(["markDefs", {
|
|
1436
|
+
_key: markDef._key
|
|
1437
|
+
}]),
|
|
1438
|
+
type: annotations.get(markDef._type)
|
|
1439
|
+
}))));
|
|
1171
1440
|
}
|
|
1441
|
+
|
|
1172
1442
|
const results = (await Promise.all([...selfChecks, ...nestedChecks])).flat();
|
|
1173
|
-
|
|
1174
|
-
|
|
1443
|
+
|
|
1444
|
+
if (rules.some(rule => rule._fieldRules)) {
|
|
1445
|
+
return lodash.uniqBy(results, rule => JSON.stringify(rule));
|
|
1175
1446
|
}
|
|
1447
|
+
|
|
1176
1448
|
return results;
|
|
1177
1449
|
}
|
|
1178
1450
|
|
|
@@ -1180,33 +1452,39 @@ function traverse(typeDef, visited) {
|
|
|
1180
1452
|
if (visited.has(typeDef)) {
|
|
1181
1453
|
return;
|
|
1182
1454
|
}
|
|
1455
|
+
|
|
1183
1456
|
visited.add(typeDef);
|
|
1184
1457
|
typeDef.validation = normalizeValidationRules(typeDef);
|
|
1458
|
+
|
|
1185
1459
|
if ("fields" in typeDef) {
|
|
1186
1460
|
for (const field of typeDef.fields) {
|
|
1187
1461
|
traverse(field.type, visited);
|
|
1188
1462
|
}
|
|
1189
1463
|
}
|
|
1464
|
+
|
|
1190
1465
|
if ("of" in typeDef) {
|
|
1191
1466
|
for (const candidate of typeDef.of) {
|
|
1192
1467
|
traverse(candidate, visited);
|
|
1193
1468
|
}
|
|
1194
1469
|
}
|
|
1470
|
+
|
|
1195
1471
|
if (typeDef.annotations) {
|
|
1196
1472
|
for (const annotation of typeDef.annotations) {
|
|
1197
1473
|
traverse(annotation, visited);
|
|
1198
1474
|
}
|
|
1199
1475
|
}
|
|
1200
1476
|
}
|
|
1477
|
+
|
|
1201
1478
|
function inferFromSchemaType(typeDef) {
|
|
1202
|
-
traverse(typeDef, /* @__PURE__ */
|
|
1479
|
+
traverse(typeDef, /* @__PURE__ */new Set());
|
|
1203
1480
|
return typeDef;
|
|
1204
1481
|
}
|
|
1205
1482
|
|
|
1206
1483
|
function inferFromSchema(schema) {
|
|
1207
1484
|
const typeNames = schema.getTypeNames();
|
|
1208
|
-
typeNames.forEach(
|
|
1485
|
+
typeNames.forEach(typeName => {
|
|
1209
1486
|
const schemaType = schema.get(typeName);
|
|
1487
|
+
|
|
1210
1488
|
if (schemaType) {
|
|
1211
1489
|
inferFromSchemaType(schemaType);
|
|
1212
1490
|
}
|