@naturalcycles/nodejs-lib 15.43.2 → 15.45.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/validation/ajv/getAjv.js +1 -1
- package/dist/validation/ajv/jsonSchemaBuilder.d.ts +28 -8
- package/dist/validation/ajv/jsonSchemaBuilder.js +40 -9
- package/dist/validation/timezones.d.ts +9 -0
- package/dist/validation/timezones.js +612 -0
- package/package.json +1 -1
- package/src/validation/ajv/getAjv.ts +1 -1
- package/src/validation/ajv/jsonSchemaBuilder.ts +56 -8
- package/src/validation/timezones.ts +616 -0
- /package/dist/validation/{ajv/tlds.d.ts → tlds.d.ts} +0 -0
- /package/dist/validation/{ajv/tlds.js → tlds.js} +0 -0
- /package/src/validation/{ajv/tlds.ts → tlds.ts} +0 -0
|
@@ -2,7 +2,7 @@ import { _lazyValue } from '@naturalcycles/js-lib';
|
|
|
2
2
|
import { Set2 } from '@naturalcycles/js-lib/object';
|
|
3
3
|
import { _substringAfterLast } from '@naturalcycles/js-lib/string';
|
|
4
4
|
import { _, Ajv } from 'ajv';
|
|
5
|
-
import { validTLDs } from '
|
|
5
|
+
import { validTLDs } from '../tlds.js';
|
|
6
6
|
/* eslint-disable @typescript-eslint/prefer-string-starts-ends-with */
|
|
7
7
|
// oxlint-disable unicorn/prefer-code-point
|
|
8
8
|
const AJV_OPTIONS = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Set2 } from '@naturalcycles/js-lib/object';
|
|
2
|
-
import { type AnyObject, type IsoDate, type IsoDateTime, type NumberEnum, type StringEnum, type StringMap, type UnixTimestamp, type UnixTimestampMillis } from '@naturalcycles/js-lib/types';
|
|
2
|
+
import { type AnyObject, type IANATimezone, type Inclusiveness, type IsoDate, type IsoDateTime, type NumberEnum, type StringEnum, type StringMap, type UnixTimestamp, type UnixTimestampMillis } from '@naturalcycles/js-lib/types';
|
|
3
3
|
export declare const j: {
|
|
4
4
|
string(): JsonSchemaStringBuilder<string, string, false>;
|
|
5
5
|
number(): JsonSchemaNumberBuilder<number, number, false>;
|
|
@@ -12,7 +12,7 @@ export declare const j: {
|
|
|
12
12
|
array<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaArrayBuilder<IN, OUT, Opt>;
|
|
13
13
|
set<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaSet2Builder<IN, OUT, Opt>;
|
|
14
14
|
buffer(): JsonSchemaBufferBuilder;
|
|
15
|
-
enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(input: T): JsonSchemaEnumBuilder<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never>;
|
|
15
|
+
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>;
|
|
16
16
|
oneOf<B extends readonly JsonSchemaAnyBuilder<any, any, boolean>[], IN = BuilderInUnion<B>, OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false>;
|
|
17
17
|
};
|
|
18
18
|
export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> {
|
|
@@ -91,6 +91,13 @@ export declare class JsonSchemaStringBuilder<IN extends string = string, OUT = I
|
|
|
91
91
|
languageTag(): this;
|
|
92
92
|
countryCode(): this;
|
|
93
93
|
currency(): this;
|
|
94
|
+
/**
|
|
95
|
+
* Validates that the input is a valid IANATimzone value.
|
|
96
|
+
*
|
|
97
|
+
* All previous expectations in the schema chain are dropped - including `.optional()` -
|
|
98
|
+
* because this call effectively starts a new schema chain as an `enum` validation.
|
|
99
|
+
*/
|
|
100
|
+
ianaTimezone(): JsonSchemaEnumBuilder<string | IANATimezone, IANATimezone, false>;
|
|
94
101
|
}
|
|
95
102
|
export interface JsonSchemaStringEmailOptions {
|
|
96
103
|
checkTLD: boolean;
|
|
@@ -104,10 +111,11 @@ export declare class JsonSchemaNumberBuilder<IN extends number = number, OUT = I
|
|
|
104
111
|
exclusiveMin(exclusiveMinimum: number): this;
|
|
105
112
|
max(maximum: number): this;
|
|
106
113
|
exclusiveMax(exclusiveMaximum: number): this;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
114
|
+
lessThan(value: number): this;
|
|
115
|
+
lessThanOrEqual(value: number): this;
|
|
116
|
+
moreThan(value: number): this;
|
|
117
|
+
moreThanOrEqual(value: number): this;
|
|
118
|
+
range(minimum: number, maximum: number, incl: Inclusiveness): this;
|
|
111
119
|
int32(): this;
|
|
112
120
|
int64(): this;
|
|
113
121
|
float(): this;
|
|
@@ -156,7 +164,7 @@ export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<strin
|
|
|
156
164
|
/**
|
|
157
165
|
* Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
|
|
158
166
|
*/
|
|
159
|
-
dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in keyof PROPS | "
|
|
167
|
+
dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in "id" | keyof PROPS | "created" | "updated"]: K extends "id" | "created" | "updated" ? {
|
|
160
168
|
id: JsonSchemaStringBuilder<string, string, false>;
|
|
161
169
|
created: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
|
|
162
170
|
updated: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
|
|
@@ -177,7 +185,8 @@ export declare class JsonSchemaBufferBuilder extends JsonSchemaAnyBuilder<string
|
|
|
177
185
|
constructor();
|
|
178
186
|
}
|
|
179
187
|
export declare class JsonSchemaEnumBuilder<IN extends string | number | boolean | null, OUT extends IN = IN, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
|
|
180
|
-
constructor(enumValues: readonly IN[]);
|
|
188
|
+
constructor(enumValues: readonly IN[], opt?: JsonBuilderRuleOpt);
|
|
189
|
+
branded<B extends IN>(): JsonSchemaEnumBuilder<B | IN, B, Opt>;
|
|
181
190
|
}
|
|
182
191
|
export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
183
192
|
readonly in?: IN;
|
|
@@ -256,6 +265,17 @@ type BuilderInUnion<B extends readonly JsonSchemaAnyBuilder<any, any, any>[]> =
|
|
|
256
265
|
[K in keyof B]: B[K] extends JsonSchemaAnyBuilder<infer I, any, any> ? I : never;
|
|
257
266
|
}[number];
|
|
258
267
|
interface JsonBuilderRuleOpt {
|
|
268
|
+
/**
|
|
269
|
+
* Text of error message to return when the validation fails for the given rule:
|
|
270
|
+
*
|
|
271
|
+
* `{ msg: "is not a valid Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
|
|
272
|
+
*/
|
|
259
273
|
msg?: string;
|
|
274
|
+
/**
|
|
275
|
+
* A friendly name for what we are validating, that will be used in error messages:
|
|
276
|
+
*
|
|
277
|
+
* `{ name: "Oompa-loompa" } => "Object.property is not a valid Oompa-loompa"`
|
|
278
|
+
*/
|
|
279
|
+
name?: string;
|
|
260
280
|
}
|
|
261
281
|
export {};
|
|
@@ -5,6 +5,7 @@ import { _uniq } from '@naturalcycles/js-lib/array';
|
|
|
5
5
|
import { _assert } from '@naturalcycles/js-lib/error';
|
|
6
6
|
import { _deepCopy, _sortObject } from '@naturalcycles/js-lib/object';
|
|
7
7
|
import { JWT_REGEX, } from '@naturalcycles/js-lib/types';
|
|
8
|
+
import { TIMEZONES } from '../timezones.js';
|
|
8
9
|
import { JSON_SCHEMA_ORDER, mergeJsonSchemaObjects } from './jsonSchemaBuilder.util.js';
|
|
9
10
|
export const j = {
|
|
10
11
|
string() {
|
|
@@ -32,7 +33,7 @@ export const j = {
|
|
|
32
33
|
buffer() {
|
|
33
34
|
return new JsonSchemaBufferBuilder();
|
|
34
35
|
},
|
|
35
|
-
enum(input) {
|
|
36
|
+
enum(input, opt) {
|
|
36
37
|
let enumValues;
|
|
37
38
|
if (Array.isArray(input)) {
|
|
38
39
|
enumValues = input;
|
|
@@ -47,7 +48,7 @@ export const j = {
|
|
|
47
48
|
}
|
|
48
49
|
}
|
|
49
50
|
_assert(enumValues, 'Unsupported enum input');
|
|
50
|
-
return new JsonSchemaEnumBuilder(enumValues);
|
|
51
|
+
return new JsonSchemaEnumBuilder(enumValues, opt);
|
|
51
52
|
},
|
|
52
53
|
oneOf(items) {
|
|
53
54
|
const schemas = items.map(b => b.build());
|
|
@@ -177,6 +178,8 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
177
178
|
return this.pattern(pattern.source, opt);
|
|
178
179
|
}
|
|
179
180
|
pattern(pattern, opt) {
|
|
181
|
+
if (opt?.name)
|
|
182
|
+
this.setErrorMessage('pattern', `is not a valid ${opt.name}`);
|
|
180
183
|
if (opt?.msg)
|
|
181
184
|
this.setErrorMessage('pattern', opt.msg);
|
|
182
185
|
Object.assign(this.schema, { pattern });
|
|
@@ -275,6 +278,16 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
275
278
|
const regex = /^[A-Z]{3}$/;
|
|
276
279
|
return this.regex(regex, { msg: 'is not a valid currency format' });
|
|
277
280
|
}
|
|
281
|
+
/**
|
|
282
|
+
* Validates that the input is a valid IANATimzone value.
|
|
283
|
+
*
|
|
284
|
+
* All previous expectations in the schema chain are dropped - including `.optional()` -
|
|
285
|
+
* because this call effectively starts a new schema chain as an `enum` validation.
|
|
286
|
+
*/
|
|
287
|
+
ianaTimezone() {
|
|
288
|
+
// UTC is added to assist unit-testing, which uses UTC by default (not technically a valid Iana timezone identifier)
|
|
289
|
+
return j.enum(TIMEZONES, { msg: 'is an invalid IANA timezone' }).branded();
|
|
290
|
+
}
|
|
278
291
|
}
|
|
279
292
|
export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
|
|
280
293
|
constructor() {
|
|
@@ -309,12 +322,23 @@ export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
|
|
|
309
322
|
Object.assign(this.schema, { exclusiveMaximum });
|
|
310
323
|
return this;
|
|
311
324
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
325
|
+
lessThan(value) {
|
|
326
|
+
return this.exclusiveMax(value);
|
|
327
|
+
}
|
|
328
|
+
lessThanOrEqual(value) {
|
|
329
|
+
return this.max(value);
|
|
330
|
+
}
|
|
331
|
+
moreThan(value) {
|
|
332
|
+
return this.exclusiveMin(value);
|
|
333
|
+
}
|
|
334
|
+
moreThanOrEqual(value) {
|
|
335
|
+
return this.min(value);
|
|
336
|
+
}
|
|
337
|
+
range(minimum, maximum, incl) {
|
|
338
|
+
if (incl === '[)') {
|
|
339
|
+
return this.moreThanOrEqual(minimum).lessThan(maximum);
|
|
340
|
+
}
|
|
341
|
+
return this.moreThanOrEqual(minimum).lessThanOrEqual(maximum);
|
|
318
342
|
}
|
|
319
343
|
int32() {
|
|
320
344
|
const MIN_INT32 = -(2 ** 31);
|
|
@@ -520,8 +544,15 @@ export class JsonSchemaBufferBuilder extends JsonSchemaAnyBuilder {
|
|
|
520
544
|
}
|
|
521
545
|
}
|
|
522
546
|
export class JsonSchemaEnumBuilder extends JsonSchemaAnyBuilder {
|
|
523
|
-
constructor(enumValues) {
|
|
547
|
+
constructor(enumValues, opt) {
|
|
524
548
|
super({ enum: enumValues });
|
|
549
|
+
if (opt?.name)
|
|
550
|
+
this.setErrorMessage('pattern', `is not a valid ${opt.name}`);
|
|
551
|
+
if (opt?.msg)
|
|
552
|
+
this.setErrorMessage('enum', opt.msg);
|
|
553
|
+
}
|
|
554
|
+
branded() {
|
|
555
|
+
return this;
|
|
525
556
|
}
|
|
526
557
|
}
|
|
527
558
|
function object(props) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A complicated merge of timezones from the underlying Javascript engine
|
|
3
|
+
* and a list exported from Wikipedia.
|
|
4
|
+
*
|
|
5
|
+
* Why? The `Int.supportedValuesOf('timeZone')` we use provide only
|
|
6
|
+
* canonical/standardized timezone values like `Europe/Stockholm`
|
|
7
|
+
* but does not list accepted aliases like `ETC/Gmt`, `CET` or `Canada/Atlantic`.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TIMEZONES: any;
|