@tsed/schema 8.13.5 → 8.14.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.
- package/lib/esm/components/default/anyMapper.js +1 -2
- package/lib/esm/components/default/classMapper.js +2 -22
- package/lib/esm/components/default/genericsMapper.js +62 -48
- package/lib/esm/components/default/lazyRefMapper.js +1 -2
- package/lib/esm/components/default/mapMapper.js +0 -2
- package/lib/esm/components/default/nextMapper.js +74 -0
- package/lib/esm/components/default/objectMapper.js +8 -3
- package/lib/esm/components/default/ofMapper.js +2 -5
- package/lib/esm/components/default/requiredMapper.js +2 -2
- package/lib/esm/components/default/schemaMapper.js +6 -7
- package/lib/esm/components/index.js +1 -7
- package/lib/esm/components/open-spec/nullableMapper.js +5 -1
- package/lib/esm/components/open-spec/operationInParameterMapper.js +3 -7
- package/lib/esm/components/open-spec/operationInQueryMapper.js +22 -17
- package/lib/esm/components/open-spec/operationMediaMapper.js +5 -2
- package/lib/esm/components/open-spec/operationRequestBodyMapper.js +2 -2
- package/lib/esm/constants/VendorKeys.js +11 -0
- package/lib/esm/decorators/collections/collectionOf.js +14 -3
- package/lib/esm/decorators/common/description.js +9 -12
- package/lib/esm/decorators/common/discriminatorKey.js +1 -1
- package/lib/esm/decorators/common/forwardGroups.js +1 -1
- package/lib/esm/decorators/common/groups.js +15 -26
- package/lib/esm/decorators/common/oneOf.js +1 -1
- package/lib/esm/decorators/generics/genericOf.js +8 -17
- package/lib/esm/decorators/generics/generics.js +3 -3
- package/lib/esm/decorators/operations/redirect.js +1 -1
- package/lib/esm/decorators/operations/returns.js +40 -63
- package/lib/esm/domain/JsonEntityStore.js +40 -41
- package/lib/esm/domain/JsonMedia.js +27 -6
- package/lib/esm/domain/JsonMethodStore.js +28 -9
- package/lib/esm/domain/JsonOperation.js +15 -0
- package/lib/esm/domain/JsonParameter.js +11 -10
- package/lib/esm/domain/JsonParameterStore.js +3 -9
- package/lib/esm/domain/JsonPropertyStore.js +14 -45
- package/lib/esm/domain/JsonSchema.js +287 -80
- package/lib/esm/fn/email.js +2 -2
- package/lib/esm/fn/uri.js +2 -2
- package/lib/esm/fn/url.js +2 -2
- package/lib/esm/index.js +3 -8
- package/lib/esm/utils/generics.js +3 -32
- package/lib/esm/utils/getJsonSchema.js +24 -17
- package/lib/esm/utils/mergeSchema.js +98 -0
- package/lib/esm/utils/ref.js +14 -13
- package/lib/types/components/default/classMapper.d.ts +1 -1
- package/lib/types/components/default/genericsMapper.d.ts +9 -2
- package/lib/types/components/default/lazyRefMapper.d.ts +1 -1
- package/lib/types/components/default/nextMapper.d.ts +5 -0
- package/lib/types/components/default/ofMapper.d.ts +1 -1
- package/lib/types/components/index.d.ts +1 -7
- package/lib/types/components/open-spec/nullableMapper.d.ts +2 -1
- package/lib/types/components/open-spec/operationInQueryMapper.d.ts +1 -1
- package/lib/types/constants/VendorKeys.d.ts +10 -0
- package/lib/types/decorators/collections/collectionOf.d.ts +1 -1
- package/lib/types/decorators/generics/genericOf.d.ts +3 -0
- package/lib/types/decorators/generics/generics.d.ts +2 -2
- package/lib/types/decorators/operations/returns.d.ts +11 -9
- package/lib/types/domain/JsonEntityStore.d.ts +20 -18
- package/lib/types/domain/JsonMedia.d.ts +4 -5
- package/lib/types/domain/JsonMethodStore.d.ts +9 -2
- package/lib/types/domain/JsonOperation.d.ts +1 -0
- package/lib/types/domain/JsonParameter.d.ts +2 -7
- package/lib/types/domain/JsonParameterStore.d.ts +0 -2
- package/lib/types/domain/JsonPropertyStore.d.ts +1 -20
- package/lib/types/domain/JsonSchema.d.ts +82 -39
- package/lib/types/index.d.ts +3 -8
- package/lib/types/interfaces/JsonSchemaOptions.d.ts +16 -2
- package/lib/types/utils/generics.d.ts +7 -48
- package/lib/types/utils/getJsonSchema.d.ts +2 -1
- package/lib/types/utils/mergeSchema.d.ts +2 -0
- package/lib/types/utils/ref.d.ts +4 -2
- package/package.json +7 -7
- package/lib/esm/components/async-api/channelsMapper.js +0 -57
- package/lib/esm/components/async-api/generate.js +0 -17
- package/lib/esm/components/async-api/messageMapper.js +0 -39
- package/lib/esm/components/async-api/payloadMapper.js +0 -47
- package/lib/esm/components/async-api/responseMapper.js +0 -53
- package/lib/esm/components/default/itemMapper.js +0 -5
- package/lib/esm/components/default/propertiesMapper.js +0 -20
- package/lib/esm/utils/somethingOf.js +0 -11
- package/lib/types/components/async-api/channelsMapper.d.ts +0 -2
- package/lib/types/components/async-api/generate.d.ts +0 -1
- package/lib/types/components/async-api/messageMapper.d.ts +0 -6
- package/lib/types/components/async-api/payloadMapper.d.ts +0 -4
- package/lib/types/components/async-api/responseMapper.d.ts +0 -6
- package/lib/types/components/default/itemMapper.d.ts +0 -2
- package/lib/types/components/default/propertiesMapper.d.ts +0 -3
- package/lib/types/utils/somethingOf.d.ts +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { DecoratorTypes, Metadata, prototypeOf } from "@tsed/core";
|
|
2
|
+
import { DecoratorTypes, isClass, Metadata, prototypeOf } from "@tsed/core";
|
|
3
3
|
import { JsonEntityComponent } from "../decorators/config/jsonEntityComponent.js";
|
|
4
4
|
import { JsonEntityStore } from "./JsonEntityStore.js";
|
|
5
5
|
import { JsonSchema } from "./JsonSchema.js";
|
|
@@ -8,43 +8,8 @@ let JsonPropertyStore = class JsonPropertyStore extends JsonEntityStore {
|
|
|
8
8
|
super(...arguments);
|
|
9
9
|
this.parent = JsonEntityStore.from(this.target);
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* @returns {boolean}
|
|
14
|
-
*/
|
|
15
|
-
get required() {
|
|
16
|
-
return this.parent.schema.isRequired(this.propertyKey);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Change the state of the required data.
|
|
20
|
-
* @param value
|
|
21
|
-
*/
|
|
22
|
-
set required(value) {
|
|
23
|
-
if (value) {
|
|
24
|
-
this.parent.schema.addRequired(this.propertyKey);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
this.parent.schema.removeRequired(this.propertyKey);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
get allowedRequiredValues() {
|
|
31
|
-
return this.schema.$allow;
|
|
32
|
-
}
|
|
33
|
-
discriminatorKey() {
|
|
34
|
-
this.parent.schema.discriminatorKey(String(this.propertyKey));
|
|
35
|
-
this.itemSchema.isDiscriminatorKey = true;
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
isDiscriminatorKey() {
|
|
39
|
-
return this.itemSchema.isDiscriminatorKey;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Check precondition between value, required and allowedRequiredValues to know if the entity is required.
|
|
43
|
-
* @param value
|
|
44
|
-
* @returns {boolean}
|
|
45
|
-
*/
|
|
46
|
-
isRequired(value) {
|
|
47
|
-
return this.required && [undefined, null, ""].includes(value) && !this.allowedRequiredValues.includes(value);
|
|
11
|
+
static get(target, propertyKey) {
|
|
12
|
+
return JsonEntityStore.from(prototypeOf(target), propertyKey);
|
|
48
13
|
}
|
|
49
14
|
build() {
|
|
50
15
|
if (!this._type) {
|
|
@@ -55,19 +20,23 @@ let JsonPropertyStore = class JsonPropertyStore extends JsonEntityStore {
|
|
|
55
20
|
let schema = properties[this.propertyName];
|
|
56
21
|
if (!schema) {
|
|
57
22
|
this.parent.children.set(this.propertyName, this);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
23
|
+
if (this.isCollection) {
|
|
24
|
+
schema = JsonSchema.from({
|
|
25
|
+
type: this.collectionType
|
|
26
|
+
});
|
|
27
|
+
schema.itemSchema(this.type);
|
|
28
|
+
}
|
|
29
|
+
else if (isClass(this.type)) {
|
|
30
|
+
schema = JsonSchema.from({ type: "object" });
|
|
62
31
|
schema.itemSchema(this.type);
|
|
63
32
|
}
|
|
33
|
+
else {
|
|
34
|
+
schema = JsonSchema.from({ type: this.type });
|
|
35
|
+
}
|
|
64
36
|
}
|
|
65
37
|
this.parent.schema.addProperty(this.propertyName, schema);
|
|
66
38
|
this._schema = schema;
|
|
67
39
|
}
|
|
68
|
-
static get(target, propertyKey) {
|
|
69
|
-
return JsonEntityStore.from(prototypeOf(target), propertyKey);
|
|
70
|
-
}
|
|
71
40
|
};
|
|
72
41
|
JsonPropertyStore = __decorate([
|
|
73
42
|
JsonEntityComponent(DecoratorTypes.PROP)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { ancestorsOf, classOf, isArray, isClass, isFunction, isObject, isPrimitiveClass, nameOf, uniq } from "@tsed/core";
|
|
1
|
+
import { ancestorOf, ancestorsOf, classOf, isArray, isClass, isFunction, isObject, isPlainObject, isPrimitiveClass, nameOf, uniq } from "@tsed/core";
|
|
2
2
|
import { Hooks } from "@tsed/hooks";
|
|
3
|
+
import { VendorKeys } from "../constants/VendorKeys.js";
|
|
3
4
|
import { enumsRegistry } from "../registries/enumRegistries.js";
|
|
4
5
|
import { execMapper } from "../registries/JsonSchemaMapperContainer.js";
|
|
5
6
|
import { getComputedType } from "../utils/getComputedType.js";
|
|
6
7
|
import { getJsonType } from "../utils/getJsonType.js";
|
|
8
|
+
import { matchGroups } from "../utils/matchGroups.js";
|
|
7
9
|
import { serializeEnumValues } from "../utils/serializeEnumValues.js";
|
|
8
10
|
import { toJsonRegex } from "../utils/toJsonRegex.js";
|
|
9
11
|
import { Discriminator } from "./JsonDiscriminator.js";
|
|
@@ -15,6 +17,9 @@ function mapProperties(properties) {
|
|
|
15
17
|
}
|
|
16
18
|
return Object.entries(properties).reduce((properties, [key, schema]) => {
|
|
17
19
|
properties[toJsonRegex(key)] = mapToJsonSchema(schema);
|
|
20
|
+
if (schema instanceof JsonSchema) {
|
|
21
|
+
schema.propertyKey(toJsonRegex(key));
|
|
22
|
+
}
|
|
18
23
|
return properties;
|
|
19
24
|
}, {});
|
|
20
25
|
}
|
|
@@ -36,35 +41,83 @@ function mapToJsonSchema(item) {
|
|
|
36
41
|
}
|
|
37
42
|
return item;
|
|
38
43
|
}
|
|
44
|
+
function isEnum(type) {
|
|
45
|
+
return isObject(type) && !("toJSON" in type);
|
|
46
|
+
}
|
|
47
|
+
function mapGenerics(jsonSchema, generics) {
|
|
48
|
+
const genericLabels = jsonSchema.getGenericLabels();
|
|
49
|
+
if (!genericLabels) {
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
const [types, ...nextTypes] = generics;
|
|
53
|
+
return types.reduce((mapping, type, index) => {
|
|
54
|
+
const label = genericLabels[index];
|
|
55
|
+
if (label) {
|
|
56
|
+
if (isEnum(type)) {
|
|
57
|
+
mapping[label] = [JsonSchema.from({ type: "string", enum: Object.values(type) })];
|
|
58
|
+
}
|
|
59
|
+
else if (nextTypes.length) {
|
|
60
|
+
const nextSchema = mapToJsonSchema(type);
|
|
61
|
+
mapping[label] = [nextSchema, mapGenerics(nextSchema, nextTypes)];
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
mapping[label] = [mapToJsonSchema(type)];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return mapping;
|
|
68
|
+
}, {});
|
|
69
|
+
}
|
|
39
70
|
export class JsonSchema extends Map {
|
|
40
|
-
|
|
71
|
+
/**
|
|
72
|
+
* All required fields are stored here
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
#required;
|
|
76
|
+
/**
|
|
77
|
+
* Internal custom props
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
#vendors;
|
|
41
81
|
#discriminator;
|
|
42
|
-
#genericLabels;
|
|
43
|
-
#nestedGenerics;
|
|
44
82
|
#alias;
|
|
45
83
|
#itemSchema;
|
|
84
|
+
/**
|
|
85
|
+
* This flag is used to know if the schema is created to link property/param to a class schema.
|
|
86
|
+
* @private
|
|
87
|
+
*/
|
|
88
|
+
#isLocalSchema;
|
|
46
89
|
#target;
|
|
47
|
-
#isGeneric;
|
|
48
90
|
#isCollection;
|
|
49
|
-
#
|
|
91
|
+
#useRefLabel;
|
|
92
|
+
#propertyKey;
|
|
50
93
|
constructor(obj = {}) {
|
|
51
94
|
super();
|
|
52
95
|
this.$kind = "schema";
|
|
53
96
|
this.$isJsonDocument = true;
|
|
54
97
|
this.$hooks = new Hooks();
|
|
55
|
-
this.$required = new Set();
|
|
56
98
|
this.$allow = [];
|
|
57
|
-
this.$forwardGroups = false;
|
|
58
99
|
this.$ignore = false;
|
|
59
100
|
this.isDiscriminatorKey = false;
|
|
60
101
|
this.isDiscriminator = false;
|
|
61
|
-
|
|
102
|
+
/**
|
|
103
|
+
* All required fields are stored here
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
this.#required = new Set();
|
|
107
|
+
/**
|
|
108
|
+
* Internal custom props
|
|
109
|
+
* @private
|
|
110
|
+
*/
|
|
111
|
+
this.#vendors = new Map();
|
|
62
112
|
this.#discriminator = null;
|
|
63
|
-
this.#nestedGenerics = [];
|
|
64
113
|
this.#alias = new Map();
|
|
65
|
-
|
|
114
|
+
/**
|
|
115
|
+
* This flag is used to know if the schema is created to link property/param to a class schema.
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
this.#isLocalSchema = false;
|
|
66
119
|
this.#isCollection = false;
|
|
67
|
-
this.#
|
|
120
|
+
this.#useRefLabel = false;
|
|
68
121
|
if (obj) {
|
|
69
122
|
this.assign(obj);
|
|
70
123
|
}
|
|
@@ -72,32 +125,27 @@ export class JsonSchema extends Map {
|
|
|
72
125
|
get alias() {
|
|
73
126
|
return this.#alias;
|
|
74
127
|
}
|
|
75
|
-
get nestedGenerics() {
|
|
76
|
-
return this.#nestedGenerics;
|
|
77
|
-
}
|
|
78
|
-
set nestedGenerics(value) {
|
|
79
|
-
this.#nestedGenerics = value;
|
|
80
|
-
}
|
|
81
|
-
get genericLabels() {
|
|
82
|
-
return this.#genericLabels;
|
|
83
|
-
}
|
|
84
|
-
set genericLabels(value) {
|
|
85
|
-
this.#genericLabels = value;
|
|
86
|
-
}
|
|
87
128
|
get isClass() {
|
|
88
|
-
return isClass(this.class) && !
|
|
129
|
+
return isClass(this.class) && !this.isCollection;
|
|
89
130
|
}
|
|
90
131
|
/**
|
|
91
|
-
*
|
|
132
|
+
* The current schema is a collection
|
|
92
133
|
*/
|
|
93
134
|
get isCollection() {
|
|
94
135
|
return this.#isCollection;
|
|
95
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The current schema is a reference to another schema
|
|
139
|
+
* to link property/param to a class schema (if the reference exists).
|
|
140
|
+
*/
|
|
141
|
+
get isLocalSchema() {
|
|
142
|
+
return this.#isLocalSchema;
|
|
143
|
+
}
|
|
96
144
|
/**
|
|
97
145
|
* Current schema is a generic
|
|
98
146
|
*/
|
|
99
147
|
get isGeneric() {
|
|
100
|
-
return this
|
|
148
|
+
return this.has(VendorKeys.GENERIC_LABEL);
|
|
101
149
|
}
|
|
102
150
|
get discriminatorAncestor() {
|
|
103
151
|
const ancestors = ancestorsOf(this.#target);
|
|
@@ -105,22 +153,27 @@ export class JsonSchema extends Map {
|
|
|
105
153
|
return ancestor && JsonEntityStore.from(ancestor).schema;
|
|
106
154
|
}
|
|
107
155
|
/**
|
|
108
|
-
*
|
|
156
|
+
* Return the itemSchema computed type.
|
|
157
|
+
* If the type is a function used for a recursive model,
|
|
158
|
+
* the function will be called to get the right type.
|
|
109
159
|
*/
|
|
110
|
-
get hasGenerics() {
|
|
111
|
-
return !!(this.nestedGenerics && this.nestedGenerics.length);
|
|
112
|
-
}
|
|
113
|
-
get genericType() {
|
|
114
|
-
return this.get("$ref");
|
|
115
|
-
}
|
|
116
160
|
get class() {
|
|
117
|
-
|
|
161
|
+
if (this.#isLocalSchema) {
|
|
162
|
+
return this.#itemSchema?.getTarget();
|
|
163
|
+
}
|
|
164
|
+
return getComputedType(this.#target);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Return the itemSchema computed type.
|
|
168
|
+
*/
|
|
169
|
+
get collectionClass() {
|
|
170
|
+
return this.isCollection && this.#itemSchema ? this.#itemSchema.class : this.class;
|
|
118
171
|
}
|
|
119
172
|
get canRef() {
|
|
120
|
-
return this.#
|
|
173
|
+
return this.#useRefLabel;
|
|
121
174
|
}
|
|
122
175
|
get isNullable() {
|
|
123
|
-
return this
|
|
176
|
+
return !!this.get("nullable");
|
|
124
177
|
}
|
|
125
178
|
get isReadOnly() {
|
|
126
179
|
return this.get("readOnly");
|
|
@@ -131,15 +184,105 @@ export class JsonSchema extends Map {
|
|
|
131
184
|
get hasDiscriminator() {
|
|
132
185
|
return !!this.#discriminator;
|
|
133
186
|
}
|
|
134
|
-
static from(
|
|
135
|
-
|
|
187
|
+
static from(item = {}) {
|
|
188
|
+
if (item instanceof JsonSchema) {
|
|
189
|
+
return item;
|
|
190
|
+
}
|
|
191
|
+
if (classOf(item) !== Object && isClass(item)) {
|
|
192
|
+
return JsonEntityStore.from(item).schema;
|
|
193
|
+
}
|
|
194
|
+
if (isPrimitiveClass(item)) {
|
|
195
|
+
return new JsonSchema({ type: item });
|
|
196
|
+
}
|
|
197
|
+
return new JsonSchema(item);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check if the schema as key, #key or x-key
|
|
201
|
+
* @param key
|
|
202
|
+
*/
|
|
203
|
+
has(key) {
|
|
204
|
+
if (super.has(key)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (super.has(`#${key}`)) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return this.#vendors.has(key);
|
|
211
|
+
}
|
|
212
|
+
get(key, defaultValue) {
|
|
213
|
+
if (this.#vendors.has(key)) {
|
|
214
|
+
return this.#vendors.get(key);
|
|
215
|
+
}
|
|
216
|
+
if (super.has(key)) {
|
|
217
|
+
return super.get(key);
|
|
218
|
+
}
|
|
219
|
+
if (super.has(`#${key}`)) {
|
|
220
|
+
return super.get(`#${key}`);
|
|
221
|
+
}
|
|
222
|
+
return defaultValue;
|
|
223
|
+
}
|
|
224
|
+
forwardGroups(bool = true) {
|
|
225
|
+
this.vendorKey(VendorKeys.FORWARD_GROUPS, bool);
|
|
226
|
+
return this;
|
|
227
|
+
}
|
|
228
|
+
groups(groups, isProperty) {
|
|
229
|
+
if (groups) {
|
|
230
|
+
this.vendorKey(VendorKeys.GROUPS, groups);
|
|
231
|
+
// this.customKey("x-groups", groups);
|
|
232
|
+
if (isProperty) {
|
|
233
|
+
this.$hooks.on("groups", (prev, givenGroups) => {
|
|
234
|
+
if (!prev) {
|
|
235
|
+
if (matchGroups(groups, givenGroups)) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return prev;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return this;
|
|
244
|
+
}
|
|
245
|
+
groupsName(groupsName) {
|
|
246
|
+
groupsName && this.vendorKey(VendorKeys.GROUPS_NAME, groupsName);
|
|
247
|
+
return this;
|
|
248
|
+
}
|
|
249
|
+
allowedGroups(groups) {
|
|
250
|
+
groups && this.vendorKey(VendorKeys.ALLOWED_GROUPS, groups);
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Assign the Generic Labels used over a class or a schema.
|
|
255
|
+
* @param genericLabels
|
|
256
|
+
*/
|
|
257
|
+
genericLabels(genericLabels) {
|
|
258
|
+
this.vendorKey(VendorKeys.GENERIC_LABELS, genericLabels);
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
genericLabel(genericLabel) {
|
|
262
|
+
this.vendorKey(VendorKeys.GENERIC_LABEL, genericLabel);
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Assign the types of the generics that must be used for the property
|
|
267
|
+
* @param generics
|
|
268
|
+
*/
|
|
269
|
+
genericOf(...generics) {
|
|
270
|
+
const mapped = mapGenerics(this.#itemSchema || mapToJsonSchema(this.getTarget()), generics);
|
|
271
|
+
this.vendorKey(VendorKeys.GENERIC_OF, mapped);
|
|
272
|
+
return this;
|
|
136
273
|
}
|
|
137
274
|
nullable(value) {
|
|
138
|
-
this
|
|
275
|
+
this.vendorKey(VendorKeys.NULLABLE, value);
|
|
276
|
+
return this;
|
|
139
277
|
}
|
|
140
278
|
itemSchema(obj = {}) {
|
|
141
279
|
this.#itemSchema = this.#itemSchema || mapToJsonSchema(obj);
|
|
142
|
-
|
|
280
|
+
if (isPlainObject(obj)) {
|
|
281
|
+
this.#itemSchema.assign(obj);
|
|
282
|
+
}
|
|
283
|
+
if (!this.isCollection && this.#itemSchema?.isClass) {
|
|
284
|
+
this.#isLocalSchema = true;
|
|
285
|
+
}
|
|
143
286
|
return this.#itemSchema;
|
|
144
287
|
}
|
|
145
288
|
getAliasOf(property) {
|
|
@@ -173,7 +316,7 @@ export class JsonSchema extends Map {
|
|
|
173
316
|
* @param name
|
|
174
317
|
*/
|
|
175
318
|
label(name) {
|
|
176
|
-
this.#
|
|
319
|
+
this.#useRefLabel = true;
|
|
177
320
|
super.set("name", name);
|
|
178
321
|
return this;
|
|
179
322
|
}
|
|
@@ -225,6 +368,15 @@ export class JsonSchema extends Map {
|
|
|
225
368
|
discriminatorKey(propertyName) {
|
|
226
369
|
this.discriminator().propertyName = propertyName;
|
|
227
370
|
this.isDiscriminator = true;
|
|
371
|
+
const propertySchema = this.get("properties")[propertyName];
|
|
372
|
+
if (propertySchema) {
|
|
373
|
+
if (propertySchema.isCollection) {
|
|
374
|
+
propertySchema.itemSchema().isDiscriminatorKey = true;
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
propertySchema.isDiscriminatorKey = true;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
228
380
|
return this;
|
|
229
381
|
}
|
|
230
382
|
discriminatorValue(...values) {
|
|
@@ -368,8 +520,8 @@ export class JsonSchema extends Map {
|
|
|
368
520
|
*/
|
|
369
521
|
required(required = true) {
|
|
370
522
|
if (isArray(required)) {
|
|
371
|
-
this
|
|
372
|
-
required.forEach((value) => this
|
|
523
|
+
this.#required.clear();
|
|
524
|
+
required.forEach((value) => this.#required.add(value));
|
|
373
525
|
}
|
|
374
526
|
else {
|
|
375
527
|
const schema = this.clone();
|
|
@@ -382,15 +534,18 @@ export class JsonSchema extends Map {
|
|
|
382
534
|
return this;
|
|
383
535
|
}
|
|
384
536
|
addRequired(property) {
|
|
385
|
-
this
|
|
537
|
+
this.#required.add(property);
|
|
386
538
|
return this;
|
|
387
539
|
}
|
|
388
540
|
removeRequired(property) {
|
|
389
|
-
this
|
|
541
|
+
this.#required.delete(property);
|
|
390
542
|
return this;
|
|
391
543
|
}
|
|
392
544
|
isRequired(property) {
|
|
393
|
-
return this
|
|
545
|
+
return this.#required.has(property);
|
|
546
|
+
}
|
|
547
|
+
getRequiredFields() {
|
|
548
|
+
return [...this.#required];
|
|
394
549
|
}
|
|
395
550
|
/**
|
|
396
551
|
* This keyword determines how child instances validate for objects, and does not directly validate the immediate instance itself.
|
|
@@ -508,7 +663,12 @@ export class JsonSchema extends Map {
|
|
|
508
663
|
* @see https://tools.ietf.org/html/draft-wright-json-schema-validation-01#section-6.28
|
|
509
664
|
*/
|
|
510
665
|
oneOf(oneOf) {
|
|
511
|
-
this.
|
|
666
|
+
if (this.isCollection) {
|
|
667
|
+
this.itemSchema().oneOf(oneOf);
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
this.setManyOf("oneOf", oneOf);
|
|
671
|
+
}
|
|
512
672
|
return this;
|
|
513
673
|
}
|
|
514
674
|
/**
|
|
@@ -606,7 +766,7 @@ export class JsonSchema extends Map {
|
|
|
606
766
|
case "map":
|
|
607
767
|
case Map:
|
|
608
768
|
super.set("type", getJsonType(type));
|
|
609
|
-
this
|
|
769
|
+
this.target(type);
|
|
610
770
|
this.#isCollection = true;
|
|
611
771
|
if (!this.has("additionalProperties")) {
|
|
612
772
|
super.set("additionalProperties", this.itemSchema({}));
|
|
@@ -615,7 +775,7 @@ export class JsonSchema extends Map {
|
|
|
615
775
|
case "array":
|
|
616
776
|
case Array:
|
|
617
777
|
super.set("type", getJsonType(type));
|
|
618
|
-
this
|
|
778
|
+
this.target(type);
|
|
619
779
|
this.#isCollection = true;
|
|
620
780
|
if (!this.has("items")) {
|
|
621
781
|
super.set("items", this.itemSchema({}));
|
|
@@ -624,7 +784,7 @@ export class JsonSchema extends Map {
|
|
|
624
784
|
case "set":
|
|
625
785
|
case Set:
|
|
626
786
|
super.set("type", getJsonType(type));
|
|
627
|
-
this
|
|
787
|
+
this.target(type);
|
|
628
788
|
this.#isCollection = true;
|
|
629
789
|
this.uniqueItems(true);
|
|
630
790
|
if (!this.has("items")) {
|
|
@@ -644,7 +804,7 @@ export class JsonSchema extends Map {
|
|
|
644
804
|
case Number:
|
|
645
805
|
case String:
|
|
646
806
|
super.set("type", getJsonType(type));
|
|
647
|
-
this
|
|
807
|
+
this.target(type);
|
|
648
808
|
if (!this.has("properties")) {
|
|
649
809
|
super.set("properties", {});
|
|
650
810
|
}
|
|
@@ -652,7 +812,7 @@ export class JsonSchema extends Map {
|
|
|
652
812
|
default:
|
|
653
813
|
if (isClass(type) || isFunction(type)) {
|
|
654
814
|
super.set("type", undefined);
|
|
655
|
-
this
|
|
815
|
+
this.target(type);
|
|
656
816
|
if (!this.has("properties")) {
|
|
657
817
|
super.set("properties", {});
|
|
658
818
|
}
|
|
@@ -660,8 +820,7 @@ export class JsonSchema extends Map {
|
|
|
660
820
|
else {
|
|
661
821
|
const jsonType = getJsonType(type);
|
|
662
822
|
if (jsonType === "generic") {
|
|
663
|
-
this
|
|
664
|
-
super.set("$ref", type);
|
|
823
|
+
this.genericLabel(type);
|
|
665
824
|
}
|
|
666
825
|
else {
|
|
667
826
|
super.set("type", jsonType);
|
|
@@ -709,6 +868,10 @@ export class JsonSchema extends Map {
|
|
|
709
868
|
super.set(`#${key}`, value);
|
|
710
869
|
return this;
|
|
711
870
|
}
|
|
871
|
+
vendorKey(key, value) {
|
|
872
|
+
this.#vendors.set(key, value);
|
|
873
|
+
return this;
|
|
874
|
+
}
|
|
712
875
|
toObject(options) {
|
|
713
876
|
return this.toJSON(options);
|
|
714
877
|
}
|
|
@@ -723,21 +886,16 @@ export class JsonSchema extends Map {
|
|
|
723
886
|
if (obj instanceof JsonSchema) {
|
|
724
887
|
this.$selfRequired = obj.$selfRequired;
|
|
725
888
|
this.$allow.push(...obj.$allow);
|
|
726
|
-
obj
|
|
727
|
-
|
|
728
|
-
|
|
889
|
+
this.#required = new Set(obj.#required.keys());
|
|
890
|
+
this.#alias = new Map(this.#alias.entries());
|
|
891
|
+
this.#vendors = new Map(obj.#vendors.entries());
|
|
729
892
|
this.#discriminator = this.#discriminator ? new Discriminator(this.#discriminator) : null;
|
|
730
893
|
this.isDiscriminator = obj.isDiscriminator;
|
|
731
894
|
this.isDiscriminatorKey = obj.isDiscriminatorKey;
|
|
732
|
-
this.#
|
|
733
|
-
this.#alias = new Map(this.#alias.entries());
|
|
734
|
-
obj.#genericLabels && (this.#genericLabels = [...obj.#genericLabels]);
|
|
735
|
-
this.#nestedGenerics = obj.#nestedGenerics.map((item) => [...item]);
|
|
895
|
+
this.#useRefLabel = obj.#useRefLabel;
|
|
736
896
|
this.#target = obj.#target;
|
|
737
|
-
this.#isGeneric = obj.#isGeneric;
|
|
738
897
|
this.#isCollection = obj.#isCollection;
|
|
739
|
-
this.#
|
|
740
|
-
this.#nullable = obj.#nullable;
|
|
898
|
+
this.#isLocalSchema = obj.#isLocalSchema;
|
|
741
899
|
super.set("type", obj.get("type"));
|
|
742
900
|
}
|
|
743
901
|
return this;
|
|
@@ -751,17 +909,6 @@ export class JsonSchema extends Map {
|
|
|
751
909
|
}
|
|
752
910
|
return this;
|
|
753
911
|
}
|
|
754
|
-
/**
|
|
755
|
-
* Return the itemSchema computed type.
|
|
756
|
-
* If the type is a function used for recursive model,
|
|
757
|
-
* the function will be called to get the right type.
|
|
758
|
-
*/
|
|
759
|
-
getComputedType() {
|
|
760
|
-
return getComputedType(this.#target);
|
|
761
|
-
}
|
|
762
|
-
getComputedItemType() {
|
|
763
|
-
return this.#itemSchema ? this.#itemSchema.getComputedType() : this.getComputedType();
|
|
764
|
-
}
|
|
765
912
|
/**
|
|
766
913
|
* Return the Json type as string
|
|
767
914
|
*/
|
|
@@ -771,24 +918,84 @@ export class JsonSchema extends Map {
|
|
|
771
918
|
return o.getJsonType();
|
|
772
919
|
});
|
|
773
920
|
}
|
|
774
|
-
return this.get("type") || getJsonType(this.
|
|
921
|
+
return this.get("type") || getJsonType(this.class);
|
|
775
922
|
}
|
|
776
923
|
getTarget() {
|
|
777
924
|
return this.#target;
|
|
778
925
|
}
|
|
926
|
+
getAllowedGroups() {
|
|
927
|
+
return this.get(VendorKeys.ALLOWED_GROUPS);
|
|
928
|
+
}
|
|
929
|
+
getAllowedRequiredValues() {
|
|
930
|
+
return this.$allow;
|
|
931
|
+
}
|
|
932
|
+
getGroups() {
|
|
933
|
+
return this.get(VendorKeys.GROUPS);
|
|
934
|
+
}
|
|
935
|
+
getGroupsName() {
|
|
936
|
+
return this.get(VendorKeys.GROUPS_NAME);
|
|
937
|
+
}
|
|
779
938
|
/**
|
|
780
939
|
* Get the symbolic name of the entity
|
|
781
940
|
*/
|
|
782
941
|
getName() {
|
|
783
|
-
return this.get("name") || (isClass(this.#target) ? nameOf(classOf(this.
|
|
942
|
+
return this.get("name") || (isClass(this.#target) ? nameOf(classOf(this.class)) : "");
|
|
784
943
|
}
|
|
785
944
|
clone() {
|
|
786
945
|
return new JsonSchema(this);
|
|
787
946
|
}
|
|
947
|
+
getGenericLabels() {
|
|
948
|
+
const labels = this.get(VendorKeys.GENERIC_LABELS);
|
|
949
|
+
if (this.isClass && !labels) {
|
|
950
|
+
const ancestor = ancestorOf(this.class);
|
|
951
|
+
return ancestor === Object ? undefined : JsonSchema.from(ancestor).getGenericLabels();
|
|
952
|
+
}
|
|
953
|
+
return this.get(VendorKeys.GENERIC_LABELS);
|
|
954
|
+
}
|
|
955
|
+
getGenericOf() {
|
|
956
|
+
return this.get(VendorKeys.GENERIC_OF);
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Returns the reference schema for class-based schemas.
|
|
960
|
+
* Used to get the original schema definition when this schema is a local reference.
|
|
961
|
+
* @returns The reference schema or undefined if not applicable
|
|
962
|
+
*/
|
|
963
|
+
getRefSchema() {
|
|
964
|
+
if (!this.isLocalSchema && this.isClass) {
|
|
965
|
+
const refSchema = JsonSchema.from(this.class);
|
|
966
|
+
if (refSchema !== this) {
|
|
967
|
+
return refSchema;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
propertyKey(s) {
|
|
972
|
+
this.#propertyKey = s;
|
|
973
|
+
return this;
|
|
974
|
+
}
|
|
975
|
+
getPropertyKey() {
|
|
976
|
+
return this.#propertyKey;
|
|
977
|
+
}
|
|
978
|
+
target(target) {
|
|
979
|
+
if (target === "object") {
|
|
980
|
+
this.#target = Object;
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
this.#target = target;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
isRequiredValue(property, value) {
|
|
987
|
+
if (this.isRequired(property) && [undefined, null, ""].includes(value)) {
|
|
988
|
+
const propertySchema = this.get("properties")?.[property];
|
|
989
|
+
if (propertySchema) {
|
|
990
|
+
return !propertySchema.getAllowedRequiredValues().includes(value);
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
return false;
|
|
994
|
+
}
|
|
788
995
|
setManyOf(keyword, value) {
|
|
789
996
|
let resolved = value
|
|
790
997
|
.filter((o) => {
|
|
791
|
-
if (o
|
|
998
|
+
if (o && "type" in o && o.type === "null") {
|
|
792
999
|
this.nullable(true);
|
|
793
1000
|
return false;
|
|
794
1001
|
}
|
|
@@ -807,7 +1014,7 @@ export class JsonSchema extends Map {
|
|
|
807
1014
|
}
|
|
808
1015
|
super.set(keyword, resolved);
|
|
809
1016
|
const jsonSchema = resolved[0];
|
|
810
|
-
if (jsonSchema
|
|
1017
|
+
if (jsonSchema?.isDiscriminator) {
|
|
811
1018
|
const discriminator = jsonSchema.discriminatorAncestor.discriminator();
|
|
812
1019
|
const { propertyName } = discriminator;
|
|
813
1020
|
super.set("discriminator", {
|
package/lib/esm/fn/email.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JsonFormatTypes } from "../domain/JsonFormatTypes.js";
|
|
2
|
-
import {
|
|
2
|
+
import { string } from "./string.js";
|
|
3
3
|
/**
|
|
4
4
|
* Declare a new string model with `format: email`.
|
|
5
5
|
*
|
|
@@ -13,5 +13,5 @@ import { from } from "./from.js";
|
|
|
13
13
|
* ```
|
|
14
14
|
*/
|
|
15
15
|
export function email() {
|
|
16
|
-
return
|
|
16
|
+
return string().format(JsonFormatTypes.EMAIL);
|
|
17
17
|
}
|
package/lib/esm/fn/uri.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JsonFormatTypes } from "../domain/JsonFormatTypes.js";
|
|
2
|
-
import {
|
|
2
|
+
import { string } from "./string.js";
|
|
3
3
|
/**
|
|
4
4
|
* Declare a new string model with `format: uri`.
|
|
5
5
|
*
|
|
@@ -8,5 +8,5 @@ import { from } from "./from.js";
|
|
|
8
8
|
* @schemaFunctional
|
|
9
9
|
*/
|
|
10
10
|
export function uri() {
|
|
11
|
-
return
|
|
11
|
+
return string().format(JsonFormatTypes.URI);
|
|
12
12
|
}
|