@naturalcycles/nodejs-lib 15.90.2 → 15.92.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,20 +1,19 @@
1
1
  import type { ValidationFunction, ValidationFunctionResult } from '@naturalcycles/js-lib';
2
- import type { AnyObject } from '@naturalcycles/js-lib/types';
2
+ import type { Set2 } from '@naturalcycles/js-lib/object';
3
+ import type { AnyObject, BaseDBEntity, IANATimezone, Inclusiveness, IsoDate, IsoDateTime, IsoMonth, NumberEnum, StringEnum, StringMap, UnixTimestamp, UnixTimestampMillis } from '@naturalcycles/js-lib/types';
3
4
  import type { Ajv } from 'ajv';
4
5
  import { AjvValidationError } from './ajvValidationError.js';
5
- import { JsonSchemaTerminal } from './jsonSchemaBuilder.js';
6
- import type { JsonSchema } from './jsonSchemaBuilder.js';
7
6
  /**
8
7
  * On creation - compiles ajv validation function.
9
8
  * Provides convenient methods, error reporting, etc.
10
9
  */
11
- export declare class AjvSchema<IN = unknown, OUT = IN> {
12
- schema: JsonSchema<IN, OUT>;
10
+ export declare class AjvSchema<OUT> {
11
+ schema: JsonSchema<OUT>;
13
12
  private constructor();
14
13
  /**
15
14
  * Shortcut for AjvSchema.create(schema, { lazy: true })
16
15
  */
17
- static createLazy<IN, OUT>(schema: SchemaHandledByAjv<IN, OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<IN, OUT>;
16
+ static createLazy<OUT>(schema: SchemaHandledByAjv<OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<OUT>;
18
17
  /**
19
18
  * Conveniently allows to pass either JsonSchema or JsonSchemaBuilder, or existing AjvSchema.
20
19
  * If it's already an AjvSchema - it'll just return it without any processing.
@@ -24,8 +23,8 @@ export declare class AjvSchema<IN = unknown, OUT = IN> {
24
23
  * Implementation note: JsonSchemaBuilder goes first in the union type, otherwise TypeScript fails to infer <T> type
25
24
  * correctly for some reason.
26
25
  */
27
- static create<IN, OUT = IN>(schema: SchemaHandledByAjv<IN, OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<IN, OUT>;
28
- static isJsonSchemaBuilder<IN, OUT>(schema: unknown): schema is JsonSchemaTerminal<IN, OUT, any>;
26
+ static create<OUT>(schema: SchemaHandledByAjv<OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<OUT>;
27
+ static isJsonSchemaBuilder<OUT>(schema: unknown): schema is JsonSchemaTerminal<OUT, any>;
29
28
  readonly cfg: AjvSchemaCfg;
30
29
  /**
31
30
  * It returns the original object just for convenience.
@@ -35,13 +34,13 @@ export declare class AjvSchema<IN = unknown, OUT = IN> {
35
34
  *
36
35
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
37
36
  */
38
- validate(input: IN, opt?: AjvValidationOptions<IN>): OUT;
39
- isValid(input: IN, opt?: AjvValidationOptions<IN>): boolean;
40
- getValidationResult(input: IN, opt?: AjvValidationOptions<IN>): ValidationFunctionResult<OUT, AjvValidationError>;
41
- getValidationFunction(): ValidationFunction<IN, OUT, AjvValidationError>;
42
- static isSchemaWithCachedAjvSchema<Base, IN, OUT>(schema: Base): schema is WithCachedAjvSchema<Base, IN, OUT>;
43
- static cacheAjvSchema<Base extends AnyObject, IN, OUT>(schema: Base, ajvSchema: AjvSchema<IN, OUT>): WithCachedAjvSchema<Base, IN, OUT>;
44
- static requireCachedAjvSchema<Base, IN, OUT>(schema: WithCachedAjvSchema<Base, IN, OUT>): AjvSchema<IN, OUT>;
37
+ validate(input: unknown, opt?: AjvValidationOptions): OUT;
38
+ isValid(input: unknown, opt?: AjvValidationOptions): boolean;
39
+ getValidationResult(input: unknown, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
40
+ getValidationFunction(): ValidationFunction<OUT, AjvValidationError>;
41
+ static isSchemaWithCachedAjvSchema<Base, OUT>(schema: Base): schema is WithCachedAjvSchema<Base, OUT>;
42
+ static cacheAjvSchema<Base extends AnyObject, OUT>(schema: Base, ajvSchema: AjvSchema<OUT>): WithCachedAjvSchema<Base, OUT>;
43
+ static requireCachedAjvSchema<Base, OUT>(schema: WithCachedAjvSchema<Base, OUT>): AjvSchema<OUT>;
45
44
  private getAJVValidateFunction;
46
45
  private static requireValidJsonSchema;
47
46
  private applyImprovementsOnErrorMessages;
@@ -52,10 +51,10 @@ export declare class AjvSchema<IN = unknown, OUT = IN> {
52
51
  private getObjectPropertySchema;
53
52
  }
54
53
  export declare const HIDDEN_AJV_SCHEMA: unique symbol;
55
- export type WithCachedAjvSchema<Base, IN, OUT> = Base & {
56
- [HIDDEN_AJV_SCHEMA]: AjvSchema<IN, OUT>;
54
+ export type WithCachedAjvSchema<Base, OUT> = Base & {
55
+ [HIDDEN_AJV_SCHEMA]: AjvSchema<OUT>;
57
56
  };
58
- export interface AjvValidationOptions<IN> {
57
+ export interface AjvValidationOptions {
59
58
  /**
60
59
  * Defaults to true,
61
60
  * because that's how AJV works by default,
@@ -83,7 +82,7 @@ export interface AjvValidationOptions<IN> {
83
82
  * can include it "how it was" in an error message. So, for that reason we'll use
84
83
  * `getOriginalInput()`, if it's provided.
85
84
  */
86
- getOriginalInput?: () => IN;
85
+ getOriginalInput?: () => unknown;
87
86
  }
88
87
  export interface AjvSchemaCfg {
89
88
  /**
@@ -105,4 +104,629 @@ export interface AjvSchemaCfg {
105
104
  */
106
105
  lazy?: boolean;
107
106
  }
108
- export type SchemaHandledByAjv<IN, OUT = IN> = JsonSchemaTerminal<IN, OUT, any> | JsonSchema<IN, OUT> | AjvSchema<IN, OUT>;
107
+ export type SchemaHandledByAjv<OUT> = JsonSchemaTerminal<OUT, any> | JsonSchema<OUT> | AjvSchema<OUT>;
108
+ export declare const j: {
109
+ /**
110
+ * Matches literally any value - equivalent to TypeScript's `any` type.
111
+ * Use sparingly, as it bypasses type validation entirely.
112
+ */
113
+ any(): JsonSchemaAnyBuilder<any, false>;
114
+ string(): JsonSchemaStringBuilder<string, false>;
115
+ number(): JsonSchemaNumberBuilder<number, false>;
116
+ boolean(): JsonSchemaBooleanBuilder<boolean, false>;
117
+ object: typeof object & {
118
+ dbEntity: typeof objectDbEntity;
119
+ infer: typeof objectInfer;
120
+ any(): JsonSchemaObjectBuilder<AnyObject, false>;
121
+ stringMap<S extends JsonSchemaTerminal<any, any>>(schema: S): JsonSchemaObjectBuilder<StringMap<SchemaOut<S>>, false>;
122
+ /**
123
+ * @experimental Look around, maybe you find a rule that is better for your use-case.
124
+ *
125
+ * For Record<K, V> type of validations.
126
+ * ```ts
127
+ * const schema = j.object
128
+ * .record(
129
+ * j
130
+ * .string()
131
+ * .regex(/^\d{3,4}$/)
132
+ * .branded<B>(),
133
+ * j.number().nullable(),
134
+ * )
135
+ * .isOfType<Record<B, number | null>>()
136
+ * ```
137
+ *
138
+ * When the keys of the Record are values from an Enum, prefer `j.object.withEnumKeys`!
139
+ *
140
+ * Non-matching keys will be stripped from the object, i.e. they will not cause an error.
141
+ *
142
+ * Caveat: This rule first validates values of every properties of the object, and only then validates the keys.
143
+ * A consequence of that is that the validation will throw when there is an unexpected property with a value not matching the value schema.
144
+ */
145
+ record: typeof record;
146
+ /**
147
+ * For Record<ENUM, V> type of validations.
148
+ *
149
+ * When the keys of the Record are values from an Enum,
150
+ * this helper is more performant and behaves in a more conventional manner than `j.object.record` would.
151
+ *
152
+ *
153
+ */
154
+ withEnumKeys: typeof withEnumKeys;
155
+ withRegexKeys: typeof withRegexKeys;
156
+ };
157
+ array<OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<OUT, Opt>): JsonSchemaArrayBuilder<OUT, Opt>;
158
+ tuple<const S extends JsonSchemaAnyBuilder<any, any>[]>(items: S): JsonSchemaTupleBuilder<S>;
159
+ set<OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<OUT, Opt>): JsonSchemaSet2Builder<OUT, Opt>;
160
+ buffer(): JsonSchemaBufferBuilder;
161
+ enum<const T extends any>(input: T, opt?: JsonBuilderRuleOpt | undefined): JsonSchemaEnumBuilder<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never, false>;
162
+ /**
163
+ * Use only with primitive values, otherwise this function will throw to avoid bugs.
164
+ * To validate objects, use `anyOfBy`.
165
+ *
166
+ * Our Ajv is configured to strip unexpected properties from objects,
167
+ * and since Ajv is mutating the input, this means that it cannot
168
+ * properly validate the same data over multiple schemas.
169
+ *
170
+ * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
171
+ * Use `oneOf` when schemas are mutually exclusive.
172
+ */
173
+ oneOf<B extends readonly JsonSchemaAnyBuilder<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<OUT, false>;
174
+ /**
175
+ * Use only with primitive values, otherwise this function will throw to avoid bugs.
176
+ * To validate objects, use `anyOfBy` or `anyOfThese`.
177
+ *
178
+ * Our Ajv is configured to strip unexpected properties from objects,
179
+ * and since Ajv is mutating the input, this means that it cannot
180
+ * properly validate the same data over multiple schemas.
181
+ *
182
+ * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
183
+ * Use `oneOf` when schemas are mutually exclusive.
184
+ */
185
+ anyOf<B extends readonly JsonSchemaAnyBuilder<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<OUT, false>;
186
+ /**
187
+ * Pick validation schema for an object based on the value of a specific property.
188
+ *
189
+ * ```
190
+ * const schemaMap = {
191
+ * true: successSchema,
192
+ * false: errorSchema
193
+ * }
194
+ *
195
+ * const schema = j.anyOfBy('success', schemaMap)
196
+ * ```
197
+ */
198
+ anyOfBy<D extends Record<PropertyKey, JsonSchemaTerminal<any, any>>, OUT = AnyOfByOut<D>>(propertyName: string, schemaDictionary: D): JsonSchemaAnyOfByBuilder<OUT>;
199
+ /**
200
+ * Custom version of `anyOf` which - in contrast to the original function - does not mutate the input.
201
+ * This comes with a performance penalty, so do not use it where performance matters.
202
+ *
203
+ * ```
204
+ * const schema = j.anyOfThese([successSchema, errorSchema])
205
+ * ```
206
+ */
207
+ anyOfThese<B extends readonly JsonSchemaAnyBuilder<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<OUT, false>;
208
+ and(): {
209
+ silentBob: () => never;
210
+ };
211
+ literal<const V extends string | number | boolean | null>(v: V): JsonSchemaEnumBuilder<V, false>;
212
+ };
213
+ export declare class JsonSchemaTerminal<OUT, Opt> {
214
+ protected [HIDDEN_AJV_SCHEMA]: AjvSchema<any> | undefined;
215
+ protected schema: JsonSchema;
216
+ constructor(schema: JsonSchema);
217
+ get ajvSchema(): AjvSchema<any>;
218
+ getSchema(): JsonSchema;
219
+ /**
220
+ * Produces a "clean schema object" without methods.
221
+ * Same as if it would be JSON.stringified.
222
+ */
223
+ build(): JsonSchema<OUT>;
224
+ clone(): this;
225
+ cloneAndUpdateSchema(schema: Partial<JsonSchema>): this;
226
+ validate(input: unknown, opt?: AjvValidationOptions): OUT;
227
+ isValid(input: unknown, opt?: AjvValidationOptions): boolean;
228
+ getValidationResult(input: unknown, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
229
+ getValidationFunction(): ValidationFunction<OUT, AjvValidationError>;
230
+ /**
231
+ * Specify a function to be called after the normal validation is finished.
232
+ *
233
+ * This function will receive the validated, type-safe data, and you can use it
234
+ * to do further validations, e.g. conditional validations based on certain property values,
235
+ * or to do data modifications either by mutating the input or returning a new value.
236
+ *
237
+ * If you throw an error from this function, it will show up as an error in the validation.
238
+ */
239
+ postValidation<OUT2 = OUT>(fn: PostValidatonFn<OUT, OUT2>): JsonSchemaTerminal<OUT2, Opt>;
240
+ /**
241
+ * @experimental
242
+ */
243
+ out: OUT;
244
+ opt: Opt;
245
+ }
246
+ export declare class JsonSchemaAnyBuilder<OUT, Opt> extends JsonSchemaTerminal<OUT, Opt> {
247
+ protected setErrorMessage(ruleName: string, errorMessage: string | undefined): void;
248
+ /**
249
+ * A helper function that takes a type parameter and compares it with the type inferred from the schema.
250
+ *
251
+ * When the type inferred from the schema differs from the passed-in type,
252
+ * the schema becomes unusable, by turning its type into `never`.
253
+ *
254
+ * ```ts
255
+ * const schemaGood = j.string().isOfType<string>() // ✅
256
+ *
257
+ * const schemaBad = j.string().isOfType<number>() // ❌
258
+ * schemaBad.build() // TypeError: property "build" does not exist on type "never"
259
+ *
260
+ * const result = ajvValidateRequest.body(req, schemaBad) // result will have `unknown` type
261
+ * ```
262
+ */
263
+ isOfType<ExpectedType>(): ExactMatch<ExpectedType, OUT> extends true ? this : never;
264
+ $schema($schema: string): this;
265
+ $schemaDraft7(): this;
266
+ $id($id: string): this;
267
+ title(title: string): this;
268
+ description(description: string): this;
269
+ deprecated(deprecated?: boolean): this;
270
+ type(type: string): this;
271
+ default(v: any): this;
272
+ instanceof(of: string): this;
273
+ optional(): JsonSchemaAnyBuilder<OUT | undefined, true>;
274
+ nullable(): JsonSchemaAnyBuilder<OUT | null, Opt>;
275
+ /**
276
+ * @deprecated
277
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
278
+ */
279
+ castAs<T>(): JsonSchemaAnyBuilder<T, Opt>;
280
+ /**
281
+ * Locks the given schema chain and no other modification can be done to it.
282
+ */
283
+ final(): JsonSchemaTerminal<OUT, Opt>;
284
+ /**
285
+ *
286
+ * @param validator A validator function that returns an error message or undefined.
287
+ *
288
+ * You may add multiple custom validators and they will be executed in the order you added them.
289
+ */
290
+ custom<OUT2 = OUT>(validator: CustomValidatorFn): JsonSchemaAnyBuilder<OUT2, Opt>;
291
+ /**
292
+ *
293
+ * @param converter A converter function that returns a new value.
294
+ *
295
+ * You may add multiple converters and they will be executed in the order you added them,
296
+ * each converter receiving the result from the previous one.
297
+ *
298
+ * This feature only works when the current schema is nested in an object or array schema,
299
+ * due to how mutability works in Ajv.
300
+ */
301
+ convert<OUT2>(converter: CustomConverterFn<OUT2>): JsonSchemaAnyBuilder<OUT2, Opt>;
302
+ }
303
+ export declare class JsonSchemaStringBuilder<OUT extends string | undefined = string, Opt extends boolean = false> extends JsonSchemaAnyBuilder<OUT, Opt> {
304
+ constructor();
305
+ /**
306
+ * @param optionalValues List of values that should be considered/converted as `undefined`.
307
+ *
308
+ * This `optionalValues` feature only works when the current schema is nested in an object or array schema,
309
+ * due to how mutability works in Ajv.
310
+ *
311
+ * Make sure this `optional()` call is at the end of your call chain.
312
+ *
313
+ * When `null` is included in optionalValues, the return type becomes `JsonSchemaTerminal`
314
+ * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
315
+ */
316
+ optional<T extends readonly (string | null)[] | undefined = undefined>(optionalValues?: T): T extends readonly (infer U)[] ? null extends U ? JsonSchemaTerminal<OUT | undefined, true> : JsonSchemaStringBuilder<OUT | undefined, true> : JsonSchemaStringBuilder<OUT | undefined, true>;
317
+ regex(pattern: RegExp, opt?: JsonBuilderRuleOpt): this;
318
+ pattern(pattern: string, opt?: JsonBuilderRuleOpt): this;
319
+ minLength(minLength: number): this;
320
+ maxLength(maxLength: number): this;
321
+ length(exactLength: number): this;
322
+ length(minLength: number, maxLength: number): this;
323
+ email(opt?: Partial<JsonSchemaStringEmailOptions>): this;
324
+ trim(): this;
325
+ toLowerCase(): this;
326
+ toUpperCase(): this;
327
+ truncate(toLength: number): this;
328
+ branded<B extends string>(): JsonSchemaStringBuilder<B, Opt>;
329
+ /**
330
+ * Validates that the input is a fully-specified YYYY-MM-DD formatted valid IsoDate value.
331
+ *
332
+ * All previous expectations in the schema chain are dropped - including `.optional()` -
333
+ * because this call effectively starts a new schema chain.
334
+ */
335
+ isoDate(): JsonSchemaIsoDateBuilder;
336
+ isoDateTime(): JsonSchemaStringBuilder<IsoDateTime, Opt>;
337
+ isoMonth(): JsonSchemaIsoMonthBuilder;
338
+ /**
339
+ * Validates the string format to be JWT.
340
+ * Expects the JWT to be signed!
341
+ */
342
+ jwt(): this;
343
+ url(): this;
344
+ ipv4(): this;
345
+ ipv6(): this;
346
+ slug(): this;
347
+ semVer(): this;
348
+ languageTag(): this;
349
+ countryCode(): this;
350
+ currency(): this;
351
+ /**
352
+ * Validates that the input is a valid IANATimzone value.
353
+ *
354
+ * All previous expectations in the schema chain are dropped - including `.optional()` -
355
+ * because this call effectively starts a new schema chain as an `enum` validation.
356
+ */
357
+ ianaTimezone(): JsonSchemaEnumBuilder<IANATimezone, false>;
358
+ base64Url(): this;
359
+ uuid(): this;
360
+ }
361
+ export interface JsonSchemaStringEmailOptions {
362
+ checkTLD: boolean;
363
+ }
364
+ export declare class JsonSchemaIsoDateBuilder<Opt extends boolean = false> extends JsonSchemaAnyBuilder<IsoDate, Opt> {
365
+ constructor();
366
+ /**
367
+ * @param nullValue Pass `null` to have `null` values be considered/converted as `undefined`.
368
+ *
369
+ * This `null` feature only works when the current schema is nested in an object or array schema,
370
+ * due to how mutability works in Ajv.
371
+ *
372
+ * When `null` is passed, the return type becomes `JsonSchemaTerminal`
373
+ * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
374
+ */
375
+ optional<N extends null | undefined = undefined>(nullValue?: N): N extends null ? JsonSchemaTerminal<IsoDate | undefined, true> : JsonSchemaAnyBuilder<IsoDate | undefined, true>;
376
+ before(date: string): this;
377
+ sameOrBefore(date: string): this;
378
+ after(date: string): this;
379
+ sameOrAfter(date: string): this;
380
+ between(fromDate: string, toDate: string, incl: Inclusiveness): this;
381
+ }
382
+ export interface JsonSchemaIsoDateOptions {
383
+ before?: string;
384
+ sameOrBefore?: string;
385
+ after?: string;
386
+ sameOrAfter?: string;
387
+ }
388
+ export declare class JsonSchemaIsoMonthBuilder<Opt extends boolean = false> extends JsonSchemaAnyBuilder<IsoMonth, Opt> {
389
+ constructor();
390
+ }
391
+ export interface JsonSchemaIsoMonthOptions {
392
+ }
393
+ export declare class JsonSchemaNumberBuilder<OUT extends number | undefined = number, Opt extends boolean = false> extends JsonSchemaAnyBuilder<OUT, Opt> {
394
+ constructor();
395
+ /**
396
+ * @param optionalValues List of values that should be considered/converted as `undefined`.
397
+ *
398
+ * This `optionalValues` feature only works when the current schema is nested in an object or array schema,
399
+ * due to how mutability works in Ajv.
400
+ *
401
+ * Make sure this `optional()` call is at the end of your call chain.
402
+ *
403
+ * When `null` is included in optionalValues, the return type becomes `JsonSchemaTerminal`
404
+ * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
405
+ */
406
+ optional<T extends readonly (number | null)[] | undefined = undefined>(optionalValues?: T): T extends readonly (infer U)[] ? null extends U ? JsonSchemaTerminal<OUT | undefined, true> : JsonSchemaNumberBuilder<OUT | undefined, true> : JsonSchemaNumberBuilder<OUT | undefined, true>;
407
+ integer(): this;
408
+ branded<B extends number>(): JsonSchemaNumberBuilder<B, Opt>;
409
+ multipleOf(multipleOf: number): this;
410
+ min(minimum: number): this;
411
+ exclusiveMin(exclusiveMinimum: number): this;
412
+ max(maximum: number): this;
413
+ exclusiveMax(exclusiveMaximum: number): this;
414
+ lessThan(value: number): this;
415
+ lessThanOrEqual(value: number): this;
416
+ moreThan(value: number): this;
417
+ moreThanOrEqual(value: number): this;
418
+ equal(value: number): this;
419
+ range(minimum: number, maximum: number, incl: Inclusiveness): this;
420
+ int32(): this;
421
+ int64(): this;
422
+ float(): this;
423
+ double(): this;
424
+ unixTimestamp(): JsonSchemaNumberBuilder<UnixTimestamp, Opt>;
425
+ unixTimestamp2000(): JsonSchemaNumberBuilder<UnixTimestamp, Opt>;
426
+ unixTimestampMillis(): JsonSchemaNumberBuilder<UnixTimestampMillis, Opt>;
427
+ unixTimestamp2000Millis(): JsonSchemaNumberBuilder<UnixTimestampMillis, Opt>;
428
+ utcOffset(): this;
429
+ utcOffsetHour(): this;
430
+ /**
431
+ * Specify the precision of the floating point numbers by the number of digits after the ".".
432
+ * Excess digits will be cut-off when the current schema is nested in an object or array schema,
433
+ * due to how mutability works in Ajv.
434
+ */
435
+ precision(numberOfDigits: number): this;
436
+ }
437
+ export declare class JsonSchemaBooleanBuilder<OUT extends boolean | undefined = boolean, Opt extends boolean = false> extends JsonSchemaAnyBuilder<OUT, Opt> {
438
+ constructor();
439
+ /**
440
+ * @param optionalValue One of the two possible boolean values that should be considered/converted as `undefined`.
441
+ *
442
+ * This `optionalValue` feature only works when the current schema is nested in an object or array schema,
443
+ * due to how mutability works in Ajv.
444
+ */
445
+ optional(optionalValue?: boolean): JsonSchemaBooleanBuilder<OUT | undefined, true>;
446
+ }
447
+ export declare class JsonSchemaObjectBuilder<OUT extends AnyObject, Opt extends boolean = false> extends JsonSchemaAnyBuilder<OUT, Opt> {
448
+ constructor(props?: AnyObject, opt?: JsonSchemaObjectBuilderOpts);
449
+ addProperties(props: AnyObject): this;
450
+ /**
451
+ * @param nullValue Pass `null` to have `null` values be considered/converted as `undefined`.
452
+ *
453
+ * This `null` feature only works when the current schema is nested in an object or array schema,
454
+ * due to how mutability works in Ajv.
455
+ *
456
+ * When `null` is passed, the return type becomes `JsonSchemaTerminal`
457
+ * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
458
+ */
459
+ optional<N extends null | undefined = undefined>(nullValue?: N): N extends null ? JsonSchemaTerminal<OUT | undefined, true> : JsonSchemaAnyBuilder<OUT | undefined, true>;
460
+ /**
461
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
462
+ */
463
+ allowAdditionalProperties(): this;
464
+ extend<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(props: P): JsonSchemaObjectBuilder<Override<OUT, {
465
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: P[K] extends JsonSchemaAnyBuilder<infer OUT2, any> ? OUT2 : never;
466
+ } & {
467
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: P[K] extends JsonSchemaAnyBuilder<infer OUT2, any> ? OUT2 : never;
468
+ }>, false>;
469
+ /**
470
+ * Concatenates another schema to the current schema.
471
+ *
472
+ * It expects you to use `isOfType<T>()` in the chain,
473
+ * otherwise the validation will throw. This is to ensure
474
+ * that the schemas you concatenated match the intended final type.
475
+ *
476
+ * ```ts
477
+ * interface Foo { foo: string }
478
+ * const fooSchema = j.object<Foo>({ foo: j.string() })
479
+ *
480
+ * interface Bar { bar: number }
481
+ * const barSchema = j.object<Bar>({ bar: j.number() })
482
+ *
483
+ * interface Shu { foo: string, bar: number }
484
+ * const shuSchema = fooSchema.concat(barSchema).isOfType<Shu>() // important
485
+ * ```
486
+ */
487
+ concat<OUT2 extends AnyObject>(other: JsonSchemaObjectBuilder<OUT2, any>): JsonSchemaObjectBuilder<OUT & OUT2, false>;
488
+ /**
489
+ * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
490
+ */
491
+ dbEntity(): JsonSchemaObjectBuilder<Override<OUT, {
492
+ id: string;
493
+ created: any;
494
+ updated: any;
495
+ } & {}>, false>;
496
+ minProperties(minProperties: number): this;
497
+ maxProperties(maxProperties: number): this;
498
+ exclusiveProperties(propNames: readonly (keyof OUT & string)[]): this;
499
+ }
500
+ interface JsonSchemaObjectBuilderOpts {
501
+ hasIsOfTypeCheck?: false;
502
+ patternProperties?: StringMap<JsonSchema<any>>;
503
+ keySchema?: JsonSchema;
504
+ }
505
+ export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<string, JsonSchemaAnyBuilder<any, any>>, Opt extends boolean = false> extends JsonSchemaAnyBuilder<Expand<{
506
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
507
+ } & {
508
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
509
+ }>, Opt> {
510
+ constructor(props?: PROPS);
511
+ addProperties(props: PROPS): this;
512
+ /**
513
+ * @param nullValue Pass `null` to have `null` values be considered/converted as `undefined`.
514
+ *
515
+ * This `null` feature only works when the current schema is nested in an object or array schema,
516
+ * due to how mutability works in Ajv.
517
+ *
518
+ * When `null` is passed, the return type becomes `JsonSchemaTerminal`
519
+ * (no further chaining allowed) because the schema is wrapped in an anyOf structure.
520
+ */
521
+ optional<N extends null | undefined = undefined>(nullValue?: N): N extends null ? JsonSchemaTerminal<Expand<{
522
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
523
+ } & {
524
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
525
+ }> | undefined, true> : JsonSchemaAnyBuilder<Expand<{
526
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
527
+ } & {
528
+ [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: PROPS[K] extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
529
+ }> | undefined, true>;
530
+ /**
531
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
532
+ */
533
+ allowAdditionalProperties(): this;
534
+ extend<NEW_PROPS extends Record<string, JsonSchemaAnyBuilder<any, any>>>(props: NEW_PROPS): JsonSchemaObjectInferringBuilder<{
535
+ [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS ? NEW_PROPS[K] : K extends keyof PROPS ? PROPS[K] : never;
536
+ }, Opt>;
537
+ /**
538
+ * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
539
+ */
540
+ dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in "created" | "id" | "updated" | keyof PROPS]: K extends "created" | "id" | "updated" ? {
541
+ id: JsonSchemaStringBuilder<string, false>;
542
+ created: JsonSchemaNumberBuilder<UnixTimestamp, false>;
543
+ updated: JsonSchemaNumberBuilder<UnixTimestamp, false>;
544
+ }[K] : K extends keyof PROPS ? PROPS[K] : never; }, Opt>;
545
+ }
546
+ export declare class JsonSchemaArrayBuilder<OUT, Opt> extends JsonSchemaAnyBuilder<OUT[], Opt> {
547
+ constructor(itemsSchema: JsonSchemaAnyBuilder<OUT, Opt>);
548
+ minLength(minItems: number): this;
549
+ maxLength(maxItems: number): this;
550
+ length(exactLength: number): this;
551
+ length(minItems: number, maxItems: number): this;
552
+ exactLength(length: number): this;
553
+ unique(): this;
554
+ }
555
+ export declare class JsonSchemaSet2Builder<OUT, Opt> extends JsonSchemaAnyBuilder<Set2<OUT>, Opt> {
556
+ constructor(itemsSchema: JsonSchemaAnyBuilder<OUT, Opt>);
557
+ min(minItems: number): this;
558
+ max(maxItems: number): this;
559
+ }
560
+ export declare class JsonSchemaBufferBuilder extends JsonSchemaAnyBuilder<Buffer, false> {
561
+ constructor();
562
+ }
563
+ export declare class JsonSchemaEnumBuilder<OUT extends string | number | boolean | null, Opt extends boolean = false> extends JsonSchemaAnyBuilder<OUT, Opt> {
564
+ constructor(enumValues: readonly OUT[], baseType: EnumBaseType, opt?: JsonBuilderRuleOpt);
565
+ branded<B extends OUT>(): JsonSchemaEnumBuilder<B, Opt>;
566
+ }
567
+ export declare class JsonSchemaTupleBuilder<ITEMS extends JsonSchemaAnyBuilder<any, any>[]> extends JsonSchemaAnyBuilder<TupleOut<ITEMS>, false> {
568
+ constructor(items: ITEMS);
569
+ }
570
+ export declare class JsonSchemaAnyOfByBuilder<OUT> extends JsonSchemaAnyBuilder<OUT, false> {
571
+ constructor(propertyName: string, schemaDictionary: Record<PropertyKey, JsonSchemaTerminal<any, any>>);
572
+ }
573
+ export declare class JsonSchemaAnyOfTheseBuilder<OUT> extends JsonSchemaAnyBuilder<OUT, false> {
574
+ constructor(propertyName: string, schemaDictionary: Record<PropertyKey, JsonSchemaTerminal<any, any>>);
575
+ }
576
+ type EnumBaseType = 'string' | 'number' | 'other';
577
+ export interface JsonSchema<OUT = unknown> {
578
+ readonly out?: OUT;
579
+ $schema?: string;
580
+ $id?: string;
581
+ title?: string;
582
+ description?: string;
583
+ deprecated?: boolean;
584
+ readOnly?: boolean;
585
+ writeOnly?: boolean;
586
+ type?: string | string[];
587
+ items?: JsonSchema;
588
+ prefixItems?: JsonSchema[];
589
+ properties?: {
590
+ [K in keyof OUT]: JsonSchema<OUT[K]>;
591
+ };
592
+ patternProperties?: StringMap<JsonSchema<any>>;
593
+ required?: string[];
594
+ additionalProperties?: boolean;
595
+ minProperties?: number;
596
+ maxProperties?: number;
597
+ default?: OUT;
598
+ if?: JsonSchema;
599
+ then?: JsonSchema;
600
+ else?: JsonSchema;
601
+ anyOf?: JsonSchema[];
602
+ oneOf?: JsonSchema[];
603
+ /**
604
+ * This is a temporary "intermediate AST" field that is used inside the parser.
605
+ * In the final schema this field will NOT be present.
606
+ */
607
+ optionalField?: true;
608
+ pattern?: string;
609
+ minLength?: number;
610
+ maxLength?: number;
611
+ format?: string;
612
+ contentMediaType?: string;
613
+ contentEncoding?: string;
614
+ multipleOf?: number;
615
+ minimum?: number;
616
+ exclusiveMinimum?: number;
617
+ maximum?: number;
618
+ exclusiveMaximum?: number;
619
+ minItems?: number;
620
+ maxItems?: number;
621
+ uniqueItems?: boolean;
622
+ enum?: any;
623
+ hasIsOfTypeCheck?: boolean;
624
+ email?: JsonSchemaStringEmailOptions;
625
+ Set2?: JsonSchema;
626
+ Buffer?: true;
627
+ IsoDate?: JsonSchemaIsoDateOptions;
628
+ IsoDateTime?: true;
629
+ IsoMonth?: JsonSchemaIsoMonthOptions;
630
+ instanceof?: string | string[];
631
+ transform?: {
632
+ trim?: true;
633
+ toLowerCase?: true;
634
+ toUpperCase?: true;
635
+ truncate?: number;
636
+ };
637
+ errorMessages?: StringMap<string>;
638
+ optionalValues?: (string | number | boolean | null)[];
639
+ keySchema?: JsonSchema;
640
+ isUndefined?: true;
641
+ minProperties2?: number;
642
+ exclusiveProperties?: (readonly string[])[];
643
+ anyOfBy?: {
644
+ propertyName: string;
645
+ schemaDictionary: Record<string, JsonSchema>;
646
+ };
647
+ anyOfThese?: JsonSchema[];
648
+ precision?: number;
649
+ customValidations?: CustomValidatorFn[];
650
+ customConversions?: CustomConverterFn<any>[];
651
+ postValidation?: PostValidatonFn<any, OUT>;
652
+ }
653
+ declare function object(props: AnyObject): never;
654
+ declare function object<OUT extends AnyObject>(props: {
655
+ [K in keyof Required<OUT>]-?: JsonSchemaTerminal<OUT[K], any>;
656
+ }): JsonSchemaObjectBuilder<OUT, false>;
657
+ declare function objectInfer<P extends Record<string, JsonSchemaAnyBuilder<any, any>>>(props: P): JsonSchemaObjectInferringBuilder<P, false>;
658
+ declare function objectDbEntity(props: AnyObject): never;
659
+ declare function objectDbEntity<OUT extends BaseDBEntity, EXTRA_KEYS extends Exclude<keyof OUT, keyof BaseDBEntity> = Exclude<keyof OUT, keyof BaseDBEntity>>(props: {
660
+ [K in EXTRA_KEYS]-?: BuilderFor<OUT[K]>;
661
+ } & (ExactMatch<OUT['id'], BaseDBEntity['id']> extends true ? {
662
+ id?: BuilderFor<BaseDBEntity['id']>;
663
+ } : {
664
+ id: BuilderFor<OUT['id']>;
665
+ }) & (ExactMatch<OUT['created'], BaseDBEntity['created']> extends true ? {
666
+ created?: BuilderFor<BaseDBEntity['created']>;
667
+ } : {
668
+ created: BuilderFor<OUT['created']>;
669
+ }) & (ExactMatch<OUT['updated'], BaseDBEntity['updated']> extends true ? {
670
+ updated?: BuilderFor<BaseDBEntity['updated']>;
671
+ } : {
672
+ updated: BuilderFor<OUT['updated']>;
673
+ })): JsonSchemaObjectBuilder<OUT, false>;
674
+ declare function record<KS extends JsonSchemaAnyBuilder<any, any>, VS extends JsonSchemaAnyBuilder<any, any>, Opt extends boolean = SchemaOpt<VS>>(keySchema: KS, valueSchema: VS): JsonSchemaObjectBuilder<Opt extends true ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>> : Record<SchemaOut<KS>, SchemaOut<VS>>, false>;
675
+ declare function withRegexKeys<S extends JsonSchemaAnyBuilder<any, any>>(keyRegex: RegExp | string, schema: S): JsonSchemaObjectBuilder<StringMap<SchemaOut<S>>, false>;
676
+ /**
677
+ * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
678
+ */
679
+ declare function withEnumKeys<const T extends readonly (string | number)[] | StringEnum | NumberEnum, S extends JsonSchemaAnyBuilder<any, any>, K extends string | number = EnumKeyUnion<T>, Opt extends boolean = SchemaOpt<S>>(keys: T, schema: S): JsonSchemaObjectBuilder<Opt extends true ? {
680
+ [P in K]?: SchemaOut<S>;
681
+ } : {
682
+ [P in K]: SchemaOut<S>;
683
+ }, false>;
684
+ type Expand<T> = {
685
+ [K in keyof T]: T[K];
686
+ };
687
+ type StripIndexSignatureDeep<T> = T extends readonly unknown[] ? T : T extends Record<string, any> ? {
688
+ [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: StripIndexSignatureDeep<T[K]>;
689
+ } : T;
690
+ type RelaxIndexSignature<T> = T extends readonly unknown[] ? T : T extends AnyObject ? {
691
+ [K in keyof T]: RelaxIndexSignature<T[K]>;
692
+ } : T;
693
+ type Override<T, U> = Omit<T, keyof U> & U;
694
+ declare const allowExtraKeysSymbol: unique symbol;
695
+ type HasAllowExtraKeys<T> = T extends {
696
+ readonly [allowExtraKeysSymbol]?: true;
697
+ } ? true : false;
698
+ type IsAny<T> = 0 extends 1 & T ? true : false;
699
+ type IsAssignableRelaxed<A, B> = IsAny<RelaxIndexSignature<A>> extends true ? true : [RelaxIndexSignature<A>] extends [B] ? true : false;
700
+ type ExactMatchBase<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => (T extends B ? 1 : 2) ? (<T>() => T extends B ? 1 : 2) extends <T>() => (T extends A ? 1 : 2) ? true : false : false;
701
+ type ExactMatch<A, B> = HasAllowExtraKeys<B> extends true ? IsAssignableRelaxed<B, A> : ExactMatchBase<Expand<A>, Expand<B>> extends true ? true : ExactMatchBase<Expand<StripIndexSignatureDeep<A>>, Expand<StripIndexSignatureDeep<B>>>;
702
+ type BuilderOutUnion<B extends readonly JsonSchemaAnyBuilder<any, any>[]> = {
703
+ [K in keyof B]: B[K] extends JsonSchemaAnyBuilder<infer O, any> ? O : never;
704
+ }[number];
705
+ type AnyOfByOut<D extends Record<PropertyKey, JsonSchemaTerminal<any, any>>> = {
706
+ [K in keyof D]: D[K] extends JsonSchemaTerminal<infer O, any> ? O : never;
707
+ }[keyof D];
708
+ type BuilderFor<T> = JsonSchemaAnyBuilder<T, any>;
709
+ interface JsonBuilderRuleOpt {
710
+ /**
711
+ * Text of error message to return when the validation fails for the given rule:
712
+ *
713
+ * `{ msg: "is not a valid Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
714
+ */
715
+ msg?: string;
716
+ /**
717
+ * A friendly name for what we are validating, that will be used in error messages:
718
+ *
719
+ * `{ name: "Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
720
+ */
721
+ name?: string;
722
+ }
723
+ type EnumKeyUnion<T> = T extends readonly (infer U)[] ? U : T extends StringEnum | NumberEnum ? T[keyof T] : never;
724
+ type SchemaOut<S> = S extends JsonSchemaAnyBuilder<infer OUT, any> ? OUT : never;
725
+ type SchemaOpt<S> = S extends JsonSchemaAnyBuilder<any, infer Opt> ? (Opt extends true ? true : false) : false;
726
+ type TupleOut<T extends readonly JsonSchemaAnyBuilder<any, any>[]> = {
727
+ [K in keyof T]: T[K] extends JsonSchemaAnyBuilder<infer O, any> ? O : never;
728
+ };
729
+ export type PostValidatonFn<OUT, OUT2> = (v: OUT) => OUT2;
730
+ export type CustomValidatorFn = (v: any) => string | undefined;
731
+ export type CustomConverterFn<OUT> = (v: any) => OUT;
732
+ export {};