@naturalcycles/nodejs-lib 15.76.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];
@@ -290,6 +290,7 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
290
290
  } & {}, false>;
291
291
  minProperties(minProperties: number): this;
292
292
  maxProperties(maxProperties: number): this;
293
+ exclusiveProperties(propNames: readonly (keyof IN & string)[]): this;
293
294
  }
294
295
  interface JsonSchemaObjectBuilderOpts {
295
296
  hasIsOfTypeCheck?: false;
@@ -414,6 +415,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
414
415
  optionalValues?: (string | number | boolean)[];
415
416
  keySchema?: JsonSchema;
416
417
  minProperties2?: number;
418
+ exclusiveProperties?: (readonly string[])[];
417
419
  }
418
420
  declare function object(props: AnyObject): never;
419
421
  declare function object<IN extends AnyObject>(props: {
@@ -656,6 +656,10 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
656
656
  maxProperties(maxProperties) {
657
657
  return this.cloneAndUpdateSchema({ maxProperties });
658
658
  }
659
+ exclusiveProperties(propNames) {
660
+ const exclusiveProperties = this.schema.exclusiveProperties ?? [];
661
+ return this.cloneAndUpdateSchema({ exclusiveProperties: [...exclusiveProperties, propNames] });
662
+ }
659
663
  }
660
664
  export class JsonSchemaObjectInferringBuilder extends JsonSchemaAnyBuilder {
661
665
  constructor(props) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.76.0",
4
+ "version": "15.77.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -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
 
@@ -958,6 +958,11 @@ export class JsonSchemaObjectBuilder<
958
958
  maxProperties(maxProperties: number): this {
959
959
  return this.cloneAndUpdateSchema({ maxProperties })
960
960
  }
961
+
962
+ exclusiveProperties(propNames: readonly (keyof IN & string)[]): this {
963
+ const exclusiveProperties = this.schema.exclusiveProperties ?? []
964
+ return this.cloneAndUpdateSchema({ exclusiveProperties: [...exclusiveProperties, propNames] })
965
+ }
961
966
  }
962
967
 
963
968
  interface JsonSchemaObjectBuilderOpts {
@@ -1272,6 +1277,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
1272
1277
  optionalValues?: (string | number | boolean)[]
1273
1278
  keySchema?: JsonSchema
1274
1279
  minProperties2?: number
1280
+ exclusiveProperties?: (readonly string[])[]
1275
1281
  }
1276
1282
 
1277
1283
  function object(props: AnyObject): never