@naturalcycles/nodejs-lib 15.39.0 → 15.41.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.
@@ -4,7 +4,8 @@ export declare const j: {
4
4
  string(): JsonSchemaStringBuilder<string, string, false>;
5
5
  number(): JsonSchemaNumberBuilder<number, number, false>;
6
6
  boolean(): JsonSchemaBooleanBuilder<boolean, boolean, false>;
7
- object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectBuilder<P, false>;
7
+ object: typeof object;
8
+ objectInfer<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectInferringBuilder<P, false>;
8
9
  array<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaArrayBuilder<IN, OUT, Opt>;
9
10
  set<IN, OUT, Opt>(itemSchema: JsonSchemaAnyBuilder<IN, OUT, Opt>): JsonSchemaSet2Builder<IN, OUT, Opt>;
10
11
  buffer(): JsonSchemaBufferBuilder;
@@ -47,6 +48,11 @@ export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> {
47
48
  */
48
49
  build(): JsonSchema<IN, OUT>;
49
50
  clone(): JsonSchemaAnyBuilder<IN, OUT, Opt>;
51
+ /**
52
+ * @deprecated
53
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
54
+ */
55
+ castAs<T>(): JsonSchemaAnyBuilder<T, T, Opt>;
50
56
  /**
51
57
  * @experimental
52
58
  */
@@ -113,7 +119,20 @@ export declare class JsonSchemaNumberBuilder<IN extends number = number, OUT = I
113
119
  export declare class JsonSchemaBooleanBuilder<IN extends boolean = boolean, OUT = IN, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
114
120
  constructor();
115
121
  }
116
- export declare class JsonSchemaObjectBuilder<PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>, Opt extends boolean = false> extends JsonSchemaAnyBuilder<Expand<{
122
+ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends AnyObject, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
123
+ constructor(props?: AnyObject);
124
+ addProperties(props: AnyObject): this;
125
+ /**
126
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
127
+ */
128
+ allowAdditionalProperties(): this;
129
+ extend<IN2 extends AnyObject>(props: AnyObject): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt>;
130
+ /**
131
+ * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
132
+ */
133
+ dbEntity(): JsonSchemaObjectBuilder<any, any, Opt>;
134
+ }
135
+ export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>, Opt extends boolean = false> extends JsonSchemaAnyBuilder<Expand<{
117
136
  [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never;
118
137
  } & {
119
138
  [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: PROPS[K] extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never;
@@ -124,13 +143,17 @@ export declare class JsonSchemaObjectBuilder<PROPS extends Record<string, JsonSc
124
143
  }>, Opt> {
125
144
  constructor(props?: PROPS);
126
145
  addProperties(props: PROPS): this;
127
- extend<NEW_PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: NEW_PROPS): JsonSchemaObjectBuilder<{
146
+ /**
147
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
148
+ */
149
+ allowAdditionalProperties(): this;
150
+ extend<NEW_PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: NEW_PROPS): JsonSchemaObjectInferringBuilder<{
128
151
  [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS ? NEW_PROPS[K] : K extends keyof PROPS ? PROPS[K] : never;
129
152
  }, Opt>;
130
153
  /**
131
154
  * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
132
155
  */
133
- dbEntity(): JsonSchemaObjectBuilder<{ [K in keyof PROPS | "id" | "created" | "updated"]: K extends "id" | "created" | "updated" ? {
156
+ dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in keyof PROPS | "id" | "created" | "updated"]: K extends "id" | "created" | "updated" ? {
134
157
  id: JsonSchemaStringBuilder<string, string, false>;
135
158
  created: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
136
159
  updated: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
@@ -209,6 +232,10 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
209
232
  errorMessages?: StringMap<string>;
210
233
  hasIsOfTypeCheck?: boolean;
211
234
  }
235
+ declare function object(props: AnyObject): never;
236
+ declare function object<IN extends AnyObject>(props: {
237
+ [key in keyof IN]: JsonSchemaAnyBuilder<any, IN[key], any>;
238
+ }): JsonSchemaObjectBuilder<IN, IN, false>;
212
239
  type Expand<T> = T extends infer O ? {
213
240
  [K in keyof O]: O[K];
214
241
  } : never;
@@ -16,8 +16,9 @@ export const j = {
16
16
  boolean() {
17
17
  return new JsonSchemaBooleanBuilder();
18
18
  },
19
- object(props) {
20
- return new JsonSchemaObjectBuilder(props);
19
+ object,
20
+ objectInfer(props) {
21
+ return new JsonSchemaObjectInferringBuilder(props);
21
22
  },
22
23
  array(itemSchema) {
23
24
  return new JsonSchemaArrayBuilder(itemSchema);
@@ -150,6 +151,13 @@ export class JsonSchemaAnyBuilder {
150
151
  clone() {
151
152
  return new JsonSchemaAnyBuilder(_deepCopy(this.schema));
152
153
  }
154
+ /**
155
+ * @deprecated
156
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
157
+ */
158
+ castAs() {
159
+ return this;
160
+ }
153
161
  /**
154
162
  * @experimental
155
163
  */
@@ -363,6 +371,7 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
363
371
  properties: {},
364
372
  required: [],
365
373
  additionalProperties: false,
374
+ hasIsOfTypeCheck: true,
366
375
  });
367
376
  if (props)
368
377
  this.addProperties(props);
@@ -384,6 +393,13 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
384
393
  this.schema.required = _uniq(required).sort();
385
394
  return this;
386
395
  }
396
+ /**
397
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
398
+ */
399
+ allowAdditionalProperties() {
400
+ Object.assign(this.schema, { additionalProperties: true });
401
+ return this;
402
+ }
387
403
  extend(props) {
388
404
  const newBuilder = new JsonSchemaObjectBuilder();
389
405
  Object.assign(newBuilder.schema, _deepCopy(this.schema));
@@ -403,6 +419,60 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
403
419
  });
404
420
  }
405
421
  }
422
+ export class JsonSchemaObjectInferringBuilder extends JsonSchemaAnyBuilder {
423
+ constructor(props) {
424
+ super({
425
+ type: 'object',
426
+ properties: {},
427
+ required: [],
428
+ additionalProperties: false,
429
+ });
430
+ if (props)
431
+ this.addProperties(props);
432
+ }
433
+ addProperties(props) {
434
+ const properties = {};
435
+ const required = [];
436
+ for (const [key, builder] of Object.entries(props)) {
437
+ const schema = builder.build();
438
+ if (!schema.optionalField) {
439
+ required.push(key);
440
+ }
441
+ else {
442
+ schema.optionalField = undefined;
443
+ }
444
+ properties[key] = schema;
445
+ }
446
+ this.schema.properties = properties;
447
+ this.schema.required = _uniq(required).sort();
448
+ return this;
449
+ }
450
+ /**
451
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
452
+ */
453
+ allowAdditionalProperties() {
454
+ Object.assign(this.schema, { additionalProperties: true });
455
+ return this;
456
+ }
457
+ extend(props) {
458
+ const newBuilder = new JsonSchemaObjectInferringBuilder();
459
+ Object.assign(newBuilder.schema, _deepCopy(this.schema));
460
+ const incomingSchemaBuilder = new JsonSchemaObjectInferringBuilder(props);
461
+ mergeJsonSchemaObjects(newBuilder.schema, incomingSchemaBuilder.schema);
462
+ return newBuilder;
463
+ }
464
+ /**
465
+ * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
466
+ */
467
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
468
+ dbEntity() {
469
+ return this.extend({
470
+ id: j.string(),
471
+ created: j.number().unixTimestamp2000(),
472
+ updated: j.number().unixTimestamp2000(),
473
+ });
474
+ }
475
+ }
406
476
  export class JsonSchemaArrayBuilder extends JsonSchemaAnyBuilder {
407
477
  constructor(itemsSchema) {
408
478
  super({
@@ -451,3 +521,6 @@ export class JsonSchemaEnumBuilder extends JsonSchemaAnyBuilder {
451
521
  super({ enum: enumValues });
452
522
  }
453
523
  }
524
+ function object(props) {
525
+ return new JsonSchemaObjectBuilder(props);
526
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.39.0",
4
+ "version": "15.41.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -37,10 +37,12 @@ export const j = {
37
37
  return new JsonSchemaBooleanBuilder()
38
38
  },
39
39
 
40
- object<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
40
+ object,
41
+
42
+ objectInfer<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
41
43
  props: P,
42
- ): JsonSchemaObjectBuilder<P, false> {
43
- return new JsonSchemaObjectBuilder<P, false>(props)
44
+ ): JsonSchemaObjectInferringBuilder<P, false> {
45
+ return new JsonSchemaObjectInferringBuilder<P, false>(props)
44
46
  },
45
47
 
46
48
  array<IN, OUT, Opt>(
@@ -213,6 +215,14 @@ export class JsonSchemaAnyBuilder<IN, OUT, Opt> {
213
215
  return new JsonSchemaAnyBuilder<IN, OUT, Opt>(_deepCopy(this.schema))
214
216
  }
215
217
 
218
+ /**
219
+ * @deprecated
220
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
221
+ */
222
+ castAs<T>(): JsonSchemaAnyBuilder<T, T, Opt> {
223
+ return this as unknown as JsonSchemaAnyBuilder<T, T, Opt>
224
+ }
225
+
216
226
  /**
217
227
  * @experimental
218
228
  */
@@ -489,6 +499,76 @@ export class JsonSchemaBooleanBuilder<
489
499
  }
490
500
 
491
501
  export class JsonSchemaObjectBuilder<
502
+ IN extends AnyObject,
503
+ OUT extends AnyObject,
504
+ Opt extends boolean = false,
505
+ > extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
506
+ constructor(props?: AnyObject) {
507
+ super({
508
+ type: 'object',
509
+ properties: {},
510
+ required: [],
511
+ additionalProperties: false,
512
+ hasIsOfTypeCheck: true,
513
+ })
514
+
515
+ if (props) this.addProperties(props)
516
+ }
517
+
518
+ addProperties(props: AnyObject): this {
519
+ const properties: Record<string, JsonSchema> = {}
520
+ const required: string[] = []
521
+
522
+ for (const [key, builder] of Object.entries(props)) {
523
+ const schema = builder.build()
524
+ if (!schema.optionalField) {
525
+ required.push(key)
526
+ } else {
527
+ schema.optionalField = undefined
528
+ }
529
+ properties[key] = schema
530
+ }
531
+
532
+ this.schema.properties = properties
533
+ this.schema.required = _uniq(required).sort()
534
+
535
+ return this
536
+ }
537
+
538
+ /**
539
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
540
+ */
541
+ allowAdditionalProperties(): this {
542
+ Object.assign(this.schema, { additionalProperties: true })
543
+ return this
544
+ }
545
+
546
+ extend<IN2 extends AnyObject>(
547
+ props: AnyObject,
548
+ ): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt> {
549
+ const newBuilder = new JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt>()
550
+ Object.assign(newBuilder.schema, _deepCopy(this.schema))
551
+
552
+ const incomingSchemaBuilder = new JsonSchemaObjectBuilder<IN2, IN2, false>(props)
553
+ mergeJsonSchemaObjects(newBuilder.schema as any, incomingSchemaBuilder.schema as any)
554
+
555
+ return newBuilder
556
+ }
557
+
558
+ /**
559
+ * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
560
+ */
561
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types
562
+ dbEntity() {
563
+ return this.extend({
564
+ id: j.string(),
565
+ created: j.number().unixTimestamp2000(),
566
+ updated: j.number().unixTimestamp2000(),
567
+ })
568
+ }
569
+ }
570
+
571
+ export class JsonSchemaObjectInferringBuilder<
492
572
  PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>,
493
573
  Opt extends boolean = false,
494
574
  > extends JsonSchemaAnyBuilder<
@@ -555,9 +635,17 @@ export class JsonSchemaObjectBuilder<
555
635
  return this
556
636
  }
557
637
 
638
+ /**
639
+ * When set, the validation will not strip away properties that are not specified explicitly in the schema.
640
+ */
641
+ allowAdditionalProperties(): this {
642
+ Object.assign(this.schema, { additionalProperties: true })
643
+ return this
644
+ }
645
+
558
646
  extend<NEW_PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
559
647
  props: NEW_PROPS,
560
- ): JsonSchemaObjectBuilder<
648
+ ): JsonSchemaObjectInferringBuilder<
561
649
  {
562
650
  [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS
563
651
  ? NEW_PROPS[K]
@@ -567,13 +655,13 @@ export class JsonSchemaObjectBuilder<
567
655
  },
568
656
  Opt
569
657
  > {
570
- const newBuilder = new JsonSchemaObjectBuilder<PROPS, Opt>()
658
+ const newBuilder = new JsonSchemaObjectInferringBuilder<PROPS, Opt>()
571
659
  Object.assign(newBuilder.schema, _deepCopy(this.schema))
572
660
 
573
- const incomingSchemaBuilder = new JsonSchemaObjectBuilder<NEW_PROPS, false>(props)
661
+ const incomingSchemaBuilder = new JsonSchemaObjectInferringBuilder<NEW_PROPS, false>(props)
574
662
  mergeJsonSchemaObjects(newBuilder.schema as any, incomingSchemaBuilder.schema as any)
575
663
 
576
- return newBuilder as JsonSchemaObjectBuilder<
664
+ return newBuilder as JsonSchemaObjectInferringBuilder<
577
665
  {
578
666
  [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS
579
667
  ? NEW_PROPS[K]
@@ -734,6 +822,17 @@ export interface JsonSchema<IN = unknown, OUT = IN> {
734
822
  hasIsOfTypeCheck?: boolean
735
823
  }
736
824
 
825
+ function object(props: AnyObject): never
826
+ function object<IN extends AnyObject>(props: {
827
+ [key in keyof IN]: JsonSchemaAnyBuilder<any, IN[key], any>
828
+ }): JsonSchemaObjectBuilder<IN, IN, false>
829
+
830
+ function object<IN extends AnyObject>(props: {
831
+ [key in keyof IN]: JsonSchemaAnyBuilder<any, IN[key], any>
832
+ }): JsonSchemaObjectBuilder<IN, IN, false> {
833
+ return new JsonSchemaObjectBuilder<IN, IN, false>(props)
834
+ }
835
+
737
836
  type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
738
837
 
739
838
  type ExactMatch<A, B> =