@sanity/validation 2.33.4-performance-opts.16 → 2.33.4-shopify.8

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.
@@ -10,5 +10,4 @@ declare const _default: {
10
10
  };
11
11
  export default _default;
12
12
  export { RuleClass as Rule, validateDocument, inferFromSchema, inferFromSchemaType };
13
- export { validateDocumentObservable } from './validateDocument';
14
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,QAAQ,CAAA;AAC9B,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,eAAe,MAAM,mBAAmB,CAAA;AAC/C,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;;;;;;;AAEvD,wBAAwF;AACxF,OAAO,EAAC,SAAS,IAAI,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAC,CAAA;AAElF,OAAO,EAAC,0BAA0B,EAAC,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,QAAQ,CAAA;AAC9B,OAAO,gBAAgB,MAAM,oBAAoB,CAAA;AACjD,OAAO,eAAe,MAAM,mBAAmB,CAAA;AAC/C,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;;;;;;;AAEvD,wBAAwF;AACxF,OAAO,EAAC,SAAS,IAAI,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,mBAAmB,EAAC,CAAA"}
@@ -1,11 +1,9 @@
1
1
  import { SanityDocument, Schema, SchemaType, ValidationContext, ValidationMarker } from '@sanity/types';
2
- import { Observable } from 'rxjs';
3
2
  /**
4
3
  * @internal
5
4
  */
6
5
  export declare function resolveTypeForArrayItem(item: unknown, candidates: SchemaType[]): SchemaType | undefined;
7
6
  export default function validateDocument(doc: SanityDocument, schema: Schema, context?: Pick<ValidationContext, 'getDocumentExists'>): Promise<ValidationMarker[]>;
8
- export declare function validateDocumentObservable(doc: SanityDocument, schema: Schema, context?: Pick<ValidationContext, 'getDocumentExists'>): Observable<ValidationMarker[]>;
9
7
  /**
10
8
  * this is used make optional properties required by replacing optionals with
11
9
  * `T[P] | undefined`. this is used to prevent errors in `validateItem` where
@@ -19,6 +17,6 @@ declare type ExplicitUndefined<T> = {
19
17
  declare type ValidateItemOptions = {
20
18
  value: unknown;
21
19
  } & ExplicitUndefined<ValidationContext>;
22
- export declare function validateItem(opts: ValidateItemOptions): Promise<ValidationMarker[]>;
20
+ export declare function validateItem({ value, type, path, parent, ...restOfContext }: ValidateItemOptions): Promise<ValidationMarker[]>;
23
21
  export {};
24
22
  //# sourceMappingURL=validateDocument.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateDocument.d.ts","sourceRoot":"","sources":["../../src/validateDocument.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,cAAc,EACd,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAuB,UAAU,EAAK,MAAM,MAAM,CAAA;AAczD;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,UAAU,EAAE,GACvB,UAAU,GAAG,SAAS,CAiBxB;AAGD,MAAM,CAAC,OAAO,UAAU,gBAAgB,CACtC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GACrD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAE7B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GACrD,UAAU,CAAC,gBAAgB,EAAE,CAAC,CA2BhC;AAED;;;;;;GAMG;AACH,aAAK,iBAAiB,CAAC,CAAC,IAAI;KACzB,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS;CAC5F,CAAA;AAED,aAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,OAAO,CAAA;CACf,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;AAExC,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAEnF"}
1
+ {"version":3,"file":"validateDocument.d.ts","sourceRoot":"","sources":["../../src/validateDocument.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAMjB,MAAM,eAAe,CAAA;AAYtB;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,UAAU,EAAE,GACvB,UAAU,GAAG,SAAS,CAiBxB;AAED,wBAA8B,gBAAgB,CAC5C,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,GACrD,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2B7B;AAED;;;;;;GAMG;AACH,aAAK,iBAAiB,CAAC,CAAC,IAAI;KACzB,CAAC,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS;CAC5F,CAAA;AAED,aAAK,mBAAmB,GAAG;IACzB,KAAK,EAAE,OAAO,CAAA;CACf,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAAA;AAExC,wBAAsB,YAAY,CAAC,EACjC,KAAK,EACL,IAAI,EACJ,IAAS,EACT,MAAM,EACN,GAAG,aAAa,EACjB,EAAE,mBAAmB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA4HnD"}
package/lib/index.js CHANGED
@@ -28,25 +28,15 @@ Object.defineProperty(exports, "validateDocument", {
28
28
  return _validateDocument.default;
29
29
  }
30
30
  });
31
- Object.defineProperty(exports, "validateDocumentObservable", {
32
- enumerable: true,
33
- get: function get() {
34
- return _validateDocument.validateDocumentObservable;
35
- }
36
- });
37
31
 
38
32
  var _Rule = _interopRequireDefault(require("./Rule"));
39
33
 
40
- var _validateDocument = _interopRequireWildcard(require("./validateDocument"));
34
+ var _validateDocument = _interopRequireDefault(require("./validateDocument"));
41
35
 
42
36
  var _inferFromSchema = _interopRequireDefault(require("./inferFromSchema"));
43
37
 
44
38
  var _inferFromSchemaType = _interopRequireDefault(require("./inferFromSchemaType"));
45
39
 
46
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
47
-
48
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
49
-
50
40
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
51
41
 
52
42
  var _default = {
@@ -5,23 +5,14 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = validateDocument;
7
7
  exports.resolveTypeForArrayItem = resolveTypeForArrayItem;
8
- exports.validateDocumentObservable = validateDocumentObservable;
9
8
  exports.validateItem = validateItem;
10
9
 
11
10
  var _uniqBy2 = _interopRequireDefault(require("lodash/uniqBy"));
12
11
 
13
- var _flatten2 = _interopRequireDefault(require("lodash/flatten"));
14
-
15
12
  var _types = require("@sanity/types");
16
13
 
17
- var _rxjs = require("rxjs");
18
-
19
- var _operators = require("rxjs/operators");
20
-
21
14
  var _typeString = _interopRequireDefault(require("./util/typeString"));
22
15
 
23
- var _requestIdleCallback = require("./util/requestIdleCallback");
24
-
25
16
  var _ValidationError = _interopRequireDefault(require("./ValidationError"));
26
17
 
27
18
  var _normalizeValidationRules = _interopRequireDefault(require("./util/normalizeValidationRules"));
@@ -52,6 +43,10 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
52
43
 
53
44
  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; }
54
45
 
46
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
47
+
48
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
49
+
55
50
  var isRecord = maybeRecord => typeof maybeRecord === 'object' && maybeRecord !== null && !Array.isArray(maybeRecord);
56
51
 
57
52
  var isNonNullable = value => value !== null && value !== undefined;
@@ -79,36 +74,8 @@ function resolveTypeForArrayItem(item, candidates) {
79
74
  }) || candidates.find(candidate => candidate.name === itemType) || candidates.find(candidate => candidate.name === 'object' && primitive === 'object');
80
75
  }
81
76
 
82
- var EMPTY_MARKERS = [];
83
-
84
- function validateDocument(doc, schema, context) {
85
- return validateDocumentObservable(doc, schema, context).toPromise();
86
- }
87
-
88
- function validateDocumentObservable(doc, schema, context) {
89
- var documentType = schema.get(doc._type);
90
-
91
- if (!documentType) {
92
- console.warn('Schema type for object type "%s" not found, skipping validation', doc._type);
93
- return (0, _rxjs.of)(EMPTY_MARKERS);
94
- }
95
-
96
- return validateItemObservable({
97
- parent: undefined,
98
- value: doc,
99
- path: [],
100
- document: doc,
101
- type: documentType,
102
- getDocumentExists: context === null || context === void 0 ? void 0 : context.getDocumentExists
103
- }).pipe((0, _operators.catchError)(err => {
104
- console.error(err);
105
- return (0, _rxjs.of)([{
106
- type: 'validation',
107
- level: 'error',
108
- path: [],
109
- item: new _ValidationError.default(err === null || err === void 0 ? void 0 : err.message)
110
- }]);
111
- }));
77
+ function validateDocument(_x, _x2, _x3) {
78
+ return _validateDocument.apply(this, arguments);
112
79
  }
113
80
  /**
114
81
  * this is used make optional properties required by replacing optionals with
@@ -119,124 +86,146 @@ function validateDocumentObservable(doc, schema, context) {
119
86
  */
120
87
 
121
88
 
122
- function validateItem(opts) {
123
- return validateItemObservable(opts).toPromise();
124
- }
89
+ function _validateDocument() {
90
+ _validateDocument = _asyncToGenerator(function* (doc, schema, context) {
91
+ var documentType = schema.get(doc._type);
125
92
 
126
- function validateItemObservable(_ref) {
127
- var value = _ref.value,
128
- type = _ref.type,
129
- _ref$path = _ref.path,
130
- path = _ref$path === void 0 ? [] : _ref$path,
131
- parent = _ref.parent,
132
- restOfContext = _objectWithoutProperties(_ref, _excluded);
133
-
134
- var rules = (0, _normalizeValidationRules.default)(type); // run validation for the current value
135
-
136
- var selfChecks = rules.map(rule => (0, _rxjs.defer)(() => rule.validate(value, _objectSpread(_objectSpread({}, restOfContext), {}, {
137
- parent,
138
- path,
139
- type
140
- })))); // run validation for nested values (conditionally)
141
-
142
- var fieldChecks = [];
143
- var selfIsRequired = rules.some(rule => rule.isRequired());
144
- var shouldRunNestedObjectValidation = // run nested validation for objects
145
- (type === null || type === void 0 ? void 0 : type.jsonType) === 'object' && ( // if the value is truthy
146
- !!value || // or
147
- // (the value is null or undefined) and the top-level value is required
148
- (value === null || value === undefined) && selfIsRequired);
149
-
150
- if (shouldRunNestedObjectValidation) {
151
- var fieldTypes = type.fields.reduce((acc, field) => {
152
- acc[field.name] = field.type;
153
- return acc;
154
- }, {}); // Validation for rules set at the object level with `Rule.fields({/* ... */})`
155
-
156
- fieldChecks = fieldChecks.concat(rules.map(rule => rule._fieldRules).filter(isNonNullable).flatMap(fieldResults => Object.entries(fieldResults)).flatMap(_ref2 => {
157
- var _ref3 = _slicedToArray(_ref2, 2),
158
- name = _ref3[0],
159
- validation = _ref3[1];
160
-
161
- var fieldType = fieldTypes[name];
162
- return (0, _normalizeValidationRules.default)(_objectSpread(_objectSpread({}, fieldType), {}, {
163
- validation
164
- })).map(subRule => {
165
- var nestedValue = isRecord(value) ? value[name] : undefined;
166
- return (0, _rxjs.defer)(() => subRule.validate(nestedValue, _objectSpread(_objectSpread({}, restOfContext), {}, {
167
- parent: value,
168
- path: path.concat(name),
169
- type: fieldType
170
- })));
93
+ if (!documentType) {
94
+ console.warn('Schema type for object type "%s" not found, skipping validation', doc._type);
95
+ return [];
96
+ }
97
+
98
+ try {
99
+ return yield validateItem({
100
+ parent: undefined,
101
+ value: doc,
102
+ path: [],
103
+ document: doc,
104
+ type: documentType,
105
+ getDocumentExists: context === null || context === void 0 ? void 0 : context.getDocumentExists
171
106
  });
172
- })); // Validation from each field's schema `validation: Rule => {/* ... */}` function
173
-
174
- fieldChecks = fieldChecks.concat(type.fields.map(field => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
175
- parent: value,
176
- value: isRecord(value) ? value[field.name] : undefined,
177
- path: path.concat(field.name),
178
- type: field.type
179
- }))));
180
- } // note: unlike objects, arrays should not run nested validation for undefined
181
- // values because we won't have a valid path to put a marker (i.e. missing the
182
- // key or index in the path) and the downstream form builder won't have a
183
- // valid target component
184
-
185
-
186
- var shouldRunNestedValidationForArrays = (type === null || type === void 0 ? void 0 : type.jsonType) === 'array' && Array.isArray(value);
187
-
188
- if (shouldRunNestedValidationForArrays) {
189
- fieldChecks = fieldChecks.concat(value.map(item => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
190
- parent: value,
191
- value: item,
192
- path: path.concat((0, _types.isKeyedObject)(item) ? {
193
- _key: item._key
194
- } : value.indexOf(item)),
195
- type: resolveTypeForArrayItem(item, type.of)
196
- }))));
197
- } // markDefs also do no run nested validation if the parent object is undefined
198
- // for a similar reason to arrays
199
-
200
-
201
- var shouldRunNestedValidationForMarkDefs = (0, _types.isBlock)(value) && value.markDefs.length && (0, _types.isBlockSchemaType)(type);
202
-
203
- if (shouldRunNestedValidationForMarkDefs) {
204
- var _type$fields = _slicedToArray(type.fields, 1),
205
- spanChildrenField = _type$fields[0];
206
-
207
- var spanType = spanChildrenField.type.of.find(_types.isSpanSchemaType);
208
- var annotations = ((spanType === null || spanType === void 0 ? void 0 : spanType.annotations) || []).reduce((acc, annotationType) => {
209
- acc.set(annotationType.name, annotationType);
210
- return acc;
211
- }, new Map());
212
- fieldChecks = fieldChecks.concat(value.markDefs.map(markDef => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
213
- parent: value,
214
- value: markDef,
215
- path: path.concat(['markDefs', {
216
- _key: markDef._key
217
- }]),
218
- type: annotations.get(markDef._type)
219
- }))));
220
- }
107
+ } catch (err) {
108
+ console.error(err);
109
+ return [{
110
+ type: 'validation',
111
+ level: 'error',
112
+ path: [],
113
+ item: new _ValidationError.default(err === null || err === void 0 ? void 0 : err.message)
114
+ }];
115
+ }
116
+ });
117
+ return _validateDocument.apply(this, arguments);
118
+ }
221
119
 
222
- return (0, _rxjs.defer)(() => (0, _rxjs.merge)([...selfChecks, ...fieldChecks])).pipe((0, _operators.mergeMap)(validateNode => (0, _rxjs.concat)(idle(), validateNode), 40), (0, _operators.mergeAll)(), (0, _operators.toArray)(), (0, _operators.map)(_flatten2.default), (0, _operators.map)(results => {
223
- // run `uniqBy` if `_fieldRules` are present because they can
120
+ function validateItem(_x4) {
121
+ return _validateItem.apply(this, arguments);
122
+ }
123
+
124
+ function _validateItem() {
125
+ _validateItem = _asyncToGenerator(function* (_ref) {
126
+ var value = _ref.value,
127
+ type = _ref.type,
128
+ _ref$path = _ref.path,
129
+ path = _ref$path === void 0 ? [] : _ref$path,
130
+ parent = _ref.parent,
131
+ restOfContext = _objectWithoutProperties(_ref, _excluded);
132
+
133
+ var rules = (0, _normalizeValidationRules.default)(type); // run validation for the current value
134
+
135
+ var selfChecks = rules.map(rule => rule.validate(value, _objectSpread(_objectSpread({}, restOfContext), {}, {
136
+ parent,
137
+ path,
138
+ type
139
+ }))); // run validation for nested values (conditionally)
140
+
141
+ var nestedChecks = [];
142
+ var selfIsRequired = rules.some(rule => rule.isRequired());
143
+ var shouldRunNestedObjectValidation = // run nested validation for objects
144
+ (type === null || type === void 0 ? void 0 : type.jsonType) === 'object' && ( // if the value is truthy
145
+ !!value || // or
146
+ // (the value is null or undefined) and the top-level value is required
147
+ (value === null || value === undefined) && selfIsRequired);
148
+
149
+ if (shouldRunNestedObjectValidation) {
150
+ var fieldTypes = type.fields.reduce((acc, field) => {
151
+ acc[field.name] = field.type;
152
+ return acc;
153
+ }, {}); // Validation for rules set at the object level with `Rule.fields({/* ... */})`
154
+
155
+ nestedChecks = nestedChecks.concat(rules.map(rule => rule._fieldRules).filter(isNonNullable).flatMap(fieldResults => Object.entries(fieldResults)).flatMap(_ref2 => {
156
+ var _ref3 = _slicedToArray(_ref2, 2),
157
+ name = _ref3[0],
158
+ validation = _ref3[1];
159
+
160
+ var fieldType = fieldTypes[name];
161
+ return (0, _normalizeValidationRules.default)(_objectSpread(_objectSpread({}, fieldType), {}, {
162
+ validation
163
+ })).map(subRule => {
164
+ var nestedValue = isRecord(value) ? value[name] : undefined;
165
+ return subRule.validate(nestedValue, _objectSpread(_objectSpread({}, restOfContext), {}, {
166
+ parent: value,
167
+ path: path.concat(name),
168
+ type: fieldType
169
+ }));
170
+ });
171
+ })); // Validation from each field's schema `validation: Rule => {/* ... */}` function
172
+
173
+ nestedChecks = nestedChecks.concat(type.fields.map(field => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
174
+ parent: value,
175
+ value: isRecord(value) ? value[field.name] : undefined,
176
+ path: path.concat(field.name),
177
+ type: field.type
178
+ }))));
179
+ } // note: unlike objects, arrays should not run nested validation for undefined
180
+ // values because we won't have a valid path to put a marker (i.e. missing the
181
+ // key or index in the path) and the downstream form builder won't have a
182
+ // valid target component
183
+
184
+
185
+ var shouldRunNestedValidationForArrays = (type === null || type === void 0 ? void 0 : type.jsonType) === 'array' && Array.isArray(value);
186
+
187
+ if (shouldRunNestedValidationForArrays) {
188
+ nestedChecks = nestedChecks.concat(value.map(item => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
189
+ parent: value,
190
+ value: item,
191
+ path: path.concat((0, _types.isKeyedObject)(item) ? {
192
+ _key: item._key
193
+ } : value.indexOf(item)),
194
+ type: resolveTypeForArrayItem(item, type.of)
195
+ }))));
196
+ } // markDefs also do no run nested validation if the parent object is undefined
197
+ // for a similar reason to arrays
198
+
199
+
200
+ var shouldRunNestedValidationForMarkDefs = (0, _types.isBlock)(value) && value.markDefs.length && (0, _types.isBlockSchemaType)(type);
201
+
202
+ if (shouldRunNestedValidationForMarkDefs) {
203
+ var _type$fields = _slicedToArray(type.fields, 1),
204
+ spanChildrenField = _type$fields[0];
205
+
206
+ var spanType = spanChildrenField.type.of.find(_types.isSpanSchemaType);
207
+ var annotations = ((spanType === null || spanType === void 0 ? void 0 : spanType.annotations) || []).reduce((map, annotationType) => {
208
+ map.set(annotationType.name, annotationType);
209
+ return map;
210
+ }, new Map());
211
+ nestedChecks = nestedChecks.concat(value.markDefs.map(markDef => validateItem(_objectSpread(_objectSpread({}, restOfContext), {}, {
212
+ parent: value,
213
+ value: markDef,
214
+ path: path.concat(['markDefs', {
215
+ _key: markDef._key
216
+ }]),
217
+ type: annotations.get(markDef._type)
218
+ }))));
219
+ }
220
+
221
+ var results = (yield Promise.all([...selfChecks, ...nestedChecks])).flat(); // run `uniqBy` if `_fieldRules` are present because they can
224
222
  // cause repeat markers
223
+
225
224
  if (rules.some(rule => rule._fieldRules)) {
226
225
  return (0, _uniqBy2.default)(results, rule => JSON.stringify(rule));
227
226
  }
228
227
 
229
228
  return results;
230
- }));
231
- }
232
-
233
- function idle(timeout) {
234
- return new _rxjs.Observable(observer => {
235
- var handle = (0, _requestIdleCallback.requestIdleCallback)(() => {
236
- observer.complete();
237
- }, timeout ? {
238
- timeout
239
- } : undefined);
240
- return () => (0, _requestIdleCallback.cancelIdleCallback)(handle);
241
229
  });
230
+ return _validateItem.apply(this, arguments);
242
231
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/validation",
3
- "version": "2.33.4-performance-opts.16+6acb5be7ec",
3
+ "version": "2.33.4-shopify.8+b3097f8c9",
4
4
  "description": "Validation and warning infrastructure for Sanity projects",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./dist/dts",
@@ -33,13 +33,12 @@
33
33
  },
34
34
  "devDependencies": {
35
35
  "@sanity/client": "^3.3.3",
36
- "@sanity/schema": "2.33.4-performance-opts.16+6acb5be7ec"
36
+ "@sanity/schema": "2.33.4-shopify.8+b3097f8c9"
37
37
  },
38
38
  "dependencies": {
39
- "@sanity/types": "2.33.4-performance-opts.16+6acb5be7ec",
39
+ "@sanity/types": "2.33.4-shopify.8+b3097f8c9",
40
40
  "date-fns": "^2.16.1",
41
- "lodash": "^4.17.15",
42
- "rxjs": "^6.5.3"
41
+ "lodash": "^4.17.15"
43
42
  },
44
- "gitHead": "6acb5be7ec060806773c41c9b015f318e2fbfbd9"
43
+ "gitHead": "b3097f8c9ec8d874b3fd86005a17b0cb5eaf136c"
45
44
  }
package/src/index.ts CHANGED
@@ -5,5 +5,3 @@ import inferFromSchemaType from './inferFromSchemaType'
5
5
 
6
6
  export default {Rule: RuleClass, validateDocument, inferFromSchema, inferFromSchemaType}
7
7
  export {RuleClass as Rule, validateDocument, inferFromSchema, inferFromSchemaType}
8
-
9
- export {validateDocumentObservable} from './validateDocument'
@@ -687,4 +687,81 @@ describe('validateItem', () => {
687
687
  },
688
688
  ])
689
689
  })
690
+
691
+ it('runs all nested validation checks concurrently', async () => {
692
+ type Resolver = (value: true) => void
693
+ const resolvers = new Set<Resolver>()
694
+ const customValidationFn = () => new Promise<true>((resolve) => resolvers.add(resolve))
695
+
696
+ const schema: Schema = createSchema({
697
+ types: [
698
+ {
699
+ name: 'root',
700
+ type: 'object',
701
+ fields: [
702
+ {
703
+ name: 'level1Object',
704
+ type: 'object',
705
+ validation: (rule: Rule) => [
706
+ rule.custom(customValidationFn),
707
+ rule.fields({
708
+ level2String: (r) => r.custom(customValidationFn),
709
+ }),
710
+ ],
711
+ fields: [
712
+ {
713
+ name: 'level2String',
714
+ type: 'string',
715
+ validation: (rule: Rule) => rule.custom(customValidationFn),
716
+ },
717
+ ],
718
+ },
719
+ {
720
+ name: 'level1Array',
721
+ type: 'array',
722
+ validation: (rule: Rule) => rule.custom(customValidationFn),
723
+ of: [
724
+ {
725
+ type: 'object',
726
+ fields: [
727
+ {
728
+ name: 'level2Number',
729
+ type: 'number',
730
+ validation: (rule: Rule) => rule.custom(customValidationFn),
731
+ },
732
+ ],
733
+ },
734
+ ],
735
+ },
736
+ ],
737
+ validation: (rule: Rule) => rule.custom(customValidationFn),
738
+ },
739
+ ],
740
+ })
741
+
742
+ const value = {
743
+ level1Object: {level3String: 'a string'},
744
+ level1Array: [{level2Number: 5}],
745
+ }
746
+
747
+ const resultPromise = validateItem({
748
+ value,
749
+ document: undefined,
750
+ parent: undefined,
751
+ path: undefined,
752
+ type: schema.get('root'),
753
+ getDocumentExists: undefined,
754
+ })
755
+
756
+ // after `validateItem(...)` has been initiated, all of the custom
757
+ // validation calls should have fired so the resolver size should equal the
758
+ // amount of total fields
759
+ expect(resolvers.size).toBe(6)
760
+
761
+ for (const resolver of resolvers) {
762
+ resolver(true)
763
+ }
764
+
765
+ await resultPromise
766
+ })
690
767
  })
@@ -1,20 +1,17 @@
1
1
  import {
2
- isBlock,
3
- isBlockSchemaType,
4
- isKeyedObject,
5
- isSpanSchemaType,
6
- isTypedObject,
7
2
  SanityDocument,
8
3
  Schema,
9
4
  SchemaType,
10
5
  ValidationContext,
11
6
  ValidationMarker,
7
+ isKeyedObject,
8
+ isTypedObject,
9
+ isBlock,
10
+ isBlockSchemaType,
11
+ isSpanSchemaType,
12
12
  } from '@sanity/types'
13
- import {concat, defer, merge, Observable, of} from 'rxjs'
14
- import {catchError, map, mergeAll, mergeMap, toArray} from 'rxjs/operators'
15
- import {flatten, uniqBy} from 'lodash'
13
+ import {uniqBy} from 'lodash'
16
14
  import typeString from './util/typeString'
17
- import {requestIdleCallback, cancelIdleCallback} from './util/requestIdleCallback'
18
15
  import ValidationErrorClass from './ValidationError'
19
16
  import normalizeValidationRules from './util/normalizeValidationRules'
20
17
 
@@ -48,47 +45,38 @@ export function resolveTypeForArrayItem(
48
45
  candidates.find((candidate) => candidate.name === 'object' && primitive === 'object')
49
46
  )
50
47
  }
51
- const EMPTY_MARKERS: ValidationMarker[] = []
52
48
 
53
- export default function validateDocument(
49
+ export default async function validateDocument(
54
50
  doc: SanityDocument,
55
51
  schema: Schema,
56
52
  context?: Pick<ValidationContext, 'getDocumentExists'>
57
53
  ): Promise<ValidationMarker[]> {
58
- return validateDocumentObservable(doc, schema, context).toPromise()
59
- }
60
-
61
- export function validateDocumentObservable(
62
- doc: SanityDocument,
63
- schema: Schema,
64
- context?: Pick<ValidationContext, 'getDocumentExists'>
65
- ): Observable<ValidationMarker[]> {
66
54
  const documentType = schema.get(doc._type)
67
55
  if (!documentType) {
68
56
  console.warn('Schema type for object type "%s" not found, skipping validation', doc._type)
69
- return of(EMPTY_MARKERS)
57
+ return []
70
58
  }
71
59
 
72
- return validateItemObservable({
73
- parent: undefined,
74
- value: doc,
75
- path: [],
76
- document: doc,
77
- type: documentType,
78
- getDocumentExists: context?.getDocumentExists,
79
- }).pipe(
80
- catchError((err) => {
81
- console.error(err)
82
- return of([
83
- {
84
- type: 'validation' as const,
85
- level: 'error' as const,
86
- path: [],
87
- item: new ValidationErrorClass(err?.message),
88
- },
89
- ])
60
+ try {
61
+ return await validateItem({
62
+ parent: undefined,
63
+ value: doc,
64
+ path: [],
65
+ document: doc,
66
+ type: documentType,
67
+ getDocumentExists: context?.getDocumentExists,
90
68
  })
91
- )
69
+ } catch (err) {
70
+ console.error(err)
71
+ return [
72
+ {
73
+ type: 'validation',
74
+ level: 'error',
75
+ path: [],
76
+ item: new ValidationErrorClass(err?.message),
77
+ },
78
+ ]
79
+ }
92
80
  }
93
81
 
94
82
  /**
@@ -106,32 +94,27 @@ type ValidateItemOptions = {
106
94
  value: unknown
107
95
  } & ExplicitUndefined<ValidationContext>
108
96
 
109
- export function validateItem(opts: ValidateItemOptions): Promise<ValidationMarker[]> {
110
- return validateItemObservable(opts).toPromise()
111
- }
112
-
113
- function validateItemObservable({
97
+ export async function validateItem({
114
98
  value,
115
99
  type,
116
100
  path = [],
117
101
  parent,
118
102
  ...restOfContext
119
- }: ValidateItemOptions): Observable<ValidationMarker[]> {
103
+ }: ValidateItemOptions): Promise<ValidationMarker[]> {
120
104
  const rules = normalizeValidationRules(type)
105
+
121
106
  // run validation for the current value
122
107
  const selfChecks = rules.map((rule) =>
123
- defer(() =>
124
- rule.validate(value, {
125
- ...restOfContext,
126
- parent,
127
- path,
128
- type,
129
- })
130
- )
108
+ rule.validate(value, {
109
+ ...restOfContext,
110
+ parent,
111
+ path,
112
+ type,
113
+ })
131
114
  )
132
115
 
133
116
  // run validation for nested values (conditionally)
134
- let fieldChecks: Array<Observable<ValidationMarker[]>> = []
117
+ let nestedChecks: Array<Promise<ValidationMarker[]>> = []
135
118
 
136
119
  const selfIsRequired = rules.some((rule) => rule.isRequired())
137
120
  const shouldRunNestedObjectValidation =
@@ -149,7 +132,7 @@ function validateItemObservable({
149
132
  }, {})
150
133
 
151
134
  // Validation for rules set at the object level with `Rule.fields({/* ... */})`
152
- fieldChecks = fieldChecks.concat(
135
+ nestedChecks = nestedChecks.concat(
153
136
  rules
154
137
  .map((rule) => rule._fieldRules)
155
138
  .filter(isNonNullable)
@@ -158,22 +141,20 @@ function validateItemObservable({
158
141
  const fieldType = fieldTypes[name]
159
142
  return normalizeValidationRules({...fieldType, validation}).map((subRule) => {
160
143
  const nestedValue = isRecord(value) ? value[name] : undefined
161
- return defer(() =>
162
- subRule.validate(nestedValue, {
163
- ...restOfContext,
164
- parent: value,
165
- path: path.concat(name),
166
- type: fieldType,
167
- })
168
- )
144
+ return subRule.validate(nestedValue, {
145
+ ...restOfContext,
146
+ parent: value,
147
+ path: path.concat(name),
148
+ type: fieldType,
149
+ })
169
150
  })
170
151
  })
171
152
  )
172
153
 
173
154
  // Validation from each field's schema `validation: Rule => {/* ... */}` function
174
- fieldChecks = fieldChecks.concat(
155
+ nestedChecks = nestedChecks.concat(
175
156
  type.fields.map((field) =>
176
- validateItemObservable({
157
+ validateItem({
177
158
  ...restOfContext,
178
159
  parent: value,
179
160
  value: isRecord(value) ? value[field.name] : undefined,
@@ -191,9 +172,9 @@ function validateItemObservable({
191
172
  const shouldRunNestedValidationForArrays = type?.jsonType === 'array' && Array.isArray(value)
192
173
 
193
174
  if (shouldRunNestedValidationForArrays) {
194
- fieldChecks = fieldChecks.concat(
175
+ nestedChecks = nestedChecks.concat(
195
176
  value.map((item) =>
196
- validateItemObservable({
177
+ validateItem({
197
178
  ...restOfContext,
198
179
  parent: value,
199
180
  value: item,
@@ -214,16 +195,16 @@ function validateItemObservable({
214
195
  const spanType = spanChildrenField.type.of.find(isSpanSchemaType)
215
196
 
216
197
  const annotations = (spanType?.annotations || []).reduce<Map<string, SchemaType>>(
217
- (acc, annotationType) => {
218
- acc.set(annotationType.name, annotationType)
219
- return acc
198
+ (map, annotationType) => {
199
+ map.set(annotationType.name, annotationType)
200
+ return map
220
201
  },
221
202
  new Map()
222
203
  )
223
204
 
224
- fieldChecks = fieldChecks.concat(
205
+ nestedChecks = nestedChecks.concat(
225
206
  value.markDefs.map((markDef) =>
226
- validateItemObservable({
207
+ validateItem({
227
208
  ...restOfContext,
228
209
  parent: value,
229
210
  value: markDef,
@@ -234,31 +215,13 @@ function validateItemObservable({
234
215
  )
235
216
  }
236
217
 
237
- return defer(() => merge([...selfChecks, ...fieldChecks])).pipe(
238
- mergeMap((validateNode) => concat(idle(), validateNode), 40),
239
- mergeAll(),
240
- toArray(),
241
- map(flatten),
242
- map((results) => {
243
- // run `uniqBy` if `_fieldRules` are present because they can
244
- // cause repeat markers
245
- if (rules.some((rule) => rule._fieldRules)) {
246
- return uniqBy(results, (rule) => JSON.stringify(rule))
247
- }
248
- return results
249
- })
250
- )
251
- }
218
+ const results = (await Promise.all([...selfChecks, ...nestedChecks])).flat()
252
219
 
253
- function idle(timeout?: number): Observable<never> {
254
- return new Observable<never>((observer) => {
255
- const handle = requestIdleCallback(
256
- () => {
257
- observer.complete()
258
- },
259
- timeout ? {timeout} : undefined
260
- )
220
+ // run `uniqBy` if `_fieldRules` are present because they can
221
+ // cause repeat markers
222
+ if (rules.some((rule) => rule._fieldRules)) {
223
+ return uniqBy(results, (rule) => JSON.stringify(rule))
224
+ }
261
225
 
262
- return () => cancelIdleCallback(handle)
263
- })
226
+ return results
264
227
  }
@@ -1,3 +0,0 @@
1
- export declare const requestIdleCallback: ((callback: IdleRequestCallback, options?: IdleRequestOptions | undefined) => number) & typeof globalThis.requestIdleCallback;
2
- export declare const cancelIdleCallback: ((handle: number) => void) & typeof globalThis.cancelIdleCallback;
3
- //# sourceMappingURL=requestIdleCallback.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"requestIdleCallback.d.ts","sourceRoot":"","sources":["../../../src/util/requestIdleCallback.ts"],"names":[],"mappings":"AA2BA,eAAO,MAAM,mBAAmB,+HAAwD,CAAA;AACxF,eAAO,MAAM,kBAAkB,mEAAsD,CAAA"}
@@ -1,35 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.requestIdleCallback = exports.cancelIdleCallback = void 0;
7
-
8
- /**
9
- * Simple requestIdleCallback polyfill
10
- * Can be removed when all browsers support requestIdleCallback: https://caniuse.com/requestidlecallback
11
- * @param callback
12
- * @param options
13
- */
14
- var requestIdleCallbackShim = function requestIdleCallbackShim(callback, options) {
15
- var start = Date.now();
16
- return window.setTimeout(() => {
17
- callback({
18
- didTimeout: false,
19
-
20
- timeRemaining() {
21
- return Math.max(0, Date.now() - start);
22
- }
23
-
24
- });
25
- }, 0);
26
- };
27
-
28
- var cancelIdleCallbackShim = function cancelIdleCallbackShim(handle) {
29
- return window.clearTimeout(handle);
30
- };
31
-
32
- var requestIdleCallback = window.requestIdleCallback || requestIdleCallbackShim;
33
- exports.requestIdleCallback = requestIdleCallback;
34
- var cancelIdleCallback = window.cancelIdleCallback || cancelIdleCallbackShim;
35
- exports.cancelIdleCallback = cancelIdleCallback;
@@ -1,29 +0,0 @@
1
- /**
2
- * Simple requestIdleCallback polyfill
3
- * Can be removed when all browsers support requestIdleCallback: https://caniuse.com/requestidlecallback
4
- * @param callback
5
- * @param options
6
- */
7
- const requestIdleCallbackShim: typeof window.requestIdleCallback = function requestIdleCallbackShim(
8
- callback,
9
- options?
10
- ): number {
11
- const start = Date.now()
12
- return window.setTimeout(() => {
13
- callback({
14
- didTimeout: false,
15
- timeRemaining() {
16
- return Math.max(0, Date.now() - start)
17
- },
18
- })
19
- }, 0)
20
- }
21
-
22
- const cancelIdleCallbackShim: typeof window.cancelIdleCallback = function cancelIdleCallbackShim(
23
- handle: number
24
- ): void {
25
- return window.clearTimeout(handle)
26
- }
27
-
28
- export const requestIdleCallback = window.requestIdleCallback || requestIdleCallbackShim
29
- export const cancelIdleCallback = window.cancelIdleCallback || cancelIdleCallbackShim