@oscarpalmer/jhunal 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/constants.d.mts +7 -3
  2. package/dist/constants.mjs +34 -12
  3. package/dist/helpers/message.helper.d.mts +11 -0
  4. package/dist/helpers/message.helper.mjs +70 -0
  5. package/dist/helpers/misc.helper.d.mts +22 -0
  6. package/dist/helpers/misc.helper.mjs +56 -0
  7. package/dist/index.d.mts +304 -275
  8. package/dist/index.mjs +187 -154
  9. package/dist/models/validation.model.d.mts +18 -7
  10. package/dist/schematic.d.mts +25 -7
  11. package/dist/schematic.mjs +6 -4
  12. package/dist/validator/base.validator.d.mts +6 -0
  13. package/dist/validator/base.validator.mjs +19 -0
  14. package/dist/validator/function.validator.d.mts +6 -0
  15. package/dist/validator/function.validator.mjs +9 -0
  16. package/dist/validator/named.handler.d.mts +6 -0
  17. package/dist/validator/named.handler.mjs +22 -0
  18. package/dist/validator/named.validator.d.mts +7 -0
  19. package/dist/validator/named.validator.mjs +39 -0
  20. package/dist/validator/object.validator.d.mts +7 -0
  21. package/dist/{validation.mjs → validator/object.validator.mjs} +20 -98
  22. package/dist/validator/schematic.validator.d.mts +7 -0
  23. package/dist/validator/schematic.validator.mjs +16 -0
  24. package/package.json +1 -1
  25. package/src/constants.ts +42 -10
  26. package/src/helpers/message.helper.ts +152 -0
  27. package/src/helpers/misc.helper.ts +93 -0
  28. package/src/index.ts +3 -3
  29. package/src/models/validation.model.ts +19 -6
  30. package/src/schematic.ts +43 -16
  31. package/src/validator/base.validator.ts +31 -0
  32. package/src/validator/function.validator.ts +9 -0
  33. package/src/validator/named.handler.ts +50 -0
  34. package/src/validator/named.validator.ts +62 -0
  35. package/src/{validation.ts → validator/object.validator.ts} +23 -181
  36. package/src/validator/schematic.validator.ts +25 -0
  37. package/dist/helpers.d.mts +0 -28
  38. package/dist/helpers.mjs +0 -120
  39. package/dist/validation.d.mts +0 -7
  40. package/src/helpers.ts +0 -249
package/dist/index.d.mts CHANGED
@@ -1,6 +1,228 @@
1
1
  import { Constructor, GenericCallback, PlainObject, Simplify } from "@oscarpalmer/atoms/models";
2
2
  import { Result } from "@oscarpalmer/atoms/result/models";
3
3
 
4
+ //#region src/models/schema.plain.model.d.ts
5
+ /**
6
+ * A generic schema allowing nested schemas, {@link SchemaEntry} values, or arrays of {@link SchemaEntry} as values
7
+ */
8
+ type PlainSchema = {
9
+ [key: string]: PlainSchema | SchemaEntry | SchemaEntry[] | undefined;
10
+ } & {
11
+ $required?: never;
12
+ $type?: never;
13
+ $validators?: never;
14
+ };
15
+ /**
16
+ * A schema for validating objects
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const schema: Schema = {
21
+ * name: 'string',
22
+ * age: 'number',
23
+ * tags: ['string', 'number'],
24
+ * };
25
+ * ```
26
+ */
27
+ type Schema = PlainSchema;
28
+ /**
29
+ * A union of all valid types for a single schema entry
30
+ *
31
+ * Can be a {@link Constructor}, {@link PlainSchema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
32
+ */
33
+ type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
34
+ /**
35
+ * A property definition with explicit type(s), an optional requirement flag, and optional validators
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * const prop: SchemaProperty = {
40
+ * $required: false,
41
+ * $type: ['string', 'number'],
42
+ * $validators: {
43
+ * string: (v) => v.length > 0,
44
+ * number: (v) => v > 0,
45
+ * },
46
+ * };
47
+ * ```
48
+ */
49
+ type SchemaProperty = {
50
+ /**
51
+ * Whether the property is required _(defaults to `true`)_
52
+ */
53
+ $required?: boolean;
54
+ /**
55
+ * The type(s) the property value must match; a single {@link SchemaPropertyType} or an array
56
+ */
57
+ $type: SchemaPropertyType | SchemaPropertyType[];
58
+ /**
59
+ * Optional validators keyed by {@link ValueName}, applied during validation
60
+ */
61
+ $validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
62
+ };
63
+ /**
64
+ * A union of valid types for a {@link SchemaProperty}'s `$type` field
65
+ *
66
+ * Can be a {@link Constructor}, {@link PlainSchema}, {@link Schematic}, {@link ValueName} string, or a custom validator function
67
+ */
68
+ type SchemaPropertyType = Constructor | PlainSchema | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
69
+ /**
70
+ * A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
71
+ *
72
+ * Each key may hold a single validator or an array of validators that receive the typed value
73
+ *
74
+ * @template Value `$type` value(s) to derive validator keys from
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const validators: PropertyValidators<'string'> = {
79
+ * string: (value) => value.length > 0,
80
+ * };
81
+ * ```
82
+ */
83
+ type PropertyValidators<Value> = { [Key in ExtractValueNames<Value>]?: ((value: Values[Key]) => boolean) | Array<(value: Values[Key]) => boolean> };
84
+ //#endregion
85
+ //#region src/models/misc.model.d.ts
86
+ /**
87
+ * Removes duplicate types from a tuple, preserving first occurrence order
88
+ *
89
+ * @template Value Tuple to deduplicate
90
+ * @template Seen Accumulator for already-seen types _(internal)_
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * // DeduplicateTuple<['string', 'number', 'string']>
95
+ * // => ['string', 'number']
96
+ * ```
97
+ */
98
+ type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Value extends [infer Head, ...infer Tail] ? Head extends Seen[number] ? DeduplicateTuple<Tail, Seen> : DeduplicateTuple<Tail, [...Seen, Head]> : Seen;
99
+ /**
100
+ * Recursively extracts {@link ValueName} strings from a type, unwrapping arrays and readonly arrays
101
+ *
102
+ * @template Value Type to extract value names from
103
+ *
104
+ * @example
105
+ * ```ts
106
+ * // ExtractValueNames<'string'> => 'string'
107
+ * // ExtractValueNames<['string', 'number']> => 'string' | 'number'
108
+ * ```
109
+ */
110
+ type ExtractValueNames<Value> = Value extends ValueName ? Value : Value extends (infer Item)[] ? ExtractValueNames<Item> : Value extends readonly (infer Item)[] ? ExtractValueNames<Item> : never;
111
+ /**
112
+ * Determines whether a schema entry is optional
113
+ *
114
+ * Returns `true` if the entry is a {@link SchemaProperty} with `$required` set to `false`; otherwise returns `false`
115
+ *
116
+ * @template Value Schema entry to check
117
+ */
118
+ type IsOptionalProperty<Value> = Value extends SchemaProperty ? Value['$required'] extends false ? true : false : false;
119
+ /**
120
+ * Extracts the last member from a union type by leveraging contravariance of function parameter types
121
+ *
122
+ * @template Value Union type
123
+ */
124
+ type LastOfUnion<Value> = UnionToIntersection<Value extends unknown ? () => Value : never> extends (() => infer Item) ? Item : never;
125
+ /**
126
+ * Extracts keys from an object type that are optional
127
+ *
128
+ * @template Value Object type to inspect
129
+ */
130
+ type OptionalKeys<Value> = { [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never }[keyof Value];
131
+ /**
132
+ * Extracts keys from an object type that are required _(i.e., not optional)_
133
+ *
134
+ * @template Value Object type to inspect
135
+ */
136
+ type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
137
+ /**
138
+ * Generates all permutations of a tuple type
139
+ *
140
+ * Used by {@link UnwrapSingle} to allow schema types in any order for small tuples _(length ≤ 5)_
141
+ *
142
+ * @template Tuple Tuple to permute
143
+ * @template Elput Accumulator for the current permutation _(internal; name is Tuple backwards)_
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * // TuplePermutations<['string', 'number']>
148
+ * // => ['string', 'number'] | ['number', 'string']
149
+ * ```
150
+ */
151
+ type TuplePermutations<Tuple extends unknown[], Elput extends unknown[] = []> = Tuple['length'] extends 0 ? Elput : { [Key in keyof Tuple]: TuplePermutations<TupleRemoveAt<Tuple, Key & `${number}`>, [...Elput, Tuple[Key]]> }[keyof Tuple & `${number}`];
152
+ /**
153
+ * Removes the element at a given index from a tuple
154
+ *
155
+ * Used internally by {@link TuplePermutations}
156
+ *
157
+ * @template Items Tuple to remove from
158
+ * @template Item Index as a string literal
159
+ * @template Prefix Accumulator for elements before the target _(internal)_
160
+ */
161
+ type TupleRemoveAt<Items extends unknown[], Item extends string, Prefix extends unknown[] = []> = Items extends [infer Head, ...infer Tail] ? `${Prefix['length']}` extends Item ? [...Prefix, ...Tail] : TupleRemoveAt<Tail, Item, [...Prefix, Head]> : Prefix;
162
+ /**
163
+ * Converts a union type into an intersection
164
+ *
165
+ * Uses the contravariance of function parameter types to collapse a union into an intersection
166
+ *
167
+ * @template Value Union type to convert
168
+ *
169
+ * @example
170
+ * ```ts
171
+ * // UnionToIntersection<{ a: 1 } | { b: 2 }>
172
+ * // => { a: 1 } & { b: 2 }
173
+ * ```
174
+ */
175
+ type UnionToIntersection<Value> = (Value extends unknown ? (value: Value) => void : never) extends ((value: infer Item) => void) ? Item : never;
176
+ /**
177
+ * Converts a union type into an ordered tuple
178
+ *
179
+ * Repeatedly extracts the {@link LastOfUnion} member and prepends it to the accumulator
180
+ *
181
+ * @template Value Union type to convert
182
+ * @template Items Accumulator for the resulting tuple _(internal)_
183
+ *
184
+ * @example
185
+ * ```ts
186
+ * // UnionToTuple<'a' | 'b' | 'c'>
187
+ * // => ['a', 'b', 'c']
188
+ * ```
189
+ */
190
+ type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends [never] ? Items : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Items]>;
191
+ /**
192
+ * Unwraps a single-element tuple to its inner type
193
+ *
194
+ * For tuples of length 2–5, returns all {@link TuplePermutations} to allow types in any order. Longer tuples are returned as-is
195
+ *
196
+ * @template Value Tuple to potentially unwrap
197
+ *
198
+ * @example
199
+ * ```ts
200
+ * // UnwrapSingle<['string']> => 'string'
201
+ * // UnwrapSingle<['string', 'number']> => ['string', 'number'] | ['number', 'string']
202
+ * ```
203
+ */
204
+ type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only] ? Only : Value['length'] extends 1 | 2 | 3 | 4 | 5 ? TuplePermutations<Value> : Value;
205
+ /**
206
+ * A union of valid type name strings, e.g. `'string'`, `'number'`, `'date'`
207
+ */
208
+ type ValueName = keyof Values;
209
+ /**
210
+ * Maps {@link ValueName} strings to their TypeScript equivalents
211
+ */
212
+ type Values = {
213
+ array: unknown[];
214
+ bigint: bigint;
215
+ boolean: boolean;
216
+ date: Date;
217
+ function: Function;
218
+ null: null;
219
+ number: number;
220
+ object: object;
221
+ string: string;
222
+ symbol: symbol;
223
+ undefined: undefined;
224
+ };
225
+ //#endregion
4
226
  //#region src/models/infer.model.d.ts
5
227
  /**
6
228
  * Infers the TypeScript type from a {@link Schema} definition
@@ -181,72 +403,9 @@ type TypedSchemaRequired<Model extends PlainObject> = {
181
403
  $required?: true;
182
404
  } & TypedSchema<Model>;
183
405
  //#endregion
184
- //#region src/models/validation.model.d.ts
185
- type ReportingInformation = Record<ReportingType, boolean> & {
186
- type: ReportingType;
187
- };
188
- /**
189
- * Controls how validation failures are reported
190
- *
191
- * - `'none'`, returns a boolean _(default)_
192
- * - `'first'`, returns the first failure as a `Result`
193
- * - `'all'`, returns all failures as a `Result` _(from same level)_
194
- * - `'throw'`, throws a {@link ValidationError} on failure
195
- */
196
- type ReportingType = 'all' | 'first' | 'none' | 'throw';
197
- /**
198
- * Thrown when a schema definition is invalid
199
- */
200
- declare class SchematicError extends Error {
201
- constructor(message: string);
202
- }
203
- /**
204
- * Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
205
- */
206
- declare class ValidationError extends Error {
207
- readonly information: ValidationInformation[];
208
- constructor(information: ValidationInformation[]);
209
- }
406
+ //#region src/schematic.d.ts
210
407
  /**
211
- * Describes a single validation failure
212
- */
213
- type ValidationInformation = {
214
- /** The key path of the property that failed */key: ValidationInformationKey; /** Human-readable description of the failure */
215
- message: string; /** The validator function that failed, if the failure was from a `$validators` entry */
216
- validator?: GenericCallback; /** The value that was provided */
217
- value: unknown;
218
- };
219
- /**
220
- *
221
- */
222
- type ValidationInformationKey = {
223
- full: string;
224
- short: string;
225
- };
226
- /**
227
- * Options for validation
228
- */
229
- type ValidationOptions<Errors extends ReportingType> = {
230
- /**
231
- * How should validation failures be reported; see {@link ReportingType} _(defaults to `'none'`)_
232
- */
233
- errors?: Errors;
234
- /**
235
- * Validate if unknown keys are present in the object? _(defaults to `false`)_
236
- */
237
- strict?: boolean;
238
- };
239
- type Validator = (input: unknown, parameters: ValidatorParameters, get: boolean) => boolean | ValidationInformation[];
240
- type ValidatorParameters = {
241
- information?: ValidationInformation[];
242
- output: PlainObject;
243
- reporting: ReportingInformation;
244
- strict: boolean;
245
- };
246
- //#endregion
247
- //#region src/schematic.d.ts
248
- /**
249
- * A schematic for validating objects
408
+ * A schematic for validating objects
250
409
  */
251
410
  declare class Schematic<Model> {
252
411
  #private;
@@ -260,7 +419,7 @@ declare class Schematic<Model> {
260
419
  * @param options Validation options
261
420
  * @returns Deeply cloned version of the value if it matches the schema, otherwise throws an error
262
421
  */
263
- get(value: unknown, options: ValidationOptions<'throw'>): Model;
422
+ get(value: unknown, options: GetOptions<'throw'>): Model;
264
423
  /**
265
424
  * Parse a value according to the schema
266
425
  *
@@ -278,7 +437,7 @@ declare class Schematic<Model> {
278
437
  * @param options Validation options
279
438
  * @returns Result holding deeply cloned value or all validation information
280
439
  */
281
- get(value: unknown, options: ValidationOptions<'all'>): Result<Model, ValidationInformation[]>;
440
+ get(value: unknown, options: GetOptions<'all'>): Result<Model, ValidationInformation[]>;
282
441
  /**
283
442
  * Parse a value according to the schema
284
443
  *
@@ -296,7 +455,7 @@ declare class Schematic<Model> {
296
455
  * @param options Validation options
297
456
  * @returns Result holding deeply cloned value or all validation information
298
457
  */
299
- get(value: unknown, options: ValidationOptions<'first'>): Result<Model, ValidationInformation>;
458
+ get(value: unknown, options: GetOptions<'first'>): Result<Model, ValidationInformation>;
300
459
  /**
301
460
  * Parse a value according to the schema
302
461
  *
@@ -306,6 +465,15 @@ declare class Schematic<Model> {
306
465
  * @returns Result holding deeply cloned value or all validation information
307
466
  */
308
467
  get(value: unknown, errors: 'first'): Result<Model, ValidationInformation>;
468
+ /**
469
+ * Parse a value according to the schema
470
+ *
471
+ * Returns a deeply cloned version of the value or `undefined` if the value does not match the schema
472
+ * @param value Value to parse
473
+ * @param options Validation options
474
+ * @returns Deeply cloned value, or `undefined` if it's invalid
475
+ */
476
+ get(value: unknown, options: GetOptions<'none'>): Model | undefined;
309
477
  /**
310
478
  * Parse a value according to the schema
311
479
  *
@@ -323,7 +491,7 @@ declare class Schematic<Model> {
323
491
  * @param options Validation options
324
492
  * @returns `true` if the value matches the schema, otherwise throws an error
325
493
  */
326
- is(value: unknown, options: ValidationOptions<'throw'>): asserts value is Model;
494
+ is(value: unknown, options: IsOptions<'throw'>): asserts value is Model;
327
495
  /**
328
496
  * Does the value match the schema?
329
497
  *
@@ -341,7 +509,7 @@ declare class Schematic<Model> {
341
509
  * @param options Validation options
342
510
  * @returns Result holding `true` or all validation information
343
511
  */
344
- is(value: unknown, options: ValidationOptions<'all'>): Result<true, ValidationInformation[]>;
512
+ is(value: unknown, options: IsOptions<'all'>): Result<true, ValidationInformation[]>;
345
513
  /**
346
514
  * Does the value match the schema?
347
515
  *
@@ -359,7 +527,7 @@ declare class Schematic<Model> {
359
527
  * @param options Validation options
360
528
  * @returns `true` if the value matches the schema, otherwise `false`
361
529
  */
362
- is(value: unknown, options: ValidationOptions<'first'>): Result<true, ValidationInformation>;
530
+ is(value: unknown, options: IsOptions<'first'>): Result<true, ValidationInformation>;
363
531
  /**
364
532
  * Does the value match the schema?
365
533
  *
@@ -369,6 +537,15 @@ declare class Schematic<Model> {
369
537
  * @returns `true` if the value matches the schema, otherwise `false`
370
538
  */
371
539
  is(value: unknown, errors: 'first'): Result<true, ValidationInformation>;
540
+ /**
541
+ * Does the value match the schema?
542
+ *
543
+ * Will validate that the value matches the schema and return `true` or `false`, without any validation information for validation failures
544
+ * @param value Value to validate
545
+ * @param options Validation options
546
+ * @returns `true` if the value matches the schema, otherwise `false`
547
+ */
548
+ is(value: unknown, options: IsOptions<'none'>): value is Model;
372
549
  /**
373
550
  * Does the value match the schema?
374
551
  *
@@ -396,229 +573,81 @@ declare function schematic<Model extends Schema>(schema: Model): Schematic<Infer
396
573
  */
397
574
  declare function schematic<Model extends PlainObject>(schema: TypedSchema<Model>): Schematic<Model>;
398
575
  //#endregion
399
- //#region src/models/schema.plain.model.d.ts
400
- /**
401
- * A generic schema allowing nested schemas, {@link SchemaEntry} values, or arrays of {@link SchemaEntry} as values
402
- */
403
- type PlainSchema = {
404
- [key: string]: PlainSchema | SchemaEntry | SchemaEntry[] | undefined;
405
- } & {
406
- $required?: never;
407
- $type?: never;
408
- $validators?: never;
576
+ //#region src/models/validation.model.d.ts
577
+ type ReportingInformation = Record<ReportingType, boolean> & {
578
+ type: ReportingType;
409
579
  };
410
580
  /**
411
- * A schema for validating objects
581
+ * Controls how validation failures are reported
412
582
  *
413
- * @example
414
- * ```ts
415
- * const schema: Schema = {
416
- * name: 'string',
417
- * age: 'number',
418
- * tags: ['string', 'number'],
419
- * };
420
- * ```
583
+ * - `'none'`, returns a boolean _(default)_
584
+ * - `'first'`, returns the first failure as a `Result`
585
+ * - `'all'`, returns all failures as a `Result` _(from same level)_
586
+ * - `'throw'`, throws a {@link ValidationError} on failure
421
587
  */
422
- type Schema = PlainSchema;
588
+ type ReportingType = 'all' | 'first' | 'none' | 'throw';
423
589
  /**
424
- * A union of all valid types for a single schema entry
425
- *
426
- * Can be a {@link Constructor}, {@link PlainSchema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
590
+ * Thrown when a schema definition is invalid
427
591
  */
428
- type SchemaEntry = Constructor | PlainSchema | SchemaProperty | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
592
+ declare class SchematicError extends Error {
593
+ constructor(message: string);
594
+ }
595
+ /**
596
+ * Thrown in `'throw'` mode when one or more properties fail validation; `information` holds all failures
597
+ */
598
+ declare class ValidationError extends Error {
599
+ readonly information: ValidationInformation[];
600
+ constructor(information: ValidationInformation[]);
601
+ }
602
+ /**
603
+ * Describes a single validation failure
604
+ */
605
+ type ValidationInformation = {
606
+ /** The key path of the property that failed */key: ValidationInformationKey; /** Human-readable description of the failure */
607
+ message: string; /** The validator function that failed, if the failure was from a `$validators` entry */
608
+ validator?: GenericCallback; /** The value that was provided */
609
+ value: unknown;
610
+ };
429
611
  /**
430
- * A property definition with explicit type(s), an optional requirement flag, and optional validators
431
612
  *
432
- * @example
433
- * ```ts
434
- * const prop: SchemaProperty = {
435
- * $required: false,
436
- * $type: ['string', 'number'],
437
- * $validators: {
438
- * string: (v) => v.length > 0,
439
- * number: (v) => v > 0,
440
- * },
441
- * };
442
- * ```
443
613
  */
444
- type SchemaProperty = {
445
- /**
446
- * Whether the property is required _(defaults to `true`)_
447
- */
448
- $required?: boolean;
614
+ type ValidationInformationKey = {
615
+ full: string;
616
+ short: string;
617
+ };
618
+ type BaseOptions<Errors extends ReportingType> = {
449
619
  /**
450
- * The type(s) the property value must match; a single {@link SchemaPropertyType} or an array
620
+ * How should validation failures be reported; see {@link ReportingType} _(defaults to `'none'`)_
451
621
  */
452
- $type: SchemaPropertyType | SchemaPropertyType[];
622
+ errors: Errors;
453
623
  /**
454
- * Optional validators keyed by {@link ValueName}, applied during validation
624
+ * Validate if unknown keys are present in the object? _(defaults to `false`)_
455
625
  */
456
- $validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
626
+ strict?: boolean;
457
627
  };
458
628
  /**
459
- * A union of valid types for a {@link SchemaProperty}'s `$type` field
460
- *
461
- * Can be a {@link Constructor}, {@link PlainSchema}, {@link Schematic}, {@link ValueName} string, or a custom validator function
462
- */
463
- type SchemaPropertyType = Constructor | PlainSchema | Schematic<unknown> | ValueName | ((value: unknown) => boolean);
464
- /**
465
- * A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
466
- *
467
- * Each key may hold a single validator or an array of validators that receive the typed value
468
- *
469
- * @template Value `$type` value(s) to derive validator keys from
470
- *
471
- * @example
472
- * ```ts
473
- * const validators: PropertyValidators<'string'> = {
474
- * string: (value) => value.length > 0,
475
- * };
476
- * ```
629
+ * Options for validating and getting a value from an input
477
630
  */
478
- type PropertyValidators<Value> = { [Key in ExtractValueNames<Value>]?: ((value: Values[Key]) => boolean) | Array<(value: Values[Key]) => boolean> };
479
- //#endregion
480
- //#region src/models/misc.model.d.ts
481
- /**
482
- * Removes duplicate types from a tuple, preserving first occurrence order
483
- *
484
- * @template Value Tuple to deduplicate
485
- * @template Seen Accumulator for already-seen types _(internal)_
486
- *
487
- * @example
488
- * ```ts
489
- * // DeduplicateTuple<['string', 'number', 'string']>
490
- * // => ['string', 'number']
491
- * ```
492
- */
493
- type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Value extends [infer Head, ...infer Tail] ? Head extends Seen[number] ? DeduplicateTuple<Tail, Seen> : DeduplicateTuple<Tail, [...Seen, Head]> : Seen;
494
- /**
495
- * Recursively extracts {@link ValueName} strings from a type, unwrapping arrays and readonly arrays
496
- *
497
- * @template Value Type to extract value names from
498
- *
499
- * @example
500
- * ```ts
501
- * // ExtractValueNames<'string'> => 'string'
502
- * // ExtractValueNames<['string', 'number']> => 'string' | 'number'
503
- * ```
504
- */
505
- type ExtractValueNames<Value> = Value extends ValueName ? Value : Value extends (infer Item)[] ? ExtractValueNames<Item> : Value extends readonly (infer Item)[] ? ExtractValueNames<Item> : never;
506
- /**
507
- * Determines whether a schema entry is optional
508
- *
509
- * Returns `true` if the entry is a {@link SchemaProperty} with `$required` set to `false`; otherwise returns `false`
510
- *
511
- * @template Value Schema entry to check
512
- */
513
- type IsOptionalProperty<Value> = Value extends SchemaProperty ? Value['$required'] extends false ? true : false : false;
514
- /**
515
- * Extracts the last member from a union type by leveraging contravariance of function parameter types
516
- *
517
- * @template Value Union type
518
- */
519
- type LastOfUnion<Value> = UnionToIntersection<Value extends unknown ? () => Value : never> extends (() => infer Item) ? Item : never;
520
- /**
521
- * Extracts keys from an object type that are optional
522
- *
523
- * @template Value Object type to inspect
524
- */
525
- type OptionalKeys<Value> = { [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never }[keyof Value];
526
- /**
527
- * Extracts keys from an object type that are required _(i.e., not optional)_
528
- *
529
- * @template Value Object type to inspect
530
- */
531
- type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
532
- /**
533
- * Generates all permutations of a tuple type
534
- *
535
- * Used by {@link UnwrapSingle} to allow schema types in any order for small tuples _(length ≤ 5)_
536
- *
537
- * @template Tuple Tuple to permute
538
- * @template Elput Accumulator for the current permutation _(internal; name is Tuple backwards)_
539
- *
540
- * @example
541
- * ```ts
542
- * // TuplePermutations<['string', 'number']>
543
- * // => ['string', 'number'] | ['number', 'string']
544
- * ```
545
- */
546
- type TuplePermutations<Tuple extends unknown[], Elput extends unknown[] = []> = Tuple['length'] extends 0 ? Elput : { [Key in keyof Tuple]: TuplePermutations<TupleRemoveAt<Tuple, Key & `${number}`>, [...Elput, Tuple[Key]]> }[keyof Tuple & `${number}`];
547
- /**
548
- * Removes the element at a given index from a tuple
549
- *
550
- * Used internally by {@link TuplePermutations}
551
- *
552
- * @template Items Tuple to remove from
553
- * @template Item Index as a string literal
554
- * @template Prefix Accumulator for elements before the target _(internal)_
555
- */
556
- type TupleRemoveAt<Items extends unknown[], Item extends string, Prefix extends unknown[] = []> = Items extends [infer Head, ...infer Tail] ? `${Prefix['length']}` extends Item ? [...Prefix, ...Tail] : TupleRemoveAt<Tail, Item, [...Prefix, Head]> : Prefix;
557
- /**
558
- * Converts a union type into an intersection
559
- *
560
- * Uses the contravariance of function parameter types to collapse a union into an intersection
561
- *
562
- * @template Value Union type to convert
563
- *
564
- * @example
565
- * ```ts
566
- * // UnionToIntersection<{ a: 1 } | { b: 2 }>
567
- * // => { a: 1 } & { b: 2 }
568
- * ```
569
- */
570
- type UnionToIntersection<Value> = (Value extends unknown ? (value: Value) => void : never) extends ((value: infer Item) => void) ? Item : never;
571
- /**
572
- * Converts a union type into an ordered tuple
573
- *
574
- * Repeatedly extracts the {@link LastOfUnion} member and prepends it to the accumulator
575
- *
576
- * @template Value Union type to convert
577
- * @template Items Accumulator for the resulting tuple _(internal)_
578
- *
579
- * @example
580
- * ```ts
581
- * // UnionToTuple<'a' | 'b' | 'c'>
582
- * // => ['a', 'b', 'c']
583
- * ```
584
- */
585
- type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends [never] ? Items : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Items]>;
586
- /**
587
- * Unwraps a single-element tuple to its inner type
588
- *
589
- * For tuples of length 2–5, returns all {@link TuplePermutations} to allow types in any order. Longer tuples are returned as-is
590
- *
591
- * @template Value Tuple to potentially unwrap
592
- *
593
- * @example
594
- * ```ts
595
- * // UnwrapSingle<['string']> => 'string'
596
- * // UnwrapSingle<['string', 'number']> => ['string', 'number'] | ['number', 'string']
597
- * ```
598
- */
599
- type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only] ? Only : Value['length'] extends 1 | 2 | 3 | 4 | 5 ? TuplePermutations<Value> : Value;
600
- /**
601
- * A union of valid type name strings, e.g. `'string'`, `'number'`, `'date'`
602
- */
603
- type ValueName = keyof Values;
631
+ type GetOptions<Errors extends ReportingType> = BaseOptions<Errors> & {
632
+ /**
633
+ * Get a deeply cloned version of the input? _(defaults to `true`)_
634
+ */
635
+ clone?: boolean;
636
+ };
604
637
  /**
605
- * Maps {@link ValueName} strings to their TypeScript equivalents
638
+ * Options for validation an input value
606
639
  */
607
- type Values = {
608
- array: unknown[];
609
- bigint: bigint;
610
- boolean: boolean;
611
- date: Date;
612
- function: Function;
613
- null: null;
614
- number: number;
615
- object: object;
616
- string: string;
617
- symbol: symbol;
618
- undefined: undefined;
640
+ type IsOptions<Errors extends ReportingType> = BaseOptions<Errors>;
641
+ type Validator = (input: unknown, parameters: ValidatorParameters, get: boolean) => true | ValidationInformation[];
642
+ type ValidatorParameters = {
643
+ clone: boolean;
644
+ information?: ValidationInformation[];
645
+ output: PlainObject;
646
+ reporting: ReportingInformation;
647
+ strict: boolean;
619
648
  };
620
649
  //#endregion
621
- //#region src/helpers.d.ts
650
+ //#region src/helpers/misc.helper.d.ts
622
651
  /**
623
652
  * Creates a validator function for a given constructor
624
653
  * @param constructor - Constructor to check against
@@ -633,4 +662,4 @@ declare function instanceOf<Instance>(constructor: Constructor<Instance>): (valu
633
662
  */
634
663
  declare function isSchematic(value: unknown): value is Schematic<never>;
635
664
  //#endregion
636
- export { type Schema, type Schematic, SchematicError, type TypedSchema, ValidationError, type ValidationInformation, type ValidationOptions, instanceOf, isSchematic, schematic };
665
+ export { type GetOptions, type IsOptions, type Schema, type Schematic, SchematicError, type TypedSchema, ValidationError, instanceOf, isSchematic, schematic };