@naturalcycles/nodejs-lib 15.75.0 → 15.77.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.
|
@@ -448,6 +448,35 @@ export function createAjv(opt) {
|
|
|
448
448
|
return isValid;
|
|
449
449
|
},
|
|
450
450
|
});
|
|
451
|
+
ajv.addKeyword({
|
|
452
|
+
keyword: 'exclusiveProperties',
|
|
453
|
+
type: 'object',
|
|
454
|
+
modifying: false,
|
|
455
|
+
errors: true,
|
|
456
|
+
schemaType: 'array',
|
|
457
|
+
validate: function validate(exclusiveProperties, data, _schema, ctx) {
|
|
458
|
+
if (typeof data !== 'object')
|
|
459
|
+
return true;
|
|
460
|
+
for (const props of exclusiveProperties) {
|
|
461
|
+
let numberOfDefinedProperties = 0;
|
|
462
|
+
for (const prop of props) {
|
|
463
|
+
if (data[prop] !== undefined)
|
|
464
|
+
numberOfDefinedProperties++;
|
|
465
|
+
if (numberOfDefinedProperties > 1) {
|
|
466
|
+
;
|
|
467
|
+
validate.errors = [
|
|
468
|
+
{
|
|
469
|
+
instancePath: ctx?.instancePath ?? '',
|
|
470
|
+
message: `must have only one of the "${props.join(', ')}" properties`,
|
|
471
|
+
},
|
|
472
|
+
];
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return true;
|
|
478
|
+
},
|
|
479
|
+
});
|
|
451
480
|
return ajv;
|
|
452
481
|
}
|
|
453
482
|
const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { Set2 } from '@naturalcycles/js-lib/object';
|
|
2
2
|
import { type AnyObject, type BaseDBEntity, type IANATimezone, type Inclusiveness, type IsoDate, type IsoDateTime, type IsoMonth, type NumberEnum, type StringEnum, type StringMap, type UnixTimestamp, type UnixTimestampMillis } from '@naturalcycles/js-lib/types';
|
|
3
3
|
export declare const j: {
|
|
4
|
+
/**
|
|
5
|
+
* Matches literally any value - equivalent to TypeScript's `any` type.
|
|
6
|
+
* Use sparingly, as it bypasses type validation entirely.
|
|
7
|
+
*/
|
|
8
|
+
any(): JsonSchemaAnyBuilder<any, any, false>;
|
|
4
9
|
string(): JsonSchemaStringBuilder<string, string, false>;
|
|
5
10
|
number(): JsonSchemaNumberBuilder<number, number, false>;
|
|
6
11
|
boolean(): JsonSchemaBooleanBuilder<boolean, boolean, false>;
|
|
@@ -285,6 +290,7 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
|
|
|
285
290
|
} & {}, false>;
|
|
286
291
|
minProperties(minProperties: number): this;
|
|
287
292
|
maxProperties(maxProperties: number): this;
|
|
293
|
+
exclusiveProperties(propNames: readonly (keyof IN & string)[]): this;
|
|
288
294
|
}
|
|
289
295
|
interface JsonSchemaObjectBuilderOpts {
|
|
290
296
|
hasIsOfTypeCheck?: false;
|
|
@@ -409,6 +415,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
409
415
|
optionalValues?: (string | number | boolean)[];
|
|
410
416
|
keySchema?: JsonSchema;
|
|
411
417
|
minProperties2?: number;
|
|
418
|
+
exclusiveProperties?: (readonly string[])[];
|
|
412
419
|
}
|
|
413
420
|
declare function object(props: AnyObject): never;
|
|
414
421
|
declare function object<IN extends AnyObject>(props: {
|
|
@@ -9,6 +9,13 @@ import { BASE64URL_REGEX, COUNTRY_CODE_REGEX, CURRENCY_REGEX, IPV4_REGEX, IPV6_R
|
|
|
9
9
|
import { TIMEZONES } from '../timezones.js';
|
|
10
10
|
import { isEveryItemNumber, isEveryItemPrimitive, isEveryItemString, JSON_SCHEMA_ORDER, mergeJsonSchemaObjects, } from './jsonSchemaBuilder.util.js';
|
|
11
11
|
export const j = {
|
|
12
|
+
/**
|
|
13
|
+
* Matches literally any value - equivalent to TypeScript's `any` type.
|
|
14
|
+
* Use sparingly, as it bypasses type validation entirely.
|
|
15
|
+
*/
|
|
16
|
+
any() {
|
|
17
|
+
return new JsonSchemaAnyBuilder({});
|
|
18
|
+
},
|
|
12
19
|
string() {
|
|
13
20
|
return new JsonSchemaStringBuilder();
|
|
14
21
|
},
|
|
@@ -649,6 +656,10 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
|
|
|
649
656
|
maxProperties(maxProperties) {
|
|
650
657
|
return this.cloneAndUpdateSchema({ maxProperties });
|
|
651
658
|
}
|
|
659
|
+
exclusiveProperties(propNames) {
|
|
660
|
+
const exclusiveProperties = this.schema.exclusiveProperties ?? [];
|
|
661
|
+
return this.cloneAndUpdateSchema({ exclusiveProperties: [...exclusiveProperties, propNames] });
|
|
662
|
+
}
|
|
652
663
|
}
|
|
653
664
|
export class JsonSchemaObjectInferringBuilder extends JsonSchemaAnyBuilder {
|
|
654
665
|
constructor(props) {
|
package/package.json
CHANGED
|
@@ -513,6 +513,35 @@ export function createAjv(opt?: Options): Ajv2020 {
|
|
|
513
513
|
},
|
|
514
514
|
})
|
|
515
515
|
|
|
516
|
+
ajv.addKeyword({
|
|
517
|
+
keyword: 'exclusiveProperties',
|
|
518
|
+
type: 'object',
|
|
519
|
+
modifying: false,
|
|
520
|
+
errors: true,
|
|
521
|
+
schemaType: 'array',
|
|
522
|
+
validate: function validate(exclusiveProperties: string[][], data: AnyObject, _schema, ctx) {
|
|
523
|
+
if (typeof data !== 'object') return true
|
|
524
|
+
|
|
525
|
+
for (const props of exclusiveProperties) {
|
|
526
|
+
let numberOfDefinedProperties = 0
|
|
527
|
+
for (const prop of props) {
|
|
528
|
+
if (data[prop] !== undefined) numberOfDefinedProperties++
|
|
529
|
+
if (numberOfDefinedProperties > 1) {
|
|
530
|
+
;(validate as any).errors = [
|
|
531
|
+
{
|
|
532
|
+
instancePath: ctx?.instancePath ?? '',
|
|
533
|
+
message: `must have only one of the "${props.join(', ')}" properties`,
|
|
534
|
+
},
|
|
535
|
+
]
|
|
536
|
+
return false
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return true
|
|
542
|
+
},
|
|
543
|
+
})
|
|
544
|
+
|
|
516
545
|
return ajv
|
|
517
546
|
}
|
|
518
547
|
|
|
@@ -49,6 +49,14 @@ import {
|
|
|
49
49
|
} from './jsonSchemaBuilder.util.js'
|
|
50
50
|
|
|
51
51
|
export const j = {
|
|
52
|
+
/**
|
|
53
|
+
* Matches literally any value - equivalent to TypeScript's `any` type.
|
|
54
|
+
* Use sparingly, as it bypasses type validation entirely.
|
|
55
|
+
*/
|
|
56
|
+
any(): JsonSchemaAnyBuilder<any, any, false> {
|
|
57
|
+
return new JsonSchemaAnyBuilder({})
|
|
58
|
+
},
|
|
59
|
+
|
|
52
60
|
string(): JsonSchemaStringBuilder<string, string, false> {
|
|
53
61
|
return new JsonSchemaStringBuilder()
|
|
54
62
|
},
|
|
@@ -950,6 +958,11 @@ export class JsonSchemaObjectBuilder<
|
|
|
950
958
|
maxProperties(maxProperties: number): this {
|
|
951
959
|
return this.cloneAndUpdateSchema({ maxProperties })
|
|
952
960
|
}
|
|
961
|
+
|
|
962
|
+
exclusiveProperties(propNames: readonly (keyof IN & string)[]): this {
|
|
963
|
+
const exclusiveProperties = this.schema.exclusiveProperties ?? []
|
|
964
|
+
return this.cloneAndUpdateSchema({ exclusiveProperties: [...exclusiveProperties, propNames] })
|
|
965
|
+
}
|
|
953
966
|
}
|
|
954
967
|
|
|
955
968
|
interface JsonSchemaObjectBuilderOpts {
|
|
@@ -1264,6 +1277,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
1264
1277
|
optionalValues?: (string | number | boolean)[]
|
|
1265
1278
|
keySchema?: JsonSchema
|
|
1266
1279
|
minProperties2?: number
|
|
1280
|
+
exclusiveProperties?: (readonly string[])[]
|
|
1267
1281
|
}
|
|
1268
1282
|
|
|
1269
1283
|
function object(props: AnyObject): never
|