@naturalcycles/nodejs-lib 15.127.0 → 15.129.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.
- package/dist/cache/lruMemoCache.d.ts +12 -1
- package/dist/cache/lruMemoCache.js +24 -0
- package/dist/validation/ajv/getAjv.js +11 -0
- package/dist/validation/ajv/index.d.ts +1 -0
- package/dist/validation/ajv/index.js +1 -0
- package/dist/validation/ajv/jSchema.d.ts +6 -1
- package/dist/validation/ajv/jSchema.js +22 -8
- package/dist/validation/ajv/jsonSchemaBuilder.util.d.ts +9 -0
- package/dist/validation/ajv/jsonSchemaBuilder.util.js +14 -0
- package/package.json +1 -1
- package/src/cache/lruMemoCache.ts +31 -1
- package/src/validation/ajv/getAjv.ts +13 -0
- package/src/validation/ajv/index.ts +1 -0
- package/src/validation/ajv/jSchema.ts +31 -8
- package/src/validation/ajv/jsonSchemaBuilder.util.ts +16 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MemoCache } from '@naturalcycles/js-lib/decorators';
|
|
1
|
+
import type { AsyncMemoCache, MemoCache } from '@naturalcycles/js-lib/decorators';
|
|
2
2
|
import { LRUCache } from 'lru-cache';
|
|
3
3
|
export type LRUMemoCacheOptions<KEY, VALUE> = Partial<LRUCache.Options<KEY, VALUE, any>>;
|
|
4
4
|
/**
|
|
@@ -16,3 +16,14 @@ export declare class LRUMemoCache<KEY = any, VALUE = any> implements MemoCache<K
|
|
|
16
16
|
set(k: any, v: any): void;
|
|
17
17
|
clear(): void;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Same as LRUMemoCache, but implements AsyncMemoCache interface, for when you need it.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LRUAsyncMemoCache<KEY = any, VALUE = any> implements AsyncMemoCache<KEY, VALUE> {
|
|
23
|
+
constructor(opt: LRUMemoCacheOptions<KEY, VALUE>);
|
|
24
|
+
private lru;
|
|
25
|
+
has(k: any): Promise<boolean>;
|
|
26
|
+
get(k: any): Promise<any>;
|
|
27
|
+
set(k: any, v: any): Promise<void>;
|
|
28
|
+
clear(): Promise<void>;
|
|
29
|
+
}
|
|
@@ -27,3 +27,27 @@ export class LRUMemoCache {
|
|
|
27
27
|
this.lru.clear();
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Same as LRUMemoCache, but implements AsyncMemoCache interface, for when you need it.
|
|
32
|
+
*/
|
|
33
|
+
export class LRUAsyncMemoCache {
|
|
34
|
+
constructor(opt) {
|
|
35
|
+
this.lru = new LRUCache({
|
|
36
|
+
max: 100,
|
|
37
|
+
...opt,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
lru;
|
|
41
|
+
async has(k) {
|
|
42
|
+
return this.lru.has(k);
|
|
43
|
+
}
|
|
44
|
+
async get(k) {
|
|
45
|
+
return this.lru.get(k);
|
|
46
|
+
}
|
|
47
|
+
async set(k, v) {
|
|
48
|
+
this.lru.set(k, v);
|
|
49
|
+
}
|
|
50
|
+
async clear() {
|
|
51
|
+
this.lru.clear();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -4,6 +4,7 @@ import { _deepCopy, _mapObject, Set2 } from '@naturalcycles/js-lib/object';
|
|
|
4
4
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string';
|
|
5
5
|
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
6
6
|
import { validTLDs } from '../tlds.js';
|
|
7
|
+
import { jFormats } from './jsonSchemaBuilder.util.js';
|
|
7
8
|
// oxlint-disable unicorn/prefer-code-point
|
|
8
9
|
const AJV_OPTIONS = {
|
|
9
10
|
removeAdditional: true,
|
|
@@ -371,6 +372,16 @@ export function createAjv(opt) {
|
|
|
371
372
|
return false;
|
|
372
373
|
},
|
|
373
374
|
});
|
|
375
|
+
// Annotation only (the values are validated by `enum`), registered so strict mode doesn't reject it
|
|
376
|
+
ajv.addKeyword({
|
|
377
|
+
keyword: 'enumNames',
|
|
378
|
+
schemaType: 'array',
|
|
379
|
+
});
|
|
380
|
+
// Annotation only (validated by the custom keywords, e.g `IsoDate`).
|
|
381
|
+
// `true` makes Ajv skip the format check, while unknown formats would throw in strict mode.
|
|
382
|
+
for (const format of jFormats) {
|
|
383
|
+
ajv.addFormat(format, true);
|
|
384
|
+
}
|
|
374
385
|
ajv.addKeyword({
|
|
375
386
|
keyword: 'errorMessages',
|
|
376
387
|
schemaType: 'object',
|
|
@@ -423,7 +423,7 @@ declare class JSet2Builder<OUT, Opt> extends JBuilder<Set2<OUT>, Opt> {
|
|
|
423
423
|
max(maxItems: number): this;
|
|
424
424
|
}
|
|
425
425
|
export declare class JEnum<OUT extends string | number | boolean | null, Opt extends boolean = false> extends JBuilder<OUT, Opt> {
|
|
426
|
-
constructor(enumValues: readonly OUT[], baseType: EnumBaseType, opt?: JsonBuilderRuleOpt);
|
|
426
|
+
constructor(enumValues: readonly OUT[], baseType: EnumBaseType, opt?: JsonBuilderRuleOpt, enumNames?: readonly string[]);
|
|
427
427
|
branded<B extends OUT>(): JEnum<B, Opt>;
|
|
428
428
|
}
|
|
429
429
|
export declare class JTuple<ITEMS extends JSchema<any, any>[]> extends JBuilder<TupleOut<ITEMS>, false> {
|
|
@@ -595,6 +595,11 @@ export interface JsonSchema<OUT = unknown> {
|
|
|
595
595
|
maxItems?: number;
|
|
596
596
|
uniqueItems?: boolean;
|
|
597
597
|
enum?: any;
|
|
598
|
+
/**
|
|
599
|
+
* Member names of a NumberEnum, aligned by index with `enum`.
|
|
600
|
+
* Annotation only (not validated), lets consumers render `1` as e.g `PREVENT`.
|
|
601
|
+
*/
|
|
602
|
+
enumNames?: readonly string[];
|
|
598
603
|
hasIsOfTypeCheck?: boolean;
|
|
599
604
|
email?: JsonSchemaStringEmailOptions;
|
|
600
605
|
Set2?: JsonSchema;
|
|
@@ -113,6 +113,7 @@ export const j = {
|
|
|
113
113
|
},
|
|
114
114
|
enum(input, opt) {
|
|
115
115
|
let enumValues;
|
|
116
|
+
let enumNames;
|
|
116
117
|
let baseType = 'other';
|
|
117
118
|
if (Array.isArray(input)) {
|
|
118
119
|
enumValues = input;
|
|
@@ -126,7 +127,11 @@ export const j = {
|
|
|
126
127
|
else if (typeof input === 'object') {
|
|
127
128
|
const enumType = getEnumType(input);
|
|
128
129
|
if (enumType === 'NumberEnum') {
|
|
129
|
-
|
|
130
|
+
// Not via _numberEnumKeys: it misses `_enum()` objects (no reverse mapping)
|
|
131
|
+
// and misaligns with the values when members aren't declared in ascending order
|
|
132
|
+
const numberEntries = Object.entries(input).filter(([, value]) => typeof value === 'number');
|
|
133
|
+
enumValues = numberEntries.map(([, value]) => value);
|
|
134
|
+
enumNames = numberEntries.map(([name]) => name);
|
|
130
135
|
baseType = 'number';
|
|
131
136
|
}
|
|
132
137
|
else if (enumType === 'StringEnum') {
|
|
@@ -135,7 +140,7 @@ export const j = {
|
|
|
135
140
|
}
|
|
136
141
|
}
|
|
137
142
|
_assert(enumValues, 'Unsupported enum input');
|
|
138
|
-
return new JEnum(enumValues, baseType, opt);
|
|
143
|
+
return new JEnum(enumValues, baseType, opt, enumNames);
|
|
139
144
|
},
|
|
140
145
|
/**
|
|
141
146
|
* Use only with primitive values, otherwise this function will throw to avoid bugs.
|
|
@@ -601,11 +606,15 @@ export class JString extends JBuilder {
|
|
|
601
606
|
return new JIsoDate();
|
|
602
607
|
}
|
|
603
608
|
isoDateTime() {
|
|
604
|
-
return this.cloneAndUpdateSchema({
|
|
609
|
+
return this.cloneAndUpdateSchema({
|
|
610
|
+
format: 'IsoDateTime',
|
|
611
|
+
IsoDateTime: true,
|
|
612
|
+
}).branded();
|
|
605
613
|
}
|
|
606
614
|
isoMonth() {
|
|
607
615
|
return new JBuilder({
|
|
608
616
|
type: 'string',
|
|
617
|
+
format: 'IsoMonth',
|
|
609
618
|
IsoMonth: {},
|
|
610
619
|
});
|
|
611
620
|
}
|
|
@@ -674,6 +683,7 @@ export class JIsoDate extends JBuilder {
|
|
|
674
683
|
constructor() {
|
|
675
684
|
super({
|
|
676
685
|
type: 'string',
|
|
686
|
+
format: 'IsoDate',
|
|
677
687
|
IsoDate: {},
|
|
678
688
|
});
|
|
679
689
|
}
|
|
@@ -771,16 +781,18 @@ export class JNumber extends JBuilder {
|
|
|
771
781
|
return this;
|
|
772
782
|
}
|
|
773
783
|
unixTimestamp() {
|
|
774
|
-
return this.integer().branded();
|
|
784
|
+
return this.integer().cloneAndUpdateSchema({ format: 'UnixTimestamp' }).branded();
|
|
775
785
|
}
|
|
776
786
|
unixTimestamp2000() {
|
|
777
|
-
return this.
|
|
787
|
+
return this.unixTimestamp().min(TS_2000).max(TS_2500);
|
|
778
788
|
}
|
|
779
789
|
unixTimestampMillis() {
|
|
780
|
-
return this.integer()
|
|
790
|
+
return this.integer()
|
|
791
|
+
.cloneAndUpdateSchema({ format: 'UnixTimestampMillis' })
|
|
792
|
+
.branded();
|
|
781
793
|
}
|
|
782
794
|
unixTimestamp2000Millis() {
|
|
783
|
-
return this.
|
|
795
|
+
return this.unixTimestampMillis().min(TS_2000_MILLIS).max(TS_2500_MILLIS);
|
|
784
796
|
}
|
|
785
797
|
utcOffset() {
|
|
786
798
|
return this.integer()
|
|
@@ -949,8 +961,10 @@ class JSet2Builder extends JBuilder {
|
|
|
949
961
|
}
|
|
950
962
|
}
|
|
951
963
|
export class JEnum extends JBuilder {
|
|
952
|
-
constructor(enumValues, baseType, opt) {
|
|
964
|
+
constructor(enumValues, baseType, opt, enumNames) {
|
|
953
965
|
const jsonSchema = { enum: enumValues };
|
|
966
|
+
if (enumNames)
|
|
967
|
+
jsonSchema.enumNames = enumNames;
|
|
954
968
|
// Specifying the base type helps in cases when we ask Ajv to coerce the types.
|
|
955
969
|
// Having only the `enum` in the schema does not trigger a coercion in Ajv.
|
|
956
970
|
if (baseType === 'string')
|
|
@@ -10,3 +10,12 @@ export declare function mergeJsonSchemaObjects<T1 extends AnyObject, T2 extends
|
|
|
10
10
|
export declare function isEveryItemString(arr: any[]): boolean;
|
|
11
11
|
export declare function isEveryItemNumber(arr: any[]): boolean;
|
|
12
12
|
export declare function isEveryItemPrimitive(arr: any[]): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Values of the `format` keyword that `j` builders emit, named after the js-lib types they produce.
|
|
15
|
+
* PascalCase on purpose, to never collide with standard, ajv-formats or OpenAPI formats (all lowercase),
|
|
16
|
+
* whose semantics differ: e.g `date-time` requires an offset, while `IsoDateTime` doesn't.
|
|
17
|
+
*
|
|
18
|
+
* Annotation only: validation is done by the custom keywords (e.g `IsoDate`), not by the format.
|
|
19
|
+
*/
|
|
20
|
+
export declare const jFormats: readonly ['IsoDate', 'IsoDateTime', 'IsoMonth', 'UnixTimestamp', 'UnixTimestampMillis'];
|
|
21
|
+
export type JFormat = (typeof jFormats)[number];
|
|
@@ -87,3 +87,17 @@ export function isEveryItemPrimitive(arr) {
|
|
|
87
87
|
}
|
|
88
88
|
return true;
|
|
89
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Values of the `format` keyword that `j` builders emit, named after the js-lib types they produce.
|
|
92
|
+
* PascalCase on purpose, to never collide with standard, ajv-formats or OpenAPI formats (all lowercase),
|
|
93
|
+
* whose semantics differ: e.g `date-time` requires an offset, while `IsoDateTime` doesn't.
|
|
94
|
+
*
|
|
95
|
+
* Annotation only: validation is done by the custom keywords (e.g `IsoDate`), not by the format.
|
|
96
|
+
*/
|
|
97
|
+
export const jFormats = [
|
|
98
|
+
'IsoDate',
|
|
99
|
+
'IsoDateTime',
|
|
100
|
+
'IsoMonth',
|
|
101
|
+
'UnixTimestamp',
|
|
102
|
+
'UnixTimestampMillis',
|
|
103
|
+
];
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MemoCache } from '@naturalcycles/js-lib/decorators'
|
|
1
|
+
import type { AsyncMemoCache, MemoCache } from '@naturalcycles/js-lib/decorators'
|
|
2
2
|
import { LRUCache } from 'lru-cache'
|
|
3
3
|
|
|
4
4
|
// Partial, to be able to provide default `max`
|
|
@@ -37,3 +37,33 @@ export class LRUMemoCache<KEY = any, VALUE = any> implements MemoCache<KEY, VALU
|
|
|
37
37
|
this.lru.clear()
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Same as LRUMemoCache, but implements AsyncMemoCache interface, for when you need it.
|
|
43
|
+
*/
|
|
44
|
+
export class LRUAsyncMemoCache<KEY = any, VALUE = any> implements AsyncMemoCache<KEY, VALUE> {
|
|
45
|
+
constructor(opt: LRUMemoCacheOptions<KEY, VALUE>) {
|
|
46
|
+
this.lru = new LRUCache<any, any>({
|
|
47
|
+
max: 100,
|
|
48
|
+
...opt,
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private lru!: LRUCache<any, any>
|
|
53
|
+
|
|
54
|
+
async has(k: any): Promise<boolean> {
|
|
55
|
+
return this.lru.has(k)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async get(k: any): Promise<any> {
|
|
59
|
+
return this.lru.get(k)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async set(k: any, v: any): Promise<void> {
|
|
63
|
+
this.lru.set(k, v)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async clear(): Promise<void> {
|
|
67
|
+
this.lru.clear()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
JsonSchemaIsoMonthOptions,
|
|
15
15
|
JsonSchemaStringEmailOptions,
|
|
16
16
|
} from './jSchema.js'
|
|
17
|
+
import { jFormats } from './jsonSchemaBuilder.util.js'
|
|
17
18
|
|
|
18
19
|
// oxlint-disable unicorn/prefer-code-point
|
|
19
20
|
|
|
@@ -426,6 +427,18 @@ export function createAjv(opt?: Options): Ajv2020 {
|
|
|
426
427
|
},
|
|
427
428
|
})
|
|
428
429
|
|
|
430
|
+
// Annotation only (the values are validated by `enum`), registered so strict mode doesn't reject it
|
|
431
|
+
ajv.addKeyword({
|
|
432
|
+
keyword: 'enumNames',
|
|
433
|
+
schemaType: 'array',
|
|
434
|
+
})
|
|
435
|
+
|
|
436
|
+
// Annotation only (validated by the custom keywords, e.g `IsoDate`).
|
|
437
|
+
// `true` makes Ajv skip the format check, while unknown formats would throw in strict mode.
|
|
438
|
+
for (const format of jFormats) {
|
|
439
|
+
ajv.addFormat(format, true)
|
|
440
|
+
}
|
|
441
|
+
|
|
429
442
|
ajv.addKeyword({
|
|
430
443
|
keyword: 'errorMessages',
|
|
431
444
|
schemaType: 'object',
|
|
@@ -182,6 +182,7 @@ export const j = {
|
|
|
182
182
|
| { readonly values: readonly (string | number | boolean | null)[] },
|
|
183
183
|
>(input: T, opt?: JsonBuilderRuleOpt): JEnum<T extends readonly (infer U)[] ? U : Enum<T>> {
|
|
184
184
|
let enumValues: readonly (string | number | boolean | null)[] | undefined
|
|
185
|
+
let enumNames: string[] | undefined
|
|
185
186
|
let baseType: EnumBaseType = 'other'
|
|
186
187
|
|
|
187
188
|
if (Array.isArray(input)) {
|
|
@@ -194,7 +195,11 @@ export const j = {
|
|
|
194
195
|
} else if (typeof input === 'object') {
|
|
195
196
|
const enumType = getEnumType(input)
|
|
196
197
|
if (enumType === 'NumberEnum') {
|
|
197
|
-
|
|
198
|
+
// Not via _numberEnumKeys: it misses `_enum()` objects (no reverse mapping)
|
|
199
|
+
// and misaligns with the values when members aren't declared in ascending order
|
|
200
|
+
const numberEntries = Object.entries(input).filter(([, value]) => typeof value === 'number')
|
|
201
|
+
enumValues = numberEntries.map(([, value]) => value)
|
|
202
|
+
enumNames = numberEntries.map(([name]) => name)
|
|
198
203
|
baseType = 'number'
|
|
199
204
|
} else if (enumType === 'StringEnum') {
|
|
200
205
|
enumValues = _stringEnumValues(input as StringEnum)
|
|
@@ -203,7 +208,7 @@ export const j = {
|
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
_assert(enumValues, 'Unsupported enum input')
|
|
206
|
-
return new JEnum(enumValues as any, baseType, opt)
|
|
211
|
+
return new JEnum(enumValues as any, baseType, opt, enumNames)
|
|
207
212
|
},
|
|
208
213
|
|
|
209
214
|
/**
|
|
@@ -801,12 +806,16 @@ export class JString<
|
|
|
801
806
|
}
|
|
802
807
|
|
|
803
808
|
isoDateTime(): JString<IsoDateTime, Opt> {
|
|
804
|
-
return this.cloneAndUpdateSchema({
|
|
809
|
+
return this.cloneAndUpdateSchema({
|
|
810
|
+
format: 'IsoDateTime',
|
|
811
|
+
IsoDateTime: true,
|
|
812
|
+
}).branded<IsoDateTime>()
|
|
805
813
|
}
|
|
806
814
|
|
|
807
815
|
isoMonth(): JBuilder<IsoMonth, false> {
|
|
808
816
|
return new JBuilder<IsoMonth, false>({
|
|
809
817
|
type: 'string',
|
|
818
|
+
format: 'IsoMonth',
|
|
810
819
|
IsoMonth: {},
|
|
811
820
|
})
|
|
812
821
|
}
|
|
@@ -893,6 +902,7 @@ export class JIsoDate<Opt extends boolean = false> extends JBuilder<IsoDate, Opt
|
|
|
893
902
|
constructor() {
|
|
894
903
|
super({
|
|
895
904
|
type: 'string',
|
|
905
|
+
format: 'IsoDate',
|
|
896
906
|
IsoDate: {},
|
|
897
907
|
})
|
|
898
908
|
}
|
|
@@ -1027,19 +1037,21 @@ export class JNumber<
|
|
|
1027
1037
|
}
|
|
1028
1038
|
|
|
1029
1039
|
unixTimestamp(): JNumber<UnixTimestamp, Opt> {
|
|
1030
|
-
return this.integer().branded<UnixTimestamp>()
|
|
1040
|
+
return this.integer().cloneAndUpdateSchema({ format: 'UnixTimestamp' }).branded<UnixTimestamp>()
|
|
1031
1041
|
}
|
|
1032
1042
|
|
|
1033
1043
|
unixTimestamp2000(): JNumber<UnixTimestamp, Opt> {
|
|
1034
|
-
return this.
|
|
1044
|
+
return this.unixTimestamp().min(TS_2000).max(TS_2500)
|
|
1035
1045
|
}
|
|
1036
1046
|
|
|
1037
1047
|
unixTimestampMillis(): JNumber<UnixTimestampMillis, Opt> {
|
|
1038
|
-
return this.integer()
|
|
1048
|
+
return this.integer()
|
|
1049
|
+
.cloneAndUpdateSchema({ format: 'UnixTimestampMillis' })
|
|
1050
|
+
.branded<UnixTimestampMillis>()
|
|
1039
1051
|
}
|
|
1040
1052
|
|
|
1041
1053
|
unixTimestamp2000Millis(): JNumber<UnixTimestampMillis, Opt> {
|
|
1042
|
-
return this.
|
|
1054
|
+
return this.unixTimestampMillis().min(TS_2000_MILLIS).max(TS_2500_MILLIS)
|
|
1043
1055
|
}
|
|
1044
1056
|
|
|
1045
1057
|
utcOffset(): this {
|
|
@@ -1331,8 +1343,14 @@ export class JEnum<
|
|
|
1331
1343
|
OUT extends string | number | boolean | null,
|
|
1332
1344
|
Opt extends boolean = false,
|
|
1333
1345
|
> extends JBuilder<OUT, Opt> {
|
|
1334
|
-
constructor(
|
|
1346
|
+
constructor(
|
|
1347
|
+
enumValues: readonly OUT[],
|
|
1348
|
+
baseType: EnumBaseType,
|
|
1349
|
+
opt?: JsonBuilderRuleOpt,
|
|
1350
|
+
enumNames?: readonly string[],
|
|
1351
|
+
) {
|
|
1335
1352
|
const jsonSchema: JsonSchema = { enum: enumValues }
|
|
1353
|
+
if (enumNames) jsonSchema.enumNames = enumNames
|
|
1336
1354
|
// Specifying the base type helps in cases when we ask Ajv to coerce the types.
|
|
1337
1355
|
// Having only the `enum` in the schema does not trigger a coercion in Ajv.
|
|
1338
1356
|
if (baseType === 'string') jsonSchema.type = 'string'
|
|
@@ -2086,6 +2104,11 @@ export interface JsonSchema<OUT = unknown> {
|
|
|
2086
2104
|
uniqueItems?: boolean
|
|
2087
2105
|
|
|
2088
2106
|
enum?: any
|
|
2107
|
+
/**
|
|
2108
|
+
* Member names of a NumberEnum, aligned by index with `enum`.
|
|
2109
|
+
* Annotation only (not validated), lets consumers render `1` as e.g `PREVENT`.
|
|
2110
|
+
*/
|
|
2111
|
+
enumNames?: readonly string[]
|
|
2089
2112
|
|
|
2090
2113
|
hasIsOfTypeCheck?: boolean
|
|
2091
2114
|
|
|
@@ -101,3 +101,19 @@ export function isEveryItemPrimitive(arr: any[]): boolean {
|
|
|
101
101
|
}
|
|
102
102
|
return true
|
|
103
103
|
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Values of the `format` keyword that `j` builders emit, named after the js-lib types they produce.
|
|
107
|
+
* PascalCase on purpose, to never collide with standard, ajv-formats or OpenAPI formats (all lowercase),
|
|
108
|
+
* whose semantics differ: e.g `date-time` requires an offset, while `IsoDateTime` doesn't.
|
|
109
|
+
*
|
|
110
|
+
* Annotation only: validation is done by the custom keywords (e.g `IsoDate`), not by the format.
|
|
111
|
+
*/
|
|
112
|
+
export const jFormats = [
|
|
113
|
+
'IsoDate',
|
|
114
|
+
'IsoDateTime',
|
|
115
|
+
'IsoMonth',
|
|
116
|
+
'UnixTimestamp',
|
|
117
|
+
'UnixTimestampMillis',
|
|
118
|
+
] as const
|
|
119
|
+
export type JFormat = (typeof jFormats)[number]
|