@oscarpalmer/jhunal 0.16.0 → 0.18.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 +28 -15
  2. package/dist/constants.mjs +31 -14
  3. package/dist/helpers.d.mts +8 -1
  4. package/dist/helpers.mjs +68 -3
  5. package/dist/index.d.mts +283 -262
  6. package/dist/index.mjs +189 -56
  7. package/dist/models/infer.model.d.mts +66 -0
  8. package/dist/models/infer.model.mjs +1 -0
  9. package/dist/models/misc.model.d.mts +153 -0
  10. package/dist/models/misc.model.mjs +1 -0
  11. package/dist/models/schema.plain.model.d.mts +92 -0
  12. package/dist/models/schema.plain.model.mjs +1 -0
  13. package/dist/models/schema.typed.model.d.mts +96 -0
  14. package/dist/models/schema.typed.model.mjs +1 -0
  15. package/dist/models/transform.model.d.mts +59 -0
  16. package/dist/models/transform.model.mjs +1 -0
  17. package/dist/models/validation.model.d.mts +81 -0
  18. package/dist/models/validation.model.mjs +21 -0
  19. package/dist/schematic.d.mts +20 -6
  20. package/dist/schematic.mjs +7 -12
  21. package/dist/validation/property.validation.d.mts +1 -1
  22. package/dist/validation/property.validation.mjs +21 -17
  23. package/dist/validation/value.validation.d.mts +2 -2
  24. package/dist/validation/value.validation.mjs +63 -11
  25. package/package.json +3 -3
  26. package/src/constants.ts +84 -18
  27. package/src/helpers.ts +162 -4
  28. package/src/index.ts +3 -1
  29. package/src/models/infer.model.ts +105 -0
  30. package/src/models/misc.model.ts +212 -0
  31. package/src/models/schema.plain.model.ts +110 -0
  32. package/src/models/schema.typed.model.ts +109 -0
  33. package/src/models/transform.model.ts +85 -0
  34. package/src/models/validation.model.ts +123 -0
  35. package/src/schematic.ts +29 -18
  36. package/src/validation/property.validation.ts +46 -36
  37. package/src/validation/value.validation.ts +115 -15
  38. package/dist/models.d.mts +0 -507
  39. package/dist/models.mjs +0 -18
  40. package/src/models.ts +0 -691
package/src/models.ts DELETED
@@ -1,691 +0,0 @@
1
- import type {Constructor, GenericCallback, PlainObject, Simplify} from '@oscarpalmer/atoms/models';
2
- import {ERROR_NAME} from './constants';
3
- import type {Schematic} from './schematic';
4
-
5
- /**
6
- * Removes duplicate types from a tuple, preserving first occurrence order
7
- *
8
- * @template Value - Tuple to deduplicate
9
- * @template Seen - Accumulator for already-seen types _(internal)_
10
- *
11
- * @example
12
- * ```ts
13
- * // DeduplicateTuple<['string', 'number', 'string']>
14
- * // => ['string', 'number']
15
- * ```
16
- */
17
- type DeduplicateTuple<Value extends unknown[], Seen extends unknown[] = []> = Value extends [
18
- infer Head,
19
- ...infer Tail,
20
- ]
21
- ? Head extends Seen[number]
22
- ? DeduplicateTuple<Tail, Seen>
23
- : DeduplicateTuple<Tail, [...Seen, Head]>
24
- : Seen;
25
-
26
- /**
27
- * Recursively extracts {@link ValueName} strings from a type, unwrapping arrays and readonly arrays
28
- *
29
- * @template Value - Type to extract value names from
30
- *
31
- * @example
32
- * ```ts
33
- * // ExtractValueNames<'string'> => 'string'
34
- * // ExtractValueNames<['string', 'number']> => 'string' | 'number'
35
- * ```
36
- */
37
- type ExtractValueNames<Value> = Value extends ValueName
38
- ? Value
39
- : Value extends (infer Item)[]
40
- ? ExtractValueNames<Item>
41
- : Value extends readonly (infer Item)[]
42
- ? ExtractValueNames<Item>
43
- : never;
44
-
45
- /**
46
- * Infers the TypeScript type from a {@link Schema} definition
47
- *
48
- * @template Model - Schema to infer types from
49
- *
50
- * @example
51
- * ```ts
52
- * const userSchema = {
53
- * name: 'string',
54
- * age: 'number',
55
- * address: { $required: false, $type: 'string' },
56
- * } satisfies Schema;
57
- *
58
- * type User = Infer<typeof userSchema>;
59
- * // { name: string; age: number; address?: string }
60
- * ```
61
- */
62
- export type Infer<Model extends Schema> = Simplify<
63
- {
64
- [Key in InferRequiredKeys<Model>]: InferSchemaEntry<Model[Key]>;
65
- } & {
66
- [Key in InferOptionalKeys<Model>]?: InferSchemaEntry<Model[Key]>;
67
- }
68
- >;
69
-
70
- /**
71
- * Extracts keys from a {@link Schema} whose entries are optional _(i.e., `$required` is `false`)_
72
- *
73
- * @template Model - {@link Schema} to extract optional keys from
74
- */
75
- type InferOptionalKeys<Model extends Schema> = keyof {
76
- [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? Key : never]: never;
77
- };
78
-
79
- /**
80
- * Infers the TypeScript type of a {@link SchemaProperty}'s `$type` field, unwrapping arrays to infer their item type
81
- *
82
- * @template Value - `$type` value _(single or array)_
83
- */
84
- type InferPropertyType<Value> = Value extends (infer Item)[]
85
- ? InferPropertyValue<Item>
86
- : InferPropertyValue<Value>;
87
-
88
- /**
89
- * Maps a single type definition to its TypeScript equivalent
90
- *
91
- * Resolves, in order: {@link Constructor} instances, {@link Schematic} models, {@link ValueName} strings, and nested {@link Schema} objects
92
- *
93
- * @template Value - single type definition
94
- */
95
- type InferPropertyValue<Value> =
96
- Value extends Constructor<infer Instance>
97
- ? Instance
98
- : Value extends Schematic<infer Model>
99
- ? Model
100
- : Value extends ValueName
101
- ? Values[Value & ValueName]
102
- : Value extends Schema
103
- ? Infer<Value>
104
- : never;
105
-
106
- /**
107
- * Extracts keys from a {@link Schema} whose entries are required _(i.e., `$required` is not `false`)_
108
- *
109
- * @template Model - Schema to extract required keys from
110
- */
111
- type InferRequiredKeys<Model extends Schema> = keyof {
112
- [Key in keyof Model as IsOptionalProperty<Model[Key]> extends true ? never : Key]: never;
113
- };
114
-
115
- /**
116
- * Infers the type for a top-level {@link Schema} entry, unwrapping arrays to infer their item type
117
- *
118
- * @template Value - Schema entry value _(single or array)_
119
- */
120
- type InferSchemaEntry<Value> = Value extends (infer Item)[]
121
- ? InferSchemaEntryValue<Item>
122
- : InferSchemaEntryValue<Value>;
123
-
124
- /**
125
- * Resolves a single schema entry to its TypeScript type
126
- *
127
- * Handles, in order: {@link Constructor} instances, {@link Schematic} models, {@link SchemaProperty} objects, {@link NestedSchema} objects, {@link ValueName} strings, and plain {@link Schema} objects
128
- *
129
- * @template Value - single schema entry
130
- */
131
- type InferSchemaEntryValue<Value> =
132
- Value extends Constructor<infer Instance>
133
- ? Instance
134
- : Value extends Schematic<infer Model>
135
- ? Model
136
- : Value extends SchemaProperty
137
- ? InferPropertyType<Value['$type']>
138
- : Value extends NestedSchema
139
- ? Infer<Omit<Value, '$required'>>
140
- : Value extends ValueName
141
- ? Values[Value & ValueName]
142
- : Value extends Schema
143
- ? Infer<Value>
144
- : never;
145
-
146
- /**
147
- * Determines whether a schema entry is optional
148
- *
149
- * Returns `true` if the entry is a {@link SchemaProperty} or {@link NestedSchema} with `$required` set to `false`; otherwise returns `false`
150
- *
151
- * @template Value - Schema entry to check
152
- */
153
- type IsOptionalProperty<Value> = Value extends SchemaProperty
154
- ? Value['$required'] extends false
155
- ? true
156
- : false
157
- : Value extends {$required?: boolean}
158
- ? Value extends {$required: false}
159
- ? true
160
- : false
161
- : false;
162
-
163
- /**
164
- * Extracts the last member from a union type by leveraging intersection of function return types
165
- *
166
- * @template Value - Union type
167
- */
168
- type LastOfUnion<Value> =
169
- UnionToIntersection<Value extends unknown ? () => Value : never> extends () => infer Item
170
- ? Item
171
- : never;
172
-
173
- /**
174
- * Maps each element of a tuple through {@link ToValueType}
175
- *
176
- * @template Value - Tuple of types to map
177
- */
178
- type MapToValueTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail]
179
- ? [ToValueType<Head>, ...MapToValueTypes<Tail>]
180
- : [];
181
-
182
- /**
183
- * Maps each element of a tuple through {@link ToSchemaPropertyTypeEach}
184
- *
185
- * @template Value - Tuple of types to map
186
- */
187
- type MapToSchemaPropertyTypes<Value extends unknown[]> = Value extends [infer Head, ...infer Tail]
188
- ? [ToSchemaPropertyTypeEach<Head>, ...MapToSchemaPropertyTypes<Tail>]
189
- : [];
190
-
191
- /**
192
- * A nested schema definition that may include a `$required` flag alongside arbitrary string-keyed properties
193
- *
194
- * @example
195
- * ```ts
196
- * const address: NestedSchema = {
197
- * $required: false,
198
- * street: 'string',
199
- * city: 'string',
200
- * };
201
- * ```
202
- */
203
- export type NestedSchema = {
204
- /**
205
- * Whether the nested schema is required (defaults to `true`)
206
- */
207
- $required?: boolean;
208
- } & Schema;
209
-
210
- /**
211
- * Extracts keys from an object type that are optional
212
- *
213
- * @template Value - Object type to inspect
214
- */
215
- type OptionalKeys<Value> = {
216
- [Key in keyof Value]-?: {} extends Pick<Value, Key> ? Key : never;
217
- }[keyof Value];
218
-
219
- /**
220
- * A generic schema allowing {@link NestedSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry} as values
221
- */
222
- type PlainSchema = {
223
- [key: string]: NestedSchema | SchemaEntry | SchemaEntry[];
224
- };
225
-
226
- /**
227
- * A map of optional validator functions keyed by {@link ValueName}, used to add custom validation to {@link SchemaProperty} definitions
228
- *
229
- * Each key may hold a single validator or an array of validators that receive the typed value
230
- *
231
- * @template Value - `$type` value(s) to derive validator keys from
232
- *
233
- * @example
234
- * ```ts
235
- * const validators: PropertyValidators<'string'> = {
236
- * string: (value) => value.length > 0,
237
- * };
238
- * ```
239
- */
240
- type PropertyValidators<Value> = {
241
- [Key in ExtractValueNames<Value>]?:
242
- | ((value: Values[Key]) => boolean)
243
- | Array<(value: Values[Key]) => boolean>;
244
- };
245
-
246
- /**
247
- * Extracts keys from an object type that are required _(i.e., not optional)_
248
- *
249
- * @template Value - Object type to inspect
250
- */
251
- type RequiredKeys<Value> = Exclude<keyof Value, OptionalKeys<Value>>;
252
-
253
- /**
254
- * A schema for validating objects
255
- *
256
- * @example
257
- * ```ts
258
- * const schema: Schema = {
259
- * name: 'string',
260
- * age: 'number',
261
- * tags: ['string', 'number'],
262
- * };
263
- * ```
264
- */
265
- export type Schema = SchemaIndex;
266
-
267
- /**
268
- * A union of all valid types for a single schema entry
269
- *
270
- * Can be a {@link Constructor}, nested {@link Schema}, {@link SchemaProperty}, {@link Schematic}, {@link ValueName} string, or a custom validator function
271
- */
272
- type SchemaEntry =
273
- | Constructor
274
- | Schema
275
- | SchemaProperty
276
- | Schematic<unknown>
277
- | ValueName
278
- | ((value: unknown) => boolean);
279
-
280
- /**
281
- * Index signature interface backing {@link Schema}, allowing string-keyed entries of {@link NestedSchema}, {@link SchemaEntry}, or arrays of {@link SchemaEntry}
282
- */
283
- interface SchemaIndex {
284
- [key: string]: NestedSchema | SchemaEntry | SchemaEntry[];
285
- }
286
-
287
- /**
288
- * A property definition with explicit type(s), an optional requirement flag, and optional validators
289
- *
290
- * @example
291
- * ```ts
292
- * const prop: SchemaProperty = {
293
- * $required: false,
294
- * $type: ['string', 'number'],
295
- * $validators: {
296
- * string: (v) => v.length > 0,
297
- * number: (v) => v > 0,
298
- * },
299
- * };
300
- * ```
301
- */
302
- export type SchemaProperty = {
303
- /**
304
- * Whether the property is required _(defaults to `true`)_
305
- */
306
- $required?: boolean;
307
- /**
308
- * The type(s) the property value must match; a single {@link SchemaPropertyType} or an array
309
- */
310
- $type: SchemaPropertyType | SchemaPropertyType[];
311
- /**
312
- * Optional validators keyed by {@link ValueName}, applied during validation
313
- */
314
- $validators?: PropertyValidators<SchemaPropertyType | SchemaPropertyType[]>;
315
- };
316
-
317
- /**
318
- * A union of valid types for a {@link SchemaProperty}'s `$type` field
319
- *
320
- * Can be a {@link Constructor}, {@link PlainSchema}, {@link Schematic}, {@link ValueName} string, or a custom validator function
321
- */
322
- type SchemaPropertyType =
323
- | Constructor
324
- | PlainSchema
325
- | Schematic<unknown>
326
- | ValueName
327
- | ((value: unknown) => boolean);
328
-
329
- /**
330
- * A custom error class for schema validation failures, with its `name` set to {@link ERROR_NAME}
331
- *
332
- * @example
333
- * ```ts
334
- * throw new SchematicError('Expected a string, received a number');
335
- * ```
336
- */
337
- export class SchematicError extends Error {
338
- constructor(message: string) {
339
- super(message);
340
-
341
- this.name = ERROR_NAME;
342
- }
343
- }
344
-
345
- /**
346
- * Converts a type into its corresponding {@link SchemaPropertyType}-representation
347
- *
348
- * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
349
- *
350
- * @template Value - type to convert
351
- */
352
- type ToSchemaPropertyType<Value> = UnwrapSingle<
353
- DeduplicateTuple<MapToSchemaPropertyTypes<UnionToTuple<Value>>>
354
- >;
355
-
356
- /**
357
- * Converts a single type to its schema property equivalent
358
- *
359
- * {@link NestedSchema} values have `$required` stripped, plain objects become {@link TypedSchema}, and primitives go through {@link ToValueType}
360
- *
361
- * @template Value - type to convert
362
- */
363
- type ToSchemaPropertyTypeEach<Value> = Value extends NestedSchema
364
- ? Omit<Value, '$required'>
365
- : Value extends PlainObject
366
- ? TypedSchema<Value>
367
- : ToValueType<Value>;
368
-
369
- /**
370
- * Converts a type into its corresponding {@link ValueName}-representation
371
- *
372
- * Deduplicates and unwraps single-element tuples via {@link UnwrapSingle}
373
- *
374
- * @template Value - type to convert
375
- */
376
- type ToSchemaType<Value> = UnwrapSingle<DeduplicateTuple<MapToValueTypes<UnionToTuple<Value>>>>;
377
-
378
- /**
379
- * Maps a type to its {@link ValueName} string equivalent
380
- *
381
- * Resolves {@link Schematic} types as-is, then performs a reverse-lookup against {@link Values} _(excluding `'object'`)_ to find a matching key. If no match is found, `object` types resolve to `'object'` or a type-guard function, and all other unrecognised types resolve to a type-guard function
382
- *
383
- * @template Value - type to map
384
- *
385
- * @example
386
- * ```ts
387
- * // ToValueType<string> => 'string'
388
- * // ToValueType<number[]> => 'array'
389
- * // ToValueType<Date> => 'date'
390
- * ```
391
- */
392
- type ToValueType<Value> =
393
- Value extends Schematic<any>
394
- ? Value
395
- : {
396
- [Key in keyof Omit<Values, 'object'>]: Value extends Values[Key] ? Key : never;
397
- }[keyof Omit<Values, 'object'>] extends infer Match
398
- ? [Match] extends [never]
399
- ? Value extends object
400
- ? 'object' | ((value: unknown) => value is Value)
401
- : (value: unknown) => value is Value
402
- : Match
403
- : never;
404
-
405
- /**
406
- * Generates all permutations of a tuple type
407
- *
408
- * Used by {@link UnwrapSingle} to allow schema types in any order for small tuples _(length ≤ 5)_
409
- *
410
- * @template Tuple - Tuple to permute
411
- * @template Elput - Accumulator for the current permutation _(internal; name is Tuple backwards)_
412
- *
413
- * @example
414
- * ```ts
415
- * // TuplePermutations<['string', 'number']>
416
- * // => ['string', 'number'] | ['number', 'string']
417
- * ```
418
- */
419
- type TuplePermutations<
420
- Tuple extends unknown[],
421
- Elput extends unknown[] = [],
422
- > = Tuple['length'] extends 0
423
- ? Elput
424
- : {
425
- [Key in keyof Tuple]: TuplePermutations<
426
- TupleRemoveAt<Tuple, Key & `${number}`>,
427
- [...Elput, Tuple[Key]]
428
- >;
429
- }[keyof Tuple & `${number}`];
430
-
431
- /**
432
- * Removes the element at a given index from a tuple
433
- *
434
- * Used internally by {@link TuplePermutations}
435
- *
436
- * @template Items - Tuple to remove from
437
- * @template Item - Stringified index to remove
438
- * @template Prefix - Accumulator for elements before the target _(internal)_
439
- */
440
- type TupleRemoveAt<
441
- Items extends unknown[],
442
- Item extends string,
443
- Prefix extends unknown[] = [],
444
- > = Items extends [infer Head, ...infer Tail]
445
- ? `${Prefix['length']}` extends Item
446
- ? [...Prefix, ...Tail]
447
- : TupleRemoveAt<Tail, Item, [...Prefix, Head]>
448
- : Prefix;
449
-
450
- /**
451
- * A typed optional property definition generated by {@link TypedSchema} for optional keys, with `$required` set to `false` and excludes `undefined` from the type
452
- *
453
- * @template Value - Property's type _(including `undefined`)_
454
- *
455
- * @example
456
- * ```ts
457
- * // For `{ name?: string }`, the `name` key produces:
458
- * // TypedPropertyOptional<string | undefined>
459
- * // => { $required: false; $type: 'string'; ... }
460
- * ```
461
- */
462
- export type TypedPropertyOptional<Value> = {
463
- /**
464
- * The property is not required
465
- */
466
- $required: false;
467
- /**
468
- * The type(s) of the property
469
- */
470
- $type: ToSchemaPropertyType<Exclude<Value, undefined>>;
471
- /**
472
- * Custom validators for the property and its types
473
- */
474
- $validators?: PropertyValidators<ToSchemaPropertyType<Exclude<Value, undefined>>>;
475
- };
476
-
477
- /**
478
- * A typed required property definition generated by {@link TypedSchema} for required keys, with `$required` defaulting to `true`
479
- *
480
- * @template Value - Property's type
481
- *
482
- * @example
483
- * ```ts
484
- * // For `{ name: string }`, the `name` key produces:
485
- * // TypedPropertyRequired<string>
486
- * // => { $required?: true; $type: 'string'; ... }
487
- * ```
488
- */
489
- export type TypedPropertyRequired<Value> = {
490
- /**
491
- * The property is required _(defaults to `true`)_
492
- */
493
- $required?: true;
494
- /**
495
- * The type(s) of the property
496
- */
497
- $type: ToSchemaPropertyType<Value>;
498
- /**
499
- * Custom validators for the property and its types
500
- */
501
- $validators?: PropertyValidators<ToSchemaPropertyType<Value>>;
502
- };
503
-
504
- /**
505
- * Creates a schema type constrained to match a TypeScript type
506
- *
507
- * Required keys map to {@link ToSchemaType} or {@link TypedPropertyRequired}; plain object values may also use {@link Schematic}. Optional keys map to {@link TypedPropertyOptional} or, for plain objects, {@link TypedSchemaOptional}
508
- *
509
- * @template Model - Object type to generate a schema for
510
- *
511
- * @example
512
- * ```ts
513
- * type User = { name: string; age: number; bio?: string };
514
- *
515
- * const schema: TypedSchema<User> = {
516
- * name: 'string',
517
- * age: 'number',
518
- * bio: { $required: false, $type: 'string' },
519
- * };
520
- * ```
521
- */
522
- export type TypedSchema<Model extends PlainObject> = Simplify<
523
- {
524
- [Key in RequiredKeys<Model>]: Model[Key] extends PlainObject
525
- ? TypedSchemaRequired<Model[Key]> | Schematic<Model[Key]>
526
- : ToSchemaType<Model[Key]> | TypedPropertyRequired<Model[Key]>;
527
- } & {
528
- [Key in OptionalKeys<Model>]: Exclude<Model[Key], undefined> extends PlainObject
529
- ?
530
- | TypedSchemaOptional<Exclude<Model[Key], undefined>>
531
- | Schematic<Exclude<Model[Key], undefined>>
532
- : TypedPropertyOptional<Model[Key]>;
533
- }
534
- >;
535
-
536
- /**
537
- * A {@link TypedSchema} variant for optional nested objects, with `$required` fixed to `false`
538
- *
539
- * @template Model - Nested object type
540
- */
541
- type TypedSchemaOptional<Model extends PlainObject> = {
542
- $required: false;
543
- } & TypedSchema<Model>;
544
-
545
- /**
546
- * A {@link TypedSchema} variant for required nested objects, with `$required` defaulting to `true`
547
- *
548
- * @template Model - Nested object type
549
- */
550
- type TypedSchemaRequired<Model extends PlainObject> = {
551
- $required?: true;
552
- } & TypedSchema<Model>;
553
-
554
- /**
555
- * Converts a union type into an intersection
556
- *
557
- * Uses the contravariance of function parameter types to collapse a union into an intersection
558
- *
559
- * @template Value - Union type to convert
560
- *
561
- * @example
562
- * ```ts
563
- * // UnionToIntersection<{ a: 1 } | { b: 2 }>
564
- * // => { a: 1 } & { b: 2 }
565
- * ```
566
- */
567
- type UnionToIntersection<Value> = (Value extends unknown ? (value: Value) => void : never) extends (
568
- value: infer Item,
569
- ) => void
570
- ? Item
571
- : never;
572
-
573
- /**
574
- * Converts a union type into an ordered tuple
575
- *
576
- * Repeatedly extracts the {@link LastOfUnion} member and prepends it to the accumulator
577
- *
578
- * @template Value - Union type to convert
579
- * @template Items - Accumulator for the resulting tuple _(internal)_
580
- *
581
- * @example
582
- * ```ts
583
- * // UnionToTuple<'a' | 'b' | 'c'>
584
- * // => ['a', 'b', 'c']
585
- * ```
586
- */
587
- type UnionToTuple<Value, Items extends unknown[] = []> = [Value] extends [never]
588
- ? Items
589
- : UnionToTuple<Exclude<Value, LastOfUnion<Value>>, [LastOfUnion<Value>, ...Items]>;
590
-
591
- /**
592
- * Unwraps a single-element tuple to its inner type
593
- *
594
- * For tuples of length 2–5, returns all {@link TuplePermutations} to allow types in any order. Longer tuples are returned as-is
595
- *
596
- * @template Value - Tuple to potentially unwrap
597
- *
598
- * @example
599
- * ```ts
600
- * // UnwrapSingle<['string']> => 'string'
601
- * // UnwrapSingle<['string', 'number']> => ['string', 'number'] | ['number', 'string']
602
- * ```
603
- */
604
- type UnwrapSingle<Value extends unknown[]> = Value extends [infer Only]
605
- ? Only
606
- : Value['length'] extends 1 | 2 | 3 | 4 | 5
607
- ? TuplePermutations<Value>
608
- : Value;
609
-
610
- /**
611
- * The runtime representation of a parsed schema property, used internally during validation
612
- *
613
- * @example
614
- * ```ts
615
- * const parsed: ValidatedProperty = {
616
- * key: 'age',
617
- * required: true,
618
- * types: ['number'],
619
- * validators: { number: [(v) => v > 0] },
620
- * };
621
- * ```
622
- */
623
- export type ValidatedProperty = {
624
- /**
625
- * The property name in the schema
626
- */
627
- key: string;
628
- /**
629
- * Whether the property is required
630
- */
631
- required: boolean;
632
- /**
633
- * The allowed types for this property
634
- */
635
- types: ValidatedPropertyType[];
636
- /**
637
- * Custom validators grouped by {@link ValueName}
638
- */
639
- validators: ValidatedPropertyValidators;
640
- };
641
-
642
- /**
643
- * A union of valid types for a {@link ValidatedProperty}'s `types` array
644
- *
645
- * Can be a callback _(custom validator)_, a {@link Schematic}, a nested {@link ValidatedProperty}, or a {@link ValueName} string
646
- */
647
- export type ValidatedPropertyType =
648
- | GenericCallback
649
- | Schematic<unknown>
650
- | ValidatedProperty
651
- | ValueName;
652
-
653
- /**
654
- * A map of validator functions keyed by {@link ValueName}, used at runtime in {@link ValidatedProperty}
655
- *
656
- * Each key holds an array of validator functions that receive an `unknown` value and return a `boolean`
657
- */
658
- export type ValidatedPropertyValidators = {
659
- [Key in ValueName]?: Array<(value: unknown) => boolean>;
660
- };
661
-
662
- /**
663
- * Basic value types
664
- */
665
- export type ValueName = keyof Values;
666
-
667
- /**
668
- * Maps type name strings to their TypeScript equivalents
669
- *
670
- * Used by the type system to resolve {@link ValueName} strings into actual types
671
- *
672
- * @example
673
- * ```ts
674
- * // Values['string'] => string
675
- * // Values['date'] => Date
676
- * // Values['null'] => null
677
- * ```
678
- */
679
- export type Values = {
680
- array: unknown[];
681
- bigint: bigint;
682
- boolean: boolean;
683
- date: Date;
684
- function: Function;
685
- null: null;
686
- number: number;
687
- object: object;
688
- string: string;
689
- symbol: symbol;
690
- undefined: undefined;
691
- };