@serum-enterprises/schema 2.0.1-beta.2 → 3.0.0-beta.2

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 ADDED
@@ -0,0 +1,1040 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // node_modules/@serum-enterprises/json/build/index.js
34
+ var require_build = __commonJS({
35
+ "node_modules/@serum-enterprises/json/build/index.js"(exports2) {
36
+ "use strict";
37
+ Object.defineProperty(exports2, "__esModule", { value: true });
38
+ exports2.JSON = void 0;
39
+ var JSON8;
40
+ (function(JSON9) {
41
+ function isNull(value) {
42
+ return value === null;
43
+ }
44
+ JSON9.isNull = isNull;
45
+ function isBoolean(value) {
46
+ return typeof value === "boolean";
47
+ }
48
+ JSON9.isBoolean = isBoolean;
49
+ function isNumber(value) {
50
+ return Number.isFinite(value);
51
+ }
52
+ JSON9.isNumber = isNumber;
53
+ function isInteger(value) {
54
+ return Number.isSafeInteger(value);
55
+ }
56
+ JSON9.isInteger = isInteger;
57
+ function isString(value) {
58
+ return typeof value === "string";
59
+ }
60
+ JSON9.isString = isString;
61
+ function isShallowArray(value) {
62
+ return Array.isArray(value);
63
+ }
64
+ JSON9.isShallowArray = isShallowArray;
65
+ function isArray(value) {
66
+ return isShallowArray(value) && value.every((v) => isJSON(v));
67
+ }
68
+ JSON9.isArray = isArray;
69
+ function isShallowObject(value) {
70
+ return Object.prototype.toString.call(value) === "[object Object]";
71
+ }
72
+ JSON9.isShallowObject = isShallowObject;
73
+ function isObject(value) {
74
+ return isShallowObject(value) && Object.values(value).every((v) => isJSON(v));
75
+ }
76
+ JSON9.isObject = isObject;
77
+ function isPrimitive(value) {
78
+ return isBoolean(value) || isNumber(value) || isString(value);
79
+ }
80
+ JSON9.isPrimitive = isPrimitive;
81
+ function isShallowContainer(value) {
82
+ return isShallowArray(value) || isShallowObject(value);
83
+ }
84
+ JSON9.isShallowContainer = isShallowContainer;
85
+ function isContainer(value) {
86
+ return isArray(value) || isObject(value);
87
+ }
88
+ JSON9.isContainer = isContainer;
89
+ function isShallowJSON(value) {
90
+ return isNull(value) || isPrimitive(value) || isShallowArray(value) || isShallowObject(value);
91
+ }
92
+ JSON9.isShallowJSON = isShallowJSON;
93
+ function isJSON(value) {
94
+ return isNull(value) || isPrimitive(value) || isContainer(value);
95
+ }
96
+ JSON9.isJSON = isJSON;
97
+ function clone(value) {
98
+ if (isShallowObject(value))
99
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, clone(v)]));
100
+ else if (isShallowArray(value))
101
+ return value.map((v) => clone(v));
102
+ else
103
+ return value;
104
+ }
105
+ JSON9.clone = clone;
106
+ function parse(value) {
107
+ return globalThis.JSON.parse(value);
108
+ }
109
+ JSON9.parse = parse;
110
+ function stringify(value) {
111
+ return globalThis.JSON.stringify(value);
112
+ }
113
+ JSON9.stringify = stringify;
114
+ })(JSON8 || (exports2.JSON = JSON8 = {}));
115
+ }
116
+ });
117
+
118
+ // node_modules/@serum-enterprises/option/build/Option.js
119
+ var require_Option = __commonJS({
120
+ "node_modules/@serum-enterprises/option/build/Option.js"(exports2) {
121
+ "use strict";
122
+ Object.defineProperty(exports2, "__esModule", { value: true });
123
+ exports2.None = exports2.Some = exports2.Option = void 0;
124
+ var Option6 = class _Option {
125
+ static Some(value) {
126
+ return new Some(value);
127
+ }
128
+ static None() {
129
+ return new None();
130
+ }
131
+ isSome() {
132
+ return this instanceof Some;
133
+ }
134
+ isNone() {
135
+ return this instanceof None;
136
+ }
137
+ onSome(fn) {
138
+ if (this.isSome())
139
+ fn(this.value);
140
+ return this;
141
+ }
142
+ onNone(fn) {
143
+ if (this.isNone())
144
+ fn();
145
+ return this;
146
+ }
147
+ map(fn) {
148
+ return this.match((value) => _Option.Some(fn(value)), () => _Option.None());
149
+ }
150
+ match(onSome, onNone) {
151
+ if (this.isSome())
152
+ return onSome(this.value);
153
+ else
154
+ return onNone();
155
+ }
156
+ };
157
+ exports2.Option = Option6;
158
+ var Some = class extends Option6 {
159
+ _value;
160
+ constructor(value) {
161
+ super();
162
+ this._value = value;
163
+ }
164
+ get value() {
165
+ return this._value;
166
+ }
167
+ };
168
+ exports2.Some = Some;
169
+ var None = class extends Option6 {
170
+ };
171
+ exports2.None = None;
172
+ }
173
+ });
174
+
175
+ // src/index.ts
176
+ var index_exports = {};
177
+ __export(index_exports, {
178
+ Schema: () => Schema,
179
+ Validator: () => Validator,
180
+ Validators: () => Validators
181
+ });
182
+ module.exports = __toCommonJS(index_exports);
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
+
206
+ // src/lib/util.ts
207
+ var AssertError = class extends Error {
208
+ };
209
+ var DefinitionError = class extends Error {
210
+ };
211
+
212
+ // src/validators/JSON.ts
213
+ var JSONValidator = class _JSONValidator extends Validator {
214
+ static fromJSON(_definition, _path = "definition") {
215
+ return new _JSONValidator();
216
+ }
217
+ assert(data, path = "data") {
218
+ if (!import_json.JSON.isJSON(data))
219
+ throw new AssertError(`Expected ${path} to be valid JSON`);
220
+ }
221
+ isSubset(other) {
222
+ return other instanceof _JSONValidator;
223
+ }
224
+ toJSON() {
225
+ return {
226
+ type: "json"
227
+ };
228
+ }
229
+ };
230
+
231
+ // src/validators/Boolean.ts
232
+ var import_json2 = __toESM(require_build());
233
+ var import_option = __toESM(require_Option());
234
+ var BooleanValidator = class _BooleanValidator extends Validator {
235
+ static fromJSON(definition, path = "definition") {
236
+ const validatorInstance = new _BooleanValidator();
237
+ if ("nullable" in definition) {
238
+ if (!import_json2.JSON.isBoolean(definition["nullable"]))
239
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
240
+ validatorInstance.nullable(definition["nullable"]);
241
+ }
242
+ if ("equals" in definition) {
243
+ if (!import_json2.JSON.isBoolean(definition["equals"]))
244
+ throw new DefinitionError(`Expected ${path}.equals to be a Boolean`);
245
+ validatorInstance.equals(definition["equals"]);
246
+ }
247
+ return validatorInstance;
248
+ }
249
+ _nullable = import_option.Option.None();
250
+ _equals = import_option.Option.None();
251
+ nullable(flag) {
252
+ this._nullable = flag ?? true ? import_option.Option.Some(null) : import_option.Option.None();
253
+ return this;
254
+ }
255
+ equals(value) {
256
+ this._equals = import_option.Option.Some(value);
257
+ return this;
258
+ }
259
+ assert(data, path = "data") {
260
+ if (import_json2.JSON.isBoolean(data)) {
261
+ if (this._equals.isSome() && this._equals.value !== data)
262
+ throw new AssertError(`Expected ${path} to be ${this._equals.value}${this._nullable.isSome() ? "" : " or Null"}`);
263
+ } else if (import_json2.JSON.isNull(data)) {
264
+ if (!this._nullable.isSome())
265
+ throw new AssertError(`Expected ${path} to be a Boolean${this._nullable.isSome() ? " or Null" : ""}`);
266
+ } else
267
+ throw new AssertError(`Expected ${path} to be a Boolean${this._nullable.isSome() ? " or Null" : ""}`);
268
+ }
269
+ isSubset(other) {
270
+ if (other instanceof JSONValidator)
271
+ return true;
272
+ if (!(other instanceof _BooleanValidator))
273
+ return false;
274
+ if (this._nullable.isSome() && !other._nullable.isSome())
275
+ return false;
276
+ if (other._equals.isSome()) {
277
+ if (this._equals.isSome())
278
+ return this._equals.value === other._equals.value;
279
+ else
280
+ return false;
281
+ }
282
+ return true;
283
+ }
284
+ toJSON() {
285
+ const definition = {
286
+ type: "boolean"
287
+ };
288
+ if (this._nullable.isSome())
289
+ definition["nullable"] = true;
290
+ if (this._equals.isSome())
291
+ definition["equals"] = this._equals.value;
292
+ return definition;
293
+ }
294
+ };
295
+
296
+ // src/validators/Number.ts
297
+ var import_json3 = __toESM(require_build());
298
+ var import_option2 = __toESM(require_Option());
299
+ var NumberValidator = class _NumberValidator extends Validator {
300
+ static fromJSON(definition, path = "definition") {
301
+ const validatorInstance = new _NumberValidator();
302
+ if ("nullable" in definition) {
303
+ if (!import_json3.JSON.isBoolean(definition["nullable"]))
304
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
305
+ validatorInstance.nullable(definition["nullable"]);
306
+ }
307
+ if ("equals" in definition) {
308
+ if (!import_json3.JSON.isNumber(definition["equals"]))
309
+ throw new DefinitionError(`Expected ${path}.equals to be a Number`);
310
+ validatorInstance.equals(definition["equals"], `${path}.equals`);
311
+ }
312
+ if ("integer" in definition) {
313
+ if (!import_json3.JSON.isBoolean(definition["integer"]))
314
+ throw new DefinitionError(`Expected ${path}.integer to be a Boolean`);
315
+ validatorInstance.integer(definition["integer"], `${path}.integer`);
316
+ }
317
+ if ("min" in definition) {
318
+ if (!import_json3.JSON.isNumber(definition["min"]))
319
+ throw new DefinitionError(`Expected ${path}.min to be a Number`);
320
+ validatorInstance.min(definition["min"], `${path}.min`);
321
+ }
322
+ if ("max" in definition) {
323
+ if (!import_json3.JSON.isNumber(definition["max"]))
324
+ throw new DefinitionError(`Expected ${path}.max to be a Number`);
325
+ validatorInstance.max(definition["max"], `${path}.max`);
326
+ }
327
+ return validatorInstance;
328
+ }
329
+ _nullable = import_option2.Option.None();
330
+ _equals = import_option2.Option.None();
331
+ _integer = import_option2.Option.None();
332
+ _min = import_option2.Option.None();
333
+ _max = import_option2.Option.None();
334
+ nullable(flag) {
335
+ this._nullable = flag ?? true ? import_option2.Option.Some(null) : import_option2.Option.None();
336
+ return this;
337
+ }
338
+ equals(value, path = "equals") {
339
+ if (this._integer.isSome() && !Number.isSafeInteger(value))
340
+ throw new DefinitionError(`Expected Equals Rule to be an Integer according to the Integer Rule at Path ${path}`);
341
+ if (this._min.isSome() && this._min.value > value)
342
+ throw new DefinitionError(`Expected Equals Rule to be larger than or equal to the Minimum Rule at Path ${path}`);
343
+ if (this._max.isSome() && this._max.value < value)
344
+ throw new DefinitionError(`Expected Equals Rule to be smaller than or equal to the Maximum Rule at Path ${path}`);
345
+ this._equals = import_option2.Option.Some(value);
346
+ return this;
347
+ }
348
+ integer(flag = true, path = "integer") {
349
+ if (flag && this._equals.isSome() && !Number.isSafeInteger(this._equals.value))
350
+ throw new DefinitionError(`Expected Integer Rule to be a false due to the Equals Rule being a Float at Path ${path}`);
351
+ this._integer = flag ? import_option2.Option.Some(null) : import_option2.Option.None();
352
+ return this;
353
+ }
354
+ min(value, path = "min") {
355
+ if (this._max.isSome() && this._max.value < value)
356
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
357
+ if (this._equals.isSome() && this._equals.value < value)
358
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to the Equals Rule at Path ${path}`);
359
+ this._min = import_option2.Option.Some(value);
360
+ return this;
361
+ }
362
+ max(value, path = "max") {
363
+ if (this._min.isSome() && this._min.value > value)
364
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
365
+ if (this._equals.isSome() && this._equals.value > value)
366
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to the Equals Rule at Path ${path}`);
367
+ this._max = import_option2.Option.Some(value);
368
+ return this;
369
+ }
370
+ assert(data, path = "data") {
371
+ if (import_json3.JSON.isNumber(data)) {
372
+ if (this._equals.isSome() && this._equals.value !== data)
373
+ throw new AssertError(`Expected ${path} to be ${this._equals.value}`);
374
+ if (this._integer.isSome() && !Number.isInteger(data))
375
+ throw new AssertError(`Expected ${path} to be an Integer`);
376
+ if (this._min.isSome() && this._min.value > data)
377
+ throw new AssertError(`Expected ${path} to be at least ${this._min.value}`);
378
+ if (this._max.isSome() && this._max.value < data)
379
+ throw new AssertError(`Expected ${path} to be at most ${this._max.value}`);
380
+ } else if (import_json3.JSON.isNull(data)) {
381
+ if (!this._nullable.isSome())
382
+ throw new AssertError(`Expected ${path} to be a Number${this._nullable.isSome() ? " or Null" : ""}`);
383
+ } else
384
+ throw new AssertError(`Expected ${path} to be a Number${this._nullable.isSome() ? " or Null" : ""}`);
385
+ }
386
+ isSubset(other) {
387
+ if (other instanceof JSONValidator)
388
+ return true;
389
+ if (!(other instanceof _NumberValidator))
390
+ return false;
391
+ if (this._nullable.isSome() && !other._nullable.isSome())
392
+ return false;
393
+ if (this._equals.isSome()) {
394
+ if (other._equals.isSome() && other._equals.value !== this._equals.value)
395
+ return false;
396
+ if (other._integer.isSome() && !Number.isInteger(this._equals.value))
397
+ return false;
398
+ if (other._min.isSome() && other._min.value > this._equals.value)
399
+ return false;
400
+ if (other._max.isSome() && other._max.value < this._equals.value)
401
+ return false;
402
+ return true;
403
+ }
404
+ if (other._equals.isSome())
405
+ return false;
406
+ if (!this._integer.isSome() && other._integer.isSome())
407
+ return false;
408
+ if (other._min.isSome() && (!this._min.isSome() || this._min.value < other._min.value))
409
+ return false;
410
+ if (other._max.isSome() && (!this._max.isSome() || this._max.value > other._max.value))
411
+ return false;
412
+ return true;
413
+ }
414
+ toJSON() {
415
+ const definition = {
416
+ type: "number"
417
+ };
418
+ if (this._nullable.isSome())
419
+ definition["nullable"] = true;
420
+ if (this._equals.isSome())
421
+ definition["equals"] = this._equals.value;
422
+ if (this._integer.isSome())
423
+ definition["integer"] = true;
424
+ if (this._min.isSome())
425
+ definition["min"] = this._min.value;
426
+ if (this._max.isSome())
427
+ definition["max"] = this._max.value;
428
+ return definition;
429
+ }
430
+ };
431
+
432
+ // src/validators/String.ts
433
+ var import_json4 = __toESM(require_build());
434
+ var import_option3 = __toESM(require_Option());
435
+ var StringValidator = class _StringValidator extends Validator {
436
+ static fromJSON(definition, path = "schema") {
437
+ const validatorInstance = new _StringValidator();
438
+ if ("nullable" in definition) {
439
+ if (!import_json4.JSON.isBoolean(definition["nullable"]))
440
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
441
+ validatorInstance.nullable(definition["nullable"]);
442
+ }
443
+ if ("equals" in definition) {
444
+ if (!import_json4.JSON.isString(definition["equals"]))
445
+ throw new DefinitionError(`Expected ${path}.equals to be a String`);
446
+ validatorInstance.equals(definition["equals"], `${path}.equals`);
447
+ }
448
+ if ("min" in definition) {
449
+ if (!import_json4.JSON.isNumber(definition["min"]))
450
+ throw new DefinitionError(`Expected ${path}.min to be a positive Integer`);
451
+ validatorInstance.min(definition["min"], `${path}.min`);
452
+ }
453
+ if ("max" in definition) {
454
+ if (!import_json4.JSON.isNumber(definition["max"]))
455
+ throw new DefinitionError(`Expected ${path}.max to be a positive Integer`);
456
+ validatorInstance.max(definition["max"], `${path}.max`);
457
+ }
458
+ return validatorInstance;
459
+ }
460
+ _nullable = import_option3.Option.None();
461
+ _equals = import_option3.Option.None();
462
+ _min = import_option3.Option.None();
463
+ _max = import_option3.Option.None();
464
+ nullable(flag) {
465
+ this._nullable = flag ?? true ? import_option3.Option.Some(null) : import_option3.Option.None();
466
+ return this;
467
+ }
468
+ equals(value, path = "equals") {
469
+ if (this._min.isSome() && this._min.value > value.length)
470
+ throw new DefinitionError(`Expected the Equals Rules Length to be larger than or equal to the Minimum Rule at Path ${path}`);
471
+ if (this._max.isSome() && this._max.value < value.length)
472
+ throw new DefinitionError(`Expected the Equals Rules Length to be smaller than or equal to the Maximum Rule at Path ${path}`);
473
+ this._equals = import_option3.Option.Some(value);
474
+ return this;
475
+ }
476
+ min(value, path = "min") {
477
+ if (!Number.isSafeInteger(value) || value < 0)
478
+ throw new DefinitionError(`Expected ${path}.min to be a positive Integer`);
479
+ if (this._max.isSome() && this._max.value < value)
480
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
481
+ if (this._equals.isSome() && this._equals.value.length < value)
482
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to the Equals Rules Length at Path ${path}`);
483
+ this._min = import_option3.Option.Some(value);
484
+ return this;
485
+ }
486
+ max(value, path = "max") {
487
+ if (!Number.isSafeInteger(value) || value < 0)
488
+ throw new DefinitionError(`Expected ${path}.max to be a positive Integer`);
489
+ if (this._min.isSome() && this._min.value > value)
490
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
491
+ if (this._equals.isSome() && this._equals.value.length > value)
492
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to the Equals Rules Length at Path ${path}`);
493
+ this._max = import_option3.Option.Some(value);
494
+ return this;
495
+ }
496
+ assert(data, path = "data") {
497
+ if (import_json4.JSON.isString(data)) {
498
+ if (this._equals.isSome() && this._equals.value !== data)
499
+ throw new AssertError(`Expected ${path} to be ${this._equals.value}`);
500
+ if (this._min.isSome() && this._min.value > data.length)
501
+ throw new AssertError(`Expected ${path} to be at least ${this._min.value} characters long`);
502
+ if (this._max.isSome() && this._max.value < data.length)
503
+ throw new AssertError(`Expected ${path} to be at most ${this._max.value} characters long`);
504
+ } else if (import_json4.JSON.isNull(data)) {
505
+ if (!this._nullable.isSome())
506
+ throw new AssertError(`Expected ${path} to be a String${this._nullable.isSome() ? " or Null" : ""}`);
507
+ } else
508
+ throw new AssertError(`Expected ${path} to be a String${this._nullable.isSome() ? " or Null" : ""}`);
509
+ }
510
+ isSubset(other) {
511
+ if (other instanceof JSONValidator)
512
+ return true;
513
+ if (!(other instanceof _StringValidator))
514
+ return false;
515
+ if (this._nullable.isSome() && !other._nullable.isSome())
516
+ return false;
517
+ if (this._equals.isSome()) {
518
+ if (other._equals.isSome() && other._equals.value !== this._equals.value)
519
+ return false;
520
+ if (other._min.isSome() && other._min.value > this._equals.value.length)
521
+ return false;
522
+ if (other._max.isSome() && other._max.value < this._equals.value.length)
523
+ return false;
524
+ return true;
525
+ }
526
+ if (other._equals.isSome())
527
+ return false;
528
+ if (other._min.isSome() && (!this._min.isSome() || this._min.value < other._min.value))
529
+ return false;
530
+ if (other._max.isSome() && (!this._max.isSome() || this._max.value > other._max.value))
531
+ return false;
532
+ return true;
533
+ }
534
+ toJSON() {
535
+ const definition = {
536
+ type: "string"
537
+ };
538
+ if (this._nullable.isSome())
539
+ definition["nullable"] = true;
540
+ if (this._equals.isSome())
541
+ definition["equals"] = this._equals.value;
542
+ if (this._min.isSome())
543
+ definition["min"] = this._min.value;
544
+ if (this._max.isSome())
545
+ definition["max"] = this._max.value;
546
+ return definition;
547
+ }
548
+ };
549
+
550
+ // src/validators/Array.ts
551
+ var import_json5 = __toESM(require_build());
552
+ var import_option4 = __toESM(require_Option());
553
+ var ArrayValidator = class _ArrayValidator extends Validator {
554
+ static fromJSON(definition, path = "definition") {
555
+ const validatorInstance = new _ArrayValidator();
556
+ if ("nullable" in definition) {
557
+ if (!import_json5.JSON.isBoolean(definition["nullable"]))
558
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
559
+ validatorInstance.nullable(definition["nullable"]);
560
+ }
561
+ if ("min" in definition) {
562
+ if (!import_json5.JSON.isNumber(definition["min"]))
563
+ throw new DefinitionError(`Expected ${path}.min to be a Number`);
564
+ validatorInstance.min(definition["min"], `${path}.min`);
565
+ }
566
+ if ("max" in definition) {
567
+ if (!import_json5.JSON.isNumber(definition["max"]))
568
+ throw new DefinitionError(`Expected ${path}.max to be a Number`);
569
+ validatorInstance.max(definition["max"], `${path}.max`);
570
+ }
571
+ if ("every" in definition) {
572
+ if (!import_json5.JSON.isObject(definition["every"]))
573
+ throw new DefinitionError(`Expected ${path}.every to be an Object`);
574
+ validatorInstance.every(
575
+ fromJSON(definition["every"], `${path}.every`)
576
+ );
577
+ }
578
+ if ("tuple" in definition) {
579
+ if (!import_json5.JSON.isShallowArray(definition["tuple"]))
580
+ throw new DefinitionError(`Expected ${path}.tuple to be an Array`);
581
+ const tupleSchemas = [];
582
+ const errors = [];
583
+ definition["tuple"].forEach((tupleDef, index) => {
584
+ try {
585
+ tupleSchemas.push(fromJSON(tupleDef, `${path}.tuple[${index}]`));
586
+ } catch (e) {
587
+ if (!(e instanceof DefinitionError))
588
+ throw new DefinitionError(`Fatal Error: Undefined Error thrown by Domain.fromJSON at ${path}`);
589
+ errors.push(e);
590
+ }
591
+ });
592
+ if (errors.length > 0)
593
+ throw new DefinitionError(`Multiple Definition Errors detected at ${path} (see cause)`, { cause: errors });
594
+ validatorInstance.tuple(tupleSchemas, `${path}.tuple`);
595
+ }
596
+ return validatorInstance;
597
+ }
598
+ _nullable = import_option4.Option.None();
599
+ _every = import_option4.Option.None();
600
+ _tuple = import_option4.Option.None();
601
+ _min = import_option4.Option.None();
602
+ _max = import_option4.Option.None();
603
+ nullable(flag) {
604
+ this._nullable = flag ?? true ? import_option4.Option.Some(null) : import_option4.Option.None();
605
+ return this;
606
+ }
607
+ min(value, path = "min") {
608
+ if (this._max.isSome() && this._max.value < value)
609
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
610
+ if (this._tuple.isSome() && value < this._tuple.value.length)
611
+ throw new DefinitionError(`Expected Minimum Rule to be larger than or equal to Tuple Length at Path ${path}`);
612
+ this._min = import_option4.Option.Some(value);
613
+ return this;
614
+ }
615
+ max(value, path = "max") {
616
+ if (this._min.isSome() && this._min.value > value)
617
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
618
+ if (this._tuple.isSome() && value < this._tuple.value.length)
619
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Tuple Length at Path ${path}`);
620
+ this._max = import_option4.Option.Some(value);
621
+ return this;
622
+ }
623
+ every(validator) {
624
+ this._every = import_option4.Option.Some(validator);
625
+ return this;
626
+ }
627
+ /**
628
+ * Applies ONLY to prefix indices [0..validators.length - 1]
629
+ * If every() is set, prefix elements are effectively `T[i] & E`.
630
+ */
631
+ tuple(validators, path = "tuple") {
632
+ if (this._min.isSome() && this._min.value < validators.length)
633
+ throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Minimum Rule at Path ${path}`);
634
+ if (this._max.isSome() && this._max.value < validators.length)
635
+ throw new DefinitionError(`Expected Tuple Length to be smaller than or equal to Maximum Rule at Path ${path}`);
636
+ this._tuple = import_option4.Option.Some(validators);
637
+ return this;
638
+ }
639
+ assert(data, path = "data") {
640
+ if (import_json5.JSON.isShallowArray(data)) {
641
+ if (this._min.isSome() && this._min.value > data.length)
642
+ throw new AssertError(`Expected ${path} to be at least ${this._min.value} Elements long`);
643
+ if (this._max.isSome() && this._max.value < data.length)
644
+ throw new AssertError(`Expected ${path} to be at most ${this._max.value} Elements long`);
645
+ const errors = [];
646
+ if (this._every.isSome()) {
647
+ const validator = this._every.value;
648
+ data.forEach((value, index) => {
649
+ try {
650
+ validator.assert(value, `${path}[${index}]`);
651
+ } catch (e) {
652
+ if (!(e instanceof AssertError))
653
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
654
+ errors.push(e);
655
+ }
656
+ });
657
+ }
658
+ if (this._tuple.isSome()) {
659
+ if (data.length < this._tuple.value.length)
660
+ throw new AssertError(`Expected ${path} to be at least ${this._tuple.value.length} Elements long (Tuple Constraint)`);
661
+ this._tuple.value.forEach((validator, index) => {
662
+ try {
663
+ validator.assert(data[index], `${path}[${index}]`);
664
+ } catch (e) {
665
+ if (!(e instanceof AssertError))
666
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}[${index}]`);
667
+ errors.push(e);
668
+ }
669
+ });
670
+ }
671
+ if (errors.length > 0)
672
+ throw new AssertError(`Multiple Errors while asserting ${path} (see cause)`, { cause: errors });
673
+ } else if (import_json5.JSON.isNull(data)) {
674
+ if (!this._nullable.isSome())
675
+ throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
676
+ } else
677
+ throw new AssertError(`Expected ${path} to be an Array${this._nullable.isSome() ? " or Null" : ""}`);
678
+ }
679
+ isSubset(other) {
680
+ if (other instanceof JSONValidator)
681
+ return true;
682
+ if (!(other instanceof _ArrayValidator))
683
+ return false;
684
+ if (this._nullable.isSome() && !other._nullable.isSome())
685
+ return false;
686
+ const thisTupleLen = this._tuple.isSome() ? this._tuple.value.length : 0;
687
+ const otherTupleLen = other._tuple.isSome() ? other._tuple.value.length : 0;
688
+ const thisMin = this._min.isSome() ? this._min.value : 0;
689
+ const otherMin = other._min.isSome() ? other._min.value : 0;
690
+ const thisMax = this._max.isSome() ? this._max.value : Infinity;
691
+ const otherMax = other._max.isSome() ? other._max.value : Infinity;
692
+ const thisEffectiveMin = Math.max(thisMin, thisTupleLen);
693
+ const otherEffectiveMin = Math.max(otherMin, otherTupleLen);
694
+ if (thisEffectiveMin < otherEffectiveMin)
695
+ return false;
696
+ if (thisMax > otherMax)
697
+ return false;
698
+ const indexConjuncts = (i) => {
699
+ const conjuncts = [];
700
+ if (this._every.isSome())
701
+ conjuncts.push(this._every.value);
702
+ if (this._tuple.isSome() && i < this._tuple.value.length)
703
+ conjuncts.push(this._tuple.value[i]);
704
+ return conjuncts;
705
+ };
706
+ const conjunctsSubset = (conjuncts, target) => {
707
+ if (conjuncts.length === 0)
708
+ return false;
709
+ return conjuncts.some((c) => c.isSubset(target));
710
+ };
711
+ if (other._tuple.isSome()) {
712
+ for (let i = 0; i < other._tuple.value.length; i++) {
713
+ const aConj = indexConjuncts(i);
714
+ if (!conjunctsSubset(aConj, other._tuple.value[i]))
715
+ return false;
716
+ if (other._every.isSome() && !conjunctsSubset(aConj, other._every.value))
717
+ return false;
718
+ }
719
+ }
720
+ return !(other._every.isSome() && (thisMax === Infinity ? true : thisMax > Math.max(thisTupleLen, otherTupleLen)) && (!this._every.isSome() || !this._every.value.isSubset(other._every.value)));
721
+ }
722
+ toJSON() {
723
+ const definition = { type: "array" };
724
+ if (this._nullable.isSome())
725
+ definition.nullable = true;
726
+ if (this._min.isSome())
727
+ definition.min = this._min.value;
728
+ if (this._max.isSome())
729
+ definition.max = this._max.value;
730
+ if (this._every.isSome())
731
+ definition.every = this._every.value.toJSON();
732
+ if (this._tuple.isSome())
733
+ definition.tuple = this._tuple.value.map((validator) => validator.toJSON());
734
+ return definition;
735
+ }
736
+ };
737
+
738
+ // src/validators/Object.ts
739
+ var import_json6 = __toESM(require_build());
740
+ var import_option5 = __toESM(require_Option());
741
+ var ObjectValidator = class _ObjectValidator extends Validator {
742
+ static fromJSON(definition, path = "definition") {
743
+ const validatorInstance = new _ObjectValidator();
744
+ if ("nullable" in definition) {
745
+ if (!import_json6.JSON.isBoolean(definition["nullable"]))
746
+ throw new DefinitionError(`Expected ${path}.nullable to be a Boolean`);
747
+ validatorInstance.nullable(definition["nullable"]);
748
+ }
749
+ if ("exact" in definition) {
750
+ if (!import_json6.JSON.isBoolean(definition["exact"]))
751
+ throw new DefinitionError(`Expected ${path}.exact to be a Boolean`);
752
+ validatorInstance.exact(definition["exact"], `${path}.exact`);
753
+ }
754
+ if ("min" in definition) {
755
+ if (!import_json6.JSON.isNumber(definition["min"]))
756
+ throw new DefinitionError(`Expected ${path}.min to be a Number`);
757
+ validatorInstance.min(definition["min"], `${path}.min`);
758
+ }
759
+ if ("max" in definition) {
760
+ if (!import_json6.JSON.isNumber(definition["max"]))
761
+ throw new DefinitionError(`Expected ${path}.max to be a Number`);
762
+ validatorInstance.max(definition["max"], `${path}.max`);
763
+ }
764
+ if ("every" in definition) {
765
+ validatorInstance.every(fromJSON(definition["every"], `${path}.every`));
766
+ }
767
+ if ("shape" in definition) {
768
+ if (!import_json6.JSON.isShallowObject(definition["shape"]))
769
+ throw new DefinitionError(`Expected ${path}.shape to be an Object`);
770
+ const shape = {};
771
+ const errors = [];
772
+ for (const [key, value] of Object.entries(definition["shape"])) {
773
+ try {
774
+ shape[key] = fromJSON(value, `${path}.shape.${key}`);
775
+ } catch (e) {
776
+ if (!(e instanceof DefinitionError))
777
+ throw new DefinitionError(`Fatal Error: Undefined Error thrown by Domain.fromJSON at ${path}.shape.${key}`);
778
+ errors.push(e);
779
+ }
780
+ }
781
+ if (errors.length > 0) {
782
+ throw new DefinitionError(`Multiple Definition Errors detected at ${path}.shape (see cause)`, { cause: errors });
783
+ }
784
+ validatorInstance.shape(shape, `${path}.shape`);
785
+ }
786
+ return validatorInstance;
787
+ }
788
+ _nullable = import_option5.Option.None();
789
+ _min = import_option5.Option.None();
790
+ _max = import_option5.Option.None();
791
+ _every = import_option5.Option.None();
792
+ _shape = import_option5.Option.None();
793
+ _exact = import_option5.Option.None();
794
+ nullable(flag) {
795
+ this._nullable = flag ?? true ? import_option5.Option.Some(null) : import_option5.Option.None();
796
+ return this;
797
+ }
798
+ min(value, path = "min") {
799
+ if (this._max.isSome() && this._max.value < value)
800
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Maximum Rule at Path ${path}`);
801
+ if (this._shape.isSome() && value < Object.keys(this._shape.value).length)
802
+ throw new DefinitionError(`Expected Minimum Rule to be larger than or equal to Shape Key Count at Path ${path}`);
803
+ if (this._exact.isSome() && this._shape.isSome() && value > Object.keys(this._shape.value).length)
804
+ throw new DefinitionError(`Expected Minimum Rule to be smaller than or equal to Shape Key Count due to Exact Rule at Path ${path}`);
805
+ this._min = import_option5.Option.Some(value);
806
+ return this;
807
+ }
808
+ max(value, path = "max") {
809
+ if (this._min.isSome() && this._min.value > value)
810
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Minimum Rule at Path ${path}`);
811
+ if (this._shape.isSome() && value < Object.keys(this._shape.value).length)
812
+ throw new DefinitionError(`Expected Maximum Rule to be larger than or equal to Shape Key Count at Path ${path}`);
813
+ this._max = import_option5.Option.Some(value);
814
+ return this;
815
+ }
816
+ every(validator) {
817
+ this._every = import_option5.Option.Some(validator);
818
+ return this;
819
+ }
820
+ shape(value, path = "shape") {
821
+ const shapeKeyCount = Object.keys(value).length;
822
+ if (this._min.isSome() && this._min.value < shapeKeyCount)
823
+ throw new DefinitionError(`Expected Shape Key Count to be smaller than or equal to Minimum Rule at Path ${path}`);
824
+ if (this._max.isSome() && this._max.value < shapeKeyCount)
825
+ throw new DefinitionError(`Expected Shape Key Count to be smaller than or equal to Maximum Rule at Path ${path}`);
826
+ if (this._exact.isSome() && this._min.isSome() && this._min.value > shapeKeyCount)
827
+ throw new DefinitionError(`Expected Shape Key Count to be larger than or equal to Minimum Rule due to Exact Rule at Path ${path}`);
828
+ if (this._exact.isSome() && this._max.isSome() && this._max.value < shapeKeyCount)
829
+ throw new DefinitionError(`Expected Shape Key Count to be smaller than or equal to Maximum Rule due to Exact Rule at Path ${path}`);
830
+ this._shape = import_option5.Option.Some(value);
831
+ return this;
832
+ }
833
+ exact(flag, path = "exact") {
834
+ if ((flag ?? true) && this._shape.isSome()) {
835
+ const shapeKeyCount = Object.keys(this._shape.value).length;
836
+ if (this._min.isSome() && this._min.value > shapeKeyCount)
837
+ throw new DefinitionError(`Expected Exact Rule to be false due to Minimum Rule requiring more Properties than Shape defines at Path ${path}`);
838
+ if (this._max.isSome() && this._max.value < shapeKeyCount)
839
+ throw new DefinitionError(`Expected Exact Rule to be false due to Maximum Rule allowing fewer Properties than Shape defines at Path ${path}`);
840
+ }
841
+ this._exact = flag ?? true ? import_option5.Option.Some(null) : import_option5.Option.None();
842
+ return this;
843
+ }
844
+ assert(data, path = "data") {
845
+ if (import_json6.JSON.isShallowObject(data)) {
846
+ const keys = Object.keys(data);
847
+ if (this._min.isSome() && keys.length < this._min.value)
848
+ throw new AssertError(`Expected ${path} to have at least ${this._min.value} Properties`);
849
+ if (this._max.isSome() && keys.length > this._max.value)
850
+ throw new AssertError(`Expected ${path} to have at most ${this._max.value} Properties`);
851
+ const errors = [];
852
+ if (this._shape.isSome()) {
853
+ for (const key of Object.keys(this._shape.value)) {
854
+ try {
855
+ const validator = this._shape.value[key];
856
+ validator.assert(data[key], `${path}.${key}`);
857
+ } catch (e) {
858
+ if (!(e instanceof AssertError))
859
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}.${key}`);
860
+ errors.push(e);
861
+ }
862
+ }
863
+ if (this._exact.isSome()) {
864
+ for (const key of keys) {
865
+ if (!(key in this._shape.value)) {
866
+ errors.push(new AssertError(`Unexpected property ${path}.${key}`));
867
+ }
868
+ }
869
+ }
870
+ }
871
+ if (this._every.isSome()) {
872
+ const validator = this._every.value;
873
+ for (const key of keys) {
874
+ try {
875
+ validator.assert(data[key], `${path}.${key}`);
876
+ } catch (e) {
877
+ if (!(e instanceof AssertError))
878
+ throw new AssertError(`Fatal Error: Undefined Error thrown by an Assert Method at ${path}.${key}`);
879
+ errors.push(e);
880
+ }
881
+ }
882
+ }
883
+ if (errors.length > 0)
884
+ throw new AssertError(`Multiple Errors while asserting ${path} (see cause)`, { cause: errors });
885
+ } else if (import_json6.JSON.isNull(data)) {
886
+ if (!this._nullable.isSome())
887
+ throw new AssertError(`Expected ${path} to be an Object${this._nullable.isSome() ? " or Null" : ""}`);
888
+ } else
889
+ throw new AssertError(`Expected ${path} to be an Object${this._nullable.isSome() ? " or Null" : ""}`);
890
+ }
891
+ isSubset(other) {
892
+ if (other instanceof JSONValidator)
893
+ return true;
894
+ if (!(other instanceof _ObjectValidator))
895
+ return false;
896
+ if (this._nullable.isSome() && !other._nullable.isSome())
897
+ return false;
898
+ const thisMin = this._min.isSome() ? this._min.value : 0;
899
+ const otherMin = other._min.isSome() ? other._min.value : 0;
900
+ if (thisMin < otherMin)
901
+ return false;
902
+ const thisMax = this._max.isSome() ? this._max.value : Number.POSITIVE_INFINITY;
903
+ const otherMax = other._max.isSome() ? other._max.value : Number.POSITIVE_INFINITY;
904
+ if (thisMax > otherMax)
905
+ return false;
906
+ if (other._shape.isSome()) {
907
+ if (!this._shape.isSome())
908
+ return false;
909
+ const thisShape = this._shape.value;
910
+ const otherShape = other._shape.value;
911
+ for (const key of Object.keys(otherShape)) {
912
+ if (!(key in thisShape))
913
+ return false;
914
+ const a = thisShape[key];
915
+ const b = otherShape[key];
916
+ if (!a.isSubset(b))
917
+ return false;
918
+ }
919
+ }
920
+ if (other._exact.isSome()) {
921
+ if (!this._exact.isSome())
922
+ return false;
923
+ if (!other._shape.isSome() || !this._shape.isSome())
924
+ return false;
925
+ const aKeys = Object.keys(this._shape.value).sort();
926
+ const bKeys = Object.keys(other._shape.value).sort();
927
+ if (aKeys.length !== bKeys.length)
928
+ return false;
929
+ for (let i = 0; i < aKeys.length; i++) {
930
+ if (aKeys[i] !== bKeys[i])
931
+ return false;
932
+ }
933
+ }
934
+ if (other._every.isSome()) {
935
+ const bEvery = other._every.value;
936
+ if (!this._exact.isSome()) {
937
+ if (!this._every.isSome())
938
+ return false;
939
+ if (!this._every.value.isSubset(bEvery))
940
+ return false;
941
+ }
942
+ if (this._shape.isSome()) {
943
+ for (const [_, v] of Object.entries(this._shape.value)) {
944
+ if (!v.isSubset(bEvery))
945
+ return false;
946
+ }
947
+ }
948
+ if (this._exact.isSome() && !this._shape.isSome()) {
949
+ if (!this._every.isSome())
950
+ return false;
951
+ if (!this._every.value.isSubset(bEvery))
952
+ return false;
953
+ }
954
+ }
955
+ return true;
956
+ }
957
+ toJSON() {
958
+ const schema = { type: "object" };
959
+ if (this._nullable.isSome())
960
+ schema.nullable = true;
961
+ if (this._exact.isSome())
962
+ schema.exact = true;
963
+ if (this._min.isSome())
964
+ schema.min = this._min.value;
965
+ if (this._max.isSome())
966
+ schema.max = this._max.value;
967
+ if (this._every.isSome())
968
+ schema.every = this._every.value.toJSON();
969
+ if (this._shape.isSome()) {
970
+ schema.shape = Object.fromEntries(
971
+ Object.entries(this._shape.value).map(([k, s]) => [k, s.toJSON()])
972
+ );
973
+ }
974
+ return schema;
975
+ }
976
+ };
977
+
978
+ // src/lib/fromJSON.ts
979
+ function fromJSON(definition, path) {
980
+ if (!import_json7.JSON.isShallowObject(definition))
981
+ throw new DefinitionError(`Expected ${path} to be an Object`);
982
+ if (!import_json7.JSON.isString(definition["type"]))
983
+ throw new DefinitionError(`Expected ${path}.type to be a String`);
984
+ switch (definition["type"]) {
985
+ case "json":
986
+ return JSONValidator.fromJSON(definition, path);
987
+ case "boolean":
988
+ return BooleanValidator.fromJSON(definition, path);
989
+ case "number":
990
+ return NumberValidator.fromJSON(definition, path);
991
+ case "string":
992
+ return StringValidator.fromJSON(definition, path);
993
+ case "array":
994
+ return ArrayValidator.fromJSON(definition, path);
995
+ case "object":
996
+ return ObjectValidator.fromJSON(definition, path);
997
+ default:
998
+ throw new DefinitionError(`Expected ${path}.type to be a registered Validator`);
999
+ }
1000
+ }
1001
+
1002
+ // src/index.ts
1003
+ var Schema = class {
1004
+ static get JSON() {
1005
+ return new JSONValidator();
1006
+ }
1007
+ static get Boolean() {
1008
+ return new BooleanValidator();
1009
+ }
1010
+ static get Number() {
1011
+ return new NumberValidator();
1012
+ }
1013
+ static get String() {
1014
+ return new StringValidator();
1015
+ }
1016
+ static get Array() {
1017
+ return new ArrayValidator();
1018
+ }
1019
+ static get Object() {
1020
+ return new ObjectValidator();
1021
+ }
1022
+ static fromJSON(definition, path = "definition") {
1023
+ return fromJSON(definition, path);
1024
+ }
1025
+ };
1026
+ var Validators = {
1027
+ JSON: JSONValidator,
1028
+ Boolean: BooleanValidator,
1029
+ Number: NumberValidator,
1030
+ String: StringValidator,
1031
+ Array: ArrayValidator,
1032
+ Object: ObjectValidator
1033
+ };
1034
+ // Annotate the CommonJS export names for ESM import in node:
1035
+ 0 && (module.exports = {
1036
+ Schema,
1037
+ Validator,
1038
+ Validators
1039
+ });
1040
+ //# sourceMappingURL=index.js.map