@lucania/schema 2.0.3 → 3.0.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.
@@ -1,5 +1,5 @@
1
1
  import { BaseSchemaAny } from "./typing/extended";
2
- import { DefaultValue, ModelValue, TypedMembers } from "./typing/toolbox";
2
+ import { DefaultValue, ModelValue } from "./typing/toolbox";
3
3
  import { AnySchema } from "./schema/AnySchema";
4
4
  import { ArraySchema, ArraySource } from "./schema/ArraySchema";
5
5
  import { BooleanSchema, BooleanSource } from "./schema/BooleanSchema";
@@ -33,17 +33,23 @@ export declare namespace Schema {
33
33
  function Array<Subschema extends BaseSchemaAny>(subschema: Subschema): ArraySchema<Subschema, true, undefined>;
34
34
  function Array<Subschema extends BaseSchemaAny, Required extends boolean>(subschema: Subschema, required: Required): ArraySchema<Subschema, Required, undefined>;
35
35
  function Array<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<ArraySource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): ArraySchema<Subschema, Required, Default>;
36
- function Enumeration<Members extends string[]>(subschema: TypedMembers<Members>): EnumerationSchema<Members, true, undefined>;
37
- function Enumeration<Members extends string[], Required extends boolean>(subschema: TypedMembers<Members>, required: Required): EnumerationSchema<Members, Required, undefined>;
38
- function Enumeration<Members extends string[], Required extends boolean, Default extends DefaultValue<Members[number]>>(subschema: TypedMembers<Members>, required: Required, defaultValue: Default): EnumerationSchema<Members, Required, Default>;
36
+ function Enumeration<Member extends string>(subschema: TypedMembers<Member>): EnumerationSchema<Member, true, undefined>;
37
+ function Enumeration<Member extends string, Required extends boolean>(subschema: TypedMembers<Member>, required: Required): EnumerationSchema<Member, Required, undefined>;
38
+ function Enumeration<Member extends string, Required extends boolean, Default extends DefaultValue<Member>>(subschema: TypedMembers<Member>, required: Required, defaultValue: Default): EnumerationSchema<Member, Required, Default>;
39
39
  function DynamicObject<Subschema extends BaseSchemaAny>(subschema: Subschema): DynamicObjectSchema<Subschema, true, undefined>;
40
40
  function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean>(subschema: Subschema, required: Required): DynamicObjectSchema<Subschema, Required, undefined>;
41
41
  function DynamicObject<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<DynamicObjectSource<Subschema>>>(subschema: Subschema, required: Required, defaultValue: Default): DynamicObjectSchema<Subschema, Required, Default>;
42
- function OrSet<MemberSchemas extends BaseSchemaAny[]>(subschema: TypedMembers<MemberSchemas>): OrSetSchema<MemberSchemas, true, undefined>;
43
- function OrSet<MemberSchemas extends BaseSchemaAny[], Required extends boolean>(subschema: TypedMembers<MemberSchemas>, required: Required): OrSetSchema<MemberSchemas, Required, undefined>;
44
- function OrSet<MemberSchemas extends BaseSchemaAny[], Required extends boolean, Default extends DefaultValue<OrSetSchemaSource<MemberSchemas>>>(subschema: TypedMembers<MemberSchemas>, required: Required, defaultValue: Default): OrSetSchema<MemberSchemas, Required, Default>;
45
- function Members<Members extends string[]>(...members: Members): TypedMembers<Members>;
46
- function Members<Members extends any[]>(...members: Members): TypedMembers<Members>;
42
+ function OrSet<MemberSchema extends BaseSchemaAny>(subschema: TypedMembers<MemberSchema>): OrSetSchema<MemberSchema, true, undefined>;
43
+ function OrSet<MemberSchema extends BaseSchemaAny, Required extends boolean>(subschema: TypedMembers<MemberSchema>, required: Required): OrSetSchema<MemberSchema, Required, undefined>;
44
+ function OrSet<MemberSchema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<OrSetSchemaSource<MemberSchema>>>(subschema: TypedMembers<MemberSchema>, required: Required, defaultValue: Default): OrSetSchema<MemberSchema, Required, Default>;
45
+ type TypedMembers<Member extends any> = {
46
+ $members: Member[];
47
+ };
48
+ function Members<Member extends string[]>(...members: Member): TypedMembers<Member[number]>;
49
+ function Members<Member extends number[]>(...members: Member): TypedMembers<Member[number]>;
50
+ function Members<Member extends any[]>(...members: Member): TypedMembers<Member[number]>;
51
+ function Keys<Object extends object>(object: Object): (keyof Object)[];
52
+ function Values<Object extends object>(object: Object): (Object[keyof Object])[];
47
53
  type Model<Schema extends BaseSchemaAny> = Schema extends BaseSchema<infer Source, infer Model, infer Require, infer Default> ? (ModelValue<Source, Model, Require, Default>) : never;
48
54
  type Source<Schema extends BaseSchemaAny> = Schema extends BaseSchema<infer Source, any, infer Require, infer Default> ? (SourceValue<Source, Require, Default>) : never;
49
55
  }
@@ -0,0 +1,5 @@
1
+ import { ValidationError } from "./ValidationError";
2
+ import { ValidationPass } from "./ValidationPass";
3
+ export declare class TopLevelValidationError extends ValidationError {
4
+ constructor(pass: ValidationPass);
5
+ }
@@ -4,14 +4,19 @@ import { ValidationError } from "./ValidationError";
4
4
  export declare class ValidationPass {
5
5
  readonly originalSchema: BaseSchemaAny;
6
6
  readonly originalSource: SourceValue<any, boolean, DefaultValue<any>>;
7
+ private _parent;
7
8
  private _path;
8
9
  private _schema;
9
10
  private _source;
10
- constructor(originalSchema: BaseSchemaAny, originalSource: SourceValue<any, boolean, DefaultValue<any>>);
11
+ private _errors;
12
+ constructor(originalSchema: BaseSchemaAny, originalSource: SourceValue<any, boolean, DefaultValue<any>>, parent: ValidationPass | undefined);
11
13
  get path(): string[];
12
14
  get schema(): BaseSchemaAny;
13
15
  get source(): any;
14
16
  next(path: string[], schema: BaseSchemaAny, source: SourceValue<any, boolean, DefaultValue<any>>): ValidationPass;
15
17
  assert(condition: boolean, message: string): void;
16
- getError(message?: string): ValidationError;
18
+ causeError(message?: string): ValidationError;
19
+ addError(error: ValidationError): void;
20
+ get errors(): ValidationError[];
21
+ get topLevel(): boolean;
17
22
  }
package/build/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  export * from "./builder";
2
- export { Schema as $ } from "./builder";
3
2
  export * from "./error/ValidationError";
4
3
  export * from "./error/ValidationPass";
5
4
  export * from "./schema/AnySchema";
@@ -15,3 +14,4 @@ export * from "./schema/OrSetSchema";
15
14
  export * from "./schema/StringSchema";
16
15
  export * from "./typing/extended";
17
16
  export * from "./typing/toolbox";
17
+ export { Schema as $ } from "./builder";
package/build/index.js CHANGED
@@ -8,28 +8,39 @@
8
8
  pass;
9
9
  constructor(pass, message) {
10
10
  super(message);
11
+ this.name = ValidationError.name;
11
12
  this.pass = pass;
12
13
  }
13
14
  }
14
15
 
16
+ class TopLevelValidationError extends ValidationError {
17
+ constructor(pass) {
18
+ super(pass, `Encountered ${pass.errors.length} error(s).\n * ${pass.errors.map((error) => error.message).join("\n * ")}`);
19
+ }
20
+ }
21
+
15
22
  class ValidationPass {
16
23
  originalSchema;
17
24
  originalSource;
25
+ _parent;
18
26
  _path;
19
27
  _schema;
20
28
  _source;
21
- constructor(originalSchema, originalSource) {
29
+ _errors;
30
+ constructor(originalSchema, originalSource, parent) {
31
+ this._parent = parent;
22
32
  this.originalSchema = originalSchema;
23
33
  this.originalSource = originalSource;
24
34
  this._path = [];
25
35
  this._schema = originalSchema;
26
36
  this._source = originalSource;
37
+ this._errors = [];
27
38
  }
28
39
  get path() { return this._path; }
29
40
  get schema() { return this._schema; }
30
41
  get source() { return this._source; }
31
42
  next(path, schema, source) {
32
- const nextPass = new ValidationPass(this.originalSchema, this.originalSource);
43
+ const nextPass = new ValidationPass(this.originalSchema, this.originalSource, this);
33
44
  nextPass._path = path;
34
45
  nextPass._source = source;
35
46
  nextPass._schema = schema;
@@ -37,17 +48,31 @@
37
48
  }
38
49
  assert(condition, message) {
39
50
  if (!condition) {
40
- throw this.getError(message);
51
+ throw this.causeError(message);
41
52
  }
42
53
  }
43
- getError(message) {
54
+ causeError(message) {
44
55
  if (message === undefined) {
45
- return this.getError(`Validation failed.`);
56
+ return this.causeError(`Validation failed.`);
46
57
  }
47
58
  else {
48
- return new ValidationError(this, message);
59
+ const error = new ValidationError(this, message);
60
+ this.addError(error);
61
+ if (this._parent !== undefined) {
62
+ this._parent.causeError(error.message);
63
+ }
64
+ return error;
49
65
  }
50
66
  }
67
+ addError(error) {
68
+ this._errors.push(error);
69
+ }
70
+ get errors() {
71
+ return this._errors;
72
+ }
73
+ get topLevel() {
74
+ return this._parent === undefined;
75
+ }
51
76
  }
52
77
 
53
78
  class BaseSchema {
@@ -66,35 +91,49 @@
66
91
  afterAll: []
67
92
  } : additionalValidationPasses;
68
93
  }
69
- validate(source, pass) {
94
+ validate(source, options, pass) {
70
95
  pass = this._ensurePass(source, pass);
71
96
  let result = source;
72
- result = this._executeAdditionalValidator(result, pass, "beforeAll");
73
- result = this._executeAdditionalValidator(result, pass, "beforeDefault");
74
- if (!BaseSchema.isPresent(result) && this.hasDefault()) {
75
- result = this.getDefault(pass);
76
- }
77
- result = this._executeAdditionalValidator(result, pass, "afterDefault");
78
- result = this._executeAdditionalValidator(result, pass, "beforeConversion");
79
- if (BaseSchema.isPresent(result)) {
80
- if (BaseSchema.getType(result) !== this.type) {
81
- result = this.convert(result, pass);
97
+ const presentOptions = {
98
+ collectErrors: options?.collectErrors || false
99
+ };
100
+ try {
101
+ result = this._executeAdditionalValidator(result, pass, "beforeAll");
102
+ result = this._executeAdditionalValidator(result, pass, "beforeDefault");
103
+ if (!BaseSchema.isPresent(result) && this.hasDefault()) {
104
+ result = this.getDefault(pass);
82
105
  }
83
- result = this._validate(result, pass);
84
- result = this._executeAdditionalValidator(result, pass, "afterConversion");
85
- }
86
- else {
87
- if (this._required) {
88
- throw pass.getError(pass.path.length > 0 ? `Missing required value at "${pass.path.join(".")}".` : "Missing required value.");
106
+ result = this._executeAdditionalValidator(result, pass, "afterDefault");
107
+ result = this._executeAdditionalValidator(result, pass, "beforeConversion");
108
+ if (BaseSchema.isPresent(result)) {
109
+ if (BaseSchema.getType(result) !== this.type) {
110
+ result = this.convert(result, pass);
111
+ }
112
+ result = this._validate(result, presentOptions, pass);
113
+ result = this._executeAdditionalValidator(result, pass, "afterConversion");
89
114
  }
90
115
  else {
116
+ if (this._required) {
117
+ throw pass.causeError(pass.path.length > 0 ? `Missing required value at "${pass.path.join(".")}".` : "Missing required value.");
118
+ }
119
+ else {
120
+ result = undefined;
121
+ }
122
+ }
123
+ if (this._required || result !== undefined) {
124
+ result = this._executeAdditionalValidator(result, pass, "afterAll");
125
+ }
126
+ }
127
+ catch (error) {
128
+ if (error instanceof ValidationError && presentOptions.collectErrors) {
91
129
  result = undefined;
92
130
  }
93
- result = this._validate(result, pass);
94
- result = this._executeAdditionalValidator(result, pass, "afterConversion");
131
+ else {
132
+ throw error;
133
+ }
95
134
  }
96
- if (this._required || result !== undefined) {
97
- result = this._executeAdditionalValidator(result, pass, "afterAll");
135
+ if (pass.topLevel && pass.errors.length > 0) {
136
+ throw new TopLevelValidationError(pass);
98
137
  }
99
138
  return result;
100
139
  }
@@ -135,7 +174,7 @@
135
174
  return this._default;
136
175
  }
137
176
  else {
138
- throw pass.getError(`Failed to get default. Invalid default value.`);
177
+ throw pass.causeError(`Failed to get default. Invalid default value.`);
139
178
  }
140
179
  }
141
180
  _getValueDisplay(value) {
@@ -149,7 +188,7 @@
149
188
  };
150
189
  }
151
190
  _getJsonSchemaDescription() {
152
- const pass = new ValidationPass(this, this._default);
191
+ const pass = new ValidationPass(this, this._default, undefined);
153
192
  const descriptionPieces = [];
154
193
  descriptionPieces.push(`A ${this._required ? "required" : "optional"} ${this.type}`);
155
194
  if (this.hasDefault()) {
@@ -172,7 +211,7 @@
172
211
  }
173
212
  _ensurePass(source, pass) {
174
213
  if (pass === undefined) {
175
- pass = new ValidationPass(this, source);
214
+ pass = new ValidationPass(this, source, undefined);
176
215
  }
177
216
  return pass;
178
217
  }
@@ -182,6 +221,29 @@
182
221
  }
183
222
  return source;
184
223
  }
224
+ /**
225
+ * Converts this schema to a informational string representing this schema.
226
+ *
227
+ * @note Details about this schema will be displayed in [square brackets].
228
+ * * [R] Indicates this schema is required.
229
+ * * [D] Indicates this schema has a default value.
230
+ *
231
+ * @param level The nesting level. You needn't specify this externally.
232
+ * @returns A string representation of this schema.
233
+ */
234
+ toString(level = 0) {
235
+ const modifiers = [];
236
+ if (this._required)
237
+ modifiers.push("R");
238
+ if (this._default !== undefined)
239
+ modifiers.push("D");
240
+ if (modifiers.length > 0) {
241
+ return `${this.constructor.name}[${modifiers.join("")}]`;
242
+ }
243
+ else {
244
+ return this.constructor.name;
245
+ }
246
+ }
185
247
  /**
186
248
  * Checks to see if a value is present. (Not null or undefined)
187
249
  * @param value The value to check the presence of.
@@ -215,7 +277,7 @@
215
277
 
216
278
  class AnySchema extends BaseSchema {
217
279
  get type() { return "any"; }
218
- _validate(source, pass) {
280
+ _validate(source, options, pass) {
219
281
  return source;
220
282
  }
221
283
  convert(value, pass) {
@@ -224,33 +286,24 @@
224
286
  getJsonSchema() {
225
287
  return { description: this._getJsonSchemaDescription() };
226
288
  }
289
+ clone() {
290
+ return new AnySchema(this._required, this._default, this._additionalValidationPasses);
291
+ }
227
292
  }
228
293
 
229
294
  class ArraySchema extends BaseSchema {
230
295
  subschema;
231
- constructor(subschema, required, defaultValue) {
232
- super(required, defaultValue);
296
+ constructor(subschema, required, defaultValue, additionalValidationPasses) {
297
+ super(required, defaultValue, additionalValidationPasses);
233
298
  this.subschema = subschema;
234
299
  }
235
300
  get type() { return "array"; }
236
- // public validate(source: SourceValue<ArraySource<Subschema>, Required, Default>, pass?: ValidationPass):
237
- // ModelValue<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default> {
238
- // pass = this._ensurePass(source, pass);
239
- // const result: any = super.validate(source, pass);
240
- // if (result !== undefined) {
241
- // for (const key in result) {
242
- // const nestedValue = result[key];
243
- // result[key] = this.subschema.validate(result[key], pass.next([...pass.path, key], this.subschema, nestedValue));
244
- // }
245
- // }
246
- // return result;
247
- // }
248
- _validate(source, pass) {
301
+ _validate(source, options, pass) {
249
302
  const result = [];
250
303
  if (source !== undefined) {
251
304
  for (const key in source) {
252
305
  const nestedValue = source[key];
253
- result[key] = this.subschema.validate(source[key], pass.next([...pass.path, key], this.subschema, nestedValue));
306
+ result[key] = this.subschema.validate(source[key], options, pass.next([...pass.path, key], this.subschema, nestedValue));
254
307
  }
255
308
  }
256
309
  return result;
@@ -263,7 +316,7 @@
263
316
  return [value];
264
317
  }
265
318
  else {
266
- throw pass.getError(`Unable to convert ${BaseSchema.getType(value)} to array.`);
319
+ throw pass.causeError(`Unable to convert ${BaseSchema.getType(value)} to array.`);
267
320
  }
268
321
  }
269
322
  getJsonSchema() {
@@ -273,11 +326,17 @@
273
326
  items: this.subschema.getJsonSchema()
274
327
  };
275
328
  }
329
+ clone() {
330
+ return new ArraySchema(this.subschema.clone(), this._required, this._default, this._additionalValidationPasses);
331
+ }
332
+ toString(level = 0) {
333
+ return `${super.toString(level)}(${this.subschema.toString(level)}[])`;
334
+ }
276
335
  }
277
336
 
278
337
  class BooleanSchema extends BaseSchema {
279
338
  get type() { return "boolean"; }
280
- _validate(source, pass) {
339
+ _validate(source, options, pass) {
281
340
  return source;
282
341
  }
283
342
  convert(value, pass) {
@@ -296,9 +355,12 @@
296
355
  return false;
297
356
  }
298
357
  else {
299
- throw pass.getError(`Unable to convert ${BaseSchema.getType(value)} to boolean.`);
358
+ throw pass.causeError(`Unable to convert ${BaseSchema.getType(value)} to boolean.`);
300
359
  }
301
360
  }
361
+ clone() {
362
+ return new BooleanSchema(this._required, this._default, this._additionalValidationPasses);
363
+ }
302
364
  getJsonSchema() {
303
365
  return {
304
366
  type: "boolean",
@@ -310,7 +372,7 @@
310
372
  const StandardDate = globalThis.Date;
311
373
  class DateSchema extends BaseSchema {
312
374
  get type() { return "Date"; }
313
- _validate(source, pass) {
375
+ _validate(source, options, pass) {
314
376
  return source;
315
377
  }
316
378
  convert(value, pass) {
@@ -321,7 +383,7 @@
321
383
  return new StandardDate(value);
322
384
  }
323
385
  else {
324
- throw pass.getError(`Unable to convert ${BaseSchema.getType(value)} to Date.`);
386
+ throw pass.causeError(`Unable to convert ${BaseSchema.getType(value)} to Date.`);
325
387
  }
326
388
  }
327
389
  before(date, message) {
@@ -358,6 +420,9 @@
358
420
  return model;
359
421
  }, "afterAll");
360
422
  }
423
+ clone() {
424
+ return new DateSchema(this._required, this._default, this._additionalValidationPasses);
425
+ }
361
426
  getJsonSchema() {
362
427
  return {
363
428
  type: "string",
@@ -368,29 +433,17 @@
368
433
 
369
434
  class DynamicObjectSchema extends BaseSchema {
370
435
  subschema;
371
- constructor(subschema, required, defaultValue) {
372
- super(required, defaultValue);
436
+ constructor(subschema, required, defaultValue, additionalValidationPasses) {
437
+ super(required, defaultValue, additionalValidationPasses);
373
438
  this.subschema = subschema;
374
439
  }
375
440
  get type() { return "object"; }
376
- // public validate(source: SourceValue<DynamicObjectSource<Subschema>, Required, Default>, pass?: ValidationPass):
377
- // ModelValue<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>, Required, Default> {
378
- // pass = this._ensurePass(source, pass);
379
- // const result: any = super.validate(source, pass);
380
- // if (result !== undefined) {
381
- // for (const key in result) {
382
- // const nestedValue = result[key];
383
- // result[key] = this.subschema.validate(result[key], pass.next([...pass.path, key], this.subschema, nestedValue));
384
- // }
385
- // }
386
- // return result;
387
- // }
388
- _validate(source, pass) {
441
+ _validate(source, options, pass) {
389
442
  const result = source;
390
443
  if (result !== undefined) {
391
444
  for (const key in result) {
392
445
  const nestedValue = result[key];
393
- result[key] = this.subschema.validate(result[key], pass.next([...pass.path, key], this.subschema, nestedValue));
446
+ result[key] = this.subschema.validate(result[key], options, pass.next([...pass.path, key], this.subschema, nestedValue));
394
447
  }
395
448
  }
396
449
  return result;
@@ -410,23 +463,24 @@
410
463
  additionalProperties: this.subschema.getJsonSchema()
411
464
  };
412
465
  }
466
+ clone() {
467
+ return new DynamicObjectSchema(this.subschema.clone(), this._required, this._default, this._additionalValidationPasses);
468
+ }
469
+ toString(level = 0) {
470
+ const indent = " ";
471
+ const prefix = indent.repeat(level);
472
+ return `${super.toString(level)}({\n${prefix}${indent}[string]: ${this.subschema.toString(level)}\n${prefix}})`;
473
+ }
413
474
  }
414
475
 
415
476
  class EnumerationSchema extends BaseSchema {
416
477
  members;
417
- constructor(members, required, defaultValue) {
418
- super(required, defaultValue);
478
+ constructor(members, required, defaultValue, additionalValidationPasses) {
479
+ super(required, defaultValue, additionalValidationPasses);
419
480
  this.members = members;
420
481
  }
421
482
  get type() { return "string"; }
422
- // public validate(source: SourceValue<Members[number], Required, Default>, pass?: ValidationPass):
423
- // ModelValue<Members[number], Members[number], Required, Default> {
424
- // pass = this._ensurePass(source, pass);
425
- // const result: any = super.validate(source, pass);
426
- // pass.assert(this.members.includes(result), `"${result}" is not a valid enumeration value (Expected: ${this.members.join(", ")}).`);
427
- // return result;
428
- // }
429
- _validate(source, pass) {
483
+ _validate(source, options, pass) {
430
484
  const result = source;
431
485
  pass.assert(this.members.includes(result), `"${result}" is not a valid enumeration value (Expected: ${this.members.join(", ")}).`);
432
486
  return result;
@@ -434,6 +488,9 @@
434
488
  convert(value, pass) {
435
489
  return value;
436
490
  }
491
+ clone() {
492
+ return new EnumerationSchema([...this.members], this._required, this._default, this._additionalValidationPasses);
493
+ }
437
494
  getJsonSchema() {
438
495
  return {
439
496
  type: "string",
@@ -445,7 +502,7 @@
445
502
 
446
503
  class NumberSchema extends BaseSchema {
447
504
  get type() { return "number"; }
448
- _validate(source, pass) {
505
+ _validate(source, options, pass) {
449
506
  return source;
450
507
  }
451
508
  convert(value, pass) {
@@ -465,18 +522,18 @@
465
522
  return value.getTime();
466
523
  }
467
524
  else {
468
- throw pass.getError(`Unable to convert ${BaseSchema.getType(value)} to number.`);
525
+ throw pass.causeError(`Unable to convert ${BaseSchema.getType(value)} to number.`);
469
526
  }
470
527
  }
471
528
  min(minimum, message) {
472
529
  return this.custom((model, pass) => {
473
- pass.assert(model >= minimum, message === undefined ? `Number ${model} failed minimum check. (${minimum})` : message);
530
+ pass.assert(model >= minimum, message === undefined ? `Number ${model} failed minimum check. (Must be >= ${minimum})` : message);
474
531
  return model;
475
532
  }, "afterAll");
476
533
  }
477
534
  max(maximum, message) {
478
535
  return this.custom((model, pass) => {
479
- pass.assert(model <= maximum, message === undefined ? `Number ${model} failed maximum check. (${maximum})` : message);
536
+ pass.assert(model <= maximum, message === undefined ? `Number ${model} failed maximum check. (Must be <= ${maximum})` : message);
480
537
  return model;
481
538
  }, "afterAll");
482
539
  }
@@ -489,6 +546,9 @@
489
546
  return model;
490
547
  }, "afterAll");
491
548
  }
549
+ clone() {
550
+ return new NumberSchema(this._required, this._default, this._additionalValidationPasses);
551
+ }
492
552
  getJsonSchema() {
493
553
  return {
494
554
  type: "number",
@@ -499,27 +559,12 @@
499
559
 
500
560
  class ObjectSchema extends BaseSchema {
501
561
  subschema;
502
- constructor(subschema, required, defaultValue) {
503
- super(required, defaultValue);
562
+ constructor(subschema, required, defaultValue, additionalValidationPasses) {
563
+ super(required, defaultValue, additionalValidationPasses);
504
564
  this.subschema = subschema;
505
565
  }
506
566
  get type() { return "object"; }
507
- // public validate(source: SourceValue<ObjectSource<Subschema>, Required, Default>, pass?: ValidationPass):
508
- // ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default> {
509
- // pass = this._ensurePass(source, pass);
510
- // const input: any = super.validate(source, pass);
511
- // let output: any = input;
512
- // if (typeof input === "object" && input !== null) {
513
- // output = {};
514
- // for (const key in this.subschema) {
515
- // const nestedSchema = this.subschema[key];
516
- // const nestedValue = input[key];
517
- // output[key] = this.subschema[key].validate(input[key], pass.next([...pass.path, key], nestedSchema, nestedValue));
518
- // }
519
- // }
520
- // return output;
521
- // }
522
- _validate(source, pass) {
567
+ _validate(source, options, pass) {
523
568
  const input = source;
524
569
  let output = input;
525
570
  if (typeof input === "object" && input !== null) {
@@ -527,7 +572,7 @@
527
572
  for (const key in this.subschema) {
528
573
  const nestedSchema = this.subschema[key];
529
574
  const nestedValue = input[key];
530
- output[key] = this.subschema[key].validate(input[key], pass.next([...pass.path, key], nestedSchema, nestedValue));
575
+ output[key] = this.subschema[key].validate(input[key], options, pass.next([...pass.path, key], nestedSchema, nestedValue));
531
576
  }
532
577
  }
533
578
  return output;
@@ -568,40 +613,37 @@
568
613
  properties
569
614
  };
570
615
  }
616
+ clone() {
617
+ const subschema = {};
618
+ for (const key in this.subschema) {
619
+ subschema[key] = this.subschema[key].clone();
620
+ }
621
+ return new ObjectSchema(subschema, this._required, this._default, this._additionalValidationPasses);
622
+ }
623
+ toString(level = 0) {
624
+ const indent = " ";
625
+ const prefix = indent.repeat(level);
626
+ const pieces = [];
627
+ pieces.push(`${super.toString()}({\n`);
628
+ for (const schemaKey in this.subschema) {
629
+ const subschema = this.subschema[schemaKey];
630
+ pieces.push(`${prefix}${indent}${schemaKey}: ${subschema.toString(level + 1)}\n`);
631
+ }
632
+ pieces.push(`${prefix}})`);
633
+ return pieces.join("");
634
+ }
571
635
  }
572
636
 
573
637
  class OrSetSchema extends BaseSchema {
574
638
  schemas;
575
- constructor(schemas, required, defaultValue) {
576
- super(required, defaultValue);
639
+ constructor(schemas, required, defaultValue, additionalValidationPasses) {
640
+ super(required, defaultValue, additionalValidationPasses);
577
641
  this.schemas = schemas;
578
642
  }
579
- get type() { return "string"; }
580
- // public validate(source: SourceValue<OrSetSchemaSource<MemberSchemas>, Required, Default>, pass?: ValidationPass):
581
- // ModelValue<OrSetSchemaSource<MemberSchemas>, OrSetSchemaModel<MemberSchemas>, Required, Default> {
582
- // pass = this._ensurePass(source, pass);
583
- // let result: any = super.validate(source, pass);
584
- // if (result !== undefined) {
585
- // let done = false;
586
- // const failureMessages: string[] = [];
587
- // for (let i = 0; i < this.schemas.length && !done; i++) {
588
- // const schema = this.schemas[i];
589
- // try {
590
- // result = schema.validate(result, pass);
591
- // done = true;
592
- // } catch (error) {
593
- // if (error instanceof Error) {
594
- // failureMessages.push(`Schema #${i + 1}: ${error.message}`);
595
- // } else {
596
- // failureMessages.push(`Schema #${i + 1}: ${String(error)}`);
597
- // }
598
- // pass.assert(failureMessages.length !== this.schemas.length, `Supplied value didn't match any schemas in or-set.\n${failureMessages.join("\n")}`);
599
- // }
600
- // }
601
- // }
602
- // return result;
603
- // }
604
- _validate(source, pass) {
643
+ get type() {
644
+ return "string";
645
+ }
646
+ _validate(source, options, pass) {
605
647
  let result = source;
606
648
  if (result !== undefined) {
607
649
  let done = false;
@@ -609,8 +651,10 @@
609
651
  for (let i = 0; i < this.schemas.length && !done; i++) {
610
652
  const schema = this.schemas[i];
611
653
  try {
612
- result = schema.validate(result, pass);
613
- done = true;
654
+ if (BaseSchema.getType(result) === schema.type) {
655
+ result = schema.validate(result, options, pass);
656
+ done = true;
657
+ }
614
658
  }
615
659
  catch (error) {
616
660
  if (error instanceof Error) {
@@ -619,15 +663,22 @@
619
663
  else {
620
664
  failureMessages.push(`Schema #${i + 1}: ${String(error)}`);
621
665
  }
622
- pass.assert(failureMessages.length !== this.schemas.length, `Supplied value didn't match any schemas in or-set.\n${failureMessages.join("\n")}`);
623
666
  }
624
667
  }
668
+ if (!done) {
669
+ failureMessages.push(`Conversions for schemas in an OrSet are disabled.`);
670
+ }
671
+ pass.assert(failureMessages.length === 0, `Provided value (${BaseSchema.getType(result)}) matched no schemas ` +
672
+ `(${this.schemas.map((schema) => schema.type).join(", ")}).\n${failureMessages.join("\n")}`);
625
673
  }
626
674
  return result;
627
675
  }
628
676
  convert(value, pass) {
629
677
  return value;
630
678
  }
679
+ clone() {
680
+ return new OrSetSchema(this.schemas.map((schema) => schema.clone()), this._required, this._default, this._additionalValidationPasses);
681
+ }
631
682
  getJsonSchema() {
632
683
  return { oneOf: this.schemas.map((schema) => schema.getJsonSchema()) };
633
684
  }
@@ -639,7 +690,7 @@
639
690
  // public required() { return new StringSchema(true, this._default, this._additionalValidationPasses); }
640
691
  // public optional() { return new StringSchema(false, this._default, this._additionalValidationPasses); }
641
692
  // public default<Default extends DefaultValue<StringSource>>(defaultValue: Default) { return new StringSchema(this._required, defaultValue, this._additionalValidationPasses); }
642
- _validate(source, pass) {
693
+ _validate(source, options, pass) {
643
694
  return source;
644
695
  }
645
696
  convert(value, pass) {
@@ -654,6 +705,25 @@
654
705
  }
655
706
  return value.toString();
656
707
  }
708
+ /**
709
+ * Trims strings validated by this schema.
710
+ * @see {@link String.trim}
711
+ */
712
+ trim() {
713
+ return this.custom((model) => model.trim());
714
+ }
715
+ /**
716
+ * Makes strings validated by this schema lowercase.
717
+ */
718
+ lower() {
719
+ return this.custom((model) => model.toLowerCase());
720
+ }
721
+ /**
722
+ * Makes strings validated by this schema uppercase.
723
+ */
724
+ upper() {
725
+ return this.custom((model) => model.toUpperCase());
726
+ }
657
727
  length(minimum, maximum, messageA, messageB) {
658
728
  return this.custom((model, pass) => {
659
729
  messageB = messageB === undefined ? messageA : messageB;
@@ -662,12 +732,19 @@
662
732
  return model;
663
733
  }, "afterAll");
664
734
  }
735
+ /**
736
+ * Ensures a string validated by this schema matches a given regular expression.
737
+ * With an optional custom error message.
738
+ */
665
739
  regex(expression, message) {
666
740
  return this.custom((model, pass) => {
667
741
  pass.assert(expression.test(model), message === undefined ? `String "${model}" failed regular expression check. (${expression})` : message);
668
742
  return model;
669
743
  }, "afterAll");
670
744
  }
745
+ clone() {
746
+ return new StringSchema(this._required, this._default, this._additionalValidationPasses);
747
+ }
671
748
  getJsonSchema() {
672
749
  return {
673
750
  type: "string",
@@ -719,9 +796,26 @@
719
796
  }
720
797
  Schema.OrSet = OrSet;
721
798
  function Members(...members) {
799
+ /*
800
+ * HACK START: The hermes JS engine doesn't use globalThis.Array when interpreting `...members`
801
+ * It uses `Array`, which is already defined in this namespace.
802
+ */
803
+ if (!globalThis.Array.isArray(members)) {
804
+ const validArrayEntries = globalThis.Object.entries(members).filter(([key]) => !isNaN(key));
805
+ members = validArrayEntries.map(([_, value]) => value);
806
+ }
807
+ /* HACK END */
722
808
  return { $members: members };
723
809
  }
724
810
  Schema.Members = Members;
811
+ function Keys(object) {
812
+ return globalThis.Object.keys(object);
813
+ }
814
+ Schema.Keys = Keys;
815
+ function Values(object) {
816
+ return globalThis.Object.values(object);
817
+ }
818
+ Schema.Values = Values;
725
819
  })(exports.Schema || (exports.Schema = {}));
726
820
 
727
821
  exports.$ = exports.Schema;
@@ -1,9 +1,10 @@
1
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
2
+ import { DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
4
  export declare class AnySchema<Required extends boolean, Default extends DefaultValue<any>> extends BaseSchema<any, any, Required, Default> {
5
5
  get type(): string;
6
- protected _validate(source: SourceValue<any, Required, Default>, pass: ValidationPass): ModelValue<any, any, Required, Default>;
6
+ protected _validate(source: ModelValue<any, any, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<any, any, Required, Default>;
7
7
  convert(value: any, pass: ValidationPass): any;
8
8
  getJsonSchema(): object;
9
+ clone(): AnySchema<Required, Default>;
9
10
  }
@@ -1,14 +1,16 @@
1
1
  import { ValidationPass } from "../error/ValidationPass";
2
2
  import { BaseSchemaAny } from "../typing/extended";
3
- import type { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
3
+ import type { AdditionalValidationPasses, DefaultValue, ModelValue, SourceValue, ValidationOptions } from "../typing/toolbox";
4
4
  import { BaseSchema } from "./BaseSchema";
5
5
  export type ArraySource<Subschema extends BaseSchemaAny> = (Subschema extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>[]) : never);
6
6
  export type ArrayModel<Subschema extends BaseSchemaAny> = (Subschema extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? (ModelValue<Source, Model, Required, Default>[]) : never);
7
7
  export declare class ArraySchema<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<ArraySource<Subschema>>> extends BaseSchema<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default> {
8
8
  readonly subschema: Subschema;
9
- constructor(subschema: Subschema, required: Required, defaultValue: Default);
9
+ constructor(subschema: Subschema, required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<ArraySource<Subschema>, ArrayModel<Subschema>>);
10
10
  get type(): string;
11
- protected _validate(source: SourceValue<ArraySource<Subschema>, Required, Default>, pass: ValidationPass): ModelValue<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default>;
11
+ protected _validate(source: ModelValue<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<ArraySource<Subschema>, ArrayModel<Subschema>, Required, Default>;
12
12
  convert(value: ArraySource<Subschema>, pass: ValidationPass): ArrayModel<Subschema>;
13
13
  getJsonSchema(): object;
14
+ clone(): ArraySchema<Subschema, Required, Default>;
15
+ toString(level?: number): string;
14
16
  }
@@ -1,13 +1,14 @@
1
1
  import { ValidationPass } from "../error/ValidationPass";
2
- import type { AdditionalValidationPasses, AdditionalValidator, AdditionalValidatorAfterType, AdditionalValidatorBeforeType, DefaultValue, EnsureValidator, ModelValue, SourceValue } from "../typing/toolbox";
2
+ import { BaseSchemaAny } from "../typing/extended";
3
+ import type { AdditionalValidationPasses, AdditionalValidator, AdditionalValidatorAfterType, AdditionalValidatorBeforeType, DefaultValue, EnsureValidator, ModelValue, OptionalValidationOptions, SourceValue, ValidationOptions } from "../typing/toolbox";
3
4
  export declare abstract class BaseSchema<Source, Model, Required extends boolean, Default extends DefaultValue<Source>> {
4
5
  protected readonly _required: Required;
5
6
  protected readonly _default: Default;
6
7
  protected readonly _additionalValidationPasses: AdditionalValidationPasses<Source, Model>;
7
8
  constructor(required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<Source, Model>);
8
9
  abstract get type(): string;
9
- validate(source: SourceValue<Source, Required, Default>, pass?: ValidationPass): ModelValue<Source, Model, Required, Default>;
10
- protected abstract _validate(source: SourceValue<Source, Required, Default>, pass: ValidationPass): ModelValue<Source, Model, Required, Default>;
10
+ validate(source: SourceValue<Source, Required, Default>, options?: OptionalValidationOptions, pass?: ValidationPass): ModelValue<Source, Model, Required, Default>;
11
+ protected abstract _validate(source: ModelValue<Source, Model, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<Source, Model, Required, Default>;
11
12
  abstract convert(value: Source, pass: ValidationPass): Model;
12
13
  custom(additionalValidator: AdditionalValidator<SourceValue<Source, Required, Default>>, type: AdditionalValidatorBeforeType): this;
13
14
  custom(additionalValidator: AdditionalValidator<Model>, type: AdditionalValidatorAfterType): this;
@@ -33,6 +34,18 @@ export declare abstract class BaseSchema<Source, Model, Required extends boolean
33
34
  protected _getJsonSchemaDescription(): string;
34
35
  protected _ensurePass(source: SourceValue<Source, Required, Default>, pass?: ValidationPass): ValidationPass;
35
36
  private _executeAdditionalValidator;
37
+ abstract clone(): BaseSchemaAny;
38
+ /**
39
+ * Converts this schema to a informational string representing this schema.
40
+ *
41
+ * @note Details about this schema will be displayed in [square brackets].
42
+ * * [R] Indicates this schema is required.
43
+ * * [D] Indicates this schema has a default value.
44
+ *
45
+ * @param level The nesting level. You needn't specify this externally.
46
+ * @returns A string representation of this schema.
47
+ */
48
+ toString(level?: number): string;
36
49
  /**
37
50
  * Checks to see if a value is present. (Not null or undefined)
38
51
  * @param value The value to check the presence of.
@@ -1,10 +1,11 @@
1
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
2
+ import { DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
4
  export type BooleanSource = boolean | number | string | null | undefined;
5
5
  export declare class BooleanSchema<Required extends boolean, Default extends DefaultValue<BooleanSource>> extends BaseSchema<BooleanSource, boolean, Required, Default> {
6
6
  get type(): string;
7
- protected _validate(source: SourceValue<BooleanSource, Required, Default>, pass: ValidationPass): ModelValue<BooleanSource, boolean, Required, Default>;
7
+ protected _validate(source: ModelValue<BooleanSource, boolean, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<BooleanSource, boolean, Required, Default>;
8
8
  convert(value: BooleanSource, pass: ValidationPass): boolean;
9
+ clone(): BooleanSchema<Required, Default>;
9
10
  getJsonSchema(): object;
10
11
  }
@@ -1,12 +1,12 @@
1
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
2
+ import { DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
4
  type StandardDate = globalThis.Date;
5
5
  declare const StandardDate: DateConstructor;
6
6
  export type DateSource = string | number | StandardDate;
7
7
  export declare class DateSchema<Required extends boolean, Default extends DefaultValue<DateSource>> extends BaseSchema<DateSource, StandardDate, Required, Default> {
8
8
  get type(): string;
9
- protected _validate(source: SourceValue<DateSource, Required, Default>, pass: ValidationPass): ModelValue<DateSource, Date, Required, Default>;
9
+ protected _validate(source: ModelValue<DateSource, Date, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<DateSource, Date, Required, Default>;
10
10
  convert(value: DateSource, pass: ValidationPass): StandardDate;
11
11
  before(date: Date, message?: string): this;
12
12
  after(date: Date, message?: string): this;
@@ -18,6 +18,7 @@ export declare class DateSchema<Required extends boolean, Default extends Defaul
18
18
  * @param duration milliseconds
19
19
  */
20
20
  lessThanAgo(duration: number, message?: string): this;
21
+ clone(): DateSchema<Required, Default>;
21
22
  getJsonSchema(): object;
22
23
  }
23
24
  export {};
@@ -1,6 +1,6 @@
1
- import type { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
3
2
  import { BaseSchemaAny } from "../typing/extended";
3
+ import type { AdditionalValidationPasses, DefaultValue, ModelValue, SourceValue, ValidationOptions } from "../typing/toolbox";
4
4
  import { BaseSchema } from "./BaseSchema";
5
5
  export type DynamicObjectSource<Subschema extends BaseSchemaAny> = ({
6
6
  [Key: string]: (Subschema extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>) : never);
@@ -10,9 +10,11 @@ export type DynamicObjectModel<Subschema extends BaseSchemaAny> = ({
10
10
  });
11
11
  export declare class DynamicObjectSchema<Subschema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<DynamicObjectSource<Subschema>>> extends BaseSchema<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>, Required, Default> {
12
12
  readonly subschema: Subschema;
13
- constructor(subschema: Subschema, required: Required, defaultValue: Default);
13
+ constructor(subschema: Subschema, required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>>);
14
14
  get type(): string;
15
- _validate(source: SourceValue<DynamicObjectSource<Subschema>, Required, Default>, pass: ValidationPass): ModelValue<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>, Required, Default>;
15
+ protected _validate(source: ModelValue<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<DynamicObjectSource<Subschema>, DynamicObjectModel<Subschema>, Required, Default>;
16
16
  convert(source: DynamicObjectSource<Subschema>, pass: ValidationPass): DynamicObjectModel<Subschema>;
17
17
  getJsonSchema(): object;
18
+ clone(): DynamicObjectSchema<Subschema, Required, Default>;
19
+ toString(level?: number): string;
18
20
  }
@@ -1,11 +1,12 @@
1
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
2
+ import { AdditionalValidationPasses, DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
- export declare class EnumerationSchema<Members extends string[], Required extends boolean, Default extends DefaultValue<Members[number]>> extends BaseSchema<Members[number], Members[number], Required, Default> {
5
- readonly members: Members;
6
- constructor(members: Members, required: Required, defaultValue: Default);
4
+ export declare class EnumerationSchema<Members extends string, Required extends boolean, Default extends DefaultValue<Members>> extends BaseSchema<Members, Members, Required, Default> {
5
+ readonly members: Members[];
6
+ constructor(members: Members[], required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<Members, Members>);
7
7
  get type(): string;
8
- _validate(source: SourceValue<Members[number], Required, Default>, pass: ValidationPass): ModelValue<Members[number], Members[number], Required, Default>;
9
- convert(value: Members[number], pass: ValidationPass): Members[number];
8
+ protected _validate(source: ModelValue<Members, Members, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<Members, Members, Required, Default>;
9
+ convert(value: Members, pass: ValidationPass): Members;
10
+ clone(): EnumerationSchema<Members, Required, Default>;
10
11
  getJsonSchema(): object;
11
12
  }
@@ -1,10 +1,10 @@
1
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
2
+ import { DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
4
  export type NumberSource = number | bigint | string | boolean | null | undefined | Date;
5
5
  export declare class NumberSchema<Required extends boolean, Default extends DefaultValue<NumberSource>> extends BaseSchema<NumberSource, number, Required, Default> {
6
6
  get type(): string;
7
- protected _validate(source: SourceValue<NumberSource, Required, Default>, pass: ValidationPass): ModelValue<NumberSource, number, Required, Default>;
7
+ protected _validate(source: ModelValue<NumberSource, number, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<NumberSource, number, Required, Default>;
8
8
  convert(value: NumberSource, pass: ValidationPass): number;
9
9
  min(minimum: number, message?: string): this;
10
10
  max(maximum: number, message?: string): this;
@@ -12,5 +12,6 @@ export declare class NumberSchema<Required extends boolean, Default extends Defa
12
12
  clamp(minimum: number, maximum: number, message: string): this;
13
13
  clamp(minimum: number, maximum: number, tooShortMessage: string, tooLongMessage: string): this;
14
14
  validNumber(notANumber?: boolean, message?: string): this;
15
+ clone(): NumberSchema<Required, Default>;
15
16
  getJsonSchema(): object;
16
17
  }
@@ -1,6 +1,6 @@
1
- import type { DefaultValue, Merge, ModelRequirement, ModelValue, SourceRequirement, SourceValue } from "../typing/toolbox";
2
1
  import { ValidationPass } from "../error/ValidationPass";
3
2
  import { BaseSchemaAny } from "../typing/extended";
3
+ import type { AdditionalValidationPasses, DefaultValue, Merge, ModelRequirement, ModelValue, SourceRequirement, SourceValue, ValidationOptions } from "../typing/toolbox";
4
4
  import { BaseSchema } from "./BaseSchema";
5
5
  export type ObjectSubschema = {
6
6
  [Key: string]: BaseSchemaAny;
@@ -17,10 +17,12 @@ export type ObjectModel<Subschema extends ObjectSubschema> = (Merge<{
17
17
  }>);
18
18
  export declare class ObjectSchema<Subschema extends ObjectSubschema, Required extends boolean, Default extends DefaultValue<ObjectSource<Subschema>>> extends BaseSchema<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default> {
19
19
  readonly subschema: Subschema;
20
- constructor(subschema: Subschema, required: Required, defaultValue: Default);
20
+ constructor(subschema: Subschema, required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<ObjectSource<Subschema>, ObjectModel<Subschema>>);
21
21
  get type(): string;
22
- protected _validate(source: SourceValue<ObjectSource<Subschema>, Required, Default>, pass: ValidationPass): ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default>;
22
+ protected _validate(source: ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<ObjectSource<Subschema>, ObjectModel<Subschema>, Required, Default>;
23
23
  convert(value: ObjectSource<Subschema>, pass: ValidationPass): ObjectModel<Subschema>;
24
24
  extend<ExtensionSubschema extends ObjectSubschema, ExtensionDefault extends DefaultValue<ObjectSource<ExtensionSubschema>>>(schema: ObjectSchema<ExtensionSubschema, Required, ExtensionDefault>): ObjectSchema<Subschema & ExtensionSubschema, Required, any>;
25
25
  getJsonSchema(): object;
26
+ clone(): ObjectSchema<Subschema, Required, Default>;
27
+ toString(level?: number): string;
26
28
  }
@@ -1,18 +1,15 @@
1
1
  import { ValidationPass } from "../error/ValidationPass";
2
2
  import { BaseSchemaAny } from "../typing/extended";
3
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
3
+ import { AdditionalValidationPasses, DefaultValue, ModelValue, SourceValue, ValidationOptions } from "../typing/toolbox";
4
4
  import { BaseSchema } from "./BaseSchema";
5
- export type OrSetSchemaSource<MemberSchemas extends BaseSchemaAny[]> = {
6
- [Key in keyof MemberSchemas]: (MemberSchemas[Key] extends BaseSchema<infer Source, any, infer Required, infer Default> ? (SourceValue<Source, Required, Default>) : never);
7
- }[number];
8
- export type OrSetSchemaModel<MemberSchemas extends BaseSchemaAny[]> = ({
9
- [Key in keyof MemberSchemas]: (MemberSchemas[Key] extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? (ModelValue<Source, Model, Required, Default>) : never);
10
- })[number];
11
- export declare class OrSetSchema<MemberSchemas extends BaseSchemaAny[], Required extends boolean, Default extends DefaultValue<OrSetSchemaSource<MemberSchemas>>> extends BaseSchema<OrSetSchemaSource<MemberSchemas>, OrSetSchemaModel<MemberSchemas>, Required, Default> {
12
- readonly schemas: MemberSchemas;
13
- constructor(schemas: MemberSchemas, required: Required, defaultValue: Default);
5
+ export type OrSetSchemaSource<MemberSchema extends BaseSchemaAny> = (MemberSchema extends BaseSchema<infer Source, any, infer Required, infer Default> ? SourceValue<Source, Required, Default> : never);
6
+ export type OrSetSchemaModel<MemberSchema extends BaseSchemaAny> = (MemberSchema extends BaseSchema<infer Source, infer Model, infer Required, infer Default> ? ModelValue<Source, Model, Required, Default> : never);
7
+ export declare class OrSetSchema<MemberSchema extends BaseSchemaAny, Required extends boolean, Default extends DefaultValue<OrSetSchemaSource<MemberSchema>>> extends BaseSchema<OrSetSchemaSource<MemberSchema>, OrSetSchemaModel<MemberSchema>, Required, Default> {
8
+ readonly schemas: MemberSchema[];
9
+ constructor(schemas: MemberSchema[], required: Required, defaultValue: Default, additionalValidationPasses?: AdditionalValidationPasses<OrSetSchemaSource<MemberSchema>, OrSetSchemaModel<MemberSchema>>);
14
10
  get type(): string;
15
- _validate(source: SourceValue<OrSetSchemaSource<MemberSchemas>, Required, Default>, pass: ValidationPass): ModelValue<OrSetSchemaSource<MemberSchemas>, OrSetSchemaModel<MemberSchemas>, Required, Default>;
16
- convert(value: OrSetSchemaSource<MemberSchemas>, pass: ValidationPass): OrSetSchemaModel<MemberSchemas>;
11
+ protected _validate(source: ModelValue<OrSetSchemaSource<MemberSchema>, OrSetSchemaModel<MemberSchema>, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<OrSetSchemaSource<MemberSchema>, OrSetSchemaModel<MemberSchema>, Required, Default>;
12
+ convert(value: OrSetSchemaSource<MemberSchema>, pass: ValidationPass): OrSetSchemaModel<MemberSchema>;
13
+ clone(): OrSetSchema<MemberSchema, Required, Default>;
17
14
  getJsonSchema(): object;
18
15
  }
@@ -1,14 +1,43 @@
1
1
  import { ValidationPass } from "../error/ValidationPass";
2
- import { DefaultValue, ModelValue, SourceValue } from "../typing/toolbox";
2
+ import { DefaultValue, ModelValue, ValidationOptions } from "../typing/toolbox";
3
3
  import { BaseSchema } from "./BaseSchema";
4
4
  export type StringSource = string | number | boolean | null | undefined | Date;
5
5
  export declare class StringSchema<Required extends boolean, Default extends DefaultValue<StringSource>> extends BaseSchema<StringSource, string, Required, Default> {
6
6
  get type(): string;
7
- protected _validate(source: SourceValue<StringSource, Required, Default>, pass: ValidationPass): ModelValue<StringSource, string, Required, Default>;
7
+ protected _validate(source: ModelValue<StringSource, string, Required, Default>, options: ValidationOptions, pass: ValidationPass): ModelValue<StringSource, string, Required, Default>;
8
8
  convert(value: StringSource, pass: ValidationPass): string;
9
+ /**
10
+ * Trims strings validated by this schema.
11
+ * @see {@link String.trim}
12
+ */
13
+ trim(): this;
14
+ /**
15
+ * Makes strings validated by this schema lowercase.
16
+ */
17
+ lower(): this;
18
+ /**
19
+ * Makes strings validated by this schema uppercase.
20
+ */
21
+ upper(): this;
22
+ /**
23
+ * Ensures that a string validated by this schema has a minimum (inclusive) and maximum (inclusive) length.
24
+ */
9
25
  length(minimum: number, maximum: number): this;
26
+ /**
27
+ * Ensures that a string validated by this schema has a minimum (inclusive) and maximum (inclusive) length.
28
+ * With a custom error message.
29
+ */
10
30
  length(minimum: number, maximum: number, message: string): this;
31
+ /**
32
+ * Ensures that a string validated by this schema has a minimum (inclusive) and maximum (inclusive) length.
33
+ * With custom error messages for too long, and too short.
34
+ */
11
35
  length(minimum: number, maximum: number, tooShortMessage: string, tooLongMessage: string): this;
36
+ /**
37
+ * Ensures a string validated by this schema matches a given regular expression.
38
+ * With an optional custom error message.
39
+ */
12
40
  regex(expression: RegExp, message?: string): this;
41
+ clone(): StringSchema<Required, Default>;
13
42
  getJsonSchema(): object;
14
43
  }
@@ -1,14 +1,15 @@
1
1
  import { ValidationPass } from "../error/ValidationPass";
2
2
  import { BaseSchema } from "../schema/BaseSchema";
3
3
  import { BaseSchemaAny } from "./extended";
4
+ export type ValidationOptions = {
5
+ collectErrors: boolean;
6
+ };
7
+ export type OptionalValidationOptions = Partial<ValidationOptions>;
4
8
  export type SourceRequirement<Layout extends BaseSchemaAny> = (Layout extends BaseSchema<any, any, infer Required, infer Default> ? (Required extends true ? (Default extends undefined ? true : false) : (false)) : never);
5
9
  export type SourceValue<Source, Required extends boolean, Default extends DefaultValue<Source>> = (Required extends true ? (undefined extends Default ? (Source) : (Source | undefined)) : Source | undefined);
6
10
  export type ModelRequirement<Layout extends BaseSchemaAny> = (Layout extends BaseSchema<any, any, infer Required, infer Default> ? (Required extends true ? (true) : (Default extends undefined ? false : true)) : never);
7
11
  export type ModelValue<Source, Model, Required extends boolean, Default extends DefaultValue<Source>> = (Required extends true ? Model : Default extends undefined ? Model | undefined : Model);
8
12
  export type DefaultValue<Type> = undefined | Type | ((pass: ValidationPass) => Type);
9
- export type TypedMembers<Members> = {
10
- $members: Members;
11
- };
12
13
  export type AdditionalValidatorBeforeType = ("beforeAll" | "beforeDefault" | "afterDefault");
13
14
  export type AdditionalValidatorAfterType = ("beforeConversion" | "afterConversion" | "afterAll");
14
15
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucania/schema",
3
- "version": "2.0.3",
3
+ "version": "3.0.0",
4
4
  "description": "A schema module for compile-time and runtime type checking.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -37,4 +37,4 @@
37
37
  "tslib": "^2.6.3",
38
38
  "typescript": "^5.4.5"
39
39
  }
40
- }
40
+ }