@naturalcycles/nodejs-lib 15.60.0 → 15.61.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 { _lazyValue } from '@naturalcycles/js-lib';
|
|
1
|
+
import { _isBetween, _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';
|
|
@@ -349,6 +349,25 @@ export function createAjv(opt) {
|
|
|
349
349
|
return false;
|
|
350
350
|
},
|
|
351
351
|
});
|
|
352
|
+
ajv.addKeyword({
|
|
353
|
+
keyword: 'IsoMonth',
|
|
354
|
+
type: 'string',
|
|
355
|
+
modifying: false,
|
|
356
|
+
errors: true,
|
|
357
|
+
schemaType: 'object',
|
|
358
|
+
validate: function validate(_opt, data, _schema, ctx) {
|
|
359
|
+
const isValid = isIsoMonthValid(data);
|
|
360
|
+
if (isValid)
|
|
361
|
+
return true;
|
|
362
|
+
validate.errors = [
|
|
363
|
+
{
|
|
364
|
+
instancePath: ctx?.instancePath ?? '',
|
|
365
|
+
message: `is an invalid IsoMonth`,
|
|
366
|
+
},
|
|
367
|
+
];
|
|
368
|
+
return false;
|
|
369
|
+
},
|
|
370
|
+
});
|
|
352
371
|
ajv.addKeyword({
|
|
353
372
|
keyword: 'errorMessages',
|
|
354
373
|
schemaType: 'object',
|
|
@@ -516,3 +535,21 @@ function isIsoTimezoneValid(s) {
|
|
|
516
535
|
return false; // min is -12:00
|
|
517
536
|
return true;
|
|
518
537
|
}
|
|
538
|
+
/**
|
|
539
|
+
* This is a performance optimized correct validation
|
|
540
|
+
* for ISO month formatted as "YYYY-MM".
|
|
541
|
+
*/
|
|
542
|
+
function isIsoMonthValid(s) {
|
|
543
|
+
// must be exactly "YYYY-MM"
|
|
544
|
+
if (s.length !== 7)
|
|
545
|
+
return false;
|
|
546
|
+
if (s.charCodeAt(4) !== DASH_CODE)
|
|
547
|
+
return false;
|
|
548
|
+
// fast parse numbers without substrings/Number()
|
|
549
|
+
const year = (s.charCodeAt(0) - ZERO_CODE) * 1000 +
|
|
550
|
+
(s.charCodeAt(1) - ZERO_CODE) * 100 +
|
|
551
|
+
(s.charCodeAt(2) - ZERO_CODE) * 10 +
|
|
552
|
+
(s.charCodeAt(3) - ZERO_CODE);
|
|
553
|
+
const month = (s.charCodeAt(5) - ZERO_CODE) * 10 + (s.charCodeAt(6) - ZERO_CODE);
|
|
554
|
+
return _isBetween(year, 1900, 2500, '[]') && _isBetween(month, 1, 12, '[]');
|
|
555
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Set2 } from '@naturalcycles/js-lib/object';
|
|
2
|
-
import { type AnyObject, type BaseDBEntity, type IANATimezone, type Inclusiveness, type IsoDate, type IsoDateTime, type NumberEnum, type StringEnum, type StringMap, type UnixTimestamp, type UnixTimestampMillis } from '@naturalcycles/js-lib/types';
|
|
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
4
|
string(): JsonSchemaStringBuilder<string, string, false>;
|
|
5
5
|
number(): JsonSchemaNumberBuilder<number, number, false>;
|
|
@@ -139,6 +139,7 @@ export declare class JsonSchemaStringBuilder<IN extends string | undefined = str
|
|
|
139
139
|
*/
|
|
140
140
|
isoDate(): JsonSchemaIsoDateBuilder;
|
|
141
141
|
isoDateTime(): JsonSchemaStringBuilder<IsoDateTime | IN, IsoDateTime, Opt>;
|
|
142
|
+
isoMonth(): JsonSchemaIsoMonthBuilder;
|
|
142
143
|
/**
|
|
143
144
|
* Validates the string format to be JWT.
|
|
144
145
|
* Expects the JWT to be signed!
|
|
@@ -179,6 +180,11 @@ export interface JsonSchemaIsoDateOptions {
|
|
|
179
180
|
after?: string;
|
|
180
181
|
sameOrAfter?: string;
|
|
181
182
|
}
|
|
183
|
+
export declare class JsonSchemaIsoMonthBuilder<Opt extends boolean = false> extends JsonSchemaAnyBuilder<string | IsoDate, IsoMonth, Opt> {
|
|
184
|
+
constructor();
|
|
185
|
+
}
|
|
186
|
+
export interface JsonSchemaIsoMonthOptions {
|
|
187
|
+
}
|
|
182
188
|
export declare class JsonSchemaNumberBuilder<IN extends number | undefined = number, OUT = IN, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
|
|
183
189
|
constructor();
|
|
184
190
|
/**
|
|
@@ -343,6 +349,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
343
349
|
Buffer?: true;
|
|
344
350
|
IsoDate?: JsonSchemaIsoDateOptions;
|
|
345
351
|
IsoDateTime?: true;
|
|
352
|
+
IsoMonth?: JsonSchemaIsoMonthOptions;
|
|
346
353
|
instanceof?: string | string[];
|
|
347
354
|
transform?: {
|
|
348
355
|
trim?: true;
|
|
@@ -322,6 +322,9 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
|
|
|
322
322
|
isoDateTime() {
|
|
323
323
|
return this.cloneAndUpdateSchema({ IsoDateTime: true }).branded();
|
|
324
324
|
}
|
|
325
|
+
isoMonth() {
|
|
326
|
+
return new JsonSchemaIsoMonthBuilder();
|
|
327
|
+
}
|
|
325
328
|
/**
|
|
326
329
|
* Validates the string format to be JWT.
|
|
327
330
|
* Expects the JWT to be signed!
|
|
@@ -404,6 +407,14 @@ export class JsonSchemaIsoDateBuilder extends JsonSchemaAnyBuilder {
|
|
|
404
407
|
return this.cloneAndUpdateSchema(schemaPatch);
|
|
405
408
|
}
|
|
406
409
|
}
|
|
410
|
+
export class JsonSchemaIsoMonthBuilder extends JsonSchemaAnyBuilder {
|
|
411
|
+
constructor() {
|
|
412
|
+
super({
|
|
413
|
+
type: 'string',
|
|
414
|
+
IsoMonth: {},
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}
|
|
407
418
|
export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
|
|
408
419
|
constructor() {
|
|
409
420
|
super({
|
package/package.json
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { _lazyValue } from '@naturalcycles/js-lib'
|
|
1
|
+
import { _isBetween, _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 type { AnyObject } from '@naturalcycles/js-lib/types'
|
|
5
5
|
import { Ajv, type Options, type ValidateFunction } from 'ajv'
|
|
6
6
|
import { validTLDs } from '../tlds.js'
|
|
7
|
-
import type {
|
|
7
|
+
import type {
|
|
8
|
+
JsonSchemaIsoDateOptions,
|
|
9
|
+
JsonSchemaIsoMonthOptions,
|
|
10
|
+
JsonSchemaStringEmailOptions,
|
|
11
|
+
} from './jsonSchemaBuilder.js'
|
|
8
12
|
|
|
9
13
|
/* eslint-disable @typescript-eslint/prefer-string-starts-ends-with */
|
|
10
14
|
// oxlint-disable unicorn/prefer-code-point
|
|
@@ -383,7 +387,7 @@ export function createAjv(opt?: Options): Ajv {
|
|
|
383
387
|
modifying: false,
|
|
384
388
|
errors: true,
|
|
385
389
|
schemaType: 'boolean',
|
|
386
|
-
validate: function validate(_opt:
|
|
390
|
+
validate: function validate(_opt: JsonSchemaIsoMonthOptions, data: string, _schema, ctx) {
|
|
387
391
|
const isValid = isIsoDateTimeValid(data)
|
|
388
392
|
if (isValid) return true
|
|
389
393
|
;(validate as any).errors = [
|
|
@@ -396,6 +400,25 @@ export function createAjv(opt?: Options): Ajv {
|
|
|
396
400
|
},
|
|
397
401
|
})
|
|
398
402
|
|
|
403
|
+
ajv.addKeyword({
|
|
404
|
+
keyword: 'IsoMonth',
|
|
405
|
+
type: 'string',
|
|
406
|
+
modifying: false,
|
|
407
|
+
errors: true,
|
|
408
|
+
schemaType: 'object',
|
|
409
|
+
validate: function validate(_opt: true, data: string, _schema, ctx) {
|
|
410
|
+
const isValid = isIsoMonthValid(data)
|
|
411
|
+
if (isValid) return true
|
|
412
|
+
;(validate as any).errors = [
|
|
413
|
+
{
|
|
414
|
+
instancePath: ctx?.instancePath ?? '',
|
|
415
|
+
message: `is an invalid IsoMonth`,
|
|
416
|
+
},
|
|
417
|
+
]
|
|
418
|
+
return false
|
|
419
|
+
},
|
|
420
|
+
})
|
|
421
|
+
|
|
399
422
|
ajv.addKeyword({
|
|
400
423
|
keyword: 'errorMessages',
|
|
401
424
|
schemaType: 'object',
|
|
@@ -577,3 +600,24 @@ function isIsoTimezoneValid(s: string): boolean {
|
|
|
577
600
|
|
|
578
601
|
return true
|
|
579
602
|
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* This is a performance optimized correct validation
|
|
606
|
+
* for ISO month formatted as "YYYY-MM".
|
|
607
|
+
*/
|
|
608
|
+
function isIsoMonthValid(s: string): boolean {
|
|
609
|
+
// must be exactly "YYYY-MM"
|
|
610
|
+
if (s.length !== 7) return false
|
|
611
|
+
if (s.charCodeAt(4) !== DASH_CODE) return false
|
|
612
|
+
|
|
613
|
+
// fast parse numbers without substrings/Number()
|
|
614
|
+
const year =
|
|
615
|
+
(s.charCodeAt(0) - ZERO_CODE) * 1000 +
|
|
616
|
+
(s.charCodeAt(1) - ZERO_CODE) * 100 +
|
|
617
|
+
(s.charCodeAt(2) - ZERO_CODE) * 10 +
|
|
618
|
+
(s.charCodeAt(3) - ZERO_CODE)
|
|
619
|
+
|
|
620
|
+
const month = (s.charCodeAt(5) - ZERO_CODE) * 10 + (s.charCodeAt(6) - ZERO_CODE)
|
|
621
|
+
|
|
622
|
+
return _isBetween(year, 1900, 2500, '[]') && _isBetween(month, 1, 12, '[]')
|
|
623
|
+
}
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
type Inclusiveness,
|
|
20
20
|
type IsoDate,
|
|
21
21
|
type IsoDateTime,
|
|
22
|
+
type IsoMonth,
|
|
22
23
|
JWT_REGEX,
|
|
23
24
|
type NumberEnum,
|
|
24
25
|
type StringEnum,
|
|
@@ -453,6 +454,10 @@ export class JsonSchemaStringBuilder<
|
|
|
453
454
|
return this.cloneAndUpdateSchema({ IsoDateTime: true }).branded<IsoDateTime>()
|
|
454
455
|
}
|
|
455
456
|
|
|
457
|
+
isoMonth(): JsonSchemaIsoMonthBuilder {
|
|
458
|
+
return new JsonSchemaIsoMonthBuilder()
|
|
459
|
+
}
|
|
460
|
+
|
|
456
461
|
/**
|
|
457
462
|
* Validates the string format to be JWT.
|
|
458
463
|
* Expects the JWT to be signed!
|
|
@@ -570,6 +575,21 @@ export interface JsonSchemaIsoDateOptions {
|
|
|
570
575
|
sameOrAfter?: string
|
|
571
576
|
}
|
|
572
577
|
|
|
578
|
+
export class JsonSchemaIsoMonthBuilder<Opt extends boolean = false> extends JsonSchemaAnyBuilder<
|
|
579
|
+
string | IsoDate,
|
|
580
|
+
IsoMonth,
|
|
581
|
+
Opt
|
|
582
|
+
> {
|
|
583
|
+
constructor() {
|
|
584
|
+
super({
|
|
585
|
+
type: 'string',
|
|
586
|
+
IsoMonth: {},
|
|
587
|
+
})
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
export interface JsonSchemaIsoMonthOptions {}
|
|
592
|
+
|
|
573
593
|
export class JsonSchemaNumberBuilder<
|
|
574
594
|
IN extends number | undefined = number,
|
|
575
595
|
OUT = IN,
|
|
@@ -1126,6 +1146,7 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
|
|
|
1126
1146
|
Buffer?: true
|
|
1127
1147
|
IsoDate?: JsonSchemaIsoDateOptions
|
|
1128
1148
|
IsoDateTime?: true
|
|
1149
|
+
IsoMonth?: JsonSchemaIsoMonthOptions
|
|
1129
1150
|
instanceof?: string | string[]
|
|
1130
1151
|
transform?: { trim?: true; toLowerCase?: true; toUpperCase?: true; truncate?: number }
|
|
1131
1152
|
errorMessages?: StringMap<string>
|