@tsed/schema 8.17.1-rc.1 → 8.17.2

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,48 +1,57 @@
1
- import { cleanObject } from "@tsed/core";
1
+ import { cleanObject } from "@tsed/core/utils/cleanObject.js";
2
+ import { uniq } from "@tsed/core/utils/uniq.js";
2
3
  import { MANY_OF_PROPERTIES } from "../../constants/jsonSchemaProperties.js";
3
4
  import { registerJsonSchemaMapper } from "../../registries/JsonSchemaMapperContainer.js";
4
5
  export function nullableMapper(obj, schema) {
5
- if (!schema?.isNullable) {
6
+ if (!schema?.isNullable || obj.discriminator) {
6
7
  return obj;
7
8
  }
8
- if (!obj.discriminator) {
9
- if (obj.$ref) {
10
- obj = cleanObject({
11
- ...obj,
12
- $ref: undefined,
13
- anyOf: [
14
- { type: "null" },
15
- {
16
- $ref: obj.$ref
17
- }
18
- ]
19
- });
20
- }
21
- else {
22
- MANY_OF_PROPERTIES.some((keyword) => {
23
- if (obj[keyword]) {
24
- obj[keyword] = obj[keyword].filter((item) => item.type !== "null");
25
- if (obj[keyword].length === 1) {
26
- const base = obj[keyword];
27
- obj = cleanObject({
28
- ...obj,
29
- ...base[0],
30
- [keyword]: undefined,
31
- type: ["null", Number.isInteger(obj.multipleOf) ? "integer" : base[0].type]
32
- });
33
- }
34
- else {
35
- obj[keyword] = [{ type: "null" }].concat(obj[keyword]).map((item) => {
36
- if (Number.isInteger(item.multipleOf)) {
37
- item.type = "integer";
38
- }
39
- return item;
40
- });
41
- delete obj.type;
42
- }
9
+ if (obj.$ref) {
10
+ return cleanObject({
11
+ ...obj,
12
+ $ref: undefined,
13
+ oneOf: [
14
+ // Note: anyOf work but isn't correct, oneOf can cause issue if the object shape match with 2 or more schema with the lax constraint
15
+ { type: "null" },
16
+ {
17
+ $ref: obj.$ref
43
18
  }
44
- });
45
- }
19
+ ]
20
+ });
21
+ }
22
+ if (obj.type === "array") {
23
+ return {
24
+ oneOf: [{ type: "null" }, obj]
25
+ };
26
+ }
27
+ if (obj["oneOf"] || obj["anyOf"] || obj["allOf"]) {
28
+ MANY_OF_PROPERTIES.some((keyword) => {
29
+ if (obj[keyword]) {
30
+ obj[keyword] = obj[keyword].filter((item) => item.type !== "null");
31
+ if (obj[keyword].length === 1) {
32
+ const base = obj[keyword];
33
+ obj = cleanObject({
34
+ ...obj,
35
+ ...base[0],
36
+ [keyword]: undefined,
37
+ type: ["null", Number.isInteger(obj.multipleOf) ? "integer" : base[0].type]
38
+ });
39
+ }
40
+ else {
41
+ obj[keyword] = [{ type: "null" }].concat(obj[keyword]).map((item) => {
42
+ if (Number.isInteger(item.multipleOf)) {
43
+ item.type = "integer";
44
+ }
45
+ return item;
46
+ });
47
+ delete obj.type;
48
+ }
49
+ }
50
+ });
51
+ return obj;
52
+ }
53
+ if (obj.type) {
54
+ obj.type = uniq([].concat("null", obj.type));
46
55
  }
47
56
  return obj;
48
57
  }
@@ -12,35 +12,30 @@ export function nullableMapperOpenApi(obj, schema, options) {
12
12
  if (obj.$ref) {
13
13
  return cleanObject({
14
14
  ...obj,
15
- ...(obj.$ref && {
16
- anyOf: [
17
- {
18
- $ref: obj.$ref
19
- }
20
- ],
21
- type: undefined
22
- }),
23
- nullable: true,
24
- $ref: undefined
15
+ nullable: true
25
16
  });
26
17
  }
27
- return cleanObject({
28
- ...obj,
29
- ...(obj.anyOf?.length === 1
30
- ? {
31
- ...obj.anyOf[0],
32
- anyOf: undefined,
33
- type: Number.isInteger(obj.multipleOf) ? "integer" : obj.anyOf[0]?.type
34
- }
35
- : {
36
- type: obj.anyOf?.length > 1 ? undefined : obj.type,
37
- anyOf: obj.anyOf?.map((item) => {
18
+ function map(manyOf) {
19
+ return obj[manyOf]?.length === 1
20
+ ? cleanObject({
21
+ ...obj[manyOf][0],
22
+ [manyOf]: undefined,
23
+ type: Number.isInteger(obj.multipleOf) ? "integer" : obj[manyOf][0]?.type
24
+ })
25
+ : cleanObject({
26
+ type: obj[manyOf]?.length > 1 ? undefined : obj.type,
27
+ [manyOf]: obj[manyOf]?.map((item) => {
38
28
  if (Number.isInteger(item.multipleOf)) {
39
29
  item.type = "integer";
40
30
  }
41
31
  return item;
42
32
  })
43
- }),
33
+ });
34
+ }
35
+ return cleanObject({
36
+ ...obj,
37
+ ...map("oneOf"),
38
+ ...map("anyOf"),
44
39
  nullable: true
45
40
  });
46
41
  }
@@ -1,5 +1,8 @@
1
1
  import { useDecorators } from "@tsed/core";
2
- import { Any } from "./any.js";
2
+ import { JsonSchema } from "../../domain/JsonSchema.js";
3
+ import { array } from "../../fn/collection.js";
4
+ import { JsonEntityFn } from "./jsonEntityFn.js";
5
+ import { OneOf } from "./oneOf.js";
3
6
  import { Property } from "./property.js";
4
7
  /**
5
8
  * Set field as nullable.
@@ -25,5 +28,13 @@ import { Property } from "./property.js";
25
28
  */
26
29
  export function Nullable(type, ...types) {
27
30
  types = [type, ...types];
28
- return useDecorators(types.length === 1 && Property(types[0]), Any(null, ...types));
31
+ if (type === Array) {
32
+ return JsonEntityFn((entity) => {
33
+ entity.schema.assign(array()
34
+ .items({})
35
+ .$comment("Warning: you should not use @Nullable(Array), which leads to an incorrect schema. Use @Schema(array().items().nullable()) instead")
36
+ .nullable(true));
37
+ });
38
+ }
39
+ return useDecorators(types.length === 1 && !(type instanceof JsonSchema) && Property(types[0]), OneOf(null, ...types));
29
40
  }
@@ -27,16 +27,16 @@ function mapToJsonSchema(item) {
27
27
  if (isArray(item)) {
28
28
  return item.map(mapToJsonSchema);
29
29
  }
30
- if (item.isStore || item.$isJsonDocument || item.isLazyRef) {
30
+ if (item && (item.isStore || item.$isJsonDocument || item.isLazyRef)) {
31
31
  return item;
32
32
  }
33
- if (classOf(item) !== Object && isClass(item)) {
33
+ if (item && classOf(item) !== Object && isClass(item)) {
34
34
  return JsonEntityStore.from(item).schema;
35
35
  }
36
36
  if (isObject(item)) {
37
37
  return JsonSchema.from(item);
38
38
  }
39
- if (isPrimitiveClass(item)) {
39
+ if (isPrimitiveClass(item) || item === Date || item === null) {
40
40
  return JsonSchema.from({ type: item });
41
41
  }
42
42
  return item;
@@ -173,7 +173,7 @@ export class JsonSchema extends Map {
173
173
  return this.#useRefLabel;
174
174
  }
175
175
  get isNullable() {
176
- return !!this.get("nullable");
176
+ return !!this.get(VendorKeys.NULLABLE);
177
177
  }
178
178
  get isReadOnly() {
179
179
  return this.get("readOnly");
@@ -188,10 +188,10 @@ export class JsonSchema extends Map {
188
188
  if (item instanceof JsonSchema) {
189
189
  return item;
190
190
  }
191
- if (classOf(item) !== Object && isClass(item)) {
191
+ if (item && classOf(item) !== Object && isClass(item)) {
192
192
  return JsonEntityStore.from(item).schema;
193
193
  }
194
- if (isPrimitiveClass(item)) {
194
+ if (isPrimitiveClass(item) || item === Date || item === null) {
195
195
  return new JsonSchema({ type: item });
196
196
  }
197
197
  return new JsonSchema(item);
@@ -272,7 +272,9 @@ export class JsonSchema extends Map {
272
272
  return this;
273
273
  }
274
274
  nullable(value) {
275
- this.vendorKey(VendorKeys.NULLABLE, value);
275
+ if (!this.isNullable) {
276
+ this.vendorKey(VendorKeys.NULLABLE, value);
277
+ }
276
278
  return this;
277
279
  }
278
280
  itemSchema(obj = {}) {
@@ -445,6 +447,10 @@ export class JsonSchema extends Map {
445
447
  super.set("items", (this.#itemSchema = mapToJsonSchema(items)));
446
448
  return this;
447
449
  }
450
+ $comment(comment) {
451
+ super.set("$comment", comment);
452
+ return this;
453
+ }
448
454
  /**
449
455
  * Must be a non-negative integer.
450
456
  * An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword.
@@ -504,7 +510,13 @@ export class JsonSchema extends Map {
504
510
  this.set("minLength", undefined);
505
511
  break;
506
512
  case null:
507
- this.any(...["null"].concat(this.getJsonType(), this.$allow.map((v) => typeof v)));
513
+ this.nullable(true);
514
+ // this.any(
515
+ // ...["null"].concat(
516
+ // this.getJsonType(),
517
+ // this.$allow.map((v) => typeof v)
518
+ // )
519
+ // );
508
520
  break;
509
521
  }
510
522
  });
@@ -830,12 +842,12 @@ export class JsonSchema extends Map {
830
842
  return this;
831
843
  }
832
844
  any(...types) {
833
- types = types.length ? types : ["integer", "number", "string", "boolean", "array", "object", "null"];
845
+ types = types.length ? types : ["integer", "number", "string", "boolean", "array", "object", "null"]; // should be simplified by no type
834
846
  types = uniq(types).map((o) => {
835
847
  return isClass(o) ? o : { type: getJsonType(o) };
836
848
  });
837
849
  if (types.length > 1) {
838
- this.anyOf(types);
850
+ this.oneOf(types);
839
851
  }
840
852
  else {
841
853
  this.type(types[0]?.type || types[0]);
@@ -995,7 +1007,7 @@ export class JsonSchema extends Map {
995
1007
  setManyOf(keyword, value) {
996
1008
  let resolved = value
997
1009
  .filter((o) => {
998
- if (o && "type" in o && o.type === "null") {
1010
+ if ((o && "type" in o && o.type === "null") || o === null) {
999
1011
  this.nullable(true);
1000
1012
  return false;
1001
1013
  }
@@ -0,0 +1,36 @@
1
+ import { allOf } from "./allOf.js";
2
+ import { anyOf } from "./anyOf.js";
3
+ import { boolean } from "./boolean.js";
4
+ import { array, map, set } from "./collection.js";
5
+ import { date, datetime, time } from "./date.js";
6
+ import { email } from "./email.js";
7
+ import { enums } from "./enums.js";
8
+ import { integer } from "./integer.js";
9
+ import { lazyRef } from "./lazyRef.js";
10
+ import { number } from "./number.js";
11
+ import { object } from "./object.js";
12
+ import { oneOf } from "./oneOf.js";
13
+ import { string } from "./string.js";
14
+ import { uri } from "./uri.js";
15
+ import { url } from "./url.js";
16
+ export const s = {
17
+ allOf,
18
+ anyOf,
19
+ boolean,
20
+ array,
21
+ map,
22
+ set,
23
+ date,
24
+ datetime,
25
+ time,
26
+ email,
27
+ enums,
28
+ integer,
29
+ number,
30
+ lazyRef,
31
+ object,
32
+ oneOf,
33
+ string,
34
+ uri,
35
+ url
36
+ };
@@ -1,4 +1,6 @@
1
- import { isBoolean, isNumber, isString } from "@tsed/core";
1
+ import { isBoolean } from "@tsed/core/utils/isBoolean.js";
2
+ import { isNumber } from "@tsed/core/utils/isNumber.js";
3
+ import { isString } from "@tsed/core/utils/isString.js";
2
4
  import { ARRAY_PROPERTIES, BOOLEAN_PROPERTIES, COMMON_PROPERTIES, MANY_OF_PROPERTIES, NUMBER_PROPERTIES, OBJECT_PROPERTIES, STRING_PROPERTIES } from "../constants/jsonSchemaProperties.js";
3
5
  function findManyOf(obj) {
4
6
  return MANY_OF_PROPERTIES.find((keyword) => obj[keyword]);
package/lib/esm/index.js CHANGED
@@ -143,6 +143,7 @@ export * from "./fn/date.js";
143
143
  export * from "./fn/email.js";
144
144
  export * from "./fn/enums.js";
145
145
  export * from "./fn/from.js";
146
+ export * from "./fn/index.js";
146
147
  export * from "./fn/integer.js";
147
148
  export * from "./fn/lazyRef.js";
148
149
  export * from "./fn/number.js";
@@ -1,4 +1,4 @@
1
- import { AnyJsonSchema } from "../../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26
4
4
  *
@@ -10,4 +10,4 @@ import { AnyJsonSchema } from "../../domain/JsonSchema.js";
10
10
  * @input
11
11
  * @param allOf
12
12
  */
13
- export declare function AllOf(...allOf: AnyJsonSchema[]): (...args: any[]) => any;
13
+ export declare function AllOf(...allOf: Parameters<JsonSchema["allOf"]>[0]): (...args: any[]) => any;
@@ -1,4 +1,4 @@
1
- import { AnyJsonSchema } from "../../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27
4
4
  *
@@ -14,4 +14,4 @@ import { AnyJsonSchema } from "../../domain/JsonSchema.js";
14
14
  * @input
15
15
  * @param anyOf
16
16
  */
17
- export declare function AnyOf(...anyOf: AnyJsonSchema[]): (...args: any[]) => any;
17
+ export declare function AnyOf(...anyOf: Parameters<JsonSchema["anyOf"]>[0]): (...args: any[]) => any;
@@ -1,4 +1,4 @@
1
- import { AnyJsonSchema } from "../../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28
4
4
  *
@@ -14,4 +14,4 @@ import { AnyJsonSchema } from "../../domain/JsonSchema.js";
14
14
  * @input
15
15
  * @param oneOf
16
16
  */
17
- export declare function OneOf(...oneOf: AnyJsonSchema[]): (...args: any[]) => any;
17
+ export declare function OneOf(...oneOf: Parameters<JsonSchema["oneOf"]>[0]): (...args: any[]) => any;
@@ -154,6 +154,7 @@ export declare class JsonSchema extends Map<string, any> {
154
154
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.9
155
155
  */
156
156
  items(items: AnyJsonSchema | AnyJsonSchema[]): this;
157
+ $comment(comment: string): this;
157
158
  /**
158
159
  * Must be a non-negative integer.
159
160
  * An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword.
@@ -272,12 +273,12 @@ export declare class JsonSchema extends Map<string, any> {
272
273
  /**
273
274
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26
274
275
  */
275
- allOf(allOf: AnyJsonSchema[]): this;
276
+ allOf(allOf: (AnyJsonSchema | null)[]): this;
276
277
  /**
277
278
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27
278
279
  */
279
- anyOf(anyOf: AnyJsonSchema[]): this;
280
- oneOf(oneOf: AnyJsonSchema[]): this;
280
+ anyOf(anyOf: (AnyJsonSchema | null)[]): this;
281
+ oneOf(oneOf: (AnyJsonSchema | null)[]): this;
281
282
  /**
282
283
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.29
283
284
  */
@@ -381,5 +382,5 @@ export declare class JsonSchema extends Map<string, any> {
381
382
  getPropertyKey(): string | symbol | undefined;
382
383
  target(target: any): void;
383
384
  isRequiredValue(property: string, value: any): boolean;
384
- protected setManyOf(keyword: "oneOf" | "anyOf" | "allOf", value: AnyJsonSchema[]): this | undefined;
385
+ protected setManyOf(keyword: "oneOf" | "anyOf" | "allOf", value: (AnyJsonSchema | null)[]): this | undefined;
385
386
  }
@@ -1,4 +1,4 @@
1
- import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26
4
4
  *
@@ -6,4 +6,4 @@ import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
6
6
  *
7
7
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.26
8
8
  */
9
- export declare function allOf(...allOf: AnyJsonSchema[]): JsonSchema;
9
+ export declare function allOf(...allOf: Parameters<JsonSchema["allOf"]>[0]): JsonSchema;
@@ -1,7 +1,7 @@
1
- import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../domain/JsonSchema.js";
2
2
  /**
3
3
  * Declare a model with any type (By default: `integer`, `number`, `string`, `boolean`, `array`, `object`, `null`)
4
4
  *
5
5
  * See @@JsonSchema@@ to discover available methods.
6
6
  */
7
- export declare function any(...types: AnyJsonSchema[]): JsonSchema;
7
+ export declare function any(...types: Parameters<JsonSchema["oneOf"]>[0]): JsonSchema;
@@ -1,4 +1,4 @@
1
- import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27
4
4
  *
@@ -6,4 +6,4 @@ import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
6
6
  *
7
7
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.27
8
8
  */
9
- export declare function anyOf(...anyOf: AnyJsonSchema[]): JsonSchema;
9
+ export declare function anyOf(...anyOf: Parameters<JsonSchema["allOf"]>[0]): JsonSchema;
@@ -0,0 +1,36 @@
1
+ import { allOf } from "./allOf.js";
2
+ import { anyOf } from "./anyOf.js";
3
+ import { boolean } from "./boolean.js";
4
+ import { array, map, set } from "./collection.js";
5
+ import { date, datetime, time } from "./date.js";
6
+ import { email } from "./email.js";
7
+ import { enums } from "./enums.js";
8
+ import { integer } from "./integer.js";
9
+ import { lazyRef } from "./lazyRef.js";
10
+ import { number } from "./number.js";
11
+ import { object } from "./object.js";
12
+ import { oneOf } from "./oneOf.js";
13
+ import { string } from "./string.js";
14
+ import { uri } from "./uri.js";
15
+ import { url } from "./url.js";
16
+ export declare const s: {
17
+ readonly allOf: typeof allOf;
18
+ readonly anyOf: typeof anyOf;
19
+ readonly boolean: typeof boolean;
20
+ readonly array: typeof array;
21
+ readonly map: typeof map;
22
+ readonly set: typeof set;
23
+ readonly date: typeof date;
24
+ readonly datetime: typeof datetime;
25
+ readonly time: typeof time;
26
+ readonly email: typeof email;
27
+ readonly enums: typeof enums;
28
+ readonly integer: typeof integer;
29
+ readonly number: typeof number;
30
+ readonly lazyRef: typeof lazyRef;
31
+ readonly object: typeof object;
32
+ readonly oneOf: typeof oneOf;
33
+ readonly string: typeof string;
34
+ readonly uri: typeof uri;
35
+ readonly url: typeof url;
36
+ };
@@ -1,4 +1,4 @@
1
- import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
1
+ import type { JsonSchema } from "../domain/JsonSchema.js";
2
2
  /**
3
3
  * See https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28
4
4
  *
@@ -7,4 +7,4 @@ import type { AnyJsonSchema, JsonSchema } from "../domain/JsonSchema.js";
7
7
  * @schemaFunctional
8
8
  * @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28
9
9
  */
10
- export declare function oneOf(...oneOf: AnyJsonSchema[]): JsonSchema;
10
+ export declare function oneOf(...oneOf: Parameters<JsonSchema["oneOf"]>[0]): JsonSchema;
@@ -143,6 +143,7 @@ export * from "./fn/date.js";
143
143
  export * from "./fn/email.js";
144
144
  export * from "./fn/enums.js";
145
145
  export * from "./fn/from.js";
146
+ export * from "./fn/index.js";
146
147
  export * from "./fn/integer.js";
147
148
  export * from "./fn/lazyRef.js";
148
149
  export * from "./fn/number.js";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tsed/schema",
3
3
  "description": "JsonSchema module for Ts.ED Framework",
4
4
  "type": "module",
5
- "version": "8.17.1-rc.1",
5
+ "version": "8.17.2",
6
6
  "source": "./src/index.ts",
7
7
  "main": "./lib/esm/index.js",
8
8
  "module": "./lib/esm/index.js",
@@ -34,7 +34,7 @@
34
34
  "tsed"
35
35
  ],
36
36
  "dependencies": {
37
- "@tsed/openspec": "8.17.1-rc.1",
37
+ "@tsed/openspec": "8.17.2",
38
38
  "change-case": "^5.4.4",
39
39
  "json-schema": "0.4.0",
40
40
  "picomatch": "4.0.2",
@@ -43,11 +43,11 @@
43
43
  },
44
44
  "devDependencies": {
45
45
  "@apidevtools/swagger-parser": "10.1.0",
46
- "@tsed/barrels": "8.17.1-rc.1",
47
- "@tsed/core": "8.17.1-rc.1",
48
- "@tsed/hooks": "8.17.1-rc.1",
49
- "@tsed/openspec": "8.17.1-rc.1",
50
- "@tsed/typescript": "8.17.1-rc.1",
46
+ "@tsed/barrels": "8.17.2",
47
+ "@tsed/core": "8.17.2",
48
+ "@tsed/hooks": "8.17.2",
49
+ "@tsed/openspec": "8.17.2",
50
+ "@tsed/typescript": "8.17.2",
51
51
  "@types/fs-extra": "11.0.4",
52
52
  "@types/json-schema": "7.0.15",
53
53
  "@types/picomatch": "3.0.2",
@@ -76,8 +76,5 @@
76
76
  },
77
77
  "homepage": "https://github.com/tsedio/tsed/tree/production/packages/specs/schema",
78
78
  "author": "Romain Lenzotti",
79
- "license": "MIT",
80
- "publishConfig": {
81
- "tag": "rc"
82
- }
79
+ "license": "MIT"
83
80
  }