@naturalcycles/nodejs-lib 15.57.1 → 15.59.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.
@@ -39,9 +39,9 @@ export declare class AjvSchema<IN = unknown, OUT = IN> {
39
39
  *
40
40
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
41
41
  */
42
- validate(input: IN, opt?: AjvValidationOptions): OUT;
43
- isValid(input: IN, opt?: AjvValidationOptions): boolean;
44
- getValidationResult(input: IN, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
42
+ validate(input: IN, opt?: AjvValidationOptions<IN>): OUT;
43
+ isValid(input: IN, opt?: AjvValidationOptions<IN>): boolean;
44
+ getValidationResult(input: IN, opt?: AjvValidationOptions<IN>): ValidationFunctionResult<OUT, AjvValidationError>;
45
45
  getValidationFunction(): ValidationFunction<IN, OUT, AjvValidationError>;
46
46
  static isSchemaWithCachedAjvSchema<Base, IN, OUT>(schema: Base): schema is WithCachedAjvSchema<Base, IN, OUT>;
47
47
  static cacheAjvSchema<Base extends AnyObject, IN, OUT>(schema: Base, ajvSchema: AjvSchema<IN, OUT>): WithCachedAjvSchema<Base, IN, OUT>;
@@ -54,7 +54,7 @@ export declare const HIDDEN_AJV_SCHEMA: unique symbol;
54
54
  export type WithCachedAjvSchema<Base, IN, OUT> = Base & {
55
55
  [HIDDEN_AJV_SCHEMA]: AjvSchema<IN, OUT>;
56
56
  };
57
- export interface AjvValidationOptions {
57
+ export interface AjvValidationOptions<IN> {
58
58
  /**
59
59
  * Defaults to true,
60
60
  * because that's how AJV works by default,
@@ -73,6 +73,16 @@ export interface AjvValidationOptions {
73
73
  mutateInput?: boolean;
74
74
  inputName?: string;
75
75
  inputId?: string;
76
+ /**
77
+ * Function that returns "original input".
78
+ * What is original input?
79
+ * It's an input in its original non-mutated form.
80
+ * Why is it needed?
81
+ * Because we mutates the Input here. And after its been mutated - we no longer
82
+ * can include it "how it was" in an error message. So, for that reason we'll use
83
+ * `getOriginalInput()`, if it's provided.
84
+ */
85
+ getOriginalInput?: () => IN;
76
86
  }
77
87
  export interface AjvSchemaCfg {
78
88
  /**
@@ -108,7 +108,7 @@ export class AjvSchema {
108
108
  const item = opt.mutateInput !== false || typeof input !== 'object'
109
109
  ? input // mutate
110
110
  : _deepCopy(input); // not mutate
111
- const valid = fn(item); // mutates item
111
+ const valid = fn(item); // mutates item, but not input
112
112
  _typeCast(item);
113
113
  if (valid)
114
114
  return [null, item];
@@ -122,7 +122,8 @@ export class AjvSchema {
122
122
  });
123
123
  // Note: if we mutated the input already, e.g stripped unknown properties,
124
124
  // the error message Input would contain already mutated object print, such as Input: {}
125
- const inputStringified = _inspect(input, { maxLen: 4000 });
125
+ // Unless `getOriginalInput` function is provided - then it will be used to preserve the Input pureness.
126
+ const inputStringified = _inspect(opt.getOriginalInput?.() || input, { maxLen: 4000 });
126
127
  message = [message, 'Input: ' + inputStringified].join(separator);
127
128
  const err = new AjvValidationError(message, _filterNullishValues({
128
129
  errors,
@@ -374,6 +374,27 @@ export function createAjv(opt) {
374
374
  return true;
375
375
  },
376
376
  });
377
+ ajv.addKeyword({
378
+ keyword: 'keySchema',
379
+ type: 'object',
380
+ modifying: true,
381
+ errors: false,
382
+ schemaType: 'object',
383
+ compile(innerSchema, _parentSchema, _it) {
384
+ const isValidKeyFn = ajv.compile(innerSchema);
385
+ function validate(data, _ctx) {
386
+ if (typeof data !== 'object' || data === null)
387
+ return true;
388
+ for (const key of Object.keys(data)) {
389
+ if (!isValidKeyFn(key)) {
390
+ delete data[key];
391
+ }
392
+ }
393
+ return true;
394
+ }
395
+ return validate;
396
+ },
397
+ });
377
398
  return ajv;
378
399
  }
379
400
  const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
@@ -9,7 +9,40 @@ export declare const j: {
9
9
  infer: typeof objectInfer;
10
10
  any(): JsonSchemaObjectBuilder<AnyObject, AnyObject, false>;
11
11
  stringMap<S extends JsonSchemaTerminal<any, any, any>>(schema: S): JsonSchemaObjectBuilder<StringMap<SchemaIn<S>>, StringMap<SchemaOut<S>>>;
12
+ /**
13
+ * @experimental Look around, maybe you find a rule that is better for your use-case.
14
+ *
15
+ * For Record<K, V> type of validations.
16
+ * ```ts
17
+ * const schema = j.object
18
+ * .record(
19
+ * j
20
+ * .string()
21
+ * .regex(/^\d{3,4}$/)
22
+ * .branded<B>(),
23
+ * j.number().nullable(),
24
+ * )
25
+ * .isOfType<Record<B, number | null>>()
26
+ * ```
27
+ *
28
+ * When the keys of the Record are values from an Enum, prefer `j.object.withEnumKeys`!
29
+ *
30
+ * Non-matching keys will be stripped from the object, i.e. they will not cause an error.
31
+ *
32
+ * Caveat: This rule first validates values of every properties of the object, and only then validates the keys.
33
+ * A consequence of that is that the validation will throw when there is an unexpected property with a value not matching the value schema.
34
+ */
35
+ record: typeof record;
36
+ /**
37
+ * For Record<ENUM, V> type of validations.
38
+ *
39
+ * When the keys of the Record are values from an Enum,
40
+ * this helper is more performant and behaves in a more conventional manner than `j.object.record` would.
41
+ *
42
+ *
43
+ */
12
44
  withEnumKeys: typeof withEnumKeys;
45
+ withRegexKeys: typeof withRegexKeys;
13
46
  };
14
47
  array<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaArrayBuilder<IN, OUT, Opt>;
15
48
  set<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaSet2Builder<IN, OUT, Opt>;
@@ -205,6 +238,7 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
205
238
  interface JsonSchemaObjectBuilderOpts {
206
239
  hasIsOfTypeCheck?: false;
207
240
  patternProperties?: StringMap<JsonSchema<any, any>>;
241
+ keySchema?: JsonSchema;
208
242
  }
209
243
  export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>, Opt extends boolean = false> extends JsonSchemaAnyBuilder<Expand<{
210
244
  [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never;
@@ -316,6 +350,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
316
350
  };
317
351
  errorMessages?: StringMap<string>;
318
352
  optionalValues?: (string | number | boolean)[];
353
+ keySchema?: JsonSchema;
319
354
  }
320
355
  declare function object(props: AnyObject): never;
321
356
  declare function object<IN extends AnyObject>(props: {
@@ -338,6 +373,8 @@ declare function objectDbEntity<IN extends BaseDBEntity & AnyObject, EXTRA_KEYS
338
373
  } : {
339
374
  updated: BuilderFor<IN['updated']>;
340
375
  })): JsonSchemaObjectBuilder<IN, IN, false>;
376
+ declare function record<KS extends JsonSchemaAnyBuilder<any, any, any>, VS extends JsonSchemaAnyBuilder<any, any, any>, Opt extends boolean = SchemaOpt<VS>>(keySchema: KS, valueSchema: VS): JsonSchemaObjectBuilder<Opt extends true ? Partial<Record<SchemaIn<KS>, SchemaIn<VS>>> : Record<SchemaIn<KS>, SchemaIn<VS>>, Opt extends true ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>> : Record<SchemaOut<KS>, SchemaOut<VS>>, false>;
377
+ declare function withRegexKeys<S extends JsonSchemaAnyBuilder<any, any, any>, Opt extends boolean = SchemaOpt<S>>(keyRegex: RegExp | string, schema: S): JsonSchemaObjectBuilder<Opt extends true ? StringMap<SchemaIn<S>> : StringMap<SchemaIn<S>>, Opt extends true ? StringMap<SchemaOut<S>> : StringMap<SchemaOut<S>>, false>;
341
378
  /**
342
379
  * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
343
380
  */
@@ -378,5 +415,5 @@ interface JsonBuilderRuleOpt {
378
415
  type EnumKeyUnion<T> = T extends readonly (infer U)[] ? U : T extends StringEnum | NumberEnum ? T[keyof T] : never;
379
416
  type SchemaIn<S> = S extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never;
380
417
  type SchemaOut<S> = S extends JsonSchemaAnyBuilder<any, infer OUT, any> ? OUT : never;
381
- type SchemaOpt<S> = S extends JsonSchemaAnyBuilder<any, any, infer Opt> ? Opt : false;
418
+ type SchemaOpt<S> = S extends JsonSchemaAnyBuilder<any, any, infer Opt> ? (Opt extends true ? true : false) : false;
382
419
  export {};
@@ -33,7 +33,40 @@ export const j = {
33
33
  },
34
34
  });
35
35
  },
36
+ /**
37
+ * @experimental Look around, maybe you find a rule that is better for your use-case.
38
+ *
39
+ * For Record<K, V> type of validations.
40
+ * ```ts
41
+ * const schema = j.object
42
+ * .record(
43
+ * j
44
+ * .string()
45
+ * .regex(/^\d{3,4}$/)
46
+ * .branded<B>(),
47
+ * j.number().nullable(),
48
+ * )
49
+ * .isOfType<Record<B, number | null>>()
50
+ * ```
51
+ *
52
+ * When the keys of the Record are values from an Enum, prefer `j.object.withEnumKeys`!
53
+ *
54
+ * Non-matching keys will be stripped from the object, i.e. they will not cause an error.
55
+ *
56
+ * Caveat: This rule first validates values of every properties of the object, and only then validates the keys.
57
+ * A consequence of that is that the validation will throw when there is an unexpected property with a value not matching the value schema.
58
+ */
59
+ record,
60
+ /**
61
+ * For Record<ENUM, V> type of validations.
62
+ *
63
+ * When the keys of the Record are values from an Enum,
64
+ * this helper is more performant and behaves in a more conventional manner than `j.object.record` would.
65
+ *
66
+ *
67
+ */
36
68
  withEnumKeys,
69
+ withRegexKeys,
37
70
  }),
38
71
  array(itemSchema) {
39
72
  return new JsonSchemaArrayBuilder(itemSchema);
@@ -527,6 +560,7 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
527
560
  additionalProperties: false,
528
561
  hasIsOfTypeCheck: opt?.hasIsOfTypeCheck ?? true,
529
562
  patternProperties: opt?.patternProperties ?? undefined,
563
+ keySchema: opt?.keySchema ?? undefined,
530
564
  });
531
565
  if (props)
532
566
  this.addProperties(props);
@@ -715,6 +749,27 @@ function objectDbEntity(props) {
715
749
  ...props,
716
750
  });
717
751
  }
752
+ function record(keySchema, valueSchema) {
753
+ const keyJsonSchema = keySchema.build();
754
+ const valueJsonSchema = valueSchema.build();
755
+ return new JsonSchemaObjectBuilder([], {
756
+ hasIsOfTypeCheck: false,
757
+ keySchema: keyJsonSchema,
758
+ patternProperties: {
759
+ ['^.*$']: valueJsonSchema,
760
+ },
761
+ });
762
+ }
763
+ function withRegexKeys(keyRegex, schema) {
764
+ const pattern = keyRegex instanceof RegExp ? keyRegex.source : keyRegex;
765
+ const jsonSchema = schema.build();
766
+ return new JsonSchemaObjectBuilder([], {
767
+ hasIsOfTypeCheck: false,
768
+ patternProperties: {
769
+ [pattern]: jsonSchema,
770
+ },
771
+ });
772
+ }
718
773
  /**
719
774
  * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
720
775
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.57.1",
4
+ "version": "15.59.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -120,13 +120,13 @@ export class AjvSchema<IN = unknown, OUT = IN> {
120
120
  *
121
121
  * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
122
122
  */
123
- validate(input: IN, opt: AjvValidationOptions = {}): OUT {
123
+ validate(input: IN, opt: AjvValidationOptions<IN> = {}): OUT {
124
124
  const [err, output] = this.getValidationResult(input, opt)
125
125
  if (err) throw err
126
126
  return output
127
127
  }
128
128
 
129
- isValid(input: IN, opt?: AjvValidationOptions): boolean {
129
+ isValid(input: IN, opt?: AjvValidationOptions<IN>): boolean {
130
130
  // todo: we can make it both fast and non-mutating by using Ajv
131
131
  // with "removeAdditional" and "useDefaults" disabled.
132
132
  const [err] = this.getValidationResult(input, opt)
@@ -135,7 +135,7 @@ export class AjvSchema<IN = unknown, OUT = IN> {
135
135
 
136
136
  getValidationResult(
137
137
  input: IN,
138
- opt: AjvValidationOptions = {},
138
+ opt: AjvValidationOptions<IN> = {},
139
139
  ): ValidationFunctionResult<OUT, AjvValidationError> {
140
140
  const fn = this.getAJVValidateFunction()
141
141
 
@@ -144,7 +144,7 @@ export class AjvSchema<IN = unknown, OUT = IN> {
144
144
  ? input // mutate
145
145
  : _deepCopy(input) // not mutate
146
146
 
147
- const valid = fn(item) // mutates item
147
+ const valid = fn(item) // mutates item, but not input
148
148
  _typeCast<OUT>(item)
149
149
  if (valid) return [null, item]
150
150
 
@@ -165,7 +165,8 @@ export class AjvSchema<IN = unknown, OUT = IN> {
165
165
 
166
166
  // Note: if we mutated the input already, e.g stripped unknown properties,
167
167
  // the error message Input would contain already mutated object print, such as Input: {}
168
- const inputStringified = _inspect(input, { maxLen: 4000 })
168
+ // Unless `getOriginalInput` function is provided - then it will be used to preserve the Input pureness.
169
+ const inputStringified = _inspect(opt.getOriginalInput?.() || input, { maxLen: 4000 })
169
170
  message = [message, 'Input: ' + inputStringified].join(separator)
170
171
 
171
172
  const err = new AjvValidationError(
@@ -245,7 +246,7 @@ export type WithCachedAjvSchema<Base, IN, OUT> = Base & {
245
246
  [HIDDEN_AJV_SCHEMA]: AjvSchema<IN, OUT>
246
247
  }
247
248
 
248
- export interface AjvValidationOptions {
249
+ export interface AjvValidationOptions<IN> {
249
250
  /**
250
251
  * Defaults to true,
251
252
  * because that's how AJV works by default,
@@ -264,6 +265,16 @@ export interface AjvValidationOptions {
264
265
  mutateInput?: boolean
265
266
  inputName?: string
266
267
  inputId?: string
268
+ /**
269
+ * Function that returns "original input".
270
+ * What is original input?
271
+ * It's an input in its original non-mutated form.
272
+ * Why is it needed?
273
+ * Because we mutates the Input here. And after its been mutated - we no longer
274
+ * can include it "how it was" in an error message. So, for that reason we'll use
275
+ * `getOriginalInput()`, if it's provided.
276
+ */
277
+ getOriginalInput?: () => IN
267
278
  }
268
279
 
269
280
  export interface AjvSchemaCfg {
@@ -1,6 +1,7 @@
1
1
  import { _lazyValue } from '@naturalcycles/js-lib'
2
2
  import { Set2 } from '@naturalcycles/js-lib/object'
3
3
  import { _substringAfterLast } from '@naturalcycles/js-lib/string'
4
+ import type { AnyObject } from '@naturalcycles/js-lib/types'
4
5
  import { Ajv, type Options, type ValidateFunction } from 'ajv'
5
6
  import { validTLDs } from '../tlds.js'
6
7
  import type { JsonSchemaIsoDateOptions, JsonSchemaStringEmailOptions } from './jsonSchemaBuilder.js'
@@ -429,6 +430,31 @@ export function createAjv(opt?: Options): Ajv {
429
430
  },
430
431
  })
431
432
 
433
+ ajv.addKeyword({
434
+ keyword: 'keySchema',
435
+ type: 'object',
436
+ modifying: true,
437
+ errors: false,
438
+ schemaType: 'object',
439
+ compile(innerSchema, _parentSchema, _it) {
440
+ const isValidKeyFn: ValidateFunction = ajv.compile(innerSchema)
441
+
442
+ function validate(data: AnyObject, _ctx: any): boolean {
443
+ if (typeof data !== 'object' || data === null) return true
444
+
445
+ for (const key of Object.keys(data)) {
446
+ if (!isValidKeyFn(key)) {
447
+ delete data[key]
448
+ }
449
+ }
450
+
451
+ return true
452
+ }
453
+
454
+ return validate
455
+ },
456
+ })
457
+
432
458
  return ajv
433
459
  }
434
460
 
@@ -82,7 +82,41 @@ export const j = {
82
82
  )
83
83
  },
84
84
 
85
+ /**
86
+ * @experimental Look around, maybe you find a rule that is better for your use-case.
87
+ *
88
+ * For Record<K, V> type of validations.
89
+ * ```ts
90
+ * const schema = j.object
91
+ * .record(
92
+ * j
93
+ * .string()
94
+ * .regex(/^\d{3,4}$/)
95
+ * .branded<B>(),
96
+ * j.number().nullable(),
97
+ * )
98
+ * .isOfType<Record<B, number | null>>()
99
+ * ```
100
+ *
101
+ * When the keys of the Record are values from an Enum, prefer `j.object.withEnumKeys`!
102
+ *
103
+ * Non-matching keys will be stripped from the object, i.e. they will not cause an error.
104
+ *
105
+ * Caveat: This rule first validates values of every properties of the object, and only then validates the keys.
106
+ * A consequence of that is that the validation will throw when there is an unexpected property with a value not matching the value schema.
107
+ */
108
+ record,
109
+
110
+ /**
111
+ * For Record<ENUM, V> type of validations.
112
+ *
113
+ * When the keys of the Record are values from an Enum,
114
+ * this helper is more performant and behaves in a more conventional manner than `j.object.record` would.
115
+ *
116
+ *
117
+ */
85
118
  withEnumKeys,
119
+ withRegexKeys,
86
120
  }),
87
121
 
88
122
  array<IN, OUT, Opt>(
@@ -749,6 +783,7 @@ export class JsonSchemaObjectBuilder<
749
783
  additionalProperties: false,
750
784
  hasIsOfTypeCheck: opt?.hasIsOfTypeCheck ?? true,
751
785
  patternProperties: opt?.patternProperties ?? undefined,
786
+ keySchema: opt?.keySchema ?? undefined,
752
787
  })
753
788
 
754
789
  if (props) this.addProperties(props)
@@ -820,6 +855,7 @@ export class JsonSchemaObjectBuilder<
820
855
  interface JsonSchemaObjectBuilderOpts {
821
856
  hasIsOfTypeCheck?: false
822
857
  patternProperties?: StringMap<JsonSchema<any, any>>
858
+ keySchema?: JsonSchema
823
859
  }
824
860
 
825
861
  export class JsonSchemaObjectInferringBuilder<
@@ -1107,6 +1143,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
1107
1143
  transform?: { trim?: true; toLowerCase?: true; toUpperCase?: true; truncate?: number }
1108
1144
  errorMessages?: StringMap<string>
1109
1145
  optionalValues?: (string | number | boolean)[]
1146
+ keySchema?: JsonSchema
1110
1147
  }
1111
1148
 
1112
1149
  function object(props: AnyObject): never
@@ -1156,6 +1193,68 @@ function objectDbEntity(props: AnyObject): any {
1156
1193
  })
1157
1194
  }
1158
1195
 
1196
+ function record<
1197
+ KS extends JsonSchemaAnyBuilder<any, any, any>,
1198
+ VS extends JsonSchemaAnyBuilder<any, any, any>,
1199
+ Opt extends boolean = SchemaOpt<VS>,
1200
+ >(
1201
+ keySchema: KS,
1202
+ valueSchema: VS,
1203
+ ): JsonSchemaObjectBuilder<
1204
+ Opt extends true
1205
+ ? Partial<Record<SchemaIn<KS>, SchemaIn<VS>>>
1206
+ : Record<SchemaIn<KS>, SchemaIn<VS>>,
1207
+ Opt extends true
1208
+ ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>>
1209
+ : Record<SchemaOut<KS>, SchemaOut<VS>>,
1210
+ false
1211
+ > {
1212
+ const keyJsonSchema = keySchema.build()
1213
+ const valueJsonSchema = valueSchema.build()
1214
+
1215
+ return new JsonSchemaObjectBuilder<
1216
+ Opt extends true
1217
+ ? Partial<Record<SchemaIn<KS>, SchemaIn<VS>>>
1218
+ : Record<SchemaIn<KS>, SchemaIn<VS>>,
1219
+ Opt extends true
1220
+ ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>>
1221
+ : Record<SchemaOut<KS>, SchemaOut<VS>>,
1222
+ false
1223
+ >([], {
1224
+ hasIsOfTypeCheck: false,
1225
+ keySchema: keyJsonSchema,
1226
+ patternProperties: {
1227
+ ['^.*$']: valueJsonSchema,
1228
+ },
1229
+ })
1230
+ }
1231
+
1232
+ function withRegexKeys<
1233
+ S extends JsonSchemaAnyBuilder<any, any, any>,
1234
+ Opt extends boolean = SchemaOpt<S>,
1235
+ >(
1236
+ keyRegex: RegExp | string,
1237
+ schema: S,
1238
+ ): JsonSchemaObjectBuilder<
1239
+ Opt extends true ? StringMap<SchemaIn<S>> : StringMap<SchemaIn<S>>,
1240
+ Opt extends true ? StringMap<SchemaOut<S>> : StringMap<SchemaOut<S>>,
1241
+ false
1242
+ > {
1243
+ const pattern = keyRegex instanceof RegExp ? keyRegex.source : keyRegex
1244
+ const jsonSchema = schema.build()
1245
+
1246
+ return new JsonSchemaObjectBuilder<
1247
+ Opt extends true ? StringMap<SchemaIn<S>> : StringMap<SchemaIn<S>>,
1248
+ Opt extends true ? StringMap<SchemaOut<S>> : StringMap<SchemaOut<S>>,
1249
+ false
1250
+ >([], {
1251
+ hasIsOfTypeCheck: false,
1252
+ patternProperties: {
1253
+ [pattern]: jsonSchema,
1254
+ },
1255
+ })
1256
+ }
1257
+
1159
1258
  /**
1160
1259
  * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
1161
1260
  */
@@ -1245,4 +1344,5 @@ type EnumKeyUnion<T> =
1245
1344
 
1246
1345
  type SchemaIn<S> = S extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never
1247
1346
  type SchemaOut<S> = S extends JsonSchemaAnyBuilder<any, infer OUT, any> ? OUT : never
1248
- type SchemaOpt<S> = S extends JsonSchemaAnyBuilder<any, any, infer Opt> ? Opt : false
1347
+ type SchemaOpt<S> =
1348
+ S extends JsonSchemaAnyBuilder<any, any, infer Opt> ? (Opt extends true ? true : false) : false