@cleverbrush/schema 1.1.11 → 2.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.
Files changed (87) hide show
  1. package/README.md +1314 -101
  2. package/dist/builders/AnySchemaBuilder.d.ts +54 -14
  3. package/dist/builders/AnySchemaBuilder.js +2 -112
  4. package/dist/builders/AnySchemaBuilder.js.map +1 -0
  5. package/dist/builders/ArraySchemaBuilder.d.ts +124 -23
  6. package/dist/builders/ArraySchemaBuilder.js +2 -284
  7. package/dist/builders/ArraySchemaBuilder.js.map +1 -0
  8. package/dist/builders/BooleanSchemaBuilder.d.ts +94 -19
  9. package/dist/builders/BooleanSchemaBuilder.js +2 -150
  10. package/dist/builders/BooleanSchemaBuilder.js.map +1 -0
  11. package/dist/builders/DateSchemaBuilder.d.ts +134 -34
  12. package/dist/builders/DateSchemaBuilder.js +2 -433
  13. package/dist/builders/DateSchemaBuilder.js.map +1 -0
  14. package/dist/builders/ExternSchemaBuilder.d.ts +200 -0
  15. package/dist/builders/ExternSchemaBuilder.js +2 -0
  16. package/dist/builders/ExternSchemaBuilder.js.map +1 -0
  17. package/dist/builders/FunctionSchemaBuilder.d.ts +57 -14
  18. package/dist/builders/FunctionSchemaBuilder.js +2 -113
  19. package/dist/builders/FunctionSchemaBuilder.js.map +1 -0
  20. package/dist/builders/LazySchemaBuilder.d.ts +167 -0
  21. package/dist/builders/NullSchemaBuilder.d.ts +162 -0
  22. package/dist/builders/NumberSchemaBuilder.d.ts +143 -31
  23. package/dist/builders/NumberSchemaBuilder.js +2 -386
  24. package/dist/builders/NumberSchemaBuilder.js.map +1 -0
  25. package/dist/builders/ObjectSchemaBuilder.d.ts +266 -61
  26. package/dist/builders/ObjectSchemaBuilder.js +2 -589
  27. package/dist/builders/ObjectSchemaBuilder.js.map +1 -0
  28. package/dist/builders/PropertyValidationResult.d.ts +68 -0
  29. package/dist/builders/RecordSchemaBuilder.d.ts +341 -0
  30. package/dist/builders/RecordSchemaBuilder.js +2 -0
  31. package/dist/builders/RecordSchemaBuilder.js.map +1 -0
  32. package/dist/builders/SchemaBuilder.d.ts +818 -30
  33. package/dist/builders/StringSchemaBuilder.d.ts +152 -37
  34. package/dist/builders/StringSchemaBuilder.js +2 -414
  35. package/dist/builders/StringSchemaBuilder.js.map +1 -0
  36. package/dist/builders/TupleSchemaBuilder.d.ts +248 -0
  37. package/dist/builders/TupleSchemaBuilder.js +2 -0
  38. package/dist/builders/TupleSchemaBuilder.js.map +1 -0
  39. package/dist/builders/UnionSchemaBuilder.d.ts +133 -39
  40. package/dist/builders/UnionSchemaBuilder.js +2 -216
  41. package/dist/builders/UnionSchemaBuilder.js.map +1 -0
  42. package/dist/chunk-BFCMDDTX.js +2 -0
  43. package/dist/chunk-BFCMDDTX.js.map +1 -0
  44. package/dist/chunk-CTP4RHDG.js +2 -0
  45. package/dist/chunk-CTP4RHDG.js.map +1 -0
  46. package/dist/chunk-EUQ5AE3H.js +2 -0
  47. package/dist/chunk-EUQ5AE3H.js.map +1 -0
  48. package/dist/chunk-FWUEUW2N.js +2 -0
  49. package/dist/chunk-FWUEUW2N.js.map +1 -0
  50. package/dist/chunk-IJ6FO37G.js +2 -0
  51. package/dist/chunk-IJ6FO37G.js.map +1 -0
  52. package/dist/chunk-KESLT5EE.js +2 -0
  53. package/dist/chunk-KESLT5EE.js.map +1 -0
  54. package/dist/chunk-KFTO7TMB.js +2 -0
  55. package/dist/chunk-KFTO7TMB.js.map +1 -0
  56. package/dist/chunk-MKAYFPAR.js +2 -0
  57. package/dist/chunk-MKAYFPAR.js.map +1 -0
  58. package/dist/chunk-NXPH3ZUW.js +2 -0
  59. package/dist/chunk-NXPH3ZUW.js.map +1 -0
  60. package/dist/chunk-S5TC6NSU.js +2 -0
  61. package/dist/chunk-S5TC6NSU.js.map +1 -0
  62. package/dist/chunk-YWBNVHR6.js +2 -0
  63. package/dist/chunk-YWBNVHR6.js.map +1 -0
  64. package/dist/chunk-Z7QZ7IXT.js +2 -0
  65. package/dist/chunk-Z7QZ7IXT.js.map +1 -0
  66. package/dist/chunk-ZAN4ZHCJ.js +2 -0
  67. package/dist/chunk-ZAN4ZHCJ.js.map +1 -0
  68. package/dist/chunk-ZUPYV5TI.js +2 -0
  69. package/dist/chunk-ZUPYV5TI.js.map +1 -0
  70. package/dist/core.d.ts +23 -0
  71. package/dist/core.js +2 -0
  72. package/dist/core.js.map +1 -0
  73. package/dist/extension.d.ts +413 -0
  74. package/dist/extensions/array.d.ts +112 -0
  75. package/dist/extensions/enum.d.ts +190 -0
  76. package/dist/extensions/index.d.ts +108 -0
  77. package/dist/extensions/nullable.d.ts +26 -0
  78. package/dist/extensions/number.d.ts +228 -0
  79. package/dist/extensions/string.d.ts +332 -0
  80. package/dist/extensions/util.d.ts +45 -0
  81. package/dist/index.d.ts +7 -20
  82. package/dist/index.js +2 -19
  83. package/dist/index.js.map +1 -0
  84. package/dist/utils/transaction.d.ts +27 -4
  85. package/package.json +74 -6
  86. package/dist/builders/SchemaBuilder.js +0 -275
  87. package/dist/utils/transaction.js +0 -178
@@ -0,0 +1,341 @@
1
+ /**
2
+ * Schema builder for objects with dynamic string keys, where every value
3
+ * must satisfy the same value schema.
4
+ *
5
+ * Equivalent to TypeScript's `Record<string, V>` (or a more constrained key
6
+ * set when using a string-literal key schema) and Zod's `z.record()`.
7
+ *
8
+ * Unlike `ObjectSchemaBuilder` — which validates objects with a **known,
9
+ * fixed set of property names** — `RecordSchemaBuilder` validates objects
10
+ * whose keys are not known at schema-definition time (look-up tables, i18n
11
+ * bundles, caches, etc.).
12
+ *
13
+ * @module
14
+ */
15
+ import { type BRAND, type InferType, SchemaBuilder, type ValidationContext, type ValidationErrorMessageProvider, type ValidationResult } from './SchemaBuilder.js';
16
+ import type { StringSchemaBuilder } from './StringSchemaBuilder.js';
17
+ /**
18
+ * Descriptor for a single key-value entry within a validated record.
19
+ * Provides `getValue`, `setValue`, and `getSchema` operations for the entry.
20
+ *
21
+ * Returned as part of {@link RecordKeyValidationResult}.
22
+ */
23
+ export type RecordKeyDescriptor<TRecord, TValueSchema extends SchemaBuilder<any, any, any, any, any>> = {
24
+ /** The key within the record this descriptor refers to. */
25
+ readonly key: string;
26
+ /** Returns the value schema every record entry must satisfy. */
27
+ getSchema(): TValueSchema;
28
+ /**
29
+ * Retrieves the value at `key` from the given record object.
30
+ * Returns `{ success: false }` when the key is not present.
31
+ */
32
+ getValue(obj: TRecord): {
33
+ value?: InferType<TValueSchema>;
34
+ success: boolean;
35
+ };
36
+ /**
37
+ * Sets the value at `key` on the given record object.
38
+ * Returns `false` when `obj` is not a non-null object.
39
+ */
40
+ setValue(obj: TRecord, value: InferType<TValueSchema>): boolean;
41
+ };
42
+ /**
43
+ * Validation result for a single key-value entry in a record.
44
+ * Returned by {@link RecordSchemaValidationResult.getErrorsFor | getErrorsFor(key)}.
45
+ */
46
+ export type RecordKeyValidationResult<TRecord, TValueSchema extends SchemaBuilder<any, any, any, any, any>> = {
47
+ /** Validation error messages for this entry; empty array when valid. */
48
+ readonly errors: ReadonlyArray<string>;
49
+ /** `true` when there are no validation errors for this entry. */
50
+ readonly isValid: boolean;
51
+ /** The value that was seen at this key during validation. */
52
+ readonly seenValue: InferType<TValueSchema> | undefined;
53
+ /** Descriptor for reading/writing the value at this key. */
54
+ readonly descriptor: RecordKeyDescriptor<TRecord, TValueSchema>;
55
+ };
56
+ /**
57
+ * Root-level validation result for the record object itself.
58
+ * Returned by {@link RecordSchemaValidationResult.getErrorsFor | getErrorsFor()} (no argument).
59
+ */
60
+ export type RecordRootValidationResult<TResult> = {
61
+ /** Root-level error messages (e.g. `"object expected"`); empty when valid. */
62
+ readonly errors: ReadonlyArray<string>;
63
+ /** `true` when there are no root-level errors. */
64
+ readonly isValid: boolean;
65
+ /** The value that was being validated. */
66
+ readonly seenValue: TResult | undefined;
67
+ };
68
+ /**
69
+ * Validation result type returned by `RecordSchemaBuilder.validate()`.
70
+ *
71
+ * Extends `ValidationResult` with:
72
+ * - `getNestedErrors()` — a per-key map of `ValidationResult` objects.
73
+ * - `getErrorsFor()` — root-level errors for the record container itself.
74
+ * - `getErrorsFor(key)` — errors, seen value, and descriptor for a specific key.
75
+ */
76
+ export type RecordSchemaValidationResult<TResult, TValueSchema extends SchemaBuilder<any, any, any, any, any>> = ValidationResult<TResult> & {
77
+ /**
78
+ * Returns per-key validation results as a plain object.
79
+ *
80
+ * Each key in the returned object corresponds to a key in the input that
81
+ * **failed** validation (in `doNotStopOnFirstError` mode) or the single
82
+ * first failing key (in the default stop-on-first-error mode). Keys that
83
+ * passed are not included.
84
+ *
85
+ * @deprecated Prefer {@link getErrorsFor} for a richer per-entry result
86
+ * that also includes a descriptor and `seenValue`.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const schema = record(string(), number().positive());
91
+ * const result = schema.validate(
92
+ * { a: 1, b: -2, c: 'oops' },
93
+ * { doNotStopOnFirstError: true }
94
+ * );
95
+ *
96
+ * if (!result.valid) {
97
+ * const nested = result.getNestedErrors();
98
+ * console.log(nested['b']); // ValidationResult for key 'b'
99
+ * console.log(nested['c']); // ValidationResult for key 'c'
100
+ * }
101
+ * ```
102
+ */
103
+ getNestedErrors(): Record<string, ValidationResult<InferType<TValueSchema>>>;
104
+ /**
105
+ * Returns root-level errors for the record container itself
106
+ * (e.g. `"object expected"` when a non-object value is passed,
107
+ * or errors from custom validators added to the record schema).
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * const schema = record(string(), number());
112
+ * const root = schema.validate(42 as any).getErrorsFor();
113
+ * // root.errors[0] === 'object expected'
114
+ * // root.isValid === false
115
+ * ```
116
+ */
117
+ getErrorsFor(): RecordRootValidationResult<TResult>;
118
+ /**
119
+ * Returns the validation result for the entry with the given key,
120
+ * including error messages, the seen value, and a descriptor for
121
+ * accessing and modifying the value at that key.
122
+ *
123
+ * If the key was not reached during validation (e.g. an earlier key
124
+ * already failed in stop-on-first-error mode), an empty result with
125
+ * `isValid: true` and no errors is returned.
126
+ *
127
+ * @param key - the key whose validation result to retrieve
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * const schema = record(string(), number().min(0));
132
+ * const result = schema.validate(
133
+ * { a: 5, b: -2 },
134
+ * { doNotStopOnFirstError: true }
135
+ * );
136
+ *
137
+ * const bErrors = result.getErrorsFor('b');
138
+ * // bErrors.isValid === false
139
+ * // bErrors.errors[0] === 'the value must be >= 0'
140
+ * // bErrors.seenValue === -2
141
+ * // bErrors.descriptor.key === 'b'
142
+ * // bErrors.descriptor.getSchema() === valueSchema
143
+ * ```
144
+ */
145
+ getErrorsFor(key: string): RecordKeyValidationResult<TResult, TValueSchema>;
146
+ };
147
+ type RecordSchemaBuilderCreateProps<TKeySchema extends StringSchemaBuilder<any, any, any, any>, TValueSchema extends SchemaBuilder<any, any, any, any, any>, R extends boolean = true> = Partial<ReturnType<RecordSchemaBuilder<TKeySchema, TValueSchema, R>['introspect']>>;
148
+ /**
149
+ * Schema builder for objects with dynamic string keys.
150
+ *
151
+ * Every key in the validated object must be accepted by `keySchema` (a
152
+ * `StringSchemaBuilder`) and every value must satisfy `valueSchema`.
153
+ *
154
+ * The inferred TypeScript type mirrors `Record<K, V>` where `K` is the
155
+ * string type produced by `keySchema` and `V` is the type produced by
156
+ * `valueSchema`.
157
+ *
158
+ * **NOTE** — this class is exported to allow extension by inheritance. Use
159
+ * the {@link record | record()} factory function instead of instantiating it
160
+ * directly.
161
+ *
162
+ * @example
163
+ * ```ts
164
+ * import { record, string, number } from '@cleverbrush/schema';
165
+ *
166
+ * // Basic: string keys, number values
167
+ * const scores = record(string(), number().min(0));
168
+ * // InferType<typeof scores> → Record<string, number>
169
+ *
170
+ * scores.validate({ alice: 95, bob: 87 }); // valid
171
+ * scores.validate({ alice: 95, bob: -1 }); // invalid (negative)
172
+ * ```
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * // Restrict keys to a specific set of literals with .equals()
177
+ * const locales = record(
178
+ * string().matches(/^[a-z]{2}(-[A-Z]{2})?$/),
179
+ * string().nonempty()
180
+ * );
181
+ * // accepts: { en: 'Hello', fr: 'Bonjour' }
182
+ * // rejects: { 123: 'oops' } ← key doesn't match pattern
183
+ * ```
184
+ *
185
+ * @see {@link record}
186
+ */
187
+ export declare class RecordSchemaBuilder<TKeySchema extends StringSchemaBuilder<any, any, any, any>, TValueSchema extends SchemaBuilder<any, any, any, any, any>, TRequired extends boolean = true, TNullable extends boolean = false, TExplicitType = undefined, THasDefault extends boolean = false, TExtensions = {}, TResult = TExplicitType extends undefined ? Record<InferType<TKeySchema>, InferType<TValueSchema>> : TExplicitType> extends SchemaBuilder<TResult, TRequired, TNullable, THasDefault, TExtensions> {
188
+ #private;
189
+ /**
190
+ * @hidden
191
+ */
192
+ static create(props: RecordSchemaBuilderCreateProps<any, any, any>): RecordSchemaBuilder<StringSchemaBuilder<any, any, any, any, {}>, SchemaBuilder<any, any, any, any, any>, true, false, undefined, false, {}, Record<any, any>>;
193
+ protected constructor(props: RecordSchemaBuilderCreateProps<TKeySchema, TValueSchema, TRequired>);
194
+ /**
195
+ * @inheritdoc
196
+ */
197
+ hasType<T>(_notUsed?: T): RecordSchemaBuilder<TKeySchema, TValueSchema, true, TNullable, T, THasDefault, TExtensions> & TExtensions;
198
+ /**
199
+ * @inheritdoc
200
+ */
201
+ clearHasType(): RecordSchemaBuilder<TKeySchema, TValueSchema, TRequired, TNullable, undefined, THasDefault, TExtensions> & TExtensions;
202
+ /**
203
+ * @hidden
204
+ */
205
+ protected createFromProps<TReq extends boolean>(props: RecordSchemaBuilderCreateProps<TKeySchema, TValueSchema, TReq>): this;
206
+ /**
207
+ * @hidden
208
+ */
209
+ required(errorMessage?: ValidationErrorMessageProvider): RecordSchemaBuilder<TKeySchema, TValueSchema, true, TNullable, TExplicitType, THasDefault, TExtensions> & TExtensions;
210
+ /**
211
+ * @hidden
212
+ */
213
+ optional(): RecordSchemaBuilder<TKeySchema, TValueSchema, false, TNullable, TExplicitType, THasDefault, TExtensions> & TExtensions;
214
+ /**
215
+ * @hidden
216
+ */
217
+ default(value: TResult | (() => TResult)): RecordSchemaBuilder<TKeySchema, TValueSchema, true, TNullable, TExplicitType, true, TExtensions> & TExtensions;
218
+ /**
219
+ * @hidden
220
+ */
221
+ clearDefault(): RecordSchemaBuilder<TKeySchema, TValueSchema, TRequired, TNullable, TExplicitType, false, TExtensions> & TExtensions;
222
+ /**
223
+ * @hidden
224
+ */
225
+ brand<TBrand extends string | symbol>(_name?: TBrand): RecordSchemaBuilder<TKeySchema, TValueSchema, TRequired, TNullable, TResult & {
226
+ readonly [K in BRAND]: TBrand;
227
+ }, THasDefault, TExtensions> & TExtensions;
228
+ /**
229
+ * Returns an introspection object describing the record schema.
230
+ */
231
+ introspect(): {
232
+ /**
233
+ * The schema every key must satisfy (a `StringSchemaBuilder`).
234
+ */
235
+ keySchema: TKeySchema;
236
+ /**
237
+ * The schema every value must satisfy.
238
+ */
239
+ valueSchema: TValueSchema;
240
+ type: string;
241
+ isRequired: boolean;
242
+ isNullable: boolean;
243
+ isReadonly: boolean;
244
+ preprocessors: readonly import("./SchemaBuilder.js").PreprocessorEntry<TResult>[];
245
+ validators: readonly import("./SchemaBuilder.js").ValidatorEntry<TResult>[];
246
+ requiredValidationErrorMessageProvider: ValidationErrorMessageProvider<SchemaBuilder<any, any, any, any, any>>;
247
+ extensions: {
248
+ [x: string]: unknown;
249
+ };
250
+ hasDefault: boolean;
251
+ defaultValue: TResult | (() => TResult) | undefined;
252
+ description: string | undefined;
253
+ hasCatch: boolean;
254
+ catchValue: TResult | (() => TResult) | undefined;
255
+ };
256
+ /**
257
+ * Core sync validation. {@inheritDoc SchemaBuilder.validate}
258
+ */
259
+ validate(object: TResult, context?: ValidationContext): RecordSchemaValidationResult<TResult, TValueSchema>;
260
+ /**
261
+ * Core async validation. {@inheritDoc SchemaBuilder.validateAsync}
262
+ */
263
+ validateAsync(object: TResult, context?: ValidationContext): Promise<RecordSchemaValidationResult<TResult, TValueSchema>>;
264
+ /**
265
+ * Core sync validation. Returns `{ valid, object, errors, getNestedErrors, getErrorsFor }`.
266
+ */
267
+ protected _validate(object: TResult, context?: ValidationContext): RecordSchemaValidationResult<TResult, TValueSchema>;
268
+ /**
269
+ * Performs async validation of the record schema.
270
+ *
271
+ * Supports async preprocessors, validators, and error message providers.
272
+ *
273
+ * @param object - the value to validate
274
+ * @param context - optional `ValidationContext` settings
275
+ */
276
+ protected _validateAsync(object: TResult, context?: ValidationContext): Promise<RecordSchemaValidationResult<TResult, TValueSchema>>;
277
+ /**
278
+ * @hidden
279
+ */
280
+ nullable(): RecordSchemaBuilder<TKeySchema, TValueSchema, TRequired, true, TExplicitType, THasDefault, TExtensions> & TExtensions;
281
+ /**
282
+ * @hidden
283
+ */
284
+ notNullable(): RecordSchemaBuilder<TKeySchema, TValueSchema, TRequired, false, TExplicitType, THasDefault, TExtensions> & TExtensions;
285
+ }
286
+ /**
287
+ * Creates a schema for objects with dynamic string keys, where every key
288
+ * must satisfy `keySchema` and every value must satisfy `valueSchema`.
289
+ *
290
+ * The inferred TypeScript type is `Record<K, V>` where `K` is derived from
291
+ * `keySchema` and `V` from `valueSchema`.
292
+ *
293
+ * @param keySchema - a `StringSchemaBuilder` that each key must satisfy
294
+ * @param valueSchema - a `SchemaBuilder` that each value must satisfy
295
+ *
296
+ * @example
297
+ * ```ts
298
+ * import { record, string, number } from '@cleverbrush/schema';
299
+ *
300
+ * // Look-up table: string keys → number scores
301
+ * const scores = record(string(), number().min(0).max(100));
302
+ * // InferType<typeof scores> → Record<string, number>
303
+ *
304
+ * scores.validate({ alice: 95, bob: 87 }); // { valid: true }
305
+ * scores.validate({ alice: 95, bob: -1 }); // { valid: false }
306
+ * ```
307
+ *
308
+ * @example
309
+ * ```ts
310
+ * // i18n bundle: locale code keys → non-empty strings
311
+ * const bundle = record(
312
+ * string().matches(/^[a-z]{2}(-[A-Z]{2})?$/),
313
+ * string().nonempty()
314
+ * );
315
+ *
316
+ * bundle.validate({ en: 'Hello', 'fr-FR': 'Bonjour' }); // valid
317
+ * bundle.validate({ en: '' }); // invalid (empty value)
318
+ * bundle.validate({ '123': 'hi' }); // invalid (bad key)
319
+ * ```
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * // Optional record with a factory default
324
+ * const cache = record(string(), number())
325
+ * .optional()
326
+ * .default(() => ({}));
327
+ * ```
328
+ *
329
+ * @example
330
+ * ```ts
331
+ * // Nested record — values are objects
332
+ * import { record, string, object, number } from '@cleverbrush/schema';
333
+ *
334
+ * const userMap = record(
335
+ * string(),
336
+ * object({ name: string(), age: number() })
337
+ * );
338
+ * ```
339
+ */
340
+ export declare function record<TKeySchema extends StringSchemaBuilder<any, any, any, any>, TValueSchema extends SchemaBuilder<any, any, any, any, any>>(keySchema: TKeySchema, valueSchema: TValueSchema): RecordSchemaBuilder<TKeySchema, TValueSchema>;
341
+ export {};
@@ -0,0 +1,2 @@
1
+ import{a,b}from"../chunk-IJ6FO37G.js";import"../chunk-CTP4RHDG.js";export{a as RecordSchemaBuilder,b as record};
2
+ //# sourceMappingURL=RecordSchemaBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}