@valbuild/core 0.79.4 → 0.80.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/declarations/src/index.d.ts +4 -3
  2. package/dist/declarations/src/initSchema.d.ts +4 -4
  3. package/dist/declarations/src/schema/array.d.ts +10 -7
  4. package/dist/declarations/src/schema/boolean.d.ts +11 -8
  5. package/dist/declarations/src/schema/date.d.ts +10 -7
  6. package/dist/declarations/src/schema/file.d.ts +11 -8
  7. package/dist/declarations/src/schema/image.d.ts +11 -8
  8. package/dist/declarations/src/schema/index.d.ts +7 -5
  9. package/dist/declarations/src/schema/keyOf.d.ts +13 -10
  10. package/dist/declarations/src/schema/literal.d.ts +11 -8
  11. package/dist/declarations/src/schema/number.d.ts +11 -8
  12. package/dist/declarations/src/schema/object.d.ts +12 -9
  13. package/dist/declarations/src/schema/record.d.ts +11 -8
  14. package/dist/declarations/src/schema/richtext.d.ts +11 -8
  15. package/dist/declarations/src/schema/string.d.ts +13 -7
  16. package/dist/declarations/src/schema/union.d.ts +14 -10
  17. package/dist/declarations/src/source/remote.d.ts +1 -1
  18. package/dist/{index-b03107f7.cjs.dev.js → index-5a7e1014.cjs.dev.js} +505 -284
  19. package/dist/{index-a2affd87.cjs.prod.js → index-74fe6f44.cjs.prod.js} +505 -284
  20. package/dist/{index-7ee9acb3.esm.js → index-bcc230b2.esm.js} +505 -284
  21. package/dist/valbuild-core.cjs.dev.js +1 -1
  22. package/dist/valbuild-core.cjs.prod.js +1 -1
  23. package/dist/valbuild-core.esm.js +1 -1
  24. package/package.json +1 -1
  25. package/patch/dist/valbuild-core-patch.cjs.dev.js +1 -1
  26. package/patch/dist/valbuild-core-patch.cjs.prod.js +1 -1
  27. package/patch/dist/valbuild-core-patch.esm.js +2 -2
@@ -190,6 +190,53 @@ var Schema = /*#__PURE__*/function () {
190
190
  _classCallCheck(this, Schema);
191
191
  }
192
192
  return _createClass(Schema, [{
193
+ key: "executeCustomValidateFunctions",
194
+ value: function executeCustomValidateFunctions(src, customValidateFunctions) {
195
+ var errors = [];
196
+ var _iterator = result._createForOfIteratorHelper(customValidateFunctions),
197
+ _step;
198
+ try {
199
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
200
+ var customValidateFunction = _step.value;
201
+ try {
202
+ var result$1 = customValidateFunction(src);
203
+ if (result$1) {
204
+ errors.push({
205
+ message: result$1,
206
+ value: src
207
+ });
208
+ }
209
+ } catch (err) {
210
+ errors.push({
211
+ message: "Error in custom validate function: ".concat(err instanceof Error ? err.message : String(err)),
212
+ value: src,
213
+ schemaError: true
214
+ });
215
+ }
216
+ }
217
+ } catch (err) {
218
+ _iterator.e(err);
219
+ } finally {
220
+ _iterator.f();
221
+ }
222
+ return errors;
223
+ }
224
+ /**
225
+ * Check if the **root** **type** of source is correct.
226
+ *
227
+ * The difference between assert and validate is:
228
+ * - assert verifies that the root **type** of the source is correct (it does not recurse down). Therefore, assert can be used as a runtime type check.
229
+ * - validate checks the **value** of the source in addition to the type. It recurses down the source.
230
+ *
231
+ * For example assert fails for a StringSchema if the source is not a string,
232
+ * it will not fail if the length is not correct.
233
+ * Validate will check the length and all other constraints.
234
+ *
235
+ * Assert is useful if you have a generic schema and need to make sure the root type is valid.
236
+ * When using assert, you must assert recursively if you want to verify the entire source.
237
+ * For example, if you have an object schema, you must assert each key / value pair manually.
238
+ */
239
+ }, {
193
240
  key: "appendValidationError",
194
241
  value:
195
242
  // remote(): Src extends RemoteCompatibleSource
@@ -200,24 +247,27 @@ var Schema = /*#__PURE__*/function () {
200
247
  // }
201
248
 
202
249
  /** MUTATES! since internal and perf sensitive */
203
- function appendValidationError(current, path, message, value) {
250
+ function appendValidationError(current, path, message, value, schemaError) {
204
251
  if (current) {
205
252
  if (current[path]) {
206
253
  current[path].push({
207
254
  message: message,
208
- value: value
255
+ value: value,
256
+ schemaError: schemaError
209
257
  });
210
258
  } else {
211
259
  current[path] = [{
212
260
  message: message,
213
- value: value
261
+ value: value,
262
+ schemaError: schemaError
214
263
  }];
215
264
  }
216
265
  return current;
217
266
  } else {
218
267
  return _defineProperty({}, path, [{
219
268
  message: message,
220
- value: value
269
+ value: value,
270
+ schemaError: schemaError
221
271
  }]);
222
272
  }
223
273
  }
@@ -332,11 +382,13 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
332
382
  var _this;
333
383
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
334
384
  var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
385
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
335
386
  _classCallCheck(this, FileSchema);
336
387
  _this = _callSuper(this, FileSchema);
337
388
  _this.options = options;
338
389
  _this.opt = opt;
339
390
  _this.isRemote = isRemote;
391
+ _this.customValidateFunctions = customValidateFunctions;
340
392
  return _this;
341
393
  }
342
394
  _inherits(FileSchema, _Schema);
@@ -347,60 +399,66 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
347
399
  }
348
400
  }, {
349
401
  key: "validate",
350
- value: function validate(path, src) {
402
+ value: function validate(validationFunction) {
403
+ return new FileSchema(this.options, this.opt, this.isRemote, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
404
+ }
405
+ }, {
406
+ key: "executeValidate",
407
+ value: function executeValidate(path, src) {
408
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
351
409
  if (this.opt && (src === null || src === undefined)) {
352
- return false;
410
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
353
411
  }
354
412
  if (src === null || src === undefined) {
355
- return _defineProperty({}, path, [{
413
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
356
414
  message: "Non-optional file was null or undefined.",
357
415
  value: src
358
- }]);
416
+ }]));
359
417
  }
360
418
  if (typeof src[FILE_REF_PROP] !== "string") {
361
- return _defineProperty({}, path, [{
419
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
362
420
  message: "File did not have a file reference string. Got: ".concat(_typeof(src[FILE_REF_PROP])),
363
421
  value: src
364
- }]);
422
+ }]));
365
423
  }
366
424
  if (this.isRemote && src[VAL_EXTENSION] !== "remote") {
367
- return _defineProperty({}, path, [{
425
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
368
426
  message: "Expected a remote file, but got a local file.",
369
427
  value: src,
370
428
  fixes: ["file:upload-remote"]
371
- }]);
429
+ }]));
372
430
  }
373
431
  if (this.isRemote && src[VAL_EXTENSION] === "remote") {
374
- return _defineProperty({}, path, [{
432
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
375
433
  message: "Remote file was not checked.",
376
434
  value: src,
377
435
  fixes: ["file:check-remote"]
378
- }]);
436
+ }]));
379
437
  }
380
438
  if (!this.isRemote && src[VAL_EXTENSION] === "remote") {
381
- return _defineProperty({}, path, [{
439
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
382
440
  message: "Expected locale file, but found remote.",
383
441
  value: src,
384
442
  fixes: ["file:download-remote"]
385
- }]);
443
+ }]));
386
444
  }
387
445
  if (src[VAL_EXTENSION] !== "file") {
388
- return _defineProperty({}, path, [{
446
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
389
447
  message: "File did not have the valid file extension type. Got: ".concat(src[VAL_EXTENSION]),
390
448
  value: src,
391
449
  fixes: ["file:change-extension", "file:check-metadata"]
392
- }]);
450
+ }]));
393
451
  }
394
- var _ref7 = this.options || {},
395
- accept = _ref7.accept;
396
- var _ref8 = src.metadata || {},
397
- mimeType = _ref8.mimeType;
452
+ var _ref8 = this.options || {},
453
+ accept = _ref8.accept;
454
+ var _ref9 = src.metadata || {},
455
+ mimeType = _ref9.mimeType;
398
456
  if (accept && mimeType && !mimeType.includes("/")) {
399
- return _defineProperty({}, path, [{
457
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
400
458
  message: "Invalid mime type format. Got: ".concat(mimeType),
401
459
  value: src,
402
460
  fixes: ["file:change-extension", "file:check-metadata"]
403
- }]);
461
+ }]));
404
462
  }
405
463
  if (accept && mimeType && mimeType.includes("/")) {
406
464
  var acceptedTypes = accept.split(",").map(function (type) {
@@ -417,45 +475,45 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
417
475
  return acceptedType === mimeType;
418
476
  });
419
477
  if (!isValidMimeType) {
420
- return _defineProperty({}, path, [{
478
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
421
479
  message: "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'"),
422
480
  value: src,
423
481
  fixes: ["file:change-extension", "file:check-metadata"]
424
- }]);
482
+ }]));
425
483
  }
426
484
  }
427
485
  var fileMimeType = Internal.filenameToMimeType(src[FILE_REF_PROP]);
428
486
  if (!fileMimeType) {
429
- return _defineProperty({}, path, [{
487
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
430
488
  message: "Could not determine mime type from file extension. Got: ".concat(src[FILE_REF_PROP]),
431
489
  value: src,
432
490
  fixes: ["file:change-extension", "file:check-metadata"]
433
- }]);
491
+ }]));
434
492
  }
435
493
  if (fileMimeType !== mimeType) {
436
- return _defineProperty({}, path, [{
494
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
437
495
  message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
438
496
  value: src,
439
497
  fixes: ["file:change-extension", "file:check-metadata"]
440
- }]);
498
+ }]));
441
499
  }
442
500
  if (src.metadata) {
443
- return _defineProperty({}, path, [{
501
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
444
502
  message: "Found metadata, but it could not be validated. File metadata must be an object with the mimeType.",
445
503
  // These validation errors will have to be picked up by logic outside of this package and revalidated. Reasons: 1) we have to read files to verify the metadata, which is handled differently in different runtimes (Browser, QuickJS, Node.js); 2) we want to keep this package dependency free.
446
504
  value: src,
447
505
  fixes: ["file:check-metadata"]
448
- }]);
506
+ }]));
449
507
  }
450
- return _defineProperty({}, path, [{
508
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
451
509
  message: "Missing File metadata.",
452
510
  value: src,
453
511
  fixes: ["file:add-metadata"]
454
- }]);
512
+ }]));
455
513
  }
456
514
  }, {
457
- key: "assert",
458
- value: function assert(path, src) {
515
+ key: "executeAssert",
516
+ value: function executeAssert(path, src) {
459
517
  if (this.opt && src === null) {
460
518
  return {
461
519
  success: true,
@@ -509,13 +567,15 @@ var FileSchema = /*#__PURE__*/function (_Schema) {
509
567
  return new FileSchema(this.options, true);
510
568
  }
511
569
  }, {
512
- key: "serialize",
513
- value: function serialize() {
570
+ key: "executeSerialize",
571
+ value: function executeSerialize() {
572
+ var _this$customValidateF;
514
573
  return {
515
574
  type: "file",
516
575
  options: this.options,
517
576
  opt: this.opt,
518
- remote: this.isRemote
577
+ remote: this.isRemote,
578
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
519
579
  };
520
580
  }
521
581
  }, {
@@ -612,22 +672,27 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
612
672
  function ObjectSchema(items) {
613
673
  var _this;
614
674
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
675
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
615
676
  _classCallCheck(this, ObjectSchema);
616
677
  _this = _callSuper(this, ObjectSchema);
617
678
  _this.items = items;
618
679
  _this.opt = opt;
680
+ _this.customValidateFunctions = customValidateFunctions;
619
681
  return _this;
620
682
  }
621
683
  _inherits(ObjectSchema, _Schema);
622
684
  return _createClass(ObjectSchema, [{
623
685
  key: "validate",
624
- value: function validate(path, src) {
625
- var _this2 = this;
686
+ value: function validate(validationFunction) {
687
+ return new ObjectSchema(this.items, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
688
+ }
689
+ }, {
690
+ key: "executeValidate",
691
+ value: function executeValidate(path, src) {
626
692
  var error = false;
627
-
628
- // TODO: src should never be undefined
693
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
629
694
  if (this.opt && (src === null || src === undefined)) {
630
- return false;
695
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
631
696
  }
632
697
  if (src === null) {
633
698
  return _defineProperty({}, path, [{
@@ -643,29 +708,41 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
643
708
  message: "Expected 'object', got 'array'"
644
709
  }]);
645
710
  }
646
- Object.entries(this.items).forEach(function (_ref4) {
647
- var _ref5 = _slicedToArray(_ref4, 2),
648
- key = _ref5[0],
649
- schema = _ref5[1];
650
- var subPath = createValPathOfItem(path, key);
711
+ var _iterator = result._createForOfIteratorHelper(customValidationErrors),
712
+ _step;
713
+ try {
714
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
715
+ var customValidationError = _step.value;
716
+ error = this.appendValidationError(error, path, customValidationError.message, src, customValidationError.schemaError);
717
+ }
718
+ } catch (err) {
719
+ _iterator.e(err);
720
+ } finally {
721
+ _iterator.f();
722
+ }
723
+ for (var _i = 0, _Object$entries = Object.entries(this.items); _i < _Object$entries.length; _i++) {
724
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
725
+ _key = _Object$entries$_i[0],
726
+ schema = _Object$entries$_i[1];
727
+ var subPath = createValPathOfItem(path, _key);
651
728
  if (!subPath) {
652
- error = _this2.appendValidationError(error, path, "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(key),
729
+ error = this.appendValidationError(error, path, "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(_key),
653
730
  // Should! never happen
654
731
  src);
655
732
  } else {
656
- var subError = schema.validate(subPath, src[key]);
733
+ var subError = schema["executeValidate"](subPath, src[_key]);
657
734
  if (subError && error) {
658
735
  error = _objectSpread2(_objectSpread2({}, subError), error);
659
736
  } else if (subError) {
660
737
  error = subError;
661
738
  }
662
739
  }
663
- });
740
+ }
664
741
  return error;
665
742
  }
666
743
  }, {
667
- key: "assert",
668
- value: function assert(path, src) {
744
+ key: "executeAssert",
745
+ value: function executeAssert(path, src) {
669
746
  if (this.opt && src === null) {
670
747
  return {
671
748
  success: true,
@@ -699,18 +776,18 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
699
776
  };
700
777
  }
701
778
  var errorsAtPath = [];
702
- for (var _i = 0, _Object$keys = Object.keys(this.items); _i < _Object$keys.length; _i++) {
703
- var _key = _Object$keys[_i];
704
- var subPath = createValPathOfItem(path, _key);
779
+ for (var _i2 = 0, _Object$keys = Object.keys(this.items); _i2 < _Object$keys.length; _i2++) {
780
+ var _key2 = _Object$keys[_i2];
781
+ var subPath = createValPathOfItem(path, _key2);
705
782
  if (!subPath) {
706
783
  errorsAtPath.push({
707
- message: "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(_key),
784
+ message: "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(_key2),
708
785
  // Should! never happen
709
786
  internalError: true
710
787
  });
711
- } else if (!(_key in src)) {
788
+ } else if (!(_key2 in src)) {
712
789
  errorsAtPath.push({
713
- message: "Expected key '".concat(_key, "' not found in object"),
790
+ message: "Expected key '".concat(_key2, "' not found in object"),
714
791
  typeError: true
715
792
  });
716
793
  }
@@ -732,17 +809,19 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
732
809
  return new ObjectSchema(this.items, true);
733
810
  }
734
811
  }, {
735
- key: "serialize",
736
- value: function serialize() {
812
+ key: "executeSerialize",
813
+ value: function executeSerialize() {
814
+ var _this$customValidateF;
737
815
  return {
738
816
  type: "object",
739
- items: Object.fromEntries(Object.entries(this.items).map(function (_ref6) {
740
- var _ref7 = _slicedToArray(_ref6, 2),
741
- key = _ref7[0],
742
- schema = _ref7[1];
743
- return [key, schema.serialize()];
817
+ items: Object.fromEntries(Object.entries(this.items).map(function (_ref5) {
818
+ var _ref6 = _slicedToArray(_ref5, 2),
819
+ key = _ref6[0],
820
+ schema = _ref6[1];
821
+ return [key, schema["executeSerialize"]()];
744
822
  })),
745
- opt: this.opt
823
+ opt: this.opt,
824
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
746
825
  };
747
826
  }
748
827
  }, {
@@ -752,16 +831,16 @@ var ObjectSchema = /*#__PURE__*/function (_Schema) {
752
831
  if (src === null) {
753
832
  return res;
754
833
  }
755
- for (var _key2 in this.items) {
756
- var itemSrc = src[_key2];
834
+ for (var _key3 in this.items) {
835
+ var itemSrc = src[_key3];
757
836
  if (itemSrc === null || itemSrc === undefined) {
758
837
  continue;
759
838
  }
760
- var subPath = unsafeCreateSourcePath(sourcePath, _key2);
761
- var itemResult = this.items[_key2]["executePreview"](subPath, itemSrc);
839
+ var subPath = unsafeCreateSourcePath(sourcePath, _key3);
840
+ var itemResult = this.items[_key3]["executePreview"](subPath, itemSrc);
762
841
  for (var keyS in itemResult) {
763
- var _key3 = keyS;
764
- res[_key3] = itemResult[_key3];
842
+ var _key4 = keyS;
843
+ res[_key4] = itemResult[_key4];
765
844
  }
766
845
  }
767
846
  return res;
@@ -776,18 +855,25 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
776
855
  function ArraySchema(item) {
777
856
  var _this;
778
857
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
858
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
779
859
  _classCallCheck(this, ArraySchema);
780
860
  _this = _callSuper(this, ArraySchema);
781
861
  _defineProperty(_this, "previewInput", null);
782
862
  _this.item = item;
783
863
  _this.opt = opt;
864
+ _this.customValidateFunctions = customValidateFunctions;
784
865
  return _this;
785
866
  }
786
867
  _inherits(ArraySchema, _Schema);
787
868
  return _createClass(ArraySchema, [{
788
869
  key: "validate",
789
- value: function validate(path, src) {
790
- var assertRes = this.assert(path, src);
870
+ value: function validate(validationFunction) {
871
+ return new ArraySchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
872
+ }
873
+ }, {
874
+ key: "executeValidate",
875
+ value: function executeValidate(path, src) {
876
+ var assertRes = this.executeAssert(path, src);
791
877
  if (!assertRes.success) {
792
878
  return assertRes.errors;
793
879
  }
@@ -801,7 +887,7 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
801
887
  i = _Object$entries$_i[1];
802
888
  var subPath = unsafeCreateSourcePath(path, Number(idx));
803
889
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
804
- var subError = this.item.validate(subPath, i);
890
+ var subError = this.item["executeValidate"](subPath, i);
805
891
  if (subError) {
806
892
  error = _objectSpread2(_objectSpread2({}, subError), error);
807
893
  }
@@ -812,8 +898,8 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
812
898
  return error;
813
899
  }
814
900
  }, {
815
- key: "assert",
816
- value: function assert(path, src) {
901
+ key: "executeAssert",
902
+ value: function executeAssert(path, src) {
817
903
  if (src === null && this.opt) {
818
904
  return {
819
905
  success: true,
@@ -857,12 +943,14 @@ var ArraySchema = /*#__PURE__*/function (_Schema) {
857
943
  return new ArraySchema(this.item, true);
858
944
  }
859
945
  }, {
860
- key: "serialize",
861
- value: function serialize() {
946
+ key: "executeSerialize",
947
+ value: function executeSerialize() {
948
+ var _this$customValidateF;
862
949
  return {
863
950
  type: "array",
864
- item: this.item.serialize(),
865
- opt: this.opt
951
+ item: this.item["executeSerialize"](),
952
+ opt: this.opt,
953
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
866
954
  };
867
955
  }
868
956
  }, {
@@ -942,36 +1030,47 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
942
1030
  function LiteralSchema(value) {
943
1031
  var _this;
944
1032
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1033
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
945
1034
  _classCallCheck(this, LiteralSchema);
946
1035
  _this = _callSuper(this, LiteralSchema);
947
1036
  _this.value = value;
948
1037
  _this.opt = opt;
1038
+ _this.customValidateFunctions = customValidateFunctions;
949
1039
  return _this;
950
1040
  }
951
1041
  _inherits(LiteralSchema, _Schema);
952
1042
  return _createClass(LiteralSchema, [{
953
1043
  key: "validate",
954
- value: function validate(path, src) {
1044
+ value: function validate(validationFunction) {
1045
+ return new LiteralSchema(this.value, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
1046
+ }
1047
+ }, {
1048
+ key: "executeValidate",
1049
+ value: function executeValidate(path, src) {
1050
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
955
1051
  if (this.opt && (src === null || src === undefined)) {
956
- return false;
1052
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
957
1053
  }
958
1054
  if (typeof src !== "string") {
959
- return _defineProperty({}, path, [{
1055
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
960
1056
  message: "Expected 'string', got '".concat(_typeof(src), "'"),
961
1057
  value: src
962
- }]);
1058
+ }]));
963
1059
  }
964
1060
  if (src !== this.value) {
965
- return _defineProperty({}, path, [{
1061
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
966
1062
  message: "Expected literal '".concat(this.value, "', got '").concat(src, "'"),
967
1063
  value: src
968
- }]);
1064
+ }]));
1065
+ }
1066
+ if (customValidationErrors.length > 0) {
1067
+ return _defineProperty({}, path, customValidationErrors);
969
1068
  }
970
1069
  return false;
971
1070
  }
972
1071
  }, {
973
- key: "assert",
974
- value: function assert(path, src) {
1072
+ key: "executeAssert",
1073
+ value: function executeAssert(path, src) {
975
1074
  if (this.opt && src === null) {
976
1075
  return {
977
1076
  success: true,
@@ -1007,12 +1106,14 @@ var LiteralSchema = /*#__PURE__*/function (_Schema) {
1007
1106
  return new LiteralSchema(this.value, true);
1008
1107
  }
1009
1108
  }, {
1010
- key: "serialize",
1011
- value: function serialize() {
1109
+ key: "executeSerialize",
1110
+ value: function executeSerialize() {
1111
+ var _this$customValidateF;
1012
1112
  return {
1013
1113
  type: "literal",
1014
1114
  value: this.value,
1015
- opt: this.opt
1115
+ opt: this.opt,
1116
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
1016
1117
  };
1017
1118
  }
1018
1119
  }, {
@@ -1030,80 +1131,87 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1030
1131
  function UnionSchema(key, items) {
1031
1132
  var _this;
1032
1133
  var opt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1134
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
1033
1135
  _classCallCheck(this, UnionSchema);
1034
1136
  _this = _callSuper(this, UnionSchema);
1035
1137
  _this.key = key;
1036
1138
  _this.items = items;
1037
1139
  _this.opt = opt;
1140
+ _this.customValidateFunctions = customValidateFunctions;
1038
1141
  return _this;
1039
1142
  }
1040
1143
  _inherits(UnionSchema, _Schema);
1041
1144
  return _createClass(UnionSchema, [{
1042
1145
  key: "validate",
1043
- value: function validate(path, src) {
1146
+ value: function validate(validationFunction) {
1147
+ return new UnionSchema(this.key, this.items, this.opt, this.customValidateFunctions.concat(validationFunction));
1148
+ }
1149
+ }, {
1150
+ key: "executeValidate",
1151
+ value: function executeValidate(path, src) {
1152
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
1044
1153
  var unknownSrc = src;
1045
- var errors = false;
1046
1154
  if (this.opt && unknownSrc === null) {
1047
- return false;
1155
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
1048
1156
  }
1049
1157
  if (!this.key) {
1050
- return _defineProperty({}, path, [{
1158
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1051
1159
  message: "Missing required first argument in union",
1052
1160
  schemaError: true
1053
- }]);
1161
+ }]));
1054
1162
  }
1055
1163
  var key = this.key;
1056
1164
  if (!Array.isArray(this.items)) {
1057
- return _defineProperty({}, path, [{
1165
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1058
1166
  message: "A union schema must take more than 1 schema arguments",
1059
1167
  schemaError: true
1060
- }]);
1168
+ }]));
1061
1169
  }
1062
1170
  if (typeof key === "string") {
1063
1171
  // tagged union
1064
1172
  if (this.items.some(function (item) {
1065
1173
  return !(item instanceof ObjectSchema);
1066
1174
  })) {
1067
- return _defineProperty({}, path, [{
1175
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1068
1176
  message: "Key is a string, so all schema items must be objects",
1069
1177
  schemaError: true
1070
- }]);
1178
+ }]));
1071
1179
  }
1072
1180
  var objectSchemas = this.items;
1073
1181
  var serializedSchemas = objectSchemas.map(function (schema) {
1074
- return schema.serialize();
1182
+ return schema["executeSerialize"]();
1075
1183
  });
1076
1184
  var illegalSchemas = serializedSchemas.filter(function (schema) {
1077
1185
  return !(schema.type === "object") || !(schema.items[key].type === "literal");
1078
1186
  });
1079
1187
  if (illegalSchemas.length > 0) {
1080
- return _defineProperty({}, path, [{
1188
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1081
1189
  message: "All schema items must be objects with a key: ".concat(key, " that is a literal schema. Found: ").concat(JSON.stringify(illegalSchemas, null, 2)),
1082
1190
  schemaError: true
1083
- }]);
1191
+ }]));
1084
1192
  }
1085
1193
  var serializedObjectSchemas = serializedSchemas;
1086
1194
  var optionalLiterals = serializedObjectSchemas.filter(function (schema) {
1087
1195
  return schema.items[key].opt;
1088
1196
  });
1089
1197
  if (optionalLiterals.length > 1) {
1090
- return _defineProperty({}, path, [{
1198
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1091
1199
  message: "Schema cannot have an optional keys: ".concat(key),
1092
1200
  schemaError: true
1093
- }]);
1201
+ }]));
1094
1202
  }
1095
1203
  if (_typeof(unknownSrc) !== "object") {
1096
- return _defineProperty({}, path, [{
1204
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1097
1205
  message: "Expected an object",
1098
1206
  typeError: true
1099
- }]);
1207
+ }]));
1100
1208
  }
1101
1209
  var objectSrc = unknownSrc;
1102
1210
  if (objectSrc[key] === undefined) {
1103
- return _defineProperty({}, path, [{
1211
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1104
1212
  message: "Missing required key: ".concat(key),
1105
1213
  typeError: true
1106
- }]);
1214
+ }]));
1107
1215
  }
1108
1216
  var foundSchemaLiterals = [];
1109
1217
  var _iterator = result._createForOfIteratorHelper(serializedObjectSchemas),
@@ -1116,10 +1224,10 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1116
1224
  if (!foundSchemaLiterals.includes(schemaKey.value)) {
1117
1225
  foundSchemaLiterals.push(schemaKey.value);
1118
1226
  } else {
1119
- return _defineProperty({}, path, [{
1227
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1120
1228
  message: "Found duplicate key in schema: ".concat(schemaKey.value),
1121
1229
  schemaError: true
1122
- }]);
1230
+ }]));
1123
1231
  }
1124
1232
  }
1125
1233
  }
@@ -1129,7 +1237,7 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1129
1237
  _iterator.f();
1130
1238
  }
1131
1239
  var objectSchemaAtKey = objectSchemas.find(function (schema) {
1132
- return !schema.items[key].validate(path, objectSrc[key]);
1240
+ return !schema["items"][key]["executeValidate"](path, objectSrc[key]);
1133
1241
  });
1134
1242
  if (!objectSchemaAtKey) {
1135
1243
  var keyPath = createValPathOfItem(path, key);
@@ -1148,7 +1256,7 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1148
1256
  }).join(", "))
1149
1257
  }]);
1150
1258
  }
1151
- var error = objectSchemaAtKey.validate(path, objectSrc);
1259
+ var error = objectSchemaAtKey["executeValidate"](path, objectSrc);
1152
1260
  if (error) {
1153
1261
  return error;
1154
1262
  }
@@ -1164,26 +1272,26 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1164
1272
  var literalItems = [key].concat(_toConsumableArray(this.items));
1165
1273
  if (typeof unknownSrc === "string") {
1166
1274
  var isMatch = literalItems.some(function (item) {
1167
- return !item.validate(path, unknownSrc);
1275
+ return !item["executeValidate"](path, unknownSrc);
1168
1276
  });
1169
1277
  if (!isMatch) {
1170
- return _defineProperty({}, path, [{
1278
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1171
1279
  message: "Union must match one of the following: ".concat(literalItems.map(function (item) {
1172
- return "\"".concat(item.value, "\"");
1280
+ return "\"".concat(item["value"], "\"");
1173
1281
  }).join(", "))
1174
- }]);
1282
+ }]));
1175
1283
  }
1176
1284
  }
1177
1285
  } else {
1178
- return _defineProperty({}, path, [{
1286
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1179
1287
  message: "Expected a string or literal"
1180
- }]);
1288
+ }]));
1181
1289
  }
1182
- return errors;
1290
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
1183
1291
  }
1184
1292
  }, {
1185
- key: "assert",
1186
- value: function assert(path, src) {
1293
+ key: "executeAssert",
1294
+ value: function executeAssert(path, src) {
1187
1295
  if (this.opt && src === null) {
1188
1296
  return {
1189
1297
  success: true,
@@ -1218,10 +1326,10 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1218
1326
  };
1219
1327
  }
1220
1328
  if (this.key instanceof LiteralSchema) {
1221
- var _ref13;
1329
+ var _ref25;
1222
1330
  var success = false;
1223
1331
  var errors = {};
1224
- var _iterator2 = result._createForOfIteratorHelper((_ref13 = [this.key]).concat.apply(_ref13, _toConsumableArray(this.items))),
1332
+ var _iterator2 = result._createForOfIteratorHelper((_ref25 = [this.key]).concat.apply(_ref25, _toConsumableArray(this.items))),
1225
1333
  _step2;
1226
1334
  try {
1227
1335
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
@@ -1242,7 +1350,7 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1242
1350
  }];
1243
1351
  continue;
1244
1352
  }
1245
- var res = itemSchema.assert(path, src);
1353
+ var res = itemSchema["executeAssert"](path, src);
1246
1354
  if (res.success) {
1247
1355
  success = true;
1248
1356
  break;
@@ -1282,7 +1390,7 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1282
1390
  try {
1283
1391
  for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
1284
1392
  var _itemSchema = _step3.value;
1285
- var _res = _itemSchema.assert(path, src);
1393
+ var _res = _itemSchema["executeAssert"](path, src);
1286
1394
  if (_res.success) {
1287
1395
  _success = true;
1288
1396
  break;
@@ -1330,25 +1438,29 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1330
1438
  return new UnionSchema(this.key, this.items, true);
1331
1439
  }
1332
1440
  }, {
1333
- key: "serialize",
1334
- value: function serialize() {
1441
+ key: "executeSerialize",
1442
+ value: function executeSerialize() {
1443
+ var _this$customValidateF2;
1335
1444
  if (typeof this.key === "string") {
1445
+ var _this$customValidateF;
1336
1446
  return {
1337
1447
  type: "union",
1338
1448
  key: this.key,
1339
1449
  items: this.items.map(function (o) {
1340
- return o.serialize();
1450
+ return o["executeSerialize"]();
1341
1451
  }),
1342
- opt: this.opt
1452
+ opt: this.opt,
1453
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
1343
1454
  };
1344
1455
  }
1345
1456
  return {
1346
1457
  type: "union",
1347
- key: this.key.serialize(),
1458
+ key: this.key["executeSerialize"](),
1348
1459
  items: this.items.map(function (o) {
1349
- return o.serialize();
1460
+ return o["executeSerialize"]();
1350
1461
  }),
1351
- opt: this.opt
1462
+ opt: this.opt,
1463
+ customValidate: this.customValidateFunctions && ((_this$customValidateF2 = this.customValidateFunctions) === null || _this$customValidateF2 === void 0 ? void 0 : _this$customValidateF2.length) > 0
1352
1464
  };
1353
1465
  }
1354
1466
  }, {
@@ -1367,9 +1479,9 @@ var UnionSchema = /*#__PURE__*/function (_Schema) {
1367
1479
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1368
1480
  function (item) {
1369
1481
  if (item instanceof ObjectSchema) {
1370
- var itemKey = item.items[unionKey];
1482
+ var itemKey = item["items"][unionKey];
1371
1483
  if (itemKey instanceof LiteralSchema) {
1372
- return _typeof(src) === "object" && unionKey in src && itemKey.value === src[unionKey];
1484
+ return _typeof(src) === "object" && unionKey in src && itemKey["value"] === src[unionKey];
1373
1485
  }
1374
1486
  }
1375
1487
  return false;
@@ -1407,11 +1519,13 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
1407
1519
  var _this;
1408
1520
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1409
1521
  var isRemote = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1522
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
1410
1523
  _classCallCheck(this, ImageSchema);
1411
1524
  _this = _callSuper(this, ImageSchema);
1412
1525
  _this.options = options;
1413
1526
  _this.opt = opt;
1414
1527
  _this.isRemote = isRemote;
1528
+ _this.customValidateFunctions = customValidateFunctions;
1415
1529
  return _this;
1416
1530
  }
1417
1531
  _inherits(ImageSchema, _Schema);
@@ -1422,60 +1536,66 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
1422
1536
  }
1423
1537
  }, {
1424
1538
  key: "validate",
1425
- value: function validate(path, src) {
1539
+ value: function validate(validationFunction) {
1540
+ return new ImageSchema(this.options, this.opt, this.isRemote, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
1541
+ }
1542
+ }, {
1543
+ key: "executeValidate",
1544
+ value: function executeValidate(path, src) {
1545
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
1426
1546
  if (this.opt && (src === null || src === undefined)) {
1427
- return false;
1547
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
1428
1548
  }
1429
1549
  if (src === null || src === undefined) {
1430
- return _defineProperty({}, path, [{
1550
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1431
1551
  message: "Non-optional image was null or undefined.",
1432
1552
  value: src
1433
- }]);
1553
+ }]));
1434
1554
  }
1435
1555
  if (this.isRemote && src[VAL_EXTENSION] !== "remote") {
1436
- return _defineProperty({}, path, [{
1556
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1437
1557
  message: "Expected a remote image, but got a local image.",
1438
1558
  value: src,
1439
1559
  fixes: ["image:upload-remote"]
1440
- }]);
1560
+ }]));
1441
1561
  }
1442
1562
  if (this.isRemote && src[VAL_EXTENSION] === "remote") {
1443
- return _defineProperty({}, path, [{
1563
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1444
1564
  message: "Remote image was not checked.",
1445
1565
  value: src,
1446
1566
  fixes: ["image:check-remote"]
1447
- }]);
1567
+ }]));
1448
1568
  }
1449
1569
  if (!this.isRemote && src[VAL_EXTENSION] === "remote") {
1450
- return _defineProperty({}, path, [{
1570
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1451
1571
  message: "Expected locale image, but found remote.",
1452
1572
  value: src,
1453
1573
  fixes: ["image:download-remote"]
1454
- }]);
1574
+ }]));
1455
1575
  }
1456
1576
  if (typeof src[FILE_REF_PROP] !== "string") {
1457
- return _defineProperty({}, path, [{
1577
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1458
1578
  message: "Image did not have a file reference string. Got: ".concat(_typeof(src[FILE_REF_PROP])),
1459
1579
  value: src
1460
- }]);
1580
+ }]));
1461
1581
  }
1462
1582
  if (src[VAL_EXTENSION] !== "file") {
1463
- return _defineProperty({}, path, [{
1583
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1464
1584
  message: "Image did not have the valid file extension type. Got: ".concat(src[VAL_EXTENSION]),
1465
1585
  value: src,
1466
1586
  fixes: ["image:change-extension", "image:check-metadata"]
1467
- }]);
1587
+ }]));
1468
1588
  }
1469
- var _ref7 = this.options || {},
1470
- accept = _ref7.accept;
1471
- var _ref8 = src.metadata || {},
1472
- mimeType = _ref8.mimeType;
1589
+ var _ref8 = this.options || {},
1590
+ accept = _ref8.accept;
1591
+ var _ref9 = src.metadata || {},
1592
+ mimeType = _ref9.mimeType;
1473
1593
  if (accept && mimeType && !mimeType.includes("/")) {
1474
- return _defineProperty({}, path, [{
1594
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1475
1595
  message: "Invalid mime type format. Got: '".concat(mimeType, "'"),
1476
1596
  value: src,
1477
1597
  fixes: ["image:check-metadata"]
1478
- }]);
1598
+ }]));
1479
1599
  }
1480
1600
  if (accept && mimeType && mimeType.includes("/")) {
1481
1601
  var acceptedTypes = accept.split(",").map(function (type) {
@@ -1492,53 +1612,53 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
1492
1612
  return acceptedType === mimeType;
1493
1613
  });
1494
1614
  if (!isValidMimeType) {
1495
- return _defineProperty({}, path, [{
1615
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1496
1616
  message: "Mime type mismatch. Found '".concat(mimeType, "' but schema accepts '").concat(accept, "'"),
1497
1617
  value: src,
1498
1618
  fixes: ["image:check-metadata"]
1499
- }]);
1619
+ }]));
1500
1620
  }
1501
1621
  }
1502
1622
  var fileMimeType = Internal.filenameToMimeType(src[FILE_REF_PROP]);
1503
1623
  if (!fileMimeType) {
1504
- return _defineProperty({}, path, [{
1624
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1505
1625
  message: "Could not determine mime type from file extension. Got: ".concat(src[FILE_REF_PROP]),
1506
1626
  value: src,
1507
1627
  fixes: ["image:check-metadata"]
1508
- }]);
1628
+ }]));
1509
1629
  }
1510
1630
  if (fileMimeType && mimeType && fileMimeType !== mimeType) {
1511
- return _defineProperty({}, path, [{
1631
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1512
1632
  message: "Mime type and file extension not matching. Mime type is '".concat(mimeType, "' but file extension is '").concat(fileMimeType, "'"),
1513
1633
  value: src,
1514
1634
  fixes: ["image:check-metadata"]
1515
- }]);
1635
+ }]));
1516
1636
  }
1517
1637
  if (src.metadata) {
1518
1638
  if (src.metadata.hotspot) {
1519
1639
  if (_typeof(src.metadata.hotspot) !== "object" || typeof src.metadata.hotspot.x !== "number" || typeof src.metadata.hotspot.y !== "number") {
1520
- return _defineProperty({}, path, [{
1640
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1521
1641
  message: "Hotspot must be an object with x and y as numbers.",
1522
1642
  value: src
1523
- }]);
1643
+ }]));
1524
1644
  }
1525
1645
  }
1526
- return _defineProperty({}, path, [{
1646
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1527
1647
  message: "Found metadata, but it could not be validated. Image metadata must be an object with the required props: width (positive number), height (positive number) and the mime type.",
1528
1648
  // These validation errors will have to be picked up by logic outside of this package and revalidated. Reasons: 1) we have to read files to verify the metadata, which is handled differently in different runtimes (Browser, QuickJS, Node.js); 2) we want to keep this package dependency free.
1529
1649
  value: src,
1530
1650
  fixes: ["image:check-metadata"]
1531
- }]);
1651
+ }]));
1532
1652
  }
1533
- return _defineProperty({}, path, [{
1653
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1534
1654
  message: "Could not validate Image metadata.",
1535
1655
  value: src,
1536
1656
  fixes: ["image:add-metadata"]
1537
- }]);
1657
+ }]));
1538
1658
  }
1539
1659
  }, {
1540
- key: "assert",
1541
- value: function assert(path, src) {
1660
+ key: "executeAssert",
1661
+ value: function executeAssert(path, src) {
1542
1662
  if (this.opt && src === null) {
1543
1663
  return {
1544
1664
  success: true,
@@ -1592,13 +1712,15 @@ var ImageSchema = /*#__PURE__*/function (_Schema) {
1592
1712
  return new ImageSchema(this.options, true, this.isRemote);
1593
1713
  }
1594
1714
  }, {
1595
- key: "serialize",
1596
- value: function serialize() {
1715
+ key: "executeSerialize",
1716
+ value: function executeSerialize() {
1717
+ var _this$customValidateF;
1597
1718
  return {
1598
1719
  type: "image",
1599
1720
  options: this.options,
1600
1721
  opt: this.opt,
1601
- remote: this.isRemote
1722
+ remote: this.isRemote,
1723
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
1602
1724
  };
1603
1725
  }
1604
1726
  }, {
@@ -1616,10 +1738,12 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
1616
1738
  function RichTextSchema(options) {
1617
1739
  var _this;
1618
1740
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1741
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
1619
1742
  _classCallCheck(this, RichTextSchema);
1620
1743
  _this = _callSuper(this, RichTextSchema);
1621
1744
  _this.options = options;
1622
1745
  _this.opt = opt;
1746
+ _this.customValidateFunctions = customValidateFunctions;
1623
1747
  return _this;
1624
1748
  }
1625
1749
  _inherits(RichTextSchema, _Schema);
@@ -1639,28 +1763,37 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
1639
1763
  }
1640
1764
  }, {
1641
1765
  key: "validate",
1642
- value: function validate(path, src) {
1643
- var assertRes = this.assert(path, src);
1766
+ value: function validate(validationFunction) {
1767
+ return new RichTextSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
1768
+ }
1769
+ }, {
1770
+ key: "executeValidate",
1771
+ value: function executeValidate(path, src) {
1772
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
1773
+ var assertRes = this.executeAssert(path, src);
1644
1774
  if (!assertRes.success) {
1645
- return _defineProperty({}, path, assertRes.errors[path]);
1775
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : assertRes.errors;
1646
1776
  }
1647
1777
  var nodes = assertRes.data;
1648
1778
  if (nodes === null && this.opt) {
1649
- return false;
1779
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
1650
1780
  }
1651
1781
  if (nodes === null) {
1652
- return _defineProperty({}, path, [{
1782
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
1653
1783
  message: "Expected 'array', got 'null'",
1654
1784
  typeError: true
1655
- }]);
1785
+ }]));
1656
1786
  }
1657
1787
  var current = {};
1658
1788
  var typeErrorRes = this.internalValidate(path, nodes, current);
1659
1789
  if (typeErrorRes) {
1660
- return typeErrorRes;
1790
+ return customValidationErrors.length > 0 ? _objectSpread2(_defineProperty({}, path, customValidationErrors), typeErrorRes) : typeErrorRes;
1661
1791
  }
1662
1792
  if (Object.keys(current).length > 0) {
1663
- return current;
1793
+ return customValidationErrors.length > 0 ? _objectSpread2(_defineProperty({}, path, customValidationErrors), current) : current;
1794
+ }
1795
+ if (customValidationErrors.length > 0) {
1796
+ return _defineProperty({}, path, customValidationErrors);
1664
1797
  }
1665
1798
  return false;
1666
1799
  }
@@ -1757,7 +1890,7 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
1757
1890
  }]);
1758
1891
  }
1759
1892
  var srcPath = unsafeCreateSourcePath(path, "src");
1760
- var imageValidationErrors = _typeof((_this2$options$inline4 = _this2.options.inline) === null || _this2$options$inline4 === void 0 ? void 0 : _this2$options$inline4.img) === "object" ? (_this2$options$inline5 = _this2.options.inline) === null || _this2$options$inline5 === void 0 ? void 0 : _this2$options$inline5.img.validate(srcPath, node.src) : new ImageSchema({}, false, false).validate(srcPath, node.src);
1893
+ var imageValidationErrors = _typeof((_this2$options$inline4 = _this2.options.inline) === null || _this2$options$inline4 === void 0 ? void 0 : _this2$options$inline4.img) === "object" ? (_this2$options$inline5 = _this2.options.inline) === null || _this2$options$inline5 === void 0 ? void 0 : _this2$options$inline5.img["executeValidate"](srcPath, node.src) : new ImageSchema({}, false, false)["executeValidate"](srcPath, node.src);
1761
1894
  if (imageValidationErrors) {
1762
1895
  for (var validationErrorPathS in imageValidationErrors) {
1763
1896
  var _current$validationEr;
@@ -1880,8 +2013,8 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
1880
2013
  return false;
1881
2014
  }
1882
2015
  }, {
1883
- key: "assert",
1884
- value: function assert(path, src) {
2016
+ key: "executeAssert",
2017
+ value: function executeAssert(path, src) {
1885
2018
  if (this.opt && src === null) {
1886
2019
  return {
1887
2020
  success: true,
@@ -2028,8 +2161,9 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
2028
2161
  return new RichTextSchema(this.options, true);
2029
2162
  }
2030
2163
  }, {
2031
- key: "serialize",
2032
- value: function serialize() {
2164
+ key: "executeSerialize",
2165
+ value: function executeSerialize() {
2166
+ var _this$customValidateF;
2033
2167
  var serializedOptions = {
2034
2168
  maxLength: this.options.maxLength,
2035
2169
  minLength: this.options.minLength,
@@ -2037,13 +2171,14 @@ var RichTextSchema = /*#__PURE__*/function (_Schema) {
2037
2171
  block: this.options.block,
2038
2172
  inline: this.options.inline && {
2039
2173
  a: this.options.inline.a,
2040
- img: this.options.inline.img && _typeof(this.options.inline.img) === "object" ? this.options.inline.img.serialize() : this.options.inline.img
2174
+ img: this.options.inline.img && _typeof(this.options.inline.img) === "object" ? this.options.inline.img["executeSerialize"]() : this.options.inline.img
2041
2175
  }
2042
2176
  };
2043
2177
  return {
2044
2178
  type: "richtext",
2045
2179
  opt: this.opt,
2046
- options: serializedOptions
2180
+ options: serializedOptions,
2181
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
2047
2182
  };
2048
2183
  }
2049
2184
  }, {
@@ -2061,48 +2196,68 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
2061
2196
  function RecordSchema(item) {
2062
2197
  var _this;
2063
2198
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2199
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
2064
2200
  _classCallCheck(this, RecordSchema);
2065
2201
  _this = _callSuper(this, RecordSchema);
2066
2202
  _defineProperty(_this, "previewInput", null);
2067
2203
  _this.item = item;
2068
2204
  _this.opt = opt;
2205
+ _this.customValidateFunctions = customValidateFunctions;
2069
2206
  return _this;
2070
2207
  }
2071
2208
  _inherits(RecordSchema, _Schema);
2072
2209
  return _createClass(RecordSchema, [{
2073
2210
  key: "validate",
2074
- value: function validate(path, src) {
2211
+ value: function validate(validationFunction) {
2212
+ return new RecordSchema(this.item, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
2213
+ }
2214
+ }, {
2215
+ key: "executeValidate",
2216
+ value: function executeValidate(path, src) {
2075
2217
  var _this2 = this;
2076
2218
  var error = false;
2219
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
2077
2220
  if (this.opt && (src === null || src === undefined)) {
2078
- return false;
2221
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
2079
2222
  }
2080
2223
  if (src === null) {
2081
- return _defineProperty({}, path, [{
2224
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2082
2225
  message: "Expected 'object', got 'null'"
2083
- }]);
2226
+ }]));
2084
2227
  }
2085
2228
  if (_typeof(src) !== "object") {
2086
- return _defineProperty({}, path, [{
2229
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2087
2230
  message: "Expected 'object', got '".concat(_typeof(src), "'")
2088
- }]);
2231
+ }]));
2089
2232
  }
2090
2233
  if (Array.isArray(src)) {
2091
- return _defineProperty({}, path, [{
2234
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2092
2235
  message: "Expected 'object', got 'array'"
2093
- }]);
2236
+ }]));
2094
2237
  }
2095
- Object.entries(src).forEach(function (_ref4) {
2096
- var _ref5 = _slicedToArray(_ref4, 2),
2097
- key = _ref5[0],
2098
- elem = _ref5[1];
2238
+ var _iterator = result._createForOfIteratorHelper(customValidationErrors),
2239
+ _step;
2240
+ try {
2241
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
2242
+ var customValidationError = _step.value;
2243
+ error = this.appendValidationError(error, path, customValidationError.message, src, customValidationError.schemaError);
2244
+ }
2245
+ } catch (err) {
2246
+ _iterator.e(err);
2247
+ } finally {
2248
+ _iterator.f();
2249
+ }
2250
+ Object.entries(src).forEach(function (_ref5) {
2251
+ var _ref6 = _slicedToArray(_ref5, 2),
2252
+ key = _ref6[0],
2253
+ elem = _ref6[1];
2099
2254
  var subPath = createValPathOfItem(path, key);
2100
2255
  if (!subPath) {
2101
2256
  error = _this2.appendValidationError(error, path, "Internal error: could not create path at ".concat(!path && typeof path === "string" ? "<empty string>" : path, " at key ").concat(elem),
2102
2257
  // Should! never happen
2103
2258
  src);
2104
2259
  } else {
2105
- var subError = _this2.item.validate(subPath, elem);
2260
+ var subError = _this2.item["executeValidate"](subPath, elem);
2106
2261
  if (subError && error) {
2107
2262
  error = _objectSpread2(_objectSpread2({}, subError), error);
2108
2263
  } else if (subError) {
@@ -2113,8 +2268,8 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
2113
2268
  return error;
2114
2269
  }
2115
2270
  }, {
2116
- key: "assert",
2117
- value: function assert(path, src) {
2271
+ key: "executeAssert",
2272
+ value: function executeAssert(path, src) {
2118
2273
  if (this.opt && src === null) {
2119
2274
  return {
2120
2275
  success: true,
@@ -2150,12 +2305,14 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
2150
2305
  return new RecordSchema(this.item, true);
2151
2306
  }
2152
2307
  }, {
2153
- key: "serialize",
2154
- value: function serialize() {
2308
+ key: "executeSerialize",
2309
+ value: function executeSerialize() {
2310
+ var _this$customValidateF;
2155
2311
  return {
2156
2312
  type: "record",
2157
- item: this.item.serialize(),
2158
- opt: this.opt
2313
+ item: this.item["executeSerialize"](),
2314
+ opt: this.opt,
2315
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
2159
2316
  };
2160
2317
  }
2161
2318
  }, {
@@ -2193,10 +2350,10 @@ var RecordSchema = /*#__PURE__*/function (_Schema) {
2193
2350
  data: {
2194
2351
  layout: "list",
2195
2352
  parent: "record",
2196
- items: Object.entries(src).map(function (_ref6) {
2197
- var _ref7 = _slicedToArray(_ref6, 2),
2198
- key = _ref7[0],
2199
- val = _ref7[1];
2353
+ items: Object.entries(src).map(function (_ref7) {
2354
+ var _ref8 = _slicedToArray(_ref7, 2),
2355
+ key = _ref8[0],
2356
+ val = _ref8[1];
2200
2357
  // NB NB: display is actually defined by the user
2201
2358
  var _prepare = prepare({
2202
2359
  key: key,
@@ -2316,6 +2473,7 @@ function resolvePath(path, valModule, schema) {
2316
2473
  throw Error("Unexpected undefined part");
2317
2474
  }
2318
2475
  if (isArraySchema(resolvedSchema)) {
2476
+ var _resolvedSchema;
2319
2477
  if (Number.isNaN(Number(part))) {
2320
2478
  throw Error("Invalid path: array schema ".concat(JSON.stringify(resolvedSchema), " must have a number as path, but got ").concat(part, ". Path: ").concat(path));
2321
2479
  }
@@ -2323,8 +2481,9 @@ function resolvePath(path, valModule, schema) {
2323
2481
  throw Error("Schema type error: expected source to be type of array, but got ".concat(_typeof(resolvedSource)));
2324
2482
  }
2325
2483
  resolvedSource = resolvedSource[part];
2326
- resolvedSchema = resolvedSchema.item;
2484
+ resolvedSchema = resolvedSchema instanceof ArraySchema ? (_resolvedSchema = resolvedSchema) === null || _resolvedSchema === void 0 ? void 0 : _resolvedSchema["item"] : resolvedSchema.item;
2327
2485
  } else if (isRecordSchema(resolvedSchema)) {
2486
+ var _resolvedSchema2;
2328
2487
  if (typeof part !== "string") {
2329
2488
  throw Error("Invalid path: record schema ".concat(resolvedSchema, " must have path: ").concat(part, " as string"));
2330
2489
  }
@@ -2335,7 +2494,7 @@ function resolvePath(path, valModule, schema) {
2335
2494
  throw Error("Invalid path: record source did not have key ".concat(part, " from path: ").concat(path));
2336
2495
  }
2337
2496
  resolvedSource = resolvedSource[part];
2338
- resolvedSchema = resolvedSchema.item;
2497
+ resolvedSchema = resolvedSchema instanceof RecordSchema ? (_resolvedSchema2 = resolvedSchema) === null || _resolvedSchema2 === void 0 ? void 0 : _resolvedSchema2["item"] : resolvedSchema.item;
2339
2498
  } else if (isObjectSchema(resolvedSchema)) {
2340
2499
  if (_typeof(resolvedSource) !== "object") {
2341
2500
  throw Error("Schema type error: expected source to be type of object, but got ".concat(_typeof(resolvedSource)));
@@ -2344,7 +2503,7 @@ function resolvePath(path, valModule, schema) {
2344
2503
  throw Error("Invalid path: object source did not have key ".concat(part, " from path: ").concat(path));
2345
2504
  }
2346
2505
  resolvedSource = resolvedSource === null ? resolvedSource : resolvedSource[part];
2347
- resolvedSchema = resolvedSchema.items[part];
2506
+ resolvedSchema = resolvedSchema instanceof ObjectSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
2348
2507
  // } else if (isI18nSchema(resolvedSchema)) {
2349
2508
  // if (!resolvedSchema.locales.includes(part)) {
2350
2509
  // throw Error(
@@ -2410,7 +2569,7 @@ function resolvePath(path, valModule, schema) {
2410
2569
  } else if (isRichTextSchema(resolvedSchema)) {
2411
2570
  if ("src" in resolvedSource && "tag" in resolvedSource && resolvedSource.tag === "img" && parts.length === 0) {
2412
2571
  var _resolvedSchema$optio, _resolvedSchema$optio2;
2413
- resolvedSchema = (_resolvedSchema$optio = resolvedSchema.options) !== null && _resolvedSchema$optio !== void 0 && (_resolvedSchema$optio = _resolvedSchema$optio.inline) !== null && _resolvedSchema$optio !== void 0 && _resolvedSchema$optio.img && typeof ((_resolvedSchema$optio2 = resolvedSchema.options) === null || _resolvedSchema$optio2 === void 0 || (_resolvedSchema$optio2 = _resolvedSchema$optio2.inline) === null || _resolvedSchema$optio2 === void 0 ? void 0 : _resolvedSchema$optio2.img) !== "boolean" ? resolvedSchema.options.inline.img : resolvedSchema;
2572
+ resolvedSchema = resolvedSchema instanceof RichTextSchema ? (_resolvedSchema$optio = resolvedSchema["options"]) !== null && _resolvedSchema$optio !== void 0 && (_resolvedSchema$optio = _resolvedSchema$optio.inline) !== null && _resolvedSchema$optio !== void 0 && _resolvedSchema$optio.img && typeof ((_resolvedSchema$optio2 = resolvedSchema["options"]) === null || _resolvedSchema$optio2 === void 0 || (_resolvedSchema$optio2 = _resolvedSchema$optio2.inline) === null || _resolvedSchema$optio2 === void 0 ? void 0 : _resolvedSchema$optio2.img) !== "boolean" ? resolvedSchema["options"].inline.img : resolvedSchema : resolvedSchema;
2414
2573
  }
2415
2574
  resolvedSource = resolvedSource[part];
2416
2575
  } else {
@@ -2457,6 +2616,7 @@ function safeResolvePath(path, valModule, schema) {
2457
2616
  };
2458
2617
  }
2459
2618
  if (isArraySchema(resolvedSchema)) {
2619
+ var _resolvedSchema3;
2460
2620
  if (Number.isNaN(Number(part))) {
2461
2621
  return {
2462
2622
  v: {
@@ -2484,8 +2644,9 @@ function safeResolvePath(path, valModule, schema) {
2484
2644
  };
2485
2645
  }
2486
2646
  resolvedSource = resolvedSource[part];
2487
- resolvedSchema = resolvedSchema.item;
2647
+ resolvedSchema = resolvedSchema instanceof ArraySchema ? (_resolvedSchema3 = resolvedSchema) === null || _resolvedSchema3 === void 0 ? void 0 : _resolvedSchema3["item"] : resolvedSchema.item;
2488
2648
  } else if (isRecordSchema(resolvedSchema)) {
2649
+ var _resolvedSchema4;
2489
2650
  if (typeof part !== "string") {
2490
2651
  return {
2491
2652
  v: {
@@ -2521,7 +2682,7 @@ function safeResolvePath(path, valModule, schema) {
2521
2682
  };
2522
2683
  }
2523
2684
  resolvedSource = resolvedSource[part];
2524
- resolvedSchema = resolvedSchema.item;
2685
+ resolvedSchema = resolvedSchema instanceof RecordSchema ? (_resolvedSchema4 = resolvedSchema) === null || _resolvedSchema4 === void 0 ? void 0 : _resolvedSchema4["item"] : resolvedSchema.item;
2525
2686
  } else if (isObjectSchema(resolvedSchema)) {
2526
2687
  if (resolvedSource === undefined) {
2527
2688
  return {
@@ -2550,7 +2711,7 @@ function safeResolvePath(path, valModule, schema) {
2550
2711
  };
2551
2712
  }
2552
2713
  resolvedSource = resolvedSource === null ? resolvedSource : resolvedSource[part];
2553
- resolvedSchema = resolvedSchema.items[part];
2714
+ resolvedSchema = resolvedSchema instanceof ObjectSchema ? resolvedSchema["items"][part] : resolvedSchema.items[part];
2554
2715
  // } else if (isI18nSchema(resolvedSchema)) {
2555
2716
  // if (!resolvedSchema.locales.includes(part)) {
2556
2717
  // throw Error(
@@ -2628,7 +2789,7 @@ function safeResolvePath(path, valModule, schema) {
2628
2789
  } else if (isRichTextSchema(resolvedSchema)) {
2629
2790
  if ("src" in resolvedSource && "tag" in resolvedSource && resolvedSource.tag === "img" && parts.length === 0) {
2630
2791
  var _resolvedSchema$optio3, _resolvedSchema$optio4;
2631
- resolvedSchema = (_resolvedSchema$optio3 = resolvedSchema.options) !== null && _resolvedSchema$optio3 !== void 0 && (_resolvedSchema$optio3 = _resolvedSchema$optio3.inline) !== null && _resolvedSchema$optio3 !== void 0 && _resolvedSchema$optio3.img && typeof ((_resolvedSchema$optio4 = resolvedSchema.options) === null || _resolvedSchema$optio4 === void 0 || (_resolvedSchema$optio4 = _resolvedSchema$optio4.inline) === null || _resolvedSchema$optio4 === void 0 ? void 0 : _resolvedSchema$optio4.img) !== "boolean" ? resolvedSchema.options.inline.img : resolvedSchema;
2792
+ resolvedSchema = resolvedSchema instanceof RichTextSchema ? (_resolvedSchema$optio3 = resolvedSchema["options"]) !== null && _resolvedSchema$optio3 !== void 0 && (_resolvedSchema$optio3 = _resolvedSchema$optio3.inline) !== null && _resolvedSchema$optio3 !== void 0 && _resolvedSchema$optio3.img && typeof ((_resolvedSchema$optio4 = resolvedSchema["options"]) === null || _resolvedSchema$optio4 === void 0 || (_resolvedSchema$optio4 = _resolvedSchema$optio4.inline) === null || _resolvedSchema$optio4 === void 0 ? void 0 : _resolvedSchema$optio4.img) !== "boolean" ? resolvedSchema["options"].inline.img : resolvedSchema : resolvedSchema;
2632
2793
  }
2633
2794
  resolvedSource = resolvedSource[part];
2634
2795
  } else {
@@ -2734,43 +2895,54 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
2734
2895
  function NumberSchema(options) {
2735
2896
  var _this;
2736
2897
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2898
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
2737
2899
  _classCallCheck(this, NumberSchema);
2738
2900
  _this = _callSuper(this, NumberSchema);
2739
2901
  _this.options = options;
2740
2902
  _this.opt = opt;
2903
+ _this.customValidateFunctions = customValidateFunctions;
2741
2904
  return _this;
2742
2905
  }
2743
2906
  _inherits(NumberSchema, _Schema);
2744
2907
  return _createClass(NumberSchema, [{
2745
2908
  key: "validate",
2746
- value: function validate(path, src) {
2909
+ value: function validate(validationFunction) {
2910
+ return new NumberSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
2911
+ }
2912
+ }, {
2913
+ key: "executeValidate",
2914
+ value: function executeValidate(path, src) {
2747
2915
  var _this$options, _this$options2;
2916
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
2748
2917
  if (this.opt && (src === null || src === undefined)) {
2749
- return false;
2918
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
2750
2919
  }
2751
2920
  if (typeof src !== "number") {
2752
- return _defineProperty({}, path, [{
2921
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2753
2922
  message: "Expected 'number', got '".concat(_typeof(src), "'"),
2754
2923
  value: src
2755
- }]);
2924
+ }]));
2756
2925
  }
2757
2926
  if ((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.max && src > this.options.max) {
2758
- return _defineProperty({}, path, [{
2927
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2759
2928
  message: "Expected 'number' less than ".concat(this.options.max),
2760
2929
  value: src
2761
- }]);
2930
+ }]));
2762
2931
  }
2763
2932
  if ((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.min && src < this.options.min) {
2764
- return _defineProperty({}, path, [{
2933
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
2765
2934
  message: "Expected 'number' greater than ".concat(this.options.min),
2766
2935
  value: src
2767
- }]);
2936
+ }]));
2937
+ }
2938
+ if (customValidationErrors.length > 0) {
2939
+ return _defineProperty({}, path, customValidationErrors);
2768
2940
  }
2769
2941
  return false;
2770
2942
  }
2771
2943
  }, {
2772
- key: "assert",
2773
- value: function assert(path, src) {
2944
+ key: "executeAssert",
2945
+ value: function executeAssert(path, src) {
2774
2946
  if (this.opt && src === null) {
2775
2947
  return {
2776
2948
  success: true,
@@ -2820,12 +2992,14 @@ var NumberSchema = /*#__PURE__*/function (_Schema) {
2820
2992
  }), this.opt);
2821
2993
  }
2822
2994
  }, {
2823
- key: "serialize",
2824
- value: function serialize() {
2995
+ key: "executeSerialize",
2996
+ value: function executeSerialize() {
2997
+ var _this$customValidateF;
2825
2998
  return {
2826
2999
  type: "number",
2827
3000
  options: this.options,
2828
- opt: this.opt
3001
+ opt: this.opt,
3002
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
2829
3003
  };
2830
3004
  }
2831
3005
  }, {
@@ -2844,11 +3018,13 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2844
3018
  var _this;
2845
3019
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2846
3020
  var isRaw = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
3021
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
2847
3022
  _classCallCheck(this, StringSchema);
2848
3023
  _this = _callSuper(this, StringSchema);
2849
3024
  _this.options = options;
2850
3025
  _this.opt = opt;
2851
3026
  _this.isRaw = isRaw;
3027
+ _this.customValidateFunctions = customValidateFunctions;
2852
3028
  return _this;
2853
3029
  }
2854
3030
 
@@ -2886,17 +3062,24 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2886
3062
  }
2887
3063
  }, {
2888
3064
  key: "regexp",
2889
- value: function regexp(_regexp) {
3065
+ value: function regexp(_regexp, message) {
2890
3066
  return new StringSchema(_objectSpread2(_objectSpread2({}, this.options), {}, {
2891
- regexp: _regexp
3067
+ regexp: _regexp,
3068
+ regExpMessage: message
2892
3069
  }), this.opt, this.isRaw);
2893
3070
  }
2894
3071
  }, {
2895
3072
  key: "validate",
2896
- value: function validate(path, src) {
3073
+ value: function validate(validationFunction) {
3074
+ return new StringSchema(this.options, this.opt, this.isRaw, this.customValidateFunctions.concat(validationFunction));
3075
+ }
3076
+ }, {
3077
+ key: "executeValidate",
3078
+ value: function executeValidate(path, src) {
2897
3079
  var _this$options, _this$options2, _this$options3;
3080
+ var errors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
2898
3081
  if (this.opt && (src === null || src === undefined)) {
2899
- return false;
3082
+ return errors.length > 0 ? _defineProperty({}, path, errors) : false;
2900
3083
  }
2901
3084
  if (typeof src !== "string") {
2902
3085
  return _defineProperty({}, path, [{
@@ -2904,7 +3087,6 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2904
3087
  value: src
2905
3088
  }]);
2906
3089
  }
2907
- var errors = [];
2908
3090
  if ((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.maxLength && src.length > this.options.maxLength) {
2909
3091
  errors.push({
2910
3092
  message: "Expected string to be at most ".concat(this.options.maxLength, " characters long, got ").concat(src.length),
@@ -2919,7 +3101,7 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2919
3101
  }
2920
3102
  if ((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.regexp && !this.options.regexp.test(src)) {
2921
3103
  errors.push({
2922
- message: "Expected string to match reg exp: ".concat(this.options.regexp.toString(), ", got '").concat(src, "'"),
3104
+ message: this.options.regExpMessage || "Expected string to match reg exp: ".concat(this.options.regexp.toString(), ", got '").concat(src, "'"),
2923
3105
  value: src
2924
3106
  });
2925
3107
  }
@@ -2929,8 +3111,8 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2929
3111
  return false;
2930
3112
  }
2931
3113
  }, {
2932
- key: "assert",
2933
- value: function assert(path, src) {
3114
+ key: "executeAssert",
3115
+ value: function executeAssert(path, src) {
2934
3116
  if (this.opt && src === null) {
2935
3117
  return {
2936
3118
  success: true,
@@ -2962,21 +3144,24 @@ var StringSchema = /*#__PURE__*/function (_Schema) {
2962
3144
  return new StringSchema(this.options, this.opt, true);
2963
3145
  }
2964
3146
  }, {
2965
- key: "serialize",
2966
- value: function serialize() {
2967
- var _this$options4, _this$options5, _this$options6;
3147
+ key: "executeSerialize",
3148
+ value: function executeSerialize() {
3149
+ var _this$options4, _this$options5, _this$options6, _this$customValidateF, _this$customValidateF2;
2968
3150
  return {
2969
3151
  type: "string",
2970
3152
  options: {
2971
3153
  maxLength: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.maxLength,
2972
3154
  minLength: (_this$options5 = this.options) === null || _this$options5 === void 0 ? void 0 : _this$options5.minLength,
2973
3155
  regexp: ((_this$options6 = this.options) === null || _this$options6 === void 0 ? void 0 : _this$options6.regexp) && {
3156
+ message: this.options.regExpMessage,
2974
3157
  source: this.options.regexp.source,
2975
3158
  flags: this.options.regexp.flags
2976
- }
3159
+ },
3160
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
2977
3161
  },
2978
3162
  opt: this.opt,
2979
- raw: this.isRaw
3163
+ raw: this.isRaw,
3164
+ customValidate: this.customValidateFunctions && ((_this$customValidateF2 = this.customValidateFunctions) === null || _this$customValidateF2 === void 0 ? void 0 : _this$customValidateF2.length) > 0
2980
3165
  };
2981
3166
  }
2982
3167
  }, {
@@ -2994,15 +3179,22 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
2994
3179
  function BooleanSchema() {
2995
3180
  var _this;
2996
3181
  var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
3182
+ var customValidateFunctions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
2997
3183
  _classCallCheck(this, BooleanSchema);
2998
3184
  _this = _callSuper(this, BooleanSchema);
2999
3185
  _this.opt = opt;
3186
+ _this.customValidateFunctions = customValidateFunctions;
3000
3187
  return _this;
3001
3188
  }
3002
3189
  _inherits(BooleanSchema, _Schema);
3003
3190
  return _createClass(BooleanSchema, [{
3004
3191
  key: "validate",
3005
- value: function validate(path, src) {
3192
+ value: function validate(validationFunction) {
3193
+ return new BooleanSchema(this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
3194
+ }
3195
+ }, {
3196
+ key: "executeValidate",
3197
+ value: function executeValidate(path, src) {
3006
3198
  if (this.opt && (src === null || src === undefined)) {
3007
3199
  return false;
3008
3200
  }
@@ -3015,8 +3207,8 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
3015
3207
  return false;
3016
3208
  }
3017
3209
  }, {
3018
- key: "assert",
3019
- value: function assert(path, src) {
3210
+ key: "executeAssert",
3211
+ value: function executeAssert(path, src) {
3020
3212
  if (this.opt && src === null) {
3021
3213
  return {
3022
3214
  success: true,
@@ -3052,11 +3244,13 @@ var BooleanSchema = /*#__PURE__*/function (_Schema) {
3052
3244
  return new BooleanSchema(true);
3053
3245
  }
3054
3246
  }, {
3055
- key: "serialize",
3056
- value: function serialize() {
3247
+ key: "executeSerialize",
3248
+ value: function executeSerialize() {
3249
+ var _this$customValidateF;
3057
3250
  return {
3058
3251
  type: "boolean",
3059
- opt: this.opt
3252
+ opt: this.opt,
3253
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
3060
3254
  };
3061
3255
  }
3062
3256
  }, {
@@ -3074,67 +3268,78 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
3074
3268
  function KeyOfSchema(schema, sourcePath) {
3075
3269
  var _this;
3076
3270
  var opt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
3271
+ var customValidateFunctions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : [];
3077
3272
  _classCallCheck(this, KeyOfSchema);
3078
3273
  _this = _callSuper(this, KeyOfSchema);
3079
3274
  _this.schema = schema;
3080
3275
  _this.sourcePath = sourcePath;
3081
3276
  _this.opt = opt;
3277
+ _this.customValidateFunctions = customValidateFunctions;
3082
3278
  return _this;
3083
3279
  }
3084
3280
  _inherits(KeyOfSchema, _Schema);
3085
3281
  return _createClass(KeyOfSchema, [{
3086
3282
  key: "validate",
3087
- value: function validate(path, src) {
3283
+ value: function validate(validationFunction) {
3284
+ return new KeyOfSchema(this.schema, this.sourcePath, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
3285
+ }
3286
+ }, {
3287
+ key: "executeValidate",
3288
+ value: function executeValidate(path, src) {
3289
+ var customValidationErrors = this.executeCustomValidateFunctions(src, this.customValidateFunctions);
3088
3290
  if (this.opt && (src === null || src === undefined)) {
3089
- return false;
3291
+ return customValidationErrors.length > 0 ? _defineProperty({}, path, customValidationErrors) : false;
3090
3292
  }
3091
3293
  if (!this.schema) {
3092
- return _defineProperty({}, path, [{
3294
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3093
3295
  message: "Schema not found for module. keyOf must be used with a Val Module"
3094
- }]);
3296
+ }]));
3095
3297
  }
3096
3298
  var serializedSchema = this.schema;
3097
3299
  if (!(serializedSchema.type === "object" || serializedSchema.type === "record")) {
3098
- return _defineProperty({}, path, [{
3300
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3099
3301
  message: "Schema in keyOf must be an 'object' or 'record'. Found '".concat(serializedSchema.type, "'")
3100
- }]);
3302
+ }]));
3101
3303
  }
3102
3304
  if (serializedSchema.opt && (src === null || src === undefined)) {
3103
3305
  return false;
3104
3306
  }
3105
3307
  if (serializedSchema.type === "record" && typeof src !== "string") {
3106
- return _defineProperty({}, path, [{
3308
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3107
3309
  message: "Type of value in keyof (record) must be 'string'"
3108
- }]);
3310
+ }]));
3109
3311
  }
3110
3312
  if (serializedSchema.type === "object") {
3111
3313
  var keys = Object.keys(serializedSchema.items);
3112
3314
  if (!keys.includes(src)) {
3113
- return _defineProperty({}, path, [{
3315
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3114
3316
  message: "Value of keyOf (object) must be: ".concat(keys.join(", "), ". Found: ").concat(src)
3115
- }]);
3317
+ }]));
3116
3318
  }
3117
3319
  }
3118
3320
  if (serializedSchema.type === "record") {
3119
3321
  if (typeof src !== "string") {
3120
- return _defineProperty({}, path, [{
3322
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3121
3323
  message: "Value of keyOf (record) must be 'string'. Found: ".concat(_typeof(src))
3122
- }]);
3324
+ }]));
3123
3325
  }
3124
- return _defineProperty({}, path, [{
3326
+ return _defineProperty({}, path, [].concat(_toConsumableArray(customValidationErrors), [{
3125
3327
  fixes: ["keyof:check-keys"],
3126
3328
  message: "Did not validate keyOf (record). This error (keyof:check-keys) should typically be processed by Val internally. Seeing this error most likely means you have a Val version mismatch.",
3127
3329
  value: {
3128
3330
  key: src,
3129
3331
  sourcePath: this.sourcePath
3130
3332
  }
3131
- }]);
3333
+ }]));
3334
+ }
3335
+ if (customValidationErrors.length > 0) {
3336
+ return _defineProperty({}, path, customValidationErrors);
3132
3337
  }
3133
3338
  return false;
3134
3339
  }
3135
3340
  }, {
3136
- key: "assert",
3137
- value: function assert(path, src) {
3341
+ key: "executeAssert",
3342
+ value: function executeAssert(path, src) {
3138
3343
  if (this.opt && src === null) {
3139
3344
  return {
3140
3345
  success: true,
@@ -3205,8 +3410,9 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
3205
3410
  return new KeyOfSchema(this.schema, this.sourcePath, true);
3206
3411
  }
3207
3412
  }, {
3208
- key: "serialize",
3209
- value: function serialize() {
3413
+ key: "executeSerialize",
3414
+ value: function executeSerialize() {
3415
+ var _this$customValidateF;
3210
3416
  var path = this.sourcePath;
3211
3417
  if (!path) {
3212
3418
  throw new Error("Cannot serialize keyOf schema with empty selector. TIP: keyOf must be used with a Val Module of record schema.");
@@ -3231,7 +3437,8 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
3231
3437
  path: path,
3232
3438
  schema: serializedSchema,
3233
3439
  opt: this.opt,
3234
- values: values
3440
+ values: values,
3441
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
3235
3442
  };
3236
3443
  }
3237
3444
  }, {
@@ -3243,23 +3450,30 @@ var KeyOfSchema = /*#__PURE__*/function (_Schema) {
3243
3450
  }(Schema);
3244
3451
  var keyOf = function keyOf(valModule) {
3245
3452
  var _valModule$GetSchema;
3246
- return new KeyOfSchema(valModule === null || valModule === void 0 || (_valModule$GetSchema = valModule[GetSchema]) === null || _valModule$GetSchema === void 0 ? void 0 : _valModule$GetSchema.serialize(), getValPath(valModule));
3453
+ return new KeyOfSchema(valModule === null || valModule === void 0 || (_valModule$GetSchema = valModule[GetSchema]) === null || _valModule$GetSchema === void 0 ? void 0 : _valModule$GetSchema["executeSerialize"](), getValPath(valModule));
3247
3454
  };
3248
3455
 
3249
3456
  var DateSchema = /*#__PURE__*/function (_Schema) {
3250
3457
  function DateSchema(options) {
3251
3458
  var _this;
3252
3459
  var opt = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
3460
+ var customValidateFunctions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
3253
3461
  _classCallCheck(this, DateSchema);
3254
3462
  _this = _callSuper(this, DateSchema);
3255
3463
  _this.options = options;
3256
3464
  _this.opt = opt;
3465
+ _this.customValidateFunctions = customValidateFunctions;
3257
3466
  return _this;
3258
3467
  }
3259
3468
  _inherits(DateSchema, _Schema);
3260
3469
  return _createClass(DateSchema, [{
3261
3470
  key: "validate",
3262
- value: function validate(path, src) {
3471
+ value: function validate(validationFunction) {
3472
+ return new DateSchema(this.options, this.opt, [].concat(_toConsumableArray(this.customValidateFunctions), [validationFunction]));
3473
+ }
3474
+ }, {
3475
+ key: "executeValidate",
3476
+ value: function executeValidate(path, src) {
3263
3477
  var _this$options, _this$options2, _this$options3, _this$options4;
3264
3478
  if (this.opt && (src === null || src === undefined)) {
3265
3479
  return false;
@@ -3309,8 +3523,8 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
3309
3523
  return false;
3310
3524
  }
3311
3525
  }, {
3312
- key: "assert",
3313
- value: function assert(path, src) {
3526
+ key: "executeAssert",
3527
+ value: function executeAssert(path, src) {
3314
3528
  if (this.opt && src === null) {
3315
3529
  return {
3316
3530
  success: true,
@@ -3360,12 +3574,14 @@ var DateSchema = /*#__PURE__*/function (_Schema) {
3360
3574
  return new DateSchema(this.options, true);
3361
3575
  }
3362
3576
  }, {
3363
- key: "serialize",
3364
- value: function serialize() {
3577
+ key: "executeSerialize",
3578
+ value: function executeSerialize() {
3579
+ var _this$customValidateF;
3365
3580
  return {
3366
3581
  type: "date",
3367
3582
  opt: this.opt,
3368
- options: this.options
3583
+ options: this.options,
3584
+ customValidate: this.customValidateFunctions && ((_this$customValidateF = this.customValidateFunctions) === null || _this$customValidateF === void 0 ? void 0 : _this$customValidateF.length) > 0
3369
3585
  };
3370
3586
  }
3371
3587
  }, {
@@ -4808,11 +5024,12 @@ function getFileHash(text) {
4808
5024
  }
4809
5025
 
4810
5026
  function deserializeSchema(serialized) {
4811
- var _serialized$options;
5027
+ var _serialized$options, _serialized$options2;
4812
5028
  switch (serialized.type) {
4813
5029
  case "string":
4814
5030
  return new StringSchema(_objectSpread2(_objectSpread2({}, serialized.options), {}, {
4815
- regexp: ((_serialized$options = serialized.options) === null || _serialized$options === void 0 ? void 0 : _serialized$options.regexp) && new RegExp(serialized.options.regexp.source, serialized.options.regexp.flags)
5031
+ regexp: ((_serialized$options = serialized.options) === null || _serialized$options === void 0 ? void 0 : _serialized$options.regexp) && new RegExp(serialized.options.regexp.source, serialized.options.regexp.flags),
5032
+ regExpMessage: (_serialized$options2 = serialized.options) === null || _serialized$options2 === void 0 || (_serialized$options2 = _serialized$options2.regexp) === null || _serialized$options2 === void 0 ? void 0 : _serialized$options2.message
4816
5033
  }), serialized.opt);
4817
5034
  case "literal":
4818
5035
  return new LiteralSchema(serialized.value, serialized.opt);
@@ -4840,12 +5057,12 @@ function deserializeSchema(serialized) {
4840
5057
  serialized.opt);
4841
5058
  case "richtext":
4842
5059
  {
4843
- var _serialized$options2, _serialized$options3;
5060
+ var _serialized$options3, _serialized$options4;
4844
5061
  var deserializedOptions = _objectSpread2(_objectSpread2({}, serialized.options || {}), {}, {
4845
- inline: _typeof((_serialized$options2 = serialized.options) === null || _serialized$options2 === void 0 || (_serialized$options2 = _serialized$options2.inline) === null || _serialized$options2 === void 0 ? void 0 : _serialized$options2.img) === "object" ? {
5062
+ inline: _typeof((_serialized$options3 = serialized.options) === null || _serialized$options3 === void 0 || (_serialized$options3 = _serialized$options3.inline) === null || _serialized$options3 === void 0 ? void 0 : _serialized$options3.img) === "object" ? {
4846
5063
  a: serialized.options.inline.a,
4847
5064
  img: deserializeSchema(serialized.options.inline.img)
4848
- } : (_serialized$options3 = serialized.options) === null || _serialized$options3 === void 0 ? void 0 : _serialized$options3.inline
5065
+ } : (_serialized$options4 = serialized.options) === null || _serialized$options4 === void 0 ? void 0 : _serialized$options4.inline
4849
5066
  });
4850
5067
  return new RichTextSchema(deserializedOptions, serialized.opt);
4851
5068
  }
@@ -4904,6 +5121,10 @@ var Internal = {
4904
5121
  hashToRemoteFileHash: hashToRemoteFileHash,
4905
5122
  splitRemoteRef: splitRemoteRef
4906
5123
  },
5124
+ validate: function validate(val, path, src) {
5125
+ var _getSchema;
5126
+ return val && ((_getSchema = getSchema(val)) === null || _getSchema === void 0 ? void 0 : _getSchema["executeValidate"](path, src));
5127
+ },
4907
5128
  isVal: isVal,
4908
5129
  isFile: isFile,
4909
5130
  createValPathOfItem: createValPathOfItem,