@naturalcycles/nodejs-lib 15.63.0 → 15.64.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.
@@ -235,16 +235,21 @@ 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(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>;
238
+ extend<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(props: P): JsonSchemaObjectBuilder<IN & {
239
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? never : K : never]: P[K] extends JsonSchemaAnyBuilder<infer IN2, any, any> ? IN2 : never;
240
+ } & {
241
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: P[K] extends JsonSchemaAnyBuilder<infer IN2, any, any> ? IN2 : never;
242
+ }, OUT & {
243
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? never : K : never]: P[K] extends JsonSchemaAnyBuilder<any, infer OUT2, any> ? OUT2 : never;
244
+ } & {
245
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? K : never : never]?: P[K] extends JsonSchemaAnyBuilder<any, infer OUT2, any> ? OUT2 : never;
246
+ }, false>;
242
247
  /**
243
248
  * Concatenates another schema to the current schema.
244
249
  *
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.
250
+ * It expects you to use `isOfType<T>()` in the chain,
251
+ * otherwise the validation will throw. This is to ensure
252
+ * that the schemas you concatenated match the intended final type.
248
253
  *
249
254
  * ```ts
250
255
  * interface Foo { foo: string }
@@ -254,15 +259,22 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
254
259
  * const barSchema = j.object<Bar>({ bar: j.number() })
255
260
  *
256
261
  * interface Shu { foo: string, bar: number }
257
- * const shuSchema = fooSchema.concat<Shu, Bar>(barSchema)
262
+ * const shuSchema = fooSchema.concat(barSchema).isOfType<Shu>() // important
258
263
  * ```
259
264
  */
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;
265
+ concat<IN2 extends AnyObject, OUT2 extends AnyObject>(other: JsonSchemaObjectBuilder<IN2, OUT2, any>): JsonSchemaObjectBuilder<IN & IN2, OUT & OUT2, false>;
262
266
  /**
263
267
  * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
264
268
  */
265
- dbEntity(): never;
269
+ dbEntity(): JsonSchemaObjectBuilder<IN & {
270
+ id: string;
271
+ created: any;
272
+ updated: any;
273
+ } & {}, OUT & {
274
+ id: string;
275
+ created: any;
276
+ updated: any;
277
+ } & {}, false>;
266
278
  minProperties(minProperties: number): this;
267
279
  maxProperties(maxProperties: number): this;
268
280
  }
@@ -292,7 +304,7 @@ export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<strin
292
304
  /**
293
305
  * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
294
306
  */
295
- dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in "id" | keyof PROPS | "created" | "updated"]: K extends "id" | "created" | "updated" ? {
307
+ dbEntity(): JsonSchemaObjectInferringBuilder<{ [K in "id" | "created" | "updated" | keyof PROPS]: K extends "id" | "created" | "updated" ? {
296
308
  id: JsonSchemaStringBuilder<string, string, false>;
297
309
  created: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
298
310
  updated: JsonSchemaNumberBuilder<UnixTimestamp, UnixTimestamp, false>;
@@ -586,18 +586,35 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
586
586
  return this.cloneAndUpdateSchema({ additionalProperties: true });
587
587
  }
588
588
  extend(props) {
589
- const clone = this.clone();
589
+ const newBuilder = new JsonSchemaObjectBuilder();
590
+ _objectAssign(newBuilder.schema, _deepCopy(this.schema));
590
591
  const incomingSchemaBuilder = new JsonSchemaObjectBuilder(props);
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;
592
+ mergeJsonSchemaObjects(newBuilder.schema, incomingSchemaBuilder.schema);
593
+ _objectAssign(newBuilder.schema, { hasIsOfTypeCheck: false });
594
+ return newBuilder;
597
595
  }
596
+ /**
597
+ * Concatenates another schema to the current schema.
598
+ *
599
+ * It expects you to use `isOfType<T>()` in the chain,
600
+ * otherwise the validation will throw. This is to ensure
601
+ * that the schemas you concatenated match the intended final type.
602
+ *
603
+ * ```ts
604
+ * interface Foo { foo: string }
605
+ * const fooSchema = j.object<Foo>({ foo: j.string() })
606
+ *
607
+ * interface Bar { bar: number }
608
+ * const barSchema = j.object<Bar>({ bar: j.number() })
609
+ *
610
+ * interface Shu { foo: string, bar: number }
611
+ * const shuSchema = fooSchema.concat(barSchema).isOfType<Shu>() // important
612
+ * ```
613
+ */
598
614
  concat(other) {
599
615
  const clone = this.clone();
600
616
  mergeJsonSchemaObjects(clone.schema, other.schema);
617
+ _objectAssign(clone.schema, { hasIsOfTypeCheck: false });
601
618
  return clone;
602
619
  }
603
620
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.63.0",
4
+ "version": "15.64.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -828,32 +828,58 @@ export class JsonSchemaObjectBuilder<
828
828
  return this.cloneAndUpdateSchema({ additionalProperties: true })
829
829
  }
830
830
 
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()
831
+ extend<P extends Record<string, JsonSchemaAnyBuilder<any, any, any>>>(
832
+ props: P,
833
+ ): JsonSchemaObjectBuilder<
834
+ IN & {
835
+ // required keys
836
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt>
837
+ ? IsOpt extends true
838
+ ? never
839
+ : K
840
+ : never]: P[K] extends JsonSchemaAnyBuilder<infer IN2, any, any> ? IN2 : never
841
+ } & {
842
+ // optional keys
843
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt>
844
+ ? IsOpt extends true
845
+ ? K
846
+ : never
847
+ : never]?: P[K] extends JsonSchemaAnyBuilder<infer IN2, any, any> ? IN2 : never
848
+ },
849
+ OUT & {
850
+ // required keys
851
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt>
852
+ ? IsOpt extends true
853
+ ? never
854
+ : K
855
+ : never]: P[K] extends JsonSchemaAnyBuilder<any, infer OUT2, any> ? OUT2 : never
856
+ } & {
857
+ // optional keys
858
+ [K in keyof P as P[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt>
859
+ ? IsOpt extends true
860
+ ? K
861
+ : never
862
+ : never]?: P[K] extends JsonSchemaAnyBuilder<any, infer OUT2, any> ? OUT2 : never
863
+ },
864
+ false
865
+ > {
866
+ const newBuilder = new JsonSchemaObjectBuilder()
867
+ _objectAssign(newBuilder.schema, _deepCopy(this.schema))
839
868
 
840
- const incomingSchemaBuilder = new JsonSchemaObjectBuilder<IN2, IN2, false>(props)
841
- mergeJsonSchemaObjects(clone.schema as any, incomingSchemaBuilder.schema as any)
869
+ const incomingSchemaBuilder = new JsonSchemaObjectBuilder(props)
870
+ mergeJsonSchemaObjects(newBuilder.schema as any, incomingSchemaBuilder.schema as any)
842
871
 
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 })
872
+ _objectAssign(newBuilder.schema, { hasIsOfTypeCheck: false })
847
873
 
848
- return clone as unknown as JsonSchemaObjectBuilder<IN & IN2, OUT & IN2, false>
874
+ return newBuilder as any
849
875
  }
850
876
 
851
877
  /**
852
878
  * Concatenates another schema to the current schema.
853
879
  *
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.
880
+ * It expects you to use `isOfType<T>()` in the chain,
881
+ * otherwise the validation will throw. This is to ensure
882
+ * that the schemas you concatenated match the intended final type.
857
883
  *
858
884
  * ```ts
859
885
  * interface Foo { foo: string }
@@ -863,19 +889,16 @@ export class JsonSchemaObjectBuilder<
863
889
  * const barSchema = j.object<Bar>({ bar: j.number() })
864
890
  *
865
891
  * interface Shu { foo: string, bar: number }
866
- * const shuSchema = fooSchema.concat<Shu, Bar>(barSchema)
892
+ * const shuSchema = fooSchema.concat(barSchema).isOfType<Shu>() // important
867
893
  * ```
868
894
  */
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 {
895
+ concat<IN2 extends AnyObject, OUT2 extends AnyObject>(
896
+ other: JsonSchemaObjectBuilder<IN2, OUT2, any>,
897
+ ): JsonSchemaObjectBuilder<IN & IN2, OUT & OUT2, false> {
876
898
  const clone = this.clone()
877
- mergeJsonSchemaObjects(clone.schema as any, other.schema)
878
- return clone
899
+ mergeJsonSchemaObjects(clone.schema as any, other.schema as any)
900
+ _objectAssign(clone.schema, { hasIsOfTypeCheck: false })
901
+ return clone as unknown as JsonSchemaObjectBuilder<IN & IN2, OUT & OUT2, false>
879
902
  }
880
903
 
881
904
  /**