@sanity/validation 3.1.4 → 3.1.5-canary.14

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.
@@ -0,0 +1,7 @@
1
+ import cjs from './index.js';
2
+
3
+ export const Rule = cjs.Rule;
4
+ export const inferFromSchema = cjs.inferFromSchema;
5
+ export const inferFromSchemaType = cjs.inferFromSchemaType;
6
+ export const validateDocument = cjs.validateDocument;
7
+ export const validateDocumentObservable = cjs.validateDocumentObservable;
package/lib/index.esm.js CHANGED
@@ -1,9 +1,3 @@
1
- const _excluded = ["value", "type", "path", "parent"];
2
- 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; }
3
- 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; }
4
- 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; }
5
- 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; }
6
- 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; }
7
1
  import cloneDeep from 'lodash/cloneDeep.js';
8
2
  import get from 'lodash/get.js';
9
3
  import { isKeyedObject, isReference, isPortableTextTextBlock, isBlockSchemaType, isSpanSchemaType, isTypedObject } from '@sanity/types';
@@ -227,16 +221,18 @@ const genericValidators = {
227
221
  return result;
228
222
  }
229
223
  };
230
- const booleanValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
224
+ const booleanValidators = {
225
+ ...genericValidators,
231
226
  presence: (flag, value, message) => {
232
227
  if (flag === "required" && typeof value !== "boolean") {
233
228
  return message || "Required";
234
229
  }
235
230
  return true;
236
231
  }
237
- });
232
+ };
238
233
  const precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
239
- const numberValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
234
+ const numberValidators = {
235
+ ...genericValidators,
240
236
  integer: (_unused, value, message) => {
241
237
  if (!Number.isInteger(value)) {
242
238
  return message || "Must be an integer";
@@ -276,11 +272,12 @@ const numberValidators = _objectSpread(_objectSpread({}, genericValidators), {},
276
272
  }
277
273
  return message || "Must be less than ".concat(maxNum);
278
274
  }
279
- });
275
+ };
280
276
  const DUMMY_ORIGIN = "http://sanity";
281
277
  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,}))$/;
282
278
  const isRelativeUrl = url => /^\.*\//.test(url);
283
- const stringValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
279
+ const stringValidators = {
280
+ ...genericValidators,
284
281
  min: (minLength, value, message) => {
285
282
  if (!value || value.length >= minLength) {
286
283
  return true;
@@ -370,8 +367,9 @@ const stringValidators = _objectSpread(_objectSpread({}, genericValidators), {},
370
367
  }
371
368
  return message || "Must be a valid email address";
372
369
  }
373
- });
374
- const arrayValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
370
+ };
371
+ const arrayValidators = {
372
+ ...genericValidators,
375
373
  min: (minLength, value, message) => {
376
374
  if (!value || value.length >= minLength) {
377
375
  return true;
@@ -447,9 +445,10 @@ const arrayValidators = _objectSpread(_objectSpread({}, genericValidators), {},
447
445
  paths
448
446
  }) : true;
449
447
  }
450
- });
448
+ };
451
449
  const metaKeys = ["_key", "_type", "_weak"];
452
- const objectValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
450
+ const objectValidators = {
451
+ ...genericValidators,
453
452
  presence: (expected, value, message) => {
454
453
  if (expected !== "required") {
455
454
  return true;
@@ -495,7 +494,7 @@ const objectValidators = _objectSpread(_objectSpread({}, genericValidators), {},
495
494
  }
496
495
  return true;
497
496
  }
498
- });
497
+ };
499
498
  function isRecord$1(obj) {
500
499
  return typeof obj === "object" && obj !== null && !Array.isArray(obj);
501
500
  }
@@ -529,7 +528,8 @@ function parseDate(date) {
529
528
  }
530
529
  return isInvalid ? null : parsed;
531
530
  }
532
- const dateValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
531
+ const dateValidators = {
532
+ ...genericValidators,
533
533
  type: (_unused, value, message) => {
534
534
  const strVal = "".concat(value);
535
535
  if (!strVal || isoDate.test(value)) {
@@ -567,7 +567,7 @@ const dateValidators = _objectSpread(_objectSpread({}, genericValidators), {}, {
567
567
  const date = getFormattedDate(context.type.name, maxDate, dateTimeOptions);
568
568
  return message || "Must be at or before ".concat(date);
569
569
  }
570
- });
570
+ };
571
571
  var _a;
572
572
  const typeValidators = {
573
573
  Boolean: booleanValidators,
@@ -596,6 +596,7 @@ const Rule = (_a = class {
596
596
  this._message = void 0;
597
597
  this._rules = [];
598
598
  this._fieldRules = void 0;
599
+ // Alias to static method, since we often have access to an _instance_ of a rule but not the actual Rule class
599
600
  this.valueOfField = _a.valueOfField.bind(_a);
600
601
  this._typeDef = typeDef;
601
602
  this.reset();
@@ -673,6 +674,7 @@ const Rule = (_a = class {
673
674
  newRule._level = this._level === "error" ? rule._level : this._level;
674
675
  return newRule;
675
676
  }
677
+ // Validation flag setters
676
678
  type(targetType) {
677
679
  const type = "".concat(targetType.slice(0, 1).toUpperCase()).concat(targetType.slice(1));
678
680
  if (!ruleConstraintTypes$1.includes(type)) {
@@ -697,6 +699,7 @@ const Rule = (_a = class {
697
699
  constraint: children
698
700
  }]);
699
701
  }
702
+ // Shared rules
700
703
  optional() {
701
704
  const rule = this.cloneWithRules([{
702
705
  flag: "presence",
@@ -744,6 +747,7 @@ const Rule = (_a = class {
744
747
  constraint: values
745
748
  }]);
746
749
  }
750
+ // Numbers only
747
751
  integer() {
748
752
  return this.cloneWithRules([{
749
753
  flag: "integer"
@@ -779,6 +783,7 @@ const Rule = (_a = class {
779
783
  constraint: num
780
784
  }]);
781
785
  }
786
+ // String only
782
787
  uppercase() {
783
788
  return this.cloneWithRules([{
784
789
  flag: "stringCasing",
@@ -834,11 +839,13 @@ const Rule = (_a = class {
834
839
  constraint
835
840
  }]);
836
841
  }
842
+ // Array only
837
843
  unique() {
838
844
  return this.cloneWithRules([{
839
845
  flag: "unique"
840
846
  }]);
841
847
  }
848
+ // Objects only
842
849
  reference() {
843
850
  return this.cloneWithRules([{
844
851
  flag: "reference"
@@ -875,7 +882,9 @@ const Rule = (_a = class {
875
882
  if (valueIsEmpty && this._required === "optional") {
876
883
  return EMPTY_ARRAY;
877
884
  }
878
- const rules = this._required === void 0 && valueIsEmpty ? this._rules.filter(curr => curr.flag === "custom") : this._rules;
885
+ const rules =
886
+ // Run only the _custom_ functions if the rule is not set to required or optional
887
+ this._required === void 0 && valueIsEmpty ? this._rules.filter(curr => curr.flag === "custom") : this._rules;
879
888
  const validators = this._type && typeValidators[this._type] || genericValidators;
880
889
  const results = await Promise.all(rules.map(async curr => {
881
890
  if (curr.flag === void 0) {
@@ -992,11 +1001,12 @@ const slugValidator = async (value, context) => {
992
1001
  }
993
1002
  const options = (_a = context == null ? void 0 : context.type) == null ? void 0 : _a.options;
994
1003
  const isUnique = (options == null ? void 0 : options.isUnique) || defaultIsUnique;
995
- const slugContext = _objectSpread(_objectSpread({}, context), {}, {
1004
+ const slugContext = {
1005
+ ...context,
996
1006
  parent: context.parent,
997
1007
  type: context.type,
998
1008
  defaultIsUnique
999
- });
1009
+ };
1000
1010
  const wasUnique = await isUnique(slugValue, slugContext);
1001
1011
  if (wasUnique) {
1002
1012
  return true;
@@ -1024,7 +1034,15 @@ function baseRuleReducer(inputRule, type) {
1024
1034
  if (isRuleConstraint(type.jsonType)) {
1025
1035
  baseRule = baseRule.type(type.jsonType);
1026
1036
  }
1027
- const typeOptionsList = (type == null ? void 0 : type.options) && typeof type.options === "object" && "list" in type.options && type.options.list;
1037
+ const typeOptionsList =
1038
+ // if type.options is truthy
1039
+ (type == null ? void 0 : type.options) &&
1040
+ // and type.options is an object (non-null from the previous)
1041
+ typeof type.options === "object" &&
1042
+ // and if `list` is in options
1043
+ "list" in type.options &&
1044
+ // then finally access the list
1045
+ type.options.list;
1028
1046
  if (Array.isArray(typeOptionsList)) {
1029
1047
  baseRule = baseRule.valid(typeOptionsList.map(option => extractValueFromListOption(option, type)));
1030
1048
  }
@@ -1053,23 +1071,27 @@ function normalizeValidationRules(typeDef) {
1053
1071
  }
1054
1072
  const validation = typeDef.validation;
1055
1073
  if (Array.isArray(validation)) {
1056
- return validation.flatMap(i => normalizeValidationRules(_objectSpread(_objectSpread({}, typeDef), {}, {
1074
+ return validation.flatMap(i => normalizeValidationRules({
1075
+ ...typeDef,
1057
1076
  validation: i
1058
- })));
1077
+ }));
1059
1078
  }
1060
1079
  if (validation instanceof Rule) {
1061
1080
  return [validation];
1062
1081
  }
1063
- const baseRule = Object.values(getTypeChain(typeDef, /* @__PURE__ */new Set()).reduce((acc, type) => {
1082
+ const baseRule =
1083
+ // using an object + Object.values to de-dupe the type chain by type name
1084
+ Object.values(getTypeChain(typeDef, /* @__PURE__ */new Set()).reduce((acc, type) => {
1064
1085
  acc[type.name] = type;
1065
1086
  return acc;
1066
1087
  }, {})).reduce(baseRuleReducer, new Rule(typeDef));
1067
1088
  if (!validation) {
1068
1089
  return [baseRule];
1069
1090
  }
1070
- return normalizeValidationRules(_objectSpread(_objectSpread({}, typeDef), {}, {
1091
+ return normalizeValidationRules({
1092
+ ...typeDef,
1071
1093
  validation: validation(baseRule)
1072
- }));
1094
+ });
1073
1095
  }
1074
1096
  const isRecord = maybeRecord => typeof maybeRecord === "object" && maybeRecord !== null && !Array.isArray(maybeRecord);
1075
1097
  const isNonNullable = value => value !== null && value !== void 0;
@@ -1131,22 +1153,25 @@ function validateDocumentObservable(getClient, doc, schema, context) {
1131
1153
  }
1132
1154
  function validateItemObservable(_ref) {
1133
1155
  let {
1134
- value,
1135
- type,
1136
- path = [],
1137
- parent
1138
- } = _ref,
1139
- restOfContext = _objectWithoutProperties(_ref, _excluded);
1156
+ value,
1157
+ type,
1158
+ path = [],
1159
+ parent,
1160
+ ...restOfContext
1161
+ } = _ref;
1140
1162
  var _a;
1141
1163
  const rules = normalizeValidationRules(type);
1142
- const selfChecks = rules.map(rule => defer(() => rule.validate(value, _objectSpread(_objectSpread({}, restOfContext), {}, {
1164
+ const selfChecks = rules.map(rule => defer(() => rule.validate(value, {
1165
+ ...restOfContext,
1143
1166
  parent,
1144
1167
  path,
1145
1168
  type
1146
- }))));
1169
+ })));
1147
1170
  let nestedChecks = [];
1148
1171
  const selfIsRequired = rules.some(rule => rule.isRequired());
1149
- const shouldRunNestedObjectValidation = (type == null ? void 0 : type.jsonType) === "object" && (!!value || (value === null || value === void 0) && selfIsRequired);
1172
+ const shouldRunNestedObjectValidation =
1173
+ // run nested validation for objects
1174
+ (type == null ? void 0 : type.jsonType) === "object" && (!!value || (value === null || value === void 0) && selfIsRequired);
1150
1175
  if (shouldRunNestedObjectValidation) {
1151
1176
  const fieldTypes = type.fields.reduce((acc, field) => {
1152
1177
  acc[field.name] = field.type;
@@ -1155,34 +1180,38 @@ function validateItemObservable(_ref) {
1155
1180
  nestedChecks = nestedChecks.concat(rules.map(rule => rule._fieldRules).filter(isNonNullable).flatMap(fieldResults => Object.entries(fieldResults)).flatMap(_ref2 => {
1156
1181
  let [name, validation] = _ref2;
1157
1182
  const fieldType = fieldTypes[name];
1158
- return normalizeValidationRules(_objectSpread(_objectSpread({}, fieldType), {}, {
1183
+ return normalizeValidationRules({
1184
+ ...fieldType,
1159
1185
  validation
1160
- })).map(subRule => {
1186
+ }).map(subRule => {
1161
1187
  const nestedValue = isRecord(value) ? value[name] : void 0;
1162
- return defer(() => subRule.validate(nestedValue, _objectSpread(_objectSpread({}, restOfContext), {}, {
1188
+ return defer(() => subRule.validate(nestedValue, {
1189
+ ...restOfContext,
1163
1190
  parent: value,
1164
1191
  path: path.concat(name),
1165
1192
  type: fieldType
1166
- })));
1193
+ }));
1167
1194
  });
1168
1195
  }));
1169
- nestedChecks = nestedChecks.concat(type.fields.map(field => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
1196
+ nestedChecks = nestedChecks.concat(type.fields.map(field => validateItemObservable({
1197
+ ...restOfContext,
1170
1198
  parent: value,
1171
1199
  value: isRecord(value) ? value[field.name] : void 0,
1172
1200
  path: path.concat(field.name),
1173
1201
  type: field.type
1174
- }))));
1202
+ })));
1175
1203
  }
1176
1204
  const shouldRunNestedValidationForArrays = (type == null ? void 0 : type.jsonType) === "array" && Array.isArray(value);
1177
1205
  if (shouldRunNestedValidationForArrays) {
1178
- nestedChecks = nestedChecks.concat(value.map((item, index) => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
1206
+ nestedChecks = nestedChecks.concat(value.map((item, index) => validateItemObservable({
1207
+ ...restOfContext,
1179
1208
  parent: value,
1180
1209
  value: item,
1181
1210
  path: path.concat(isKeyedObject(item) ? {
1182
1211
  _key: item._key
1183
1212
  } : index),
1184
1213
  type: resolveTypeForArrayItem(item, type.of)
1185
- }))));
1214
+ })));
1186
1215
  }
1187
1216
  const shouldRunNestedValidationForMarkDefs = isPortableTextTextBlock(value) && ((_a = value.markDefs) == null ? void 0 : _a.length) && isBlockSchemaType(type);
1188
1217
  if (shouldRunNestedValidationForMarkDefs) {
@@ -1192,14 +1221,15 @@ function validateItemObservable(_ref) {
1192
1221
  acc.set(annotationType.name, annotationType);
1193
1222
  return acc;
1194
1223
  }, /* @__PURE__ */new Map());
1195
- nestedChecks = nestedChecks.concat((value.markDefs || []).map(markDef => validateItemObservable(_objectSpread(_objectSpread({}, restOfContext), {}, {
1224
+ nestedChecks = nestedChecks.concat((value.markDefs || []).map(markDef => validateItemObservable({
1225
+ ...restOfContext,
1196
1226
  parent: value,
1197
1227
  value: markDef,
1198
1228
  path: path.concat(["markDefs", {
1199
1229
  _key: markDef._key
1200
1230
  }]),
1201
1231
  type: annotations.get(markDef._type)
1202
- }))));
1232
+ })));
1203
1233
  }
1204
1234
  return defer(() => merge([...selfChecks, ...nestedChecks])).pipe(mergeMap(validateNode => concat(idle(), validateNode), 40), mergeAll(), toArray(), map(flatten), map(results => {
1205
1235
  if (rules.some(rule => rule._fieldRules)) {