@naturalcycles/nodejs-lib 15.43.2 → 15.44.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,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 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;
@@ -177,7 +184,8 @@ export declare class JsonSchemaBufferBuilder extends JsonSchemaAnyBuilder<string
177
184
  constructor();
178
185
  }
179
186
  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[]);
187
+ constructor(enumValues: readonly IN[], opt?: JsonBuilderRuleOpt);
188
+ branded<B extends IN>(): JsonSchemaEnumBuilder<B | IN, B, Opt>;
181
189
  }
182
190
  export interface JsonSchema<IN = unknown, OUT = IN> {
183
191
  readonly in?: IN;
@@ -32,7 +32,7 @@ export const j = {
32
32
  buffer() {
33
33
  return new JsonSchemaBufferBuilder();
34
34
  },
35
- enum(input) {
35
+ enum(input, opt) {
36
36
  let enumValues;
37
37
  if (Array.isArray(input)) {
38
38
  enumValues = input;
@@ -47,7 +47,7 @@ export const j = {
47
47
  }
48
48
  }
49
49
  _assert(enumValues, 'Unsupported enum input');
50
- return new JsonSchemaEnumBuilder(enumValues);
50
+ return new JsonSchemaEnumBuilder(enumValues, opt);
51
51
  },
52
52
  oneOf(items) {
53
53
  const schemas = items.map(b => b.build());
@@ -275,6 +275,18 @@ export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
275
275
  const regex = /^[A-Z]{3}$/;
276
276
  return this.regex(regex, { msg: 'is not a valid currency format' });
277
277
  }
278
+ /**
279
+ * Validates that the input is a valid IANATimzone value.
280
+ *
281
+ * All previous expectations in the schema chain are dropped - including `.optional()` -
282
+ * because this call effectively starts a new schema chain as an `enum` validation.
283
+ */
284
+ ianaTimezone() {
285
+ // UTC is added to assist unit-testing, which uses UTC by default (not technically a valid Iana timezone identifier)
286
+ return j
287
+ .enum([...Intl.supportedValuesOf('timeZone'), 'UTC'], { msg: 'is an invalid IANA timezone' })
288
+ .branded();
289
+ }
278
290
  }
279
291
  export class JsonSchemaNumberBuilder extends JsonSchemaAnyBuilder {
280
292
  constructor() {
@@ -520,8 +532,13 @@ export class JsonSchemaBufferBuilder extends JsonSchemaAnyBuilder {
520
532
  }
521
533
  }
522
534
  export class JsonSchemaEnumBuilder extends JsonSchemaAnyBuilder {
523
- constructor(enumValues) {
535
+ constructor(enumValues, opt) {
524
536
  super({ enum: enumValues });
537
+ if (opt?.msg)
538
+ this.setErrorMessage('enum', opt.msg);
539
+ }
540
+ branded() {
541
+ return this;
525
542
  }
526
543
  }
527
544
  function object(props) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.43.2",
4
+ "version": "15.44.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -13,6 +13,7 @@ import type { Set2 } from '@naturalcycles/js-lib/object'
13
13
  import { _deepCopy, _sortObject } from '@naturalcycles/js-lib/object'
14
14
  import {
15
15
  type AnyObject,
16
+ type IANATimezone,
16
17
  type IsoDate,
17
18
  type IsoDateTime,
18
19
  JWT_REGEX,
@@ -63,6 +64,7 @@ export const j = {
63
64
 
64
65
  enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(
65
66
  input: T,
67
+ opt?: JsonBuilderRuleOpt,
66
68
  ): JsonSchemaEnumBuilder<
67
69
  T extends readonly (infer U)[]
68
70
  ? U
@@ -86,7 +88,7 @@ export const j = {
86
88
  }
87
89
 
88
90
  _assert(enumValues, 'Unsupported enum input')
89
- return new JsonSchemaEnumBuilder(enumValues as any)
91
+ return new JsonSchemaEnumBuilder(enumValues as any, opt)
90
92
  },
91
93
 
92
94
  oneOf<
@@ -369,6 +371,19 @@ export class JsonSchemaStringBuilder<
369
371
  const regex = /^[A-Z]{3}$/
370
372
  return this.regex(regex, { msg: 'is not a valid currency format' })
371
373
  }
374
+
375
+ /**
376
+ * Validates that the input is a valid IANATimzone value.
377
+ *
378
+ * All previous expectations in the schema chain are dropped - including `.optional()` -
379
+ * because this call effectively starts a new schema chain as an `enum` validation.
380
+ */
381
+ ianaTimezone(): JsonSchemaEnumBuilder<string | IANATimezone, IANATimezone, false> {
382
+ // UTC is added to assist unit-testing, which uses UTC by default (not technically a valid Iana timezone identifier)
383
+ return j
384
+ .enum([...Intl.supportedValuesOf('timeZone'), 'UTC'], { msg: 'is an invalid IANA timezone' })
385
+ .branded<IANATimezone>()
386
+ }
372
387
  }
373
388
 
374
389
  export interface JsonSchemaStringEmailOptions {
@@ -750,8 +765,14 @@ export class JsonSchemaEnumBuilder<
750
765
  OUT extends IN = IN,
751
766
  Opt extends boolean = false,
752
767
  > extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
753
- constructor(enumValues: readonly IN[]) {
768
+ constructor(enumValues: readonly IN[], opt?: JsonBuilderRuleOpt) {
754
769
  super({ enum: enumValues })
770
+
771
+ if (opt?.msg) this.setErrorMessage('enum', opt.msg)
772
+ }
773
+
774
+ branded<B extends IN>(): JsonSchemaEnumBuilder<B | IN, B, Opt> {
775
+ return this as unknown as JsonSchemaEnumBuilder<B | IN, B, Opt>
755
776
  }
756
777
  }
757
778