@naturalcycles/nodejs-lib 15.79.0 → 15.80.1
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,5 +1,5 @@
|
|
|
1
1
|
import { _isBetween, _lazyValue } from '@naturalcycles/js-lib';
|
|
2
|
-
import { Set2 } from '@naturalcycles/js-lib/object';
|
|
2
|
+
import { _mapObject, Set2 } from '@naturalcycles/js-lib/object';
|
|
3
3
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string';
|
|
4
4
|
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
5
5
|
import { validTLDs } from '../tlds.js';
|
|
@@ -477,6 +477,42 @@ export function createAjv(opt) {
|
|
|
477
477
|
return true;
|
|
478
478
|
},
|
|
479
479
|
});
|
|
480
|
+
ajv.addKeyword({
|
|
481
|
+
keyword: 'anyOfBy',
|
|
482
|
+
type: 'object',
|
|
483
|
+
modifying: true,
|
|
484
|
+
errors: true,
|
|
485
|
+
schemaType: 'object',
|
|
486
|
+
compile(config, _parentSchema, _it) {
|
|
487
|
+
const { propertyName, schemaDictionary } = config;
|
|
488
|
+
const isValidFnByKey = _mapObject(schemaDictionary, (key, value) => {
|
|
489
|
+
return [key, ajv.compile(value)];
|
|
490
|
+
});
|
|
491
|
+
function validate(data, ctx) {
|
|
492
|
+
if (typeof data !== 'object' || data === null)
|
|
493
|
+
return true;
|
|
494
|
+
const determinant = data[propertyName];
|
|
495
|
+
const isValidFn = isValidFnByKey[determinant];
|
|
496
|
+
if (!isValidFn) {
|
|
497
|
+
;
|
|
498
|
+
validate.errors = [
|
|
499
|
+
{
|
|
500
|
+
instancePath: ctx?.instancePath ?? '',
|
|
501
|
+
message: `could not find a suitable schema to validate against based on "${propertyName}"`,
|
|
502
|
+
},
|
|
503
|
+
];
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
const result = isValidFn(data);
|
|
507
|
+
if (!result) {
|
|
508
|
+
;
|
|
509
|
+
validate.errors = isValidFn.errors;
|
|
510
|
+
}
|
|
511
|
+
return result;
|
|
512
|
+
}
|
|
513
|
+
return validate;
|
|
514
|
+
},
|
|
515
|
+
});
|
|
480
516
|
return ajv;
|
|
481
517
|
}
|
|
482
518
|
const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
@@ -54,14 +54,31 @@ export declare const j: {
|
|
|
54
54
|
set<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaSet2Builder<IN, OUT, Opt>;
|
|
55
55
|
buffer(): JsonSchemaBufferBuilder;
|
|
56
56
|
enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(input: T, opt?: JsonBuilderRuleOpt): JsonSchemaEnumBuilder<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never>;
|
|
57
|
+
/**
|
|
58
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
59
|
+
* To validate objects, use `anyOfBy`.
|
|
60
|
+
*
|
|
61
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
62
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
63
|
+
* properly validate the same data over multiple schemas.
|
|
64
|
+
*
|
|
65
|
+
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
66
|
+
* Use `oneOf` when schemas are mutually exclusive.
|
|
67
|
+
*/
|
|
57
68
|
oneOf<B extends readonly JsonSchemaAnyBuilder<any, any, boolean>[], IN = BuilderInUnion<B>, OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false>;
|
|
58
69
|
/**
|
|
59
|
-
*
|
|
70
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
71
|
+
* To validate objects, use `anyOfBy`.
|
|
72
|
+
*
|
|
73
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
74
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
75
|
+
* properly validate the same data over multiple schemas.
|
|
60
76
|
*
|
|
61
77
|
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
62
78
|
* Use `oneOf` when schemas are mutually exclusive.
|
|
63
79
|
*/
|
|
64
80
|
anyOf<B extends readonly JsonSchemaAnyBuilder<any, any, boolean>[], IN = BuilderInUnion<B>, OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false>;
|
|
81
|
+
anyOfBy<P extends string, D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>, IN = AnyOfByIn<D>, OUT = AnyOfByOut<D>>(propertyName: P, schemaDictionary: D): JsonSchemaAnyOfByBuilder<IN, OUT, P>;
|
|
65
82
|
and(): {
|
|
66
83
|
silentBob: () => never;
|
|
67
84
|
};
|
|
@@ -348,6 +365,10 @@ export declare class JsonSchemaTupleBuilder<ITEMS extends JsonSchemaAnyBuilder<a
|
|
|
348
365
|
private readonly _items;
|
|
349
366
|
constructor(items: ITEMS);
|
|
350
367
|
}
|
|
368
|
+
export declare class JsonSchemaAnyOfByBuilder<IN, OUT, _P extends string = string> extends JsonSchemaAnyBuilder<AnyOfByInput<IN, _P> | IN, OUT, false> {
|
|
369
|
+
in: IN;
|
|
370
|
+
constructor(propertyName: string, schemaDictionary: Record<PropertyKey, JsonSchemaTerminal<any, any, any>>);
|
|
371
|
+
}
|
|
351
372
|
type EnumBaseType = 'string' | 'number' | 'other';
|
|
352
373
|
export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
353
374
|
readonly in?: IN;
|
|
@@ -415,6 +436,10 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
415
436
|
keySchema?: JsonSchema;
|
|
416
437
|
minProperties2?: number;
|
|
417
438
|
exclusiveProperties?: (readonly string[])[];
|
|
439
|
+
anyOfBy?: {
|
|
440
|
+
propertyName: string;
|
|
441
|
+
schemaDictionary: Record<string, JsonSchema>;
|
|
442
|
+
};
|
|
418
443
|
}
|
|
419
444
|
declare function object(props: AnyObject): never;
|
|
420
445
|
declare function object<IN extends AnyObject>(props: {
|
|
@@ -476,6 +501,18 @@ type BuilderOutUnion<B extends readonly JsonSchemaAnyBuilder<any, any, any>[]> =
|
|
|
476
501
|
type BuilderInUnion<B extends readonly JsonSchemaAnyBuilder<any, any, any>[]> = {
|
|
477
502
|
[K in keyof B]: B[K] extends JsonSchemaAnyBuilder<infer I, any, any> ? I : never;
|
|
478
503
|
}[number];
|
|
504
|
+
type AnyOfByIn<D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>> = {
|
|
505
|
+
[K in keyof D]: D[K] extends JsonSchemaTerminal<infer I, any, any> ? I : never;
|
|
506
|
+
}[keyof D];
|
|
507
|
+
type AnyOfByOut<D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>> = {
|
|
508
|
+
[K in keyof D]: D[K] extends JsonSchemaTerminal<any, infer O, any> ? O : never;
|
|
509
|
+
}[keyof D];
|
|
510
|
+
type AnyOfByDiscriminant<IN, P extends string> = IN extends {
|
|
511
|
+
[K in P]: infer V;
|
|
512
|
+
} ? V : never;
|
|
513
|
+
type AnyOfByInput<IN, P extends string, D = AnyOfByDiscriminant<IN, P>> = IN extends unknown ? Omit<Partial<IN>, P> & {
|
|
514
|
+
[K in P]?: D;
|
|
515
|
+
} : never;
|
|
479
516
|
type BuilderFor<T> = JsonSchemaAnyBuilder<any, T, any>;
|
|
480
517
|
interface JsonBuilderRuleOpt {
|
|
481
518
|
/**
|
|
@@ -113,24 +113,45 @@ export const j = {
|
|
|
113
113
|
_assert(enumValues, 'Unsupported enum input');
|
|
114
114
|
return new JsonSchemaEnumBuilder(enumValues, baseType, opt);
|
|
115
115
|
},
|
|
116
|
+
/**
|
|
117
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
118
|
+
* To validate objects, use `anyOfBy`.
|
|
119
|
+
*
|
|
120
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
121
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
122
|
+
* properly validate the same data over multiple schemas.
|
|
123
|
+
*
|
|
124
|
+
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
125
|
+
* Use `oneOf` when schemas are mutually exclusive.
|
|
126
|
+
*/
|
|
116
127
|
oneOf(items) {
|
|
117
128
|
const schemas = items.map(b => b.build());
|
|
129
|
+
_assert(schemas.every(hasOnlySchemasForPrimitives), 'Do not use `oneOf` validation with non-primitive types!');
|
|
118
130
|
return new JsonSchemaAnyBuilder({
|
|
119
131
|
oneOf: schemas,
|
|
120
132
|
});
|
|
121
133
|
},
|
|
122
134
|
/**
|
|
123
|
-
*
|
|
135
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
136
|
+
* To validate objects, use `anyOfBy`.
|
|
137
|
+
*
|
|
138
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
139
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
140
|
+
* properly validate the same data over multiple schemas.
|
|
124
141
|
*
|
|
125
142
|
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
126
143
|
* Use `oneOf` when schemas are mutually exclusive.
|
|
127
144
|
*/
|
|
128
145
|
anyOf(items) {
|
|
129
146
|
const schemas = items.map(b => b.build());
|
|
147
|
+
_assert(schemas.every(hasOnlySchemasForPrimitives), 'Do not use `anyOf` validation with non-primitive types!');
|
|
130
148
|
return new JsonSchemaAnyBuilder({
|
|
131
149
|
anyOf: schemas,
|
|
132
150
|
});
|
|
133
151
|
},
|
|
152
|
+
anyOfBy(propertyName, schemaDictionary) {
|
|
153
|
+
return new JsonSchemaAnyOfByBuilder(propertyName, schemaDictionary);
|
|
154
|
+
},
|
|
134
155
|
and() {
|
|
135
156
|
return {
|
|
136
157
|
silentBob: () => {
|
|
@@ -800,6 +821,22 @@ export class JsonSchemaTupleBuilder extends JsonSchemaAnyBuilder {
|
|
|
800
821
|
this._items = items;
|
|
801
822
|
}
|
|
802
823
|
}
|
|
824
|
+
export class JsonSchemaAnyOfByBuilder extends JsonSchemaAnyBuilder {
|
|
825
|
+
constructor(propertyName, schemaDictionary) {
|
|
826
|
+
const builtSchemaDictionary = {};
|
|
827
|
+
for (const [key, schema] of Object.entries(schemaDictionary)) {
|
|
828
|
+
builtSchemaDictionary[key] = schema.build();
|
|
829
|
+
}
|
|
830
|
+
super({
|
|
831
|
+
type: 'object',
|
|
832
|
+
hasIsOfTypeCheck: true,
|
|
833
|
+
anyOfBy: {
|
|
834
|
+
propertyName,
|
|
835
|
+
schemaDictionary: builtSchemaDictionary,
|
|
836
|
+
},
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
}
|
|
803
840
|
function object(props) {
|
|
804
841
|
return new JsonSchemaObjectBuilder(props);
|
|
805
842
|
}
|
|
@@ -862,3 +899,18 @@ function withEnumKeys(keys, schema) {
|
|
|
862
899
|
const props = Object.fromEntries(typedValues.map(key => [key, schema]));
|
|
863
900
|
return new JsonSchemaObjectBuilder(props, { hasIsOfTypeCheck: false });
|
|
864
901
|
}
|
|
902
|
+
function hasOnlySchemasForPrimitives(schema) {
|
|
903
|
+
if (Array.isArray(schema.type)) {
|
|
904
|
+
schema.type.every(type => ['string', 'number', 'integer', 'boolean', 'null'].includes(type));
|
|
905
|
+
}
|
|
906
|
+
else if (schema.anyOf) {
|
|
907
|
+
return schema.anyOf.every(hasOnlySchemasForPrimitives);
|
|
908
|
+
}
|
|
909
|
+
else if (schema.oneOf) {
|
|
910
|
+
return schema.oneOf.every(hasOnlySchemasForPrimitives);
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
return !!schema.type && ['string', 'number', 'integer', 'boolean', 'null'].includes(schema.type);
|
|
914
|
+
}
|
|
915
|
+
return false;
|
|
916
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { _isBetween, _lazyValue } from '@naturalcycles/js-lib'
|
|
2
|
-
import { Set2 } from '@naturalcycles/js-lib/object'
|
|
2
|
+
import { _mapObject, Set2 } from '@naturalcycles/js-lib/object'
|
|
3
3
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string'
|
|
4
4
|
import type { AnyObject } from '@naturalcycles/js-lib/types'
|
|
5
5
|
import { Ajv2020, type Options, type ValidateFunction } from 'ajv/dist/2020.js'
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
JsonSchemaIsoDateOptions,
|
|
9
9
|
JsonSchemaIsoMonthOptions,
|
|
10
10
|
JsonSchemaStringEmailOptions,
|
|
11
|
+
JsonSchemaTerminal,
|
|
11
12
|
} from './jsonSchemaBuilder.js'
|
|
12
13
|
|
|
13
14
|
/* eslint-disable @typescript-eslint/prefer-string-starts-ends-with */
|
|
@@ -542,6 +543,48 @@ export function createAjv(opt?: Options): Ajv2020 {
|
|
|
542
543
|
},
|
|
543
544
|
})
|
|
544
545
|
|
|
546
|
+
ajv.addKeyword({
|
|
547
|
+
keyword: 'anyOfBy',
|
|
548
|
+
type: 'object',
|
|
549
|
+
modifying: true,
|
|
550
|
+
errors: true,
|
|
551
|
+
schemaType: 'object',
|
|
552
|
+
compile(config, _parentSchema, _it) {
|
|
553
|
+
const { propertyName, schemaDictionary } = config
|
|
554
|
+
|
|
555
|
+
const isValidFnByKey: Record<any, ValidateFunction> = _mapObject(
|
|
556
|
+
schemaDictionary as Record<any, JsonSchemaTerminal<any, any, any>>,
|
|
557
|
+
(key, value) => {
|
|
558
|
+
return [key, ajv.compile(value)]
|
|
559
|
+
},
|
|
560
|
+
)
|
|
561
|
+
|
|
562
|
+
function validate(data: AnyObject, ctx: any): boolean {
|
|
563
|
+
if (typeof data !== 'object' || data === null) return true
|
|
564
|
+
|
|
565
|
+
const determinant = data[propertyName]
|
|
566
|
+
const isValidFn = isValidFnByKey[determinant]
|
|
567
|
+
if (!isValidFn) {
|
|
568
|
+
;(validate as any).errors = [
|
|
569
|
+
{
|
|
570
|
+
instancePath: ctx?.instancePath ?? '',
|
|
571
|
+
message: `could not find a suitable schema to validate against based on "${propertyName}"`,
|
|
572
|
+
},
|
|
573
|
+
]
|
|
574
|
+
return false
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
const result = isValidFn(data)
|
|
578
|
+
if (!result) {
|
|
579
|
+
;(validate as any).errors = isValidFn.errors
|
|
580
|
+
}
|
|
581
|
+
return result
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return validate
|
|
585
|
+
},
|
|
586
|
+
})
|
|
587
|
+
|
|
545
588
|
return ajv
|
|
546
589
|
}
|
|
547
590
|
|
|
@@ -188,19 +188,40 @@ export const j = {
|
|
|
188
188
|
return new JsonSchemaEnumBuilder(enumValues as any, baseType, opt)
|
|
189
189
|
},
|
|
190
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
193
|
+
* To validate objects, use `anyOfBy`.
|
|
194
|
+
*
|
|
195
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
196
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
197
|
+
* properly validate the same data over multiple schemas.
|
|
198
|
+
*
|
|
199
|
+
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
200
|
+
* Use `oneOf` when schemas are mutually exclusive.
|
|
201
|
+
*/
|
|
191
202
|
oneOf<
|
|
192
203
|
B extends readonly JsonSchemaAnyBuilder<any, any, boolean>[],
|
|
193
204
|
IN = BuilderInUnion<B>,
|
|
194
205
|
OUT = BuilderOutUnion<B>,
|
|
195
206
|
>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false> {
|
|
196
207
|
const schemas = items.map(b => b.build())
|
|
208
|
+
_assert(
|
|
209
|
+
schemas.every(hasOnlySchemasForPrimitives),
|
|
210
|
+
'Do not use `oneOf` validation with non-primitive types!',
|
|
211
|
+
)
|
|
212
|
+
|
|
197
213
|
return new JsonSchemaAnyBuilder<IN, OUT, false>({
|
|
198
214
|
oneOf: schemas,
|
|
199
215
|
})
|
|
200
216
|
},
|
|
201
217
|
|
|
202
218
|
/**
|
|
203
|
-
*
|
|
219
|
+
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
220
|
+
* To validate objects, use `anyOfBy`.
|
|
221
|
+
*
|
|
222
|
+
* Our Ajv is configured to strip unexpected properties from objects,
|
|
223
|
+
* and since Ajv is mutating the input, this means that it cannot
|
|
224
|
+
* properly validate the same data over multiple schemas.
|
|
204
225
|
*
|
|
205
226
|
* Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
|
|
206
227
|
* Use `oneOf` when schemas are mutually exclusive.
|
|
@@ -211,11 +232,25 @@ export const j = {
|
|
|
211
232
|
OUT = BuilderOutUnion<B>,
|
|
212
233
|
>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false> {
|
|
213
234
|
const schemas = items.map(b => b.build())
|
|
235
|
+
_assert(
|
|
236
|
+
schemas.every(hasOnlySchemasForPrimitives),
|
|
237
|
+
'Do not use `anyOf` validation with non-primitive types!',
|
|
238
|
+
)
|
|
239
|
+
|
|
214
240
|
return new JsonSchemaAnyBuilder<IN, OUT, false>({
|
|
215
241
|
anyOf: schemas,
|
|
216
242
|
})
|
|
217
243
|
},
|
|
218
244
|
|
|
245
|
+
anyOfBy<
|
|
246
|
+
P extends string,
|
|
247
|
+
D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>,
|
|
248
|
+
IN = AnyOfByIn<D>,
|
|
249
|
+
OUT = AnyOfByOut<D>,
|
|
250
|
+
>(propertyName: P, schemaDictionary: D): JsonSchemaAnyOfByBuilder<IN, OUT, P> {
|
|
251
|
+
return new JsonSchemaAnyOfByBuilder<IN, OUT, P>(propertyName, schemaDictionary)
|
|
252
|
+
},
|
|
253
|
+
|
|
219
254
|
and() {
|
|
220
255
|
return {
|
|
221
256
|
silentBob: () => {
|
|
@@ -1204,6 +1239,34 @@ export class JsonSchemaTupleBuilder<
|
|
|
1204
1239
|
}
|
|
1205
1240
|
}
|
|
1206
1241
|
|
|
1242
|
+
export class JsonSchemaAnyOfByBuilder<
|
|
1243
|
+
IN,
|
|
1244
|
+
OUT,
|
|
1245
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1246
|
+
_P extends string = string,
|
|
1247
|
+
> extends JsonSchemaAnyBuilder<AnyOfByInput<IN, _P> | IN, OUT, false> {
|
|
1248
|
+
declare in: IN
|
|
1249
|
+
|
|
1250
|
+
constructor(
|
|
1251
|
+
propertyName: string,
|
|
1252
|
+
schemaDictionary: Record<PropertyKey, JsonSchemaTerminal<any, any, any>>,
|
|
1253
|
+
) {
|
|
1254
|
+
const builtSchemaDictionary: Record<string, JsonSchema> = {}
|
|
1255
|
+
for (const [key, schema] of Object.entries(schemaDictionary)) {
|
|
1256
|
+
builtSchemaDictionary[key] = schema.build()
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
super({
|
|
1260
|
+
type: 'object',
|
|
1261
|
+
hasIsOfTypeCheck: true,
|
|
1262
|
+
anyOfBy: {
|
|
1263
|
+
propertyName,
|
|
1264
|
+
schemaDictionary: builtSchemaDictionary,
|
|
1265
|
+
},
|
|
1266
|
+
})
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1207
1270
|
type EnumBaseType = 'string' | 'number' | 'other'
|
|
1208
1271
|
|
|
1209
1272
|
export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
@@ -1283,6 +1346,10 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
1283
1346
|
keySchema?: JsonSchema
|
|
1284
1347
|
minProperties2?: number
|
|
1285
1348
|
exclusiveProperties?: (readonly string[])[]
|
|
1349
|
+
anyOfBy?: {
|
|
1350
|
+
propertyName: string
|
|
1351
|
+
schemaDictionary: Record<string, JsonSchema>
|
|
1352
|
+
}
|
|
1286
1353
|
}
|
|
1287
1354
|
|
|
1288
1355
|
function object(props: AnyObject): never
|
|
@@ -1448,6 +1515,20 @@ function withEnumKeys<
|
|
|
1448
1515
|
>(props, { hasIsOfTypeCheck: false })
|
|
1449
1516
|
}
|
|
1450
1517
|
|
|
1518
|
+
function hasOnlySchemasForPrimitives(schema: JsonSchema): boolean {
|
|
1519
|
+
if (Array.isArray(schema.type)) {
|
|
1520
|
+
schema.type.every(type => ['string', 'number', 'integer', 'boolean', 'null'].includes(type))
|
|
1521
|
+
} else if (schema.anyOf) {
|
|
1522
|
+
return schema.anyOf.every(hasOnlySchemasForPrimitives)
|
|
1523
|
+
} else if (schema.oneOf) {
|
|
1524
|
+
return schema.oneOf.every(hasOnlySchemasForPrimitives)
|
|
1525
|
+
} else {
|
|
1526
|
+
return !!schema.type && ['string', 'number', 'integer', 'boolean', 'null'].includes(schema.type)
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
return false
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1451
1532
|
type Expand<T> = { [K in keyof T]: T[K] }
|
|
1452
1533
|
|
|
1453
1534
|
type StripIndexSignatureDeep<T> = T extends readonly unknown[]
|
|
@@ -1511,6 +1592,20 @@ type BuilderInUnion<B extends readonly JsonSchemaAnyBuilder<any, any, any>[]> =
|
|
|
1511
1592
|
[K in keyof B]: B[K] extends JsonSchemaAnyBuilder<infer I, any, any> ? I : never
|
|
1512
1593
|
}[number]
|
|
1513
1594
|
|
|
1595
|
+
type AnyOfByIn<D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>> = {
|
|
1596
|
+
[K in keyof D]: D[K] extends JsonSchemaTerminal<infer I, any, any> ? I : never
|
|
1597
|
+
}[keyof D]
|
|
1598
|
+
|
|
1599
|
+
type AnyOfByOut<D extends Record<PropertyKey, JsonSchemaTerminal<any, any, any>>> = {
|
|
1600
|
+
[K in keyof D]: D[K] extends JsonSchemaTerminal<any, infer O, any> ? O : never
|
|
1601
|
+
}[keyof D]
|
|
1602
|
+
|
|
1603
|
+
type AnyOfByDiscriminant<IN, P extends string> = IN extends { [K in P]: infer V } ? V : never
|
|
1604
|
+
|
|
1605
|
+
type AnyOfByInput<IN, P extends string, D = AnyOfByDiscriminant<IN, P>> = IN extends unknown
|
|
1606
|
+
? Omit<Partial<IN>, P> & { [K in P]?: D }
|
|
1607
|
+
: never
|
|
1608
|
+
|
|
1514
1609
|
type BuilderFor<T> = JsonSchemaAnyBuilder<any, T, any>
|
|
1515
1610
|
|
|
1516
1611
|
interface JsonBuilderRuleOpt {
|