@naturalcycles/nodejs-lib 15.61.1 → 15.62.1

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.
@@ -235,11 +235,34 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
235
235
  * When set, the validation will not strip away properties that are not specified explicitly in the schema.
236
236
  */
237
237
  allowAdditionalProperties(): this;
238
- extend<IN2 extends AnyObject>(props: AnyObject): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt>;
238
+ extend(props: AnyObject): never;
239
+ extend<IN2 extends AnyObject>(props: {
240
+ [K in keyof Required<IN2>]-?: JsonSchemaAnyBuilder<any, IN2[K], any>;
241
+ }): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, false>;
242
+ /**
243
+ * Concatenates another schema to the current schema.
244
+ *
245
+ * It expects 2 types to be passed in as a generic:
246
+ * 1) the expected final type,
247
+ * 2) the type of the passed in schema.
248
+ *
249
+ * ```ts
250
+ * interface Foo { foo: string }
251
+ * const fooSchema = j.object<Foo>({ foo: j.string() })
252
+ *
253
+ * interface Bar { bar: number }
254
+ * const barSchema = j.object<Bar>({ bar: j.number() })
255
+ *
256
+ * interface Shu { foo: string, bar: number }
257
+ * const shuSchema = fooSchema.concat<Shu, Bar>(barSchema)
258
+ * ```
259
+ */
260
+ concat(other: any): never;
261
+ concat<NEW_TYPE extends AnyObject, OUT2 extends AnyObject>(other: JsonSchemaObjectBuilder<any, OUT2, any>): ExactMatch<NEW_TYPE, OUT & OUT2> extends true ? JsonSchemaObjectBuilder<NEW_TYPE, NEW_TYPE, false> : never;
239
262
  /**
240
263
  * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
241
264
  */
242
- dbEntity(): JsonSchemaObjectBuilder<any, any, Opt>;
265
+ dbEntity(): never;
243
266
  minProperties(minProperties: number): this;
244
267
  maxProperties(maxProperties: number): this;
245
268
  }
@@ -589,6 +589,15 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
589
589
  const clone = this.clone();
590
590
  const incomingSchemaBuilder = new JsonSchemaObjectBuilder(props);
591
591
  mergeJsonSchemaObjects(clone.schema, incomingSchemaBuilder.schema);
592
+ // The incoming object is type-safe because `extend<Foo>()` expects a passed in type that matches the passed in props,
593
+ // but maybe the current schema was created differently, so that's what decides the typecheckedness.
594
+ const hasIsOfTypeCheck = this.schema.hasIsOfTypeCheck;
595
+ _objectAssign(clone.schema, { hasIsOfTypeCheck });
596
+ return clone;
597
+ }
598
+ concat(other) {
599
+ const clone = this.clone();
600
+ mergeJsonSchemaObjects(clone.schema, other.schema);
592
601
  return clone;
593
602
  }
594
603
  /**
@@ -646,6 +655,10 @@ export class JsonSchemaObjectInferringBuilder extends JsonSchemaAnyBuilder {
646
655
  _objectAssign(newBuilder.schema, _deepCopy(this.schema));
647
656
  const incomingSchemaBuilder = new JsonSchemaObjectInferringBuilder(props);
648
657
  mergeJsonSchemaObjects(newBuilder.schema, incomingSchemaBuilder.schema);
658
+ // This extend function is not type-safe as it is inferring,
659
+ // so even if the base schema was already type-checked,
660
+ // the new schema loses that quality.
661
+ _objectAssign(newBuilder.schema, { hasIsOfTypeCheck: false });
649
662
  return newBuilder;
650
663
  }
651
664
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.61.1",
4
+ "version": "15.62.1",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -828,14 +828,53 @@ export class JsonSchemaObjectBuilder<
828
828
  return this.cloneAndUpdateSchema({ additionalProperties: true })
829
829
  }
830
830
 
831
- extend<IN2 extends AnyObject>(
832
- props: AnyObject,
833
- ): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt> {
834
- const clone = this.clone() as JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, Opt>
831
+ extend(props: AnyObject): never
832
+ extend<IN2 extends AnyObject>(props: {
833
+ [K in keyof Required<IN2>]-?: JsonSchemaAnyBuilder<any, IN2[K], any>
834
+ }): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, false>
835
+ extend<IN2 extends AnyObject>(props: {
836
+ [key in keyof IN2]: JsonSchemaAnyBuilder<any, IN2[key], any>
837
+ }): JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, false> {
838
+ const clone = this.clone()
835
839
 
836
840
  const incomingSchemaBuilder = new JsonSchemaObjectBuilder<IN2, IN2, false>(props)
837
841
  mergeJsonSchemaObjects(clone.schema as any, incomingSchemaBuilder.schema as any)
838
842
 
843
+ // The incoming object is type-safe because `extend<Foo>()` expects a passed in type that matches the passed in props,
844
+ // but maybe the current schema was created differently, so that's what decides the typecheckedness.
845
+ const hasIsOfTypeCheck = this.schema.hasIsOfTypeCheck
846
+ _objectAssign(clone.schema, { hasIsOfTypeCheck })
847
+
848
+ return clone as unknown as JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, false>
849
+ }
850
+
851
+ /**
852
+ * Concatenates another schema to the current schema.
853
+ *
854
+ * It expects 2 types to be passed in as a generic:
855
+ * 1) the expected final type,
856
+ * 2) the type of the passed in schema.
857
+ *
858
+ * ```ts
859
+ * interface Foo { foo: string }
860
+ * const fooSchema = j.object<Foo>({ foo: j.string() })
861
+ *
862
+ * interface Bar { bar: number }
863
+ * const barSchema = j.object<Bar>({ bar: j.number() })
864
+ *
865
+ * interface Shu { foo: string, bar: number }
866
+ * const shuSchema = fooSchema.concat<Shu, Bar>(barSchema)
867
+ * ```
868
+ */
869
+ concat(other: any): never
870
+ concat<NEW_TYPE extends AnyObject, OUT2 extends AnyObject>(
871
+ other: JsonSchemaObjectBuilder<any, OUT2, any>,
872
+ ): ExactMatch<NEW_TYPE, OUT & OUT2> extends true
873
+ ? JsonSchemaObjectBuilder<NEW_TYPE, NEW_TYPE, false>
874
+ : never
875
+ concat(other: any): any {
876
+ const clone = this.clone()
877
+ mergeJsonSchemaObjects(clone.schema as any, other.schema)
839
878
  return clone
840
879
  }
841
880
 
@@ -959,6 +998,11 @@ export class JsonSchemaObjectInferringBuilder<
959
998
  const incomingSchemaBuilder = new JsonSchemaObjectInferringBuilder<NEW_PROPS, false>(props)
960
999
  mergeJsonSchemaObjects(newBuilder.schema as any, incomingSchemaBuilder.schema as any)
961
1000
 
1001
+ // This extend function is not type-safe as it is inferring,
1002
+ // so even if the base schema was already type-checked,
1003
+ // the new schema loses that quality.
1004
+ _objectAssign(newBuilder.schema, { hasIsOfTypeCheck: false })
1005
+
962
1006
  return newBuilder as JsonSchemaObjectInferringBuilder<
963
1007
  {
964
1008
  [K in keyof PROPS | keyof NEW_PROPS]: K extends keyof NEW_PROPS