@serum-enterprises/schema 3.0.0-beta.1 → 3.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -181,6 +181,28 @@ __export(index_exports, {
181
181
  });
182
182
  module.exports = __toCommonJS(index_exports);
183
183
 
184
+ // src/Validator.ts
185
+ var Validator = class {
186
+ validate(data, path = "data") {
187
+ this.assert(data, path);
188
+ return data;
189
+ }
190
+ is(data, path = "data") {
191
+ try {
192
+ this.assert(data, path);
193
+ return true;
194
+ } catch (e) {
195
+ return false;
196
+ }
197
+ }
198
+ };
199
+
200
+ // src/lib/fromJSON.ts
201
+ var import_json7 = __toESM(require_build());
202
+
203
+ // src/validators/JSON.ts
204
+ var import_json = __toESM(require_build());
205
+
184
206
  // src/lib/util.ts
185
207
  var AssertError = class extends Error {
186
208
  };
@@ -188,7 +210,6 @@ var DefinitionError = class extends Error {
188
210
  };
189
211
 
190
212
  // src/validators/JSON.ts
191
- var import_json = __toESM(require_build());
192
213
  var JSONValidator = class _JSONValidator extends Validator {
193
214
  static fromJSON(_definition, _path = "definition") {
194
215
  return new _JSONValidator();
@@ -200,6 +221,9 @@ var JSONValidator = class _JSONValidator extends Validator {
200
221
  isSubset(other) {
201
222
  return other instanceof _JSONValidator;
202
223
  }
224
+ isEquals(other) {
225
+ return other instanceof _JSONValidator;
226
+ }
203
227
  toJSON() {
204
228
  return {
205
229
  type: "json"
@@ -260,6 +284,17 @@ var BooleanValidator = class _BooleanValidator extends Validator {
260
284
  }
261
285
  return true;
262
286
  }
287
+ isEquals(other) {
288
+ if (!(other instanceof _BooleanValidator))
289
+ return false;
290
+ if (this._nullable.isSome() !== other._nullable.isSome())
291
+ return false;
292
+ if (this._equals.isSome() !== other._equals.isSome())
293
+ return false;
294
+ if (this._equals.isSome() && other._equals.isSome() && this._equals.value !== other._equals.value)
295
+ return false;
296
+ return true;
297
+ }
263
298
  toJSON() {
264
299
  const definition = {
265
300
  type: "boolean"
@@ -390,6 +425,27 @@ var NumberValidator = class _NumberValidator extends Validator {
390
425
  return false;
391
426
  return true;
392
427
  }
428
+ isEquals(other) {
429
+ if (!(other instanceof _NumberValidator))
430
+ return false;
431
+ if (this._nullable.isSome() !== other._nullable.isSome())
432
+ return false;
433
+ if (this._integer.isSome() !== other._integer.isSome())
434
+ return false;
435
+ if (this._equals.isSome() !== other._equals.isSome())
436
+ return false;
437
+ if (this._equals.isSome() && other._equals.isSome() && this._equals.value !== other._equals.value)
438
+ return false;
439
+ if (this._min.isSome() !== other._min.isSome())
440
+ return false;
441
+ if (this._min.isSome() && other._min.isSome() && this._min.value !== other._min.value)
442
+ return false;
443
+ if (this._max.isSome() !== other._max.isSome())
444
+ return false;
445
+ if (this._max.isSome() && other._max.isSome() && this._max.value !== other._max.value)
446
+ return false;
447
+ return true;
448
+ }
393
449
  toJSON() {
394
450
  const definition = {
395
451
  type: "number"
@@ -510,6 +566,25 @@ var StringValidator = class _StringValidator extends Validator {
510
566
  return false;
511
567
  return true;
512
568
  }
569
+ isEquals(other) {
570
+ if (!(other instanceof _StringValidator))
571
+ return false;
572
+ if (this._nullable.isSome() !== other._nullable.isSome())
573
+ return false;
574
+ if (this._equals.isSome() !== other._equals.isSome())
575
+ return false;
576
+ if (this._equals.isSome() && other._equals.isSome() && this._equals.value !== other._equals.value)
577
+ return false;
578
+ if (this._min.isSome() !== other._min.isSome())
579
+ return false;
580
+ if (this._min.isSome() && other._min.isSome() && this._min.value !== other._min.value)
581
+ return false;
582
+ if (this._max.isSome() !== other._max.isSome())
583
+ return false;
584
+ if (this._max.isSome() && other._max.isSome() && this._max.value !== other._max.value)
585
+ return false;
586
+ return true;
587
+ }
513
588
  toJSON() {
514
589
  const definition = {
515
590
  type: "string"
@@ -527,230 +602,46 @@ var StringValidator = class _StringValidator extends Validator {
527
602
  };
528
603
 
529
604
  // src/validators/Array.ts
530
- var import_json5 = __toESM(require_build());
531
- var import_option4 = __toESM(require_Option());
532
- var ArrayValidator = class _ArrayValidator extends Validator {
533
- static fromJSON(definition, path = "definition") {
534
- const validatorInstance = new _ArrayValidator();
535
- if ("nullable" in definition) {
536
- if (!import_json5.JSON.isBoolean(definition["nullable"]))
537
- throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
538
- validatorInstance.nullable(definition["nullable"]);
539
- }
540
- if ("min" in definition) {
541
- if (!import_json5.JSON.isNumber(definition["min"]))
542
- throw new DefinitionError(`Expected ${path}.min to be a Number`);
543
- validatorInstance.min(definition["min"], `${path}.min`);
544
- }
545
- if ("max" in definition) {
546
- if (!import_json5.JSON.isNumber(definition["max"]))
547
- throw new DefinitionError(`Expected ${path}.max to be a Number`);
548
- validatorInstance.max(definition["max"], `${path}.max`);
549
- }
550
- if ("every" in definition) {
551
- if (!import_json5.JSON.isObject(definition["every"]))
552
- throw new DefinitionError(`Expected ${path}.every to be an Object`);
553
- validatorInstance.every(
554
- super.fromJSON(definition["every"], `${path}.every`)
555
- );
556
- }
557
- if ("tuple" in definition) {
558
- if (!import_json5.JSON.isShallowArray(definition["tuple"]))
559
- throw new DefinitionError(`Expected ${path}.tuple to be an Array`);
560
- const tupleSchemas = [];
561
- const errors = [];
562
- definition["tuple"].forEach((tupleDef, index) => {
563
- try {
564
- tupleSchemas.push(super.fromJSON(tupleDef, `${path}.tuple[${index}]`));
565
- } catch (e) {
566
- if (!(e instanceof DefinitionError))
567
- throw new DefinitionError(`Fatal Error: Undefined Error thrown by Domain.fromJSON at ${path}`);
568
- errors.push(e);
569
- }
570
- });
571
- if (errors.length > 0)
572
- throw new DefinitionError(`Multiple Definition Errors detected at ${path} (see cause)`, { cause: errors });
573
- validatorInstance.tuple(tupleSchemas, `${path}.tuple`);
574
- }
575
- return validatorInstance;
576
- }
577
- _nullable = import_option4.Option.None();
578
- _every = import_option4.Option.None();
579
- _tuple = import_option4.Option.None();
580
- _min = import_option4.Option.None();
581
- _max = import_option4.Option.None();
582
- nullable(flag) {
583
- this._nullable = flag ?? true ? import_option4.Option.Some(null) : import_option4.Option.None();
584
- return this;
585
- }
586
- min(value, path = "min") {
587
- if (this._max.isSome() && this._max.value < value)
588
- throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
589
- if (this._tuple.isSome() && value < this._tuple.value.length)
590
- throw new DefinitionError(`Expected Minimum Rule to be larger than or equal to Tuple Length at Path ${path}`);
591
- this._min = import_option4.Option.Some(value);
592
- return this;
593
- }
594
- max(value, path = "max") {
595
- if (this._min.isSome() && this._min.value > value)
596
- throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
597
- if (this._tuple.isSome() && value < this._tuple.value.length)
598
- throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Tuple Length at Path ${path}`);
599
- this._max = import_option4.Option.Some(value);
600
- return this;
601
- }
602
- every(validator) {
603
- this._every = import_option4.Option.Some(validator);
604
- return this;
605
- }
606
- /**
607
- * Applies ONLY to prefix indices [0..validators.length - 1]
608
- * If every() is set, prefix elements are effectively `T[i] & E`.
609
- */
610
- tuple(validators, path = "tuple") {
611
- if (this._min.isSome() && this._min.value < validators.length)
612
- throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Minimum Rule at Path ${path}`);
613
- if (this._max.isSome() && this._max.value < validators.length)
614
- throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Maximum Rule at Path ${path}`);
615
- this._tuple = import_option4.Option.Some(validators);
616
- return this;
617
- }
618
- assert(data, path = "data") {
619
- if (import_json5.JSON.isShallowArray(data)) {
620
- if (this._min.isSome() && this._min.value > data.length)
621
- throw new AssertError(`Expected ${path} to be at least ${this._min.value} Elements long`);
622
- if (this._max.isSome() && this._max.value < data.length)
623
- throw new AssertError(`Expected ${path} to be at most ${this._max.value} Elements long`);
624
- const errors = [];
625
- if (this._every.isSome()) {
626
- const validator = this._every.value;
627
- data.forEach((value, index) => {
628
- try {
629
- validator.assert(value, `${path}[${index}]`);
630
- } catch (e) {
631
- if (!(e instanceof AssertError))
632
- throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
633
- errors.push(e);
634
- }
635
- });
636
- }
637
- if (this._tuple.isSome()) {
638
- if (data.length < this._tuple.value.length)
639
- throw new AssertError(`Expected ${path} to be at least ${this._tuple.value.length} Elements long (Tuple Constraint)`);
640
- this._tuple.value.forEach((validator, index) => {
641
- try {
642
- validator.assert(data[index], `${path}[${index}]`);
643
- } catch (e) {
644
- if (!(e instanceof AssertError))
645
- throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
646
- errors.push(e);
647
- }
648
- });
649
- }
650
- if (errors.length > 0)
651
- throw new AssertError(`Multiple Errors while asserting ${path} (see cause)`, { cause: errors });
652
- } else if (import_json5.JSON.isNull(data)) {
653
- if (!this._nullable.isSome())
654
- throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
655
- } else
656
- throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
657
- }
658
- isSubset(other) {
659
- if (other instanceof JSONValidator)
660
- return true;
661
- if (!(other instanceof _ArrayValidator))
662
- return false;
663
- if (this._nullable.isSome() && !other._nullable.isSome())
664
- return false;
665
- const thisTupleLen = this._tuple.isSome() ? this._tuple.value.length : 0;
666
- const otherTupleLen = other._tuple.isSome() ? other._tuple.value.length : 0;
667
- const thisMin = this._min.isSome() ? this._min.value : 0;
668
- const otherMin = other._min.isSome() ? other._min.value : 0;
669
- const thisMax = this._max.isSome() ? this._max.value : Infinity;
670
- const otherMax = other._max.isSome() ? other._max.value : Infinity;
671
- const thisEffectiveMin = Math.max(thisMin, thisTupleLen);
672
- const otherEffectiveMin = Math.max(otherMin, otherTupleLen);
673
- if (thisEffectiveMin < otherEffectiveMin)
674
- return false;
675
- if (thisMax > otherMax)
676
- return false;
677
- const indexConjuncts = (i) => {
678
- const conjuncts = [];
679
- if (this._every.isSome())
680
- conjuncts.push(this._every.value);
681
- if (this._tuple.isSome() && i < this._tuple.value.length)
682
- conjuncts.push(this._tuple.value[i]);
683
- return conjuncts;
684
- };
685
- const conjunctsSubset = (conjuncts, target) => {
686
- if (conjuncts.length === 0)
687
- return false;
688
- return conjuncts.some((c) => c.isSubset(target));
689
- };
690
- if (other._tuple.isSome()) {
691
- for (let i = 0; i < other._tuple.value.length; i++) {
692
- const aConj = indexConjuncts(i);
693
- if (!conjunctsSubset(aConj, other._tuple.value[i]))
694
- return false;
695
- if (other._every.isSome() && !conjunctsSubset(aConj, other._every.value))
696
- return false;
697
- }
698
- }
699
- return !(other._every.isSome() && (thisMax === Infinity ? true : thisMax > Math.max(thisTupleLen, otherTupleLen)) && (!this._every.isSome() || !this._every.value.isSubset(other._every.value)));
700
- }
701
- toJSON() {
702
- const definition = { type: "array" };
703
- if (this._nullable.isSome())
704
- definition.nullable = true;
705
- if (this._min.isSome())
706
- definition.min = this._min.value;
707
- if (this._max.isSome())
708
- definition.max = this._max.value;
709
- if (this._every.isSome())
710
- definition.every = this._every.value.toJSON();
711
- if (this._tuple.isSome())
712
- definition.tuple = this._tuple.value.map((validator) => validator.toJSON());
713
- return definition;
714
- }
715
- };
716
-
717
- // src/validators/Object.ts
718
605
  var import_json6 = __toESM(require_build());
719
606
  var import_option5 = __toESM(require_Option());
607
+
608
+ // src/validators/Object.ts
609
+ var import_json5 = __toESM(require_build());
610
+ var import_option4 = __toESM(require_Option());
720
611
  var ObjectValidator = class _ObjectValidator extends Validator {
721
612
  static fromJSON(definition, path = "definition") {
722
613
  const validatorInstance = new _ObjectValidator();
723
614
  if ("nullable" in definition) {
724
- if (!import_json6.JSON.isBoolean(definition["nullable"]))
615
+ if (!import_json5.JSON.isBoolean(definition["nullable"]))
725
616
  throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
726
617
  validatorInstance.nullable(definition["nullable"]);
727
618
  }
728
619
  if ("exact" in definition) {
729
- if (!import_json6.JSON.isBoolean(definition["exact"]))
620
+ if (!import_json5.JSON.isBoolean(definition["exact"]))
730
621
  throw new DefinitionError(`Expected ${path}.exact to be a Boolean`);
731
622
  validatorInstance.exact(definition["exact"], `${path}.exact`);
732
623
  }
733
624
  if ("min" in definition) {
734
- if (!import_json6.JSON.isNumber(definition["min"]))
625
+ if (!import_json5.JSON.isNumber(definition["min"]))
735
626
  throw new DefinitionError(`Expected ${path}.min to be a Number`);
736
627
  validatorInstance.min(definition["min"], `${path}.min`);
737
628
  }
738
629
  if ("max" in definition) {
739
- if (!import_json6.JSON.isNumber(definition["max"]))
630
+ if (!import_json5.JSON.isNumber(definition["max"]))
740
631
  throw new DefinitionError(`Expected ${path}.max to be a Number`);
741
632
  validatorInstance.max(definition["max"], `${path}.max`);
742
633
  }
743
634
  if ("every" in definition) {
744
- validatorInstance.every(super.fromJSON(definition["every"], `${path}.every`));
635
+ validatorInstance.every(fromJSON(definition["every"], `${path}.every`));
745
636
  }
746
637
  if ("shape" in definition) {
747
- if (!import_json6.JSON.isShallowObject(definition["shape"]))
638
+ if (!import_json5.JSON.isShallowObject(definition["shape"]))
748
639
  throw new DefinitionError(`Expected ${path}.shape to be an Object`);
749
640
  const shape = {};
750
641
  const errors = [];
751
642
  for (const [key, value] of Object.entries(definition["shape"])) {
752
643
  try {
753
- shape[key] = super.fromJSON(value, `${path}.shape.${key}`);
644
+ shape[key] = fromJSON(value, `${path}.shape.${key}`);
754
645
  } catch (e) {
755
646
  if (!(e instanceof DefinitionError))
756
647
  throw new DefinitionError(`Fatal Error: Undefined Error thrown by Domain.fromJSON at ${path}.shape.${key}`);
@@ -764,14 +655,14 @@ var ObjectValidator = class _ObjectValidator extends Validator {
764
655
  }
765
656
  return validatorInstance;
766
657
  }
767
- _nullable = import_option5.Option.None();
768
- _min = import_option5.Option.None();
769
- _max = import_option5.Option.None();
770
- _every = import_option5.Option.None();
771
- _shape = import_option5.Option.None();
772
- _exact = import_option5.Option.None();
658
+ _nullable = import_option4.Option.None();
659
+ _min = import_option4.Option.None();
660
+ _max = import_option4.Option.None();
661
+ _every = import_option4.Option.None();
662
+ _shape = import_option4.Option.None();
663
+ _exact = import_option4.Option.None();
773
664
  nullable(flag) {
774
- this._nullable = flag ?? true ? import_option5.Option.Some(null) : import_option5.Option.None();
665
+ this._nullable = flag ?? true ? import_option4.Option.Some(null) : import_option4.Option.None();
775
666
  return this;
776
667
  }
777
668
  min(value, path = "min") {
@@ -781,7 +672,7 @@ var ObjectValidator = class _ObjectValidator extends Validator {
781
672
  throw new DefinitionError(`Expected Minimum Rule to be larger than or equal to Shape Key Count at Path ${path}`);
782
673
  if (this._exact.isSome() && this._shape.isSome() && value > Object.keys(this._shape.value).length)
783
674
  throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Shape Key Count due to Exact Rule at Path ${path}`);
784
- this._min = import_option5.Option.Some(value);
675
+ this._min = import_option4.Option.Some(value);
785
676
  return this;
786
677
  }
787
678
  max(value, path = "max") {
@@ -789,11 +680,11 @@ var ObjectValidator = class _ObjectValidator extends Validator {
789
680
  throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
790
681
  if (this._shape.isSome() && value < Object.keys(this._shape.value).length)
791
682
  throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Shape Key Count at Path ${path}`);
792
- this._max = import_option5.Option.Some(value);
683
+ this._max = import_option4.Option.Some(value);
793
684
  return this;
794
685
  }
795
686
  every(validator) {
796
- this._every = import_option5.Option.Some(validator);
687
+ this._every = import_option4.Option.Some(validator);
797
688
  return this;
798
689
  }
799
690
  shape(value, path = "shape") {
@@ -806,7 +697,7 @@ var ObjectValidator = class _ObjectValidator extends Validator {
806
697
  throw new DefinitionError(`Expected Shape Key Count to be larger than or equal to Minimum Rule due to Exact Rule at Path ${path}`);
807
698
  if (this._exact.isSome() && this._max.isSome() && this._max.value < shapeKeyCount)
808
699
  throw new DefinitionError(`Expected Shape Key Count to be smaller than or equal to Maximum Rule due to Exact Rule at Path ${path}`);
809
- this._shape = import_option5.Option.Some(value);
700
+ this._shape = import_option4.Option.Some(value);
810
701
  return this;
811
702
  }
812
703
  exact(flag, path = "exact") {
@@ -817,11 +708,11 @@ var ObjectValidator = class _ObjectValidator extends Validator {
817
708
  if (this._max.isSome() && this._max.value < shapeKeyCount)
818
709
  throw new DefinitionError(`Expected Exact Rule to be false due to Maximum Rule allowing fewer Properties than Shape defines at Path ${path}`);
819
710
  }
820
- this._exact = flag ?? true ? import_option5.Option.Some(null) : import_option5.Option.None();
711
+ this._exact = flag ?? true ? import_option4.Option.Some(null) : import_option4.Option.None();
821
712
  return this;
822
713
  }
823
714
  assert(data, path = "data") {
824
- if (import_json6.JSON.isShallowObject(data)) {
715
+ if (import_json5.JSON.isShallowObject(data)) {
825
716
  const keys = Object.keys(data);
826
717
  if (this._min.isSome() && keys.length < this._min.value)
827
718
  throw new AssertError(`Expected ${path} to have at least ${this._min.value} Properties`);
@@ -861,7 +752,7 @@ var ObjectValidator = class _ObjectValidator extends Validator {
861
752
  }
862
753
  if (errors.length > 0)
863
754
  throw new AssertError(`Multiple Errors while asserting ${path} (see cause)`, { cause: errors });
864
- } else if (import_json6.JSON.isNull(data)) {
755
+ } else if (import_json5.JSON.isNull(data)) {
865
756
  if (!this._nullable.isSome())
866
757
  throw new AssertError(`Expected ${path} to be an Object${this._nullable.isSome() ? " or Null" : ""}`);
867
758
  } else
@@ -933,6 +824,39 @@ var ObjectValidator = class _ObjectValidator extends Validator {
933
824
  }
934
825
  return true;
935
826
  }
827
+ isEquals(other) {
828
+ if (!(other instanceof _ObjectValidator))
829
+ return false;
830
+ if (this._nullable.isSome() !== other._nullable.isSome())
831
+ return false;
832
+ if (this._min.isSome() !== other._min.isSome())
833
+ return false;
834
+ if (this._min.isSome() && other._min.isSome() && this._min.value !== other._min.value)
835
+ return false;
836
+ if (this._max.isSome() !== other._max.isSome())
837
+ return false;
838
+ if (this._max.isSome() && other._max.isSome() && this._max.value !== other._max.value)
839
+ return false;
840
+ if (this._every.isSome() !== other._every.isSome())
841
+ return false;
842
+ if (this._every.isSome() && other._every.isSome())
843
+ return isEquals(this._every.value, other._every.value);
844
+ if (this._shape.isSome() !== other._shape.isSome())
845
+ return false;
846
+ if (this._shape.isSome() && other._shape.isSome()) {
847
+ if (Object.keys(this._shape.value).length !== Object.keys(other._shape.value).length)
848
+ return false;
849
+ for (const [k, v] of Object.entries(this._shape.value)) {
850
+ if (!(other._shape.value[k] instanceof Validator))
851
+ return false;
852
+ if (!isEquals(v, other._shape.value[k]))
853
+ return false;
854
+ }
855
+ }
856
+ if (this._exact.isSome() !== other._exact.isSome())
857
+ return false;
858
+ return true;
859
+ }
936
860
  toJSON() {
937
861
  const schema = { type: "object" };
938
862
  if (this._nullable.isSome())
@@ -954,45 +878,262 @@ var ObjectValidator = class _ObjectValidator extends Validator {
954
878
  }
955
879
  };
956
880
 
957
- // src/Validator.ts
958
- var import_json7 = __toESM(require_build());
959
- var Validator = class {
960
- static fromJSON(definition, path) {
961
- if (!import_json7.JSON.isShallowObject(definition))
962
- throw new DefinitionError(`Expected ${path} to be an Object`);
963
- if (!import_json7.JSON.isString(definition["type"]))
964
- throw new DefinitionError(`Expected ${path}.type to be a String`);
965
- switch (definition["type"]) {
966
- case "json":
967
- return JSONValidator.fromJSON(definition, path);
968
- case "boolean":
969
- return BooleanValidator.fromJSON(definition, path);
970
- case "number":
971
- return NumberValidator.fromJSON(definition, path);
972
- case "string":
973
- return StringValidator.fromJSON(definition, path);
974
- case "array":
975
- return ArrayValidator.fromJSON(definition, path);
976
- case "object":
977
- return ObjectValidator.fromJSON(definition, path);
978
- default:
979
- throw new DefinitionError(`Expected ${path}.type to be a registered Validator`);
881
+ // src/lib/isEquals.ts
882
+ function isEquals(a, b) {
883
+ if (a instanceof JSONValidator)
884
+ return a.isEquals(b);
885
+ if (a instanceof BooleanValidator)
886
+ return a.isEquals(b);
887
+ if (a instanceof NumberValidator)
888
+ return a.isEquals(b);
889
+ if (a instanceof StringValidator)
890
+ return a.isEquals(b);
891
+ if (a instanceof ArrayValidator)
892
+ return a.isEquals(b);
893
+ if (a instanceof ObjectValidator)
894
+ return a.isEquals(b);
895
+ return false;
896
+ }
897
+
898
+ // src/validators/Array.ts
899
+ var ArrayValidator = class _ArrayValidator extends Validator {
900
+ static fromJSON(definition, path = "definition") {
901
+ const validatorInstance = new _ArrayValidator();
902
+ if ("nullable" in definition) {
903
+ if (!import_json6.JSON.isBoolean(definition["nullable"]))
904
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
905
+ validatorInstance.nullable(definition["nullable"]);
906
+ }
907
+ if ("min" in definition) {
908
+ if (!import_json6.JSON.isNumber(definition["min"]))
909
+ throw new DefinitionError(`Expected ${path}.min to be a Number`);
910
+ validatorInstance.min(definition["min"], `${path}.min`);
911
+ }
912
+ if ("max" in definition) {
913
+ if (!import_json6.JSON.isNumber(definition["max"]))
914
+ throw new DefinitionError(`Expected ${path}.max to be a Number`);
915
+ validatorInstance.max(definition["max"], `${path}.max`);
980
916
  }
917
+ if ("every" in definition) {
918
+ if (!import_json6.JSON.isObject(definition["every"]))
919
+ throw new DefinitionError(`Expected ${path}.every to be an Object`);
920
+ validatorInstance.every(
921
+ fromJSON(definition["every"], `${path}.every`)
922
+ );
923
+ }
924
+ if ("tuple" in definition) {
925
+ if (!import_json6.JSON.isShallowArray(definition["tuple"]))
926
+ throw new DefinitionError(`Expected ${path}.tuple to be an Array`);
927
+ const tupleSchemas = [];
928
+ const errors = [];
929
+ definition["tuple"].forEach((tupleDef, index) => {
930
+ try {
931
+ tupleSchemas.push(fromJSON(tupleDef, `${path}.tuple[${index}]`));
932
+ } catch (e) {
933
+ if (!(e instanceof DefinitionError))
934
+ throw new DefinitionError(`Fatal Error: Undefined Error thrown by Domain.fromJSON at ${path}`);
935
+ errors.push(e);
936
+ }
937
+ });
938
+ if (errors.length > 0)
939
+ throw new DefinitionError(`Multiple Definition Errors detected at ${path} (see cause)`, { cause: errors });
940
+ validatorInstance.tuple(tupleSchemas, `${path}.tuple`);
941
+ }
942
+ return validatorInstance;
981
943
  }
982
- validate(data, path = "data") {
983
- this.assert(data, path);
984
- return data;
944
+ _nullable = import_option5.Option.None();
945
+ _every = import_option5.Option.None();
946
+ _tuple = import_option5.Option.None();
947
+ _min = import_option5.Option.None();
948
+ _max = import_option5.Option.None();
949
+ nullable(flag) {
950
+ this._nullable = flag ?? true ? import_option5.Option.Some(null) : import_option5.Option.None();
951
+ return this;
985
952
  }
986
- is(data, path = "data") {
987
- try {
988
- this.assert(data, path);
953
+ min(value, path = "min") {
954
+ if (this._max.isSome() && this._max.value < value)
955
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
956
+ if (this._tuple.isSome() && value < this._tuple.value.length)
957
+ throw new DefinitionError(`Expected Minimum Rule to be larger than or equal to Tuple Length at Path ${path}`);
958
+ this._min = import_option5.Option.Some(value);
959
+ return this;
960
+ }
961
+ max(value, path = "max") {
962
+ if (this._min.isSome() && this._min.value > value)
963
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
964
+ if (this._tuple.isSome() && value < this._tuple.value.length)
965
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Tuple Length at Path ${path}`);
966
+ this._max = import_option5.Option.Some(value);
967
+ return this;
968
+ }
969
+ every(validator) {
970
+ this._every = import_option5.Option.Some(validator);
971
+ return this;
972
+ }
973
+ /**
974
+ * Applies ONLY to prefix indices [0..validators.length - 1]
975
+ * If every() is set, prefix elements are effectively `T[i] & E`.
976
+ */
977
+ tuple(validators, path = "tuple") {
978
+ if (this._min.isSome() && this._min.value < validators.length)
979
+ throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Minimum Rule at Path ${path}`);
980
+ if (this._max.isSome() && this._max.value < validators.length)
981
+ throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Maximum Rule at Path ${path}`);
982
+ this._tuple = import_option5.Option.Some(validators);
983
+ return this;
984
+ }
985
+ assert(data, path = "data") {
986
+ if (import_json6.JSON.isShallowArray(data)) {
987
+ if (this._min.isSome() && this._min.value > data.length)
988
+ throw new AssertError(`Expected ${path} to be at least ${this._min.value} Elements long`);
989
+ if (this._max.isSome() && this._max.value < data.length)
990
+ throw new AssertError(`Expected ${path} to be at most ${this._max.value} Elements long`);
991
+ const errors = [];
992
+ if (this._every.isSome()) {
993
+ const validator = this._every.value;
994
+ data.forEach((value, index) => {
995
+ try {
996
+ validator.assert(value, `${path}[${index}]`);
997
+ } catch (e) {
998
+ if (!(e instanceof AssertError))
999
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
1000
+ errors.push(e);
1001
+ }
1002
+ });
1003
+ }
1004
+ if (this._tuple.isSome()) {
1005
+ if (data.length < this._tuple.value.length)
1006
+ throw new AssertError(`Expected ${path} to be at least ${this._tuple.value.length} Elements long (Tuple Constraint)`);
1007
+ this._tuple.value.forEach((validator, index) => {
1008
+ try {
1009
+ validator.assert(data[index], `${path}[${index}]`);
1010
+ } catch (e) {
1011
+ if (!(e instanceof AssertError))
1012
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
1013
+ errors.push(e);
1014
+ }
1015
+ });
1016
+ }
1017
+ if (errors.length > 0)
1018
+ throw new AssertError(`Multiple Errors while asserting ${path} (see cause)`, { cause: errors });
1019
+ } else if (import_json6.JSON.isNull(data)) {
1020
+ if (!this._nullable.isSome())
1021
+ throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
1022
+ } else
1023
+ throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
1024
+ }
1025
+ isSubset(other) {
1026
+ if (other instanceof JSONValidator)
989
1027
  return true;
990
- } catch (e) {
1028
+ if (!(other instanceof _ArrayValidator))
1029
+ return false;
1030
+ if (this._nullable.isSome() && !other._nullable.isSome())
1031
+ return false;
1032
+ const thisTupleLen = this._tuple.isSome() ? this._tuple.value.length : 0;
1033
+ const otherTupleLen = other._tuple.isSome() ? other._tuple.value.length : 0;
1034
+ const thisMin = this._min.isSome() ? this._min.value : 0;
1035
+ const otherMin = other._min.isSome() ? other._min.value : 0;
1036
+ const thisMax = this._max.isSome() ? this._max.value : Infinity;
1037
+ const otherMax = other._max.isSome() ? other._max.value : Infinity;
1038
+ const thisEffectiveMin = Math.max(thisMin, thisTupleLen);
1039
+ const otherEffectiveMin = Math.max(otherMin, otherTupleLen);
1040
+ if (thisEffectiveMin < otherEffectiveMin)
1041
+ return false;
1042
+ if (thisMax > otherMax)
1043
+ return false;
1044
+ const indexConjuncts = (i) => {
1045
+ const conjuncts = [];
1046
+ if (this._every.isSome())
1047
+ conjuncts.push(this._every.value);
1048
+ if (this._tuple.isSome() && i < this._tuple.value.length)
1049
+ conjuncts.push(this._tuple.value[i]);
1050
+ return conjuncts;
1051
+ };
1052
+ const conjunctsSubset = (conjuncts, target) => {
1053
+ if (conjuncts.length === 0)
1054
+ return false;
1055
+ return conjuncts.some((c) => c.isSubset(target));
1056
+ };
1057
+ if (other._tuple.isSome()) {
1058
+ for (let i = 0; i < other._tuple.value.length; i++) {
1059
+ const aConj = indexConjuncts(i);
1060
+ if (!conjunctsSubset(aConj, other._tuple.value[i]))
1061
+ return false;
1062
+ if (other._every.isSome() && !conjunctsSubset(aConj, other._every.value))
1063
+ return false;
1064
+ }
1065
+ }
1066
+ return !(other._every.isSome() && (thisMax === Infinity ? true : thisMax > Math.max(thisTupleLen, otherTupleLen)) && (!this._every.isSome() || !this._every.value.isSubset(other._every.value)));
1067
+ }
1068
+ isEquals(other) {
1069
+ if (!(other instanceof _ArrayValidator))
1070
+ return false;
1071
+ if (this._nullable.isSome() !== other._nullable.isSome())
991
1072
  return false;
1073
+ if (this._min.isSome() !== other._min.isSome())
1074
+ return false;
1075
+ if (this._min.isSome() && other._min.isSome() && this._min.value !== other._min.value)
1076
+ return false;
1077
+ if (this._max.isSome() !== other._max.isSome())
1078
+ return false;
1079
+ if (this._max.isSome() && other._max.isSome() && this._max.value !== other._max.value)
1080
+ return false;
1081
+ if (this._every.isSome() !== other._every.isSome())
1082
+ return false;
1083
+ if (this._every.isSome() && other._every.isSome() && !isEquals(this._every.value, other._every.value))
1084
+ return false;
1085
+ if (this._tuple.isSome() !== other._tuple.isSome())
1086
+ return false;
1087
+ if (this._tuple.isSome() && other._tuple.isSome()) {
1088
+ if (this._tuple.value.length !== other._tuple.value.length)
1089
+ return false;
1090
+ for (let i = 0; i < this._tuple.value.length; i++) {
1091
+ if (!isEquals(this._tuple.value[i], other._tuple.value[i]))
1092
+ return false;
1093
+ }
992
1094
  }
1095
+ return true;
1096
+ }
1097
+ toJSON() {
1098
+ const definition = { type: "array" };
1099
+ if (this._nullable.isSome())
1100
+ definition.nullable = true;
1101
+ if (this._min.isSome())
1102
+ definition.min = this._min.value;
1103
+ if (this._max.isSome())
1104
+ definition.max = this._max.value;
1105
+ if (this._every.isSome())
1106
+ definition.every = this._every.value.toJSON();
1107
+ if (this._tuple.isSome())
1108
+ definition.tuple = this._tuple.value.map((validator) => validator.toJSON());
1109
+ return definition;
993
1110
  }
994
1111
  };
995
1112
 
1113
+ // src/lib/fromJSON.ts
1114
+ function fromJSON(definition, path) {
1115
+ if (!import_json7.JSON.isShallowObject(definition))
1116
+ throw new DefinitionError(`Expected ${path} to be an Object`);
1117
+ if (!import_json7.JSON.isString(definition["type"]))
1118
+ throw new DefinitionError(`Expected ${path}.type to be a String`);
1119
+ switch (definition["type"]) {
1120
+ case "json":
1121
+ return JSONValidator.fromJSON(definition, path);
1122
+ case "boolean":
1123
+ return BooleanValidator.fromJSON(definition, path);
1124
+ case "number":
1125
+ return NumberValidator.fromJSON(definition, path);
1126
+ case "string":
1127
+ return StringValidator.fromJSON(definition, path);
1128
+ case "array":
1129
+ return ArrayValidator.fromJSON(definition, path);
1130
+ case "object":
1131
+ return ObjectValidator.fromJSON(definition, path);
1132
+ default:
1133
+ throw new DefinitionError(`Expected ${path}.type to be a registered Validator`);
1134
+ }
1135
+ }
1136
+
996
1137
  // src/index.ts
997
1138
  var Schema = class {
998
1139
  static get JSON() {
@@ -1013,6 +1154,12 @@ var Schema = class {
1013
1154
  static get Object() {
1014
1155
  return new ObjectValidator();
1015
1156
  }
1157
+ static fromJSON(definition, path = "definition") {
1158
+ return fromJSON(definition, path);
1159
+ }
1160
+ static isEquals(a, b) {
1161
+ return isEquals(a, b);
1162
+ }
1016
1163
  };
1017
1164
  var Validators = {
1018
1165
  JSON: JSONValidator,