@naturalcycles/nodejs-lib 15.85.0 → 15.87.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,4 +1,4 @@
|
|
|
1
|
-
import { _isBetween, _lazyValue } from '@naturalcycles/js-lib';
|
|
1
|
+
import { _isBetween, _lazyValue, _round } from '@naturalcycles/js-lib';
|
|
2
2
|
import { _assert } from '@naturalcycles/js-lib/error';
|
|
3
3
|
import { _deepCopy, _mapObject, Set2 } from '@naturalcycles/js-lib/object';
|
|
4
4
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string';
|
|
@@ -417,6 +417,15 @@ export function createAjv(opt) {
|
|
|
417
417
|
return validate;
|
|
418
418
|
},
|
|
419
419
|
});
|
|
420
|
+
// Validates that the value is undefined. Used in record/stringMap with optional value schemas
|
|
421
|
+
// to allow undefined values in patternProperties via anyOf.
|
|
422
|
+
ajv.addKeyword({
|
|
423
|
+
keyword: 'isUndefined',
|
|
424
|
+
modifying: false,
|
|
425
|
+
errors: false,
|
|
426
|
+
schemaType: 'boolean',
|
|
427
|
+
validate: (_schema, data) => data === undefined,
|
|
428
|
+
});
|
|
420
429
|
// This is added because Ajv validates the `min/maxProperties` before validating the properties.
|
|
421
430
|
// So, in case of `minProperties(1)` and `{ foo: 'bar' }` Ajv will let it pass, even
|
|
422
431
|
// if the property validation would strip `foo` from the data.
|
|
@@ -560,6 +569,20 @@ export function createAjv(opt) {
|
|
|
560
569
|
return validate;
|
|
561
570
|
},
|
|
562
571
|
});
|
|
572
|
+
ajv.addKeyword({
|
|
573
|
+
keyword: 'precision',
|
|
574
|
+
type: ['number'],
|
|
575
|
+
modifying: true,
|
|
576
|
+
errors: false,
|
|
577
|
+
schemaType: 'number',
|
|
578
|
+
validate: function validate(numberOfDigits, data, _schema, ctx) {
|
|
579
|
+
if (!numberOfDigits)
|
|
580
|
+
return true;
|
|
581
|
+
_assert(ctx?.parentData && ctx.parentDataProperty !== undefined, 'You should only use `precision(n) on a property of an object, or on an element of an array due to Ajv mutation issues.');
|
|
582
|
+
ctx.parentData[ctx.parentDataProperty] = _round(data, 10 ** (-1 * numberOfDigits));
|
|
583
|
+
return true;
|
|
584
|
+
},
|
|
585
|
+
});
|
|
563
586
|
return ajv;
|
|
564
587
|
}
|
|
565
588
|
const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
@@ -279,6 +279,12 @@ export declare class JsonSchemaNumberBuilder<IN extends number | undefined = num
|
|
|
279
279
|
unixTimestamp2000Millis(): JsonSchemaNumberBuilder<UnixTimestampMillis, UnixTimestampMillis, Opt>;
|
|
280
280
|
utcOffset(): this;
|
|
281
281
|
utcOffsetHour(): this;
|
|
282
|
+
/**
|
|
283
|
+
* Specify the precision of the floating point numbers by the number of digits after the ".".
|
|
284
|
+
* Excess digits will be cut-off when the current schema is nested in an object or array schema,
|
|
285
|
+
* due to how mutability works in Ajv.
|
|
286
|
+
*/
|
|
287
|
+
precision(numberOfDigits: number): this;
|
|
282
288
|
}
|
|
283
289
|
export declare class JsonSchemaBooleanBuilder<IN extends boolean | undefined = boolean, OUT = IN, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
|
|
284
290
|
constructor();
|
|
@@ -505,6 +511,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
505
511
|
errorMessages?: StringMap<string>;
|
|
506
512
|
optionalValues?: (string | number | boolean | null)[];
|
|
507
513
|
keySchema?: JsonSchema;
|
|
514
|
+
isUndefined?: true;
|
|
508
515
|
minProperties2?: number;
|
|
509
516
|
exclusiveProperties?: (readonly string[])[];
|
|
510
517
|
anyOfBy?: {
|
|
@@ -512,6 +519,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
512
519
|
schemaDictionary: Record<string, JsonSchema>;
|
|
513
520
|
};
|
|
514
521
|
anyOfThese?: JsonSchema[];
|
|
522
|
+
precision?: number;
|
|
515
523
|
}
|
|
516
524
|
declare function object(props: AnyObject): never;
|
|
517
525
|
declare function object<IN extends AnyObject>(props: {
|
|
@@ -32,11 +32,15 @@ export const j = {
|
|
|
32
32
|
return j.object({}).allowAdditionalProperties();
|
|
33
33
|
},
|
|
34
34
|
stringMap(schema) {
|
|
35
|
+
const isValueOptional = schema.getSchema().optionalField;
|
|
35
36
|
const builtSchema = schema.build();
|
|
37
|
+
const finalValueSchema = isValueOptional
|
|
38
|
+
? { anyOf: [{ isUndefined: true }, builtSchema] }
|
|
39
|
+
: builtSchema;
|
|
36
40
|
return new JsonSchemaObjectBuilder({}, {
|
|
37
41
|
hasIsOfTypeCheck: false,
|
|
38
42
|
patternProperties: {
|
|
39
|
-
'^.+$':
|
|
43
|
+
'^.+$': finalValueSchema,
|
|
40
44
|
},
|
|
41
45
|
});
|
|
42
46
|
},
|
|
@@ -632,6 +636,14 @@ export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
|
|
|
632
636
|
utcOffsetHour() {
|
|
633
637
|
return this.integer().min(-12).max(14);
|
|
634
638
|
}
|
|
639
|
+
/**
|
|
640
|
+
* Specify the precision of the floating point numbers by the number of digits after the ".".
|
|
641
|
+
* Excess digits will be cut-off when the current schema is nested in an object or array schema,
|
|
642
|
+
* due to how mutability works in Ajv.
|
|
643
|
+
*/
|
|
644
|
+
precision(numberOfDigits) {
|
|
645
|
+
return this.cloneAndUpdateSchema({ precision: numberOfDigits });
|
|
646
|
+
}
|
|
635
647
|
}
|
|
636
648
|
export class JsonSchemaBooleanBuilder extends JsonSchemaAnyBuilder {
|
|
637
649
|
constructor() {
|
|
@@ -971,12 +983,19 @@ function objectDbEntity(props) {
|
|
|
971
983
|
}
|
|
972
984
|
function record(keySchema, valueSchema) {
|
|
973
985
|
const keyJsonSchema = keySchema.build();
|
|
986
|
+
// Check if value schema is optional before build() strips the optionalField flag
|
|
987
|
+
const isValueOptional = valueSchema.getSchema()
|
|
988
|
+
.optionalField;
|
|
974
989
|
const valueJsonSchema = valueSchema.build();
|
|
990
|
+
// When value schema is optional, wrap in anyOf to allow undefined values
|
|
991
|
+
const finalValueSchema = isValueOptional
|
|
992
|
+
? { anyOf: [{ isUndefined: true }, valueJsonSchema] }
|
|
993
|
+
: valueJsonSchema;
|
|
975
994
|
return new JsonSchemaObjectBuilder([], {
|
|
976
995
|
hasIsOfTypeCheck: false,
|
|
977
996
|
keySchema: keyJsonSchema,
|
|
978
997
|
patternProperties: {
|
|
979
|
-
['^.*$']:
|
|
998
|
+
['^.*$']: finalValueSchema,
|
|
980
999
|
},
|
|
981
1000
|
});
|
|
982
1001
|
}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _isBetween, _lazyValue } from '@naturalcycles/js-lib'
|
|
1
|
+
import { _isBetween, _lazyValue, _round } from '@naturalcycles/js-lib'
|
|
2
2
|
import { _assert } from '@naturalcycles/js-lib/error'
|
|
3
3
|
import { _deepCopy, _mapObject, Set2 } from '@naturalcycles/js-lib/object'
|
|
4
4
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string'
|
|
@@ -486,6 +486,16 @@ export function createAjv(opt?: Options): Ajv2020 {
|
|
|
486
486
|
},
|
|
487
487
|
})
|
|
488
488
|
|
|
489
|
+
// Validates that the value is undefined. Used in record/stringMap with optional value schemas
|
|
490
|
+
// to allow undefined values in patternProperties via anyOf.
|
|
491
|
+
ajv.addKeyword({
|
|
492
|
+
keyword: 'isUndefined',
|
|
493
|
+
modifying: false,
|
|
494
|
+
errors: false,
|
|
495
|
+
schemaType: 'boolean',
|
|
496
|
+
validate: (_schema: boolean, data: unknown) => data === undefined,
|
|
497
|
+
})
|
|
498
|
+
|
|
489
499
|
// This is added because Ajv validates the `min/maxProperties` before validating the properties.
|
|
490
500
|
// So, in case of `minProperties(1)` and `{ foo: 'bar' }` Ajv will let it pass, even
|
|
491
501
|
// if the property validation would strip `foo` from the data.
|
|
@@ -639,6 +649,26 @@ export function createAjv(opt?: Options): Ajv2020 {
|
|
|
639
649
|
},
|
|
640
650
|
})
|
|
641
651
|
|
|
652
|
+
ajv.addKeyword({
|
|
653
|
+
keyword: 'precision',
|
|
654
|
+
type: ['number'],
|
|
655
|
+
modifying: true,
|
|
656
|
+
errors: false,
|
|
657
|
+
schemaType: 'number',
|
|
658
|
+
validate: function validate(numberOfDigits: number, data: number, _schema, ctx) {
|
|
659
|
+
if (!numberOfDigits) return true
|
|
660
|
+
|
|
661
|
+
_assert(
|
|
662
|
+
ctx?.parentData && ctx.parentDataProperty !== undefined,
|
|
663
|
+
'You should only use `precision(n) on a property of an object, or on an element of an array due to Ajv mutation issues.',
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
ctx.parentData[ctx.parentDataProperty] = _round(data, 10 ** (-1 * numberOfDigits))
|
|
667
|
+
|
|
668
|
+
return true
|
|
669
|
+
},
|
|
670
|
+
})
|
|
671
|
+
|
|
642
672
|
return ajv
|
|
643
673
|
}
|
|
644
674
|
|
|
@@ -80,14 +80,18 @@ export const j = {
|
|
|
80
80
|
stringMap<S extends JsonSchemaTerminal<any, any, any>>(
|
|
81
81
|
schema: S,
|
|
82
82
|
): JsonSchemaObjectBuilder<StringMap<SchemaIn<S>>, StringMap<SchemaOut<S>>> {
|
|
83
|
+
const isValueOptional = schema.getSchema().optionalField
|
|
83
84
|
const builtSchema = schema.build()
|
|
85
|
+
const finalValueSchema: JsonSchema = isValueOptional
|
|
86
|
+
? { anyOf: [{ isUndefined: true }, builtSchema] }
|
|
87
|
+
: builtSchema
|
|
84
88
|
|
|
85
89
|
return new JsonSchemaObjectBuilder<StringMap<SchemaIn<S>>, StringMap<SchemaOut<S>>>(
|
|
86
90
|
{},
|
|
87
91
|
{
|
|
88
92
|
hasIsOfTypeCheck: false,
|
|
89
93
|
patternProperties: {
|
|
90
|
-
'^.+$':
|
|
94
|
+
'^.+$': finalValueSchema,
|
|
91
95
|
},
|
|
92
96
|
},
|
|
93
97
|
)
|
|
@@ -888,6 +892,15 @@ export class JsonSchemaNumberBuilder<
|
|
|
888
892
|
utcOffsetHour(): this {
|
|
889
893
|
return this.integer().min(-12).max(14)
|
|
890
894
|
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Specify the precision of the floating point numbers by the number of digits after the ".".
|
|
898
|
+
* Excess digits will be cut-off when the current schema is nested in an object or array schema,
|
|
899
|
+
* due to how mutability works in Ajv.
|
|
900
|
+
*/
|
|
901
|
+
precision(numberOfDigits: number): this {
|
|
902
|
+
return this.cloneAndUpdateSchema({ precision: numberOfDigits })
|
|
903
|
+
}
|
|
891
904
|
}
|
|
892
905
|
|
|
893
906
|
export class JsonSchemaBooleanBuilder<
|
|
@@ -1565,6 +1578,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
1565
1578
|
errorMessages?: StringMap<string>
|
|
1566
1579
|
optionalValues?: (string | number | boolean | null)[]
|
|
1567
1580
|
keySchema?: JsonSchema
|
|
1581
|
+
isUndefined?: true
|
|
1568
1582
|
minProperties2?: number
|
|
1569
1583
|
exclusiveProperties?: (readonly string[])[]
|
|
1570
1584
|
anyOfBy?: {
|
|
@@ -1572,6 +1586,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
1572
1586
|
schemaDictionary: Record<string, JsonSchema>
|
|
1573
1587
|
}
|
|
1574
1588
|
anyOfThese?: JsonSchema[]
|
|
1589
|
+
precision?: number
|
|
1575
1590
|
}
|
|
1576
1591
|
|
|
1577
1592
|
function object(props: AnyObject): never
|
|
@@ -1638,8 +1653,16 @@ function record<
|
|
|
1638
1653
|
false
|
|
1639
1654
|
> {
|
|
1640
1655
|
const keyJsonSchema = keySchema.build()
|
|
1656
|
+
// Check if value schema is optional before build() strips the optionalField flag
|
|
1657
|
+
const isValueOptional = (valueSchema as JsonSchemaTerminal<any, any, any>).getSchema()
|
|
1658
|
+
.optionalField
|
|
1641
1659
|
const valueJsonSchema = valueSchema.build()
|
|
1642
1660
|
|
|
1661
|
+
// When value schema is optional, wrap in anyOf to allow undefined values
|
|
1662
|
+
const finalValueSchema: JsonSchema = isValueOptional
|
|
1663
|
+
? { anyOf: [{ isUndefined: true }, valueJsonSchema] }
|
|
1664
|
+
: valueJsonSchema
|
|
1665
|
+
|
|
1643
1666
|
return new JsonSchemaObjectBuilder<
|
|
1644
1667
|
Opt extends true
|
|
1645
1668
|
? Partial<Record<SchemaIn<KS>, SchemaIn<VS>>>
|
|
@@ -1652,7 +1675,7 @@ function record<
|
|
|
1652
1675
|
hasIsOfTypeCheck: false,
|
|
1653
1676
|
keySchema: keyJsonSchema,
|
|
1654
1677
|
patternProperties: {
|
|
1655
|
-
['^.*$']:
|
|
1678
|
+
['^.*$']: finalValueSchema,
|
|
1656
1679
|
},
|
|
1657
1680
|
})
|
|
1658
1681
|
}
|