@tsed/schema 6.80.1 → 6.84.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.
@@ -1,81 +1,288 @@
1
- import { constantCase, pascalCase, camelCase } from 'change-case';
2
- import { Store, decoratorTypeOf, nameOf, cleanObject, isFunction, isPromise, isClass, isSymbol, isPrimitiveOrPrimitiveClass, isClassObject, isDate, isCollection, classOf, isArrowFn, primitiveOf, isArray, Hooks, uniq, isObject, uniqBy, deepMerge, toMap, Entity, DecoratorTypes, descriptorOf, Metadata, isPlainObject, isPrimitiveClass, ancestorsOf, mergeReducerBuilder, UnsupportedDecoratorType, decorateMethodsOf, isString, isNumber, useDecorators, StoreSet } from '@tsed/core';
1
+ import { nameOf, isArrayOrArrayClass, isPrimitiveOrPrimitiveClass, isDate, isObject, isClass, prototypeOf, Store, decoratorTypeOf, classOf, descriptorOf, isCollection, isPlainObject, isPromise, isSymbol, isClassObject, isArrowFn, primitiveOf, isArray, Hooks, uniq, isFunction, DecoratorTypes, Metadata, toMap, cleanObject, ancestorsOf, isMethodDescriptor, uniqBy, deepMerge, isPrimitiveClass, mergeReducerBuilder, UnsupportedDecoratorType, decorateMethodsOf, isString, isNumber, useDecorators, StoreSet } from '@tsed/core';
2
+ import { __decorate } from 'tslib';
3
+ import { pascalCase } from 'pascal-case';
4
+ import { camelCase } from 'camel-case';
3
5
  import micromatch from 'micromatch';
4
6
 
5
7
  const HTTP_STATUS_MESSAGES = {
6
- "100": "Continue",
7
- "101": "Switching Protocols",
8
- "102": "Processing",
9
- "103": "Early Hints",
10
- "200": "Success",
11
- "201": "Created",
12
- "202": "Accepted",
13
- "203": "Non-Authoritative Information",
14
- "204": "No Content",
15
- "205": "Reset Content",
16
- "206": "Partial Content",
17
- "207": "Multi-Status",
18
- "208": "Already Reported",
19
- "226": "IM Used",
20
- "300": "Multiple Choices",
21
- "301": "Moved Permanently",
22
- "302": "Found",
23
- "303": "See Other",
24
- "304": "Not Modified",
25
- "305": "Use Proxy",
26
- "306": "(Unused)",
27
- "307": "Temporary Redirect",
28
- "308": "Permanent Redirect",
29
- "310": "Too Many Redirects",
30
- "400": "Bad Request",
31
- "401": "Unauthorized",
32
- "402": "Payment Required",
33
- "403": "Forbidden",
34
- "404": "Not Found",
35
- "405": "Method Not Allowed",
36
- "406": "Not Acceptable",
37
- "407": "Proxy Authentication Required",
38
- "408": "Request Timeout",
39
- "409": "Conflict",
40
- "410": "Gone",
41
- "411": "Length Required",
42
- "412": "Precondition Failed",
43
- "413": "Request Entity Too Large",
44
- "414": "Request URI Too Long",
45
- "415": "Unsupported Media Type",
46
- "416": "Request Range Unsatisfiable",
47
- "417": "Expectation Failed",
48
- "418": "I'm a Teapot",
49
- "421": "Misdirected Request",
50
- "422": "Unprocessable Entity",
51
- "423": "Locked",
52
- "424": "Failed Dependency",
53
- "425": "Too Early",
54
- "426": "Upgrade Required",
55
- "427": "Unassigned",
56
- "428": "Precondition Required",
57
- "429": "Too Many Requests",
58
- "430": "Unassigned",
59
- "431": "Request Header Fields Too Large",
60
- "451": "Unavailable For Legal Reasons",
61
- "500": "Internal Server Error",
62
- "501": "Not Implemented",
63
- "502": "Bad Gateway",
64
- "503": "Service Unavailable",
65
- "504": "Gateway Timeout",
66
- "505": "HTTP Version Not Supported",
67
- "506": "Variant Also Negotiates",
68
- "507": "Insufficient Storage",
69
- "508": "Loop Detected",
70
- "509": "Bandwidth Limit Exceeded",
71
- "510": "Not Extended",
72
- "511": "Network Authentication Required"
8
+ "100": {
9
+ label: "Continue",
10
+ code: "CONTINUE"
11
+ },
12
+ "101": {
13
+ label: "Switching Protocols",
14
+ code: "SWITCHING_PROTOCOLS"
15
+ },
16
+ "102": {
17
+ label: "Processing",
18
+ code: "PROCESSING"
19
+ },
20
+ "103": {
21
+ label: "Early Hints",
22
+ code: "EARLY_HINTS"
23
+ },
24
+ "200": {
25
+ label: "Success",
26
+ code: "SUCCESS"
27
+ },
28
+ "201": {
29
+ label: "Created",
30
+ code: "CREATED"
31
+ },
32
+ "202": {
33
+ label: "Accepted",
34
+ code: "ACCEPTED"
35
+ },
36
+ "203": {
37
+ label: "Non-Authoritative Information",
38
+ code: "NON_AUTHORITATIVE_INFORMATION"
39
+ },
40
+ "204": {
41
+ label: "No Content",
42
+ code: "NO_CONTENT"
43
+ },
44
+ "205": {
45
+ label: "Reset Content",
46
+ code: "RESET_CONTENT"
47
+ },
48
+ "206": {
49
+ label: "Partial Content",
50
+ code: "PARTIAL_CONTENT"
51
+ },
52
+ "207": {
53
+ label: "Multi-Status",
54
+ code: "MULTI_STATUS"
55
+ },
56
+ "208": {
57
+ label: "Already Reported",
58
+ code: "ALREADY_REPORTED"
59
+ },
60
+ "226": {
61
+ label: "IM Used",
62
+ code: "IM_USED"
63
+ },
64
+ "300": {
65
+ label: "Multiple Choices",
66
+ code: "MULTIPLE_CHOICES"
67
+ },
68
+ "301": {
69
+ label: "Moved Permanently",
70
+ code: "MOVED_PERMANENTLY"
71
+ },
72
+ "302": {
73
+ label: "Found",
74
+ code: "FOUND"
75
+ },
76
+ "303": {
77
+ label: "See Other",
78
+ code: "SEE_OTHER"
79
+ },
80
+ "304": {
81
+ label: "Not Modified",
82
+ code: "NOT_MODIFIED"
83
+ },
84
+ "305": {
85
+ label: "Use Proxy",
86
+ code: "USE_PROXY"
87
+ },
88
+ "306": {
89
+ label: "(Unused)",
90
+ code: "UNUSED"
91
+ },
92
+ "307": {
93
+ label: "Temporary Redirect",
94
+ code: "TEMPORARY_REDIRECT"
95
+ },
96
+ "308": {
97
+ label: "Permanent Redirect",
98
+ code: "PERMANENT_REDIRECT"
99
+ },
100
+ "310": {
101
+ label: "Too Many Redirects",
102
+ code: "TOO_MANY_REDIRECTS"
103
+ },
104
+ "400": {
105
+ label: "Bad Request",
106
+ code: "BAD_REQUEST"
107
+ },
108
+ "401": {
109
+ label: "Unauthorized",
110
+ code: "UNAUTHORIZED"
111
+ },
112
+ "402": {
113
+ label: "Payment Required",
114
+ code: "PAYMENT_REQUIRED"
115
+ },
116
+ "403": {
117
+ label: "Forbidden",
118
+ code: "FORBIDDEN"
119
+ },
120
+ "404": {
121
+ label: "Not Found",
122
+ code: "NOT_FOUND"
123
+ },
124
+ "405": {
125
+ label: "Method Not Allowed",
126
+ code: "METHOD_NOT_ALLOWED"
127
+ },
128
+ "406": {
129
+ label: "Not Acceptable",
130
+ code: "NOT_ACCEPTABLE"
131
+ },
132
+ "407": {
133
+ label: "Proxy Authentication Required",
134
+ code: "PROXY_AUTHENTICATION_REQUIRED"
135
+ },
136
+ "408": {
137
+ label: "Request Timeout",
138
+ code: "REQUEST_TIMEOUT"
139
+ },
140
+ "409": {
141
+ label: "Conflict",
142
+ code: "CONFLICT"
143
+ },
144
+ "410": {
145
+ label: "Gone",
146
+ code: "GONE"
147
+ },
148
+ "411": {
149
+ label: "Length Required",
150
+ code: "LENGTH_REQUIRED"
151
+ },
152
+ "412": {
153
+ label: "Precondition Failed",
154
+ code: "PRECONDITION_FAILED"
155
+ },
156
+ "413": {
157
+ label: "Request Entity Too Large",
158
+ code: "REQUEST_ENTITY_TOO_LARGE"
159
+ },
160
+ "414": {
161
+ label: "Request URI Too Long",
162
+ code: "REQUEST_URI_TOO_LONG"
163
+ },
164
+ "415": {
165
+ label: "Unsupported Media Type",
166
+ code: "UNSUPPORTED_MEDIA_TYPE"
167
+ },
168
+ "416": {
169
+ label: "Request Range Unsatisfiable",
170
+ code: "REQUEST_RANGE_UNSATISFIABLE"
171
+ },
172
+ "417": {
173
+ label: "Expectation Failed",
174
+ code: "EXPECTATION_FAILED"
175
+ },
176
+ "418": {
177
+ label: "I'm a Teapot",
178
+ code: "I_M_A_TEAPOT"
179
+ },
180
+ "421": {
181
+ label: "Misdirected Request",
182
+ code: "MISDIRECTED_REQUEST"
183
+ },
184
+ "422": {
185
+ label: "Unprocessable Entity",
186
+ code: "UNPROCESSABLE_ENTITY"
187
+ },
188
+ "423": {
189
+ label: "Locked",
190
+ code: "LOCKED"
191
+ },
192
+ "424": {
193
+ label: "Failed Dependency",
194
+ code: "FAILED_DEPENDENCY"
195
+ },
196
+ "425": {
197
+ label: "Too Early",
198
+ code: "TOO_EARLY"
199
+ },
200
+ "426": {
201
+ label: "Upgrade Required",
202
+ code: "UPGRADE_REQUIRED"
203
+ },
204
+ "427": {
205
+ label: "Unassigned",
206
+ code: "UNASSIGNED"
207
+ },
208
+ "428": {
209
+ label: "Precondition Required",
210
+ code: "PRECONDITION_REQUIRED"
211
+ },
212
+ "429": {
213
+ label: "Too Many Requests",
214
+ code: "TOO_MANY_REQUESTS"
215
+ },
216
+ "430": {
217
+ label: "Unassigned",
218
+ code: "UNASSIGNED"
219
+ },
220
+ "431": {
221
+ label: "Request Header Fields Too Large",
222
+ code: "REQUEST_HEADER_FIELDS_TOO_LARGE"
223
+ },
224
+ "451": {
225
+ label: "Unavailable For Legal Reasons",
226
+ code: "UNAVAILABLE_FOR_LEGAL_REASONS"
227
+ },
228
+ "500": {
229
+ label: "Internal Server Error",
230
+ code: "INTERNAL_SERVER_ERROR"
231
+ },
232
+ "501": {
233
+ label: "Not Implemented",
234
+ code: "NOT_IMPLEMENTED"
235
+ },
236
+ "502": {
237
+ label: "Bad Gateway",
238
+ code: "BAD_GATEWAY"
239
+ },
240
+ "503": {
241
+ label: "Service Unavailable",
242
+ code: "SERVICE_UNAVAILABLE"
243
+ },
244
+ "504": {
245
+ label: "Gateway Timeout",
246
+ code: "GATEWAY_TIMEOUT"
247
+ },
248
+ "505": {
249
+ label: "HTTP Version Not Supported",
250
+ code: "HTTP_VERSION_NOT_SUPPORTED"
251
+ },
252
+ "506": {
253
+ label: "Variant Also Negotiates",
254
+ code: "VARIANT_ALSO_NEGOTIATES"
255
+ },
256
+ "507": {
257
+ label: "Insufficient Storage",
258
+ code: "INSUFFICIENT_STORAGE"
259
+ },
260
+ "508": {
261
+ label: "Loop Detected",
262
+ code: "LOOP_DETECTED"
263
+ },
264
+ "509": {
265
+ label: "Bandwidth Limit Exceeded",
266
+ code: "BANDWIDTH_LIMIT_EXCEEDED"
267
+ },
268
+ "510": {
269
+ label: "Not Extended",
270
+ code: "NOT_EXTENDED"
271
+ },
272
+ "511": {
273
+ label: "Network Authentication Required",
274
+ code: "NETWORK_AUTHENTICATION_REQUIRED"
275
+ }
73
276
  };
74
277
  function getStatusConstant(status) {
75
- return constantCase(HTTP_STATUS_MESSAGES[status]);
278
+ var _HTTP_STATUS_MESSAGES;
279
+
280
+ return (_HTTP_STATUS_MESSAGES = HTTP_STATUS_MESSAGES[status]) == null ? void 0 : _HTTP_STATUS_MESSAGES.code;
76
281
  }
77
282
  function getStatusMessage(status) {
78
- return HTTP_STATUS_MESSAGES[status];
283
+ var _HTTP_STATUS_MESSAGES2;
284
+
285
+ return (_HTTP_STATUS_MESSAGES2 = HTTP_STATUS_MESSAGES[status]) == null ? void 0 : _HTTP_STATUS_MESSAGES2.label;
79
286
  }
80
287
 
81
288
  const HTTP_METHODS = ["all", "checkout", "connect", "copy", "delete", "get", "head", "lock", "merge", "mkactivity", "mkcol", "move", "m-search", "notify", "options", "param", "patch", "post", "propfind", "propatch", "purge", "put", "report", "search", "subscribe", "trace", "unlock", "unsuscribe"];
@@ -174,457 +381,228 @@ function execMapper(type, schema, options) {
174
381
  /**
175
382
  * @ignore
176
383
  */
384
+
177
385
  const JsonEntitiesContainer = new Map();
386
+ class JsonEntityStore {
387
+ constructor(options) {
388
+ this.isStore = true;
389
+ const {
390
+ target,
391
+ propertyKey,
392
+ descriptor,
393
+ index,
394
+ decoratorType
395
+ } = options;
396
+ this.target = target;
397
+ this.propertyKey = propertyKey;
398
+ this.propertyName = String(propertyKey);
399
+ this.descriptor = descriptor;
400
+ this.index = index;
401
+ this.decoratorType = decoratorType;
402
+ this.token = target;
403
+ this.store = options.store;
404
+ this.parent = this;
405
+ }
406
+ /**
407
+ * Return the class name of the entity.
408
+ * @returns {string}
409
+ */
178
410
 
179
- /**
180
- * @ignore
181
- */
182
411
 
183
- function isJsonEntityStore(model) {
184
- return model.isStore;
185
- }
186
- /**
187
- * @ignore
188
- */
412
+ get targetName() {
413
+ return nameOf(this.token);
414
+ }
415
+ /**
416
+ *
417
+ * @returns {boolean}
418
+ */
189
419
 
190
- function getJsonEntityStore(...args) {
191
- if (isJsonEntityStore(args[0])) {
192
- return args[0];
420
+
421
+ get isCollection() {
422
+ return !!this.collectionType;
423
+ }
424
+ /**
425
+ *
426
+ * @returns {boolean}
427
+ */
428
+
429
+
430
+ get isArray() {
431
+ return isArrayOrArrayClass(this.collectionType);
193
432
  }
433
+ /**
434
+ *
435
+ * @returns {boolean}
436
+ */
194
437
 
195
- const store = Store.from(...args);
196
438
 
197
- if (!store.has("JsonEntityStore")) {
198
- const entityStore = JsonEntitiesContainer.get(decoratorTypeOf(args)) || JsonEntitiesContainer.get("default");
199
- const jsonSchemaStore = new entityStore({
200
- store,
201
- target: args[0],
202
- propertyKey: args[1],
203
- index: typeof args[2] === "number" ? args[2] : undefined,
204
- descriptor: typeof args[2] === "object" ? args[2] : undefined
205
- });
206
- store.set("JsonEntityStore", jsonSchemaStore);
439
+ get isPrimitive() {
440
+ return isPrimitiveOrPrimitiveClass(this._type);
207
441
  }
442
+ /**
443
+ *
444
+ * @returns {boolean}
445
+ */
208
446
 
209
- return store.get("JsonEntityStore");
210
- }
211
447
 
212
- class JsonLazyRef {
213
- constructor(getType) {
214
- this.getType = getType;
215
- this.isLazyRef = true;
448
+ get isDate() {
449
+ return isDate(this.computedType);
216
450
  }
451
+ /**
452
+ *
453
+ * @returns {boolean}
454
+ */
217
455
 
218
- get target() {
219
- return this.getType();
456
+
457
+ get isObject() {
458
+ return isObject(this.computedType);
459
+ }
460
+ /**
461
+ *
462
+ */
463
+
464
+
465
+ get isClass() {
466
+ return isClass(this.computedType);
220
467
  }
468
+ /**
469
+ * Return the JsonSchema
470
+ */
471
+
221
472
 
222
473
  get schema() {
223
- return getJsonEntityStore(this.getType()).schema;
474
+ return this._schema;
224
475
  }
225
476
 
226
- get name() {
227
- return nameOf(this.getType());
477
+ get nestedGenerics() {
478
+ return this.schema.nestedGenerics;
228
479
  }
229
480
 
230
- toJSON(options) {
231
- return this.getType() && execMapper("schema", this.schema, options);
481
+ set nestedGenerics(nestedGenerics) {
482
+ this.schema.nestedGenerics = nestedGenerics;
232
483
  }
484
+ /**
485
+ *
486
+ * @returns {Type<any>}
487
+ */
233
488
 
234
- }
235
489
 
236
- const _excluded$8 = ["genericLabels", "genericTypes"];
490
+ get type() {
491
+ return this._type;
492
+ }
493
+ /**
494
+ * Get original type without transformation
495
+ * @param value
496
+ */
237
497
 
238
- /**
239
- * @ignore
240
- * @param genericLabels
241
- * @param genericTypes
242
- */
243
- function getGenericsMap(genericLabels, genericTypes) {
244
- return genericLabels.reduce((map, item, index) => map.set(item, genericTypes[index]), new Map());
245
- }
246
- /**
247
- * @ignore
248
- * @param options
249
- */
250
498
 
251
- function mapGenericsOptions(options) {
252
- if (options.genericLabels && options.genericTypes) {
253
- const {
254
- genericLabels,
255
- genericTypes
256
- } = options,
257
- ops = _objectWithoutPropertiesLoose(options, _excluded$8);
499
+ set type(value) {
500
+ this._type = value;
501
+ this.build();
502
+ }
503
+ /**
504
+ * Return the itemSchema computed type. if the type is a function used for recursive model, the function will be called to
505
+ * get the right type.
506
+ */
258
507
 
259
- return _extends({}, ops, {
260
- generics: getGenericsMap(genericLabels, genericTypes)
261
- });
508
+
509
+ get computedType() {
510
+ return this.itemSchema.getComputedType();
262
511
  }
263
512
 
264
- return options;
265
- }
266
- /**
267
- * @ignore
268
- * @param value
269
- */
513
+ get itemSchema() {
514
+ return this.isCollection ? this.schema.itemSchema() : this.schema;
515
+ }
270
516
 
271
- function popGenerics(value) {
272
- const [genericTypes, ...out] = value.nestedGenerics;
273
- return {
274
- genericTypes,
275
- nestedGenerics: out
276
- };
277
- }
517
+ get parentSchema() {
518
+ return this.parent.schema;
519
+ }
278
520
 
279
- var SpecTypes;
521
+ static from(...args) {
522
+ if (args[0].isStore) {
523
+ return args[0];
524
+ }
280
525
 
281
- (function (SpecTypes) {
282
- SpecTypes["JSON"] = "jsonschema";
283
- SpecTypes["SWAGGER"] = "swagger2";
284
- SpecTypes["OPENAPI"] = "openapi3";
285
- })(SpecTypes || (SpecTypes = {}));
526
+ const target = args[0];
286
527
 
287
- /**
288
- * ignore
289
- * @param options
290
- */
528
+ if (args.length > 1) {
529
+ args[0] = prototypeOf(args[0]);
530
+ }
291
531
 
292
- function getHost(options) {
293
- const {
294
- host = `#/${options.specType === "openapi3" ? "components/schemas" : "definitions"}`
295
- } = options;
296
- return host;
297
- }
298
- /**
299
- * @ignore
300
- */
532
+ const store = Store.from(...args);
301
533
 
534
+ if (!store.has("JsonEntityStore")) {
535
+ const decoratorType = decoratorTypeOf(args);
536
+ const entityStore = JsonEntitiesContainer.get(decoratorType); // istanbul ignore next
302
537
 
303
- function createRefName(name, options) {
304
- if (options.groups && options.groups.length) {
305
- return pascalCase(`${name} ${options.groups.join(" ")}`);
306
- }
538
+ if (!entityStore) {
539
+ throw Error("Unsupported json entity type");
540
+ }
307
541
 
308
- return name;
309
- }
310
- /**
311
- * @ignore
312
- */
542
+ const jsonSchemaStore = new entityStore({
543
+ store,
544
+ decoratorType,
545
+ target: classOf(target),
546
+ propertyKey: args[1],
547
+ index: typeof args[2] === "number" ? args[2] : undefined,
548
+ descriptor: typeof args[2] === "object" ? args[2] : undefined
549
+ });
550
+ jsonSchemaStore.build();
551
+ store.set("JsonEntityStore", jsonSchemaStore);
552
+ }
313
553
 
314
- function createRef(name, schema, options) {
315
- const host = getHost(options);
316
- const ref = {
317
- $ref: `${host}/${name}`
318
- };
319
- const nullable = schema.nullable;
320
- const readOnly = schema.get ? schema.get("readOnly") : undefined;
554
+ return store.get("JsonEntityStore");
555
+ }
321
556
 
322
- if (nullable || readOnly) {
323
- switch (options.specType) {
324
- case SpecTypes.OPENAPI:
325
- return cleanObject({
326
- nullable: nullable ? true : undefined,
327
- readOnly: readOnly ? true : undefined,
328
- allOf: [ref]
329
- });
557
+ static fromMethod(target, propertyKey) {
558
+ return this.from(target, propertyKey, descriptorOf(target, propertyKey));
559
+ }
330
560
 
331
- case SpecTypes.JSON:
332
- return cleanObject({
333
- readOnly,
334
- oneOf: [nullable && {
335
- type: "null"
336
- }, ref].filter(Boolean)
337
- });
561
+ get(key, defaultValue) {
562
+ return this.store.get(key, defaultValue);
563
+ }
338
564
 
339
- case SpecTypes.SWAGGER:
340
- // unsupported
341
- if (readOnly) {
342
- return {
343
- readOnly,
344
- allOf: [ref]
345
- };
346
- }
565
+ set(key, value) {
566
+ return this.store.set(key, value);
567
+ }
347
568
 
348
- break;
569
+ buildType(type) {
570
+ if (isCollection(type)) {
571
+ this.collectionType = type;
572
+ } else {
573
+ this._type = type; // issue #1534: Enum metadata stored as plain object instead of String (see: https://github.com/tsedio/tsed/issues/1534)
574
+
575
+ if (this._type && isPlainObject(this._type)) {
576
+ this._type = String;
577
+ }
349
578
  }
350
579
  }
351
580
 
352
- return ref;
353
581
  }
582
+
354
583
  /**
355
584
  * @ignore
356
585
  */
357
586
 
358
- function toRef(value, schema, options) {
359
- const name = createRefName(value.getName(), options);
360
- options.schemas[value.getName()] = schema;
361
- return createRef(name, value, options);
362
- }
363
-
364
- function anyMapper(input, options = {}) {
365
- options.schemas = options.schemas || {};
366
-
367
- if (typeof input !== "object" || input === null) {
368
- return input;
587
+ function getComputedType(target) {
588
+ if (isPromise(target)) {
589
+ return Object;
369
590
  }
370
591
 
371
- if (input instanceof JsonLazyRef) {
372
- return execMapper("lazyRef", input, options);
592
+ if (isClass(target) || isSymbol(target) || isPrimitiveOrPrimitiveClass(target) || isClassObject(target) || isDate(target) || isCollection(target)) {
593
+ return classOf(target);
373
594
  }
374
595
 
375
- if ("toJSON" in input) {
376
- const schema = input.toJSON(mapGenericsOptions(options));
377
- return input.canRef ? toRef(input, schema, options) : schema;
596
+ if (isArrowFn(target)) {
597
+ return target();
378
598
  }
379
599
 
380
- return execMapper("object", input, options);
600
+ return target;
381
601
  }
382
- registerJsonSchemaMapper("any", anyMapper);
383
602
 
384
- const isSuccessStatus = code => Number(code) && 200 <= Number(code) && Number(code) < 300;
385
- const isRedirectionStatus = code => Number(code) && 300 <= Number(code) && Number(code) < 400;
386
-
387
- class JsonMap extends Map {
388
- constructor(obj = {}) {
389
- super();
390
- this.assign(obj);
391
- }
392
-
393
- assign(obj = {}) {
394
- Object.entries(obj).forEach(([key, value]) => {
395
- if (isFunction(this[key])) {
396
- this[key](value);
397
- } else {
398
- this.set(key, value);
399
- }
400
- });
401
- return this;
402
- }
403
-
404
- toJSON(options = {}) {
405
- return execMapper("map", this, options);
406
- }
407
-
408
- }
409
-
410
- var JsonParameterTypes;
411
-
412
- (function (JsonParameterTypes) {
413
- JsonParameterTypes["BODY"] = "body";
414
- JsonParameterTypes["PATH"] = "path";
415
- JsonParameterTypes["QUERY"] = "query";
416
- JsonParameterTypes["HEADER"] = "header";
417
- JsonParameterTypes["COOKIES"] = "cookie";
418
- JsonParameterTypes["FILES"] = "files";
419
- })(JsonParameterTypes || (JsonParameterTypes = {}));
420
- /**
421
- * @ignore
422
- */
423
-
424
-
425
- function formatParameterType(type) {
426
- return String(type).toLowerCase().replace("raw_", "").replace("cookies", "cookie");
427
- }
428
- /**
429
- * @ignore
430
- */
431
-
432
- function isParameterType(type) {
433
- return Object.values(JsonParameterTypes).includes(formatParameterType(type));
434
- }
435
-
436
- /**
437
- * @ignore
438
- */
439
-
440
- function toJsonMapCollection(content, klass = JsonMap) {
441
- return Object.entries(content).reduce((content, [key, value]) => {
442
- content.set(key, new klass(value));
443
- return content;
444
- }, new JsonMap());
445
- }
446
-
447
- class JsonRequestBody extends JsonMap {
448
- constructor(obj = {}) {
449
- super(obj);
450
- this.content(obj.content || {});
451
- }
452
-
453
- description(description) {
454
- this.set("description", description);
455
- return this;
456
- }
457
-
458
- content(content) {
459
- this.set("content", toJsonMapCollection(content));
460
- return this;
461
- }
462
-
463
- addContent(mediaType, schema) {
464
- const content = this.get("content");
465
- const mediaContent = new JsonMap();
466
- mediaContent.set("schema", schema);
467
- content.set(mediaType, mediaContent);
468
- return this;
469
- }
470
-
471
- required(required) {
472
- this.set("required", required);
473
- return this;
474
- }
475
-
476
- }
477
-
478
- /**
479
- * Map input header to a standard open spec header
480
- * @param headers
481
- * @ignore
482
- */
483
-
484
- function mapHeaders(headers) {
485
- return Object.keys(headers).reduce((newHeaders, key) => {
486
- const value = headers[key];
487
- let type = typeof value;
488
- let options = {
489
- example: value
490
- };
491
-
492
- if (type === "object") {
493
- options = value;
494
- options.example = options.value === undefined ? options.example : options.value;
495
- delete options.value;
496
- type = typeof options.example;
497
- }
498
-
499
- options.type = options.type || type;
500
- newHeaders[key] = cleanObject(options);
501
- return newHeaders;
502
- }, {});
503
- }
504
-
505
- const _excluded$7 = ["type"];
506
- class JsonMedia extends JsonMap {
507
- constructor() {
508
- super(...arguments);
509
- this.groups = [];
510
- }
511
-
512
- schema(schema) {
513
- this.set("schema", schema);
514
- return this;
515
- }
516
-
517
- examples(examples) {
518
- this.set("examples", examples);
519
- return this;
520
- }
521
-
522
- toJSON(options = {}) {
523
- return super.toJSON(_extends({}, options, {
524
- groups: this.groups
525
- }));
526
- }
527
-
528
- }
529
- class JsonResponse extends JsonMap {
530
- constructor(obj = {}) {
531
- super(obj);
532
- this.content(obj.content || {});
533
- }
534
-
535
- description(description) {
536
- this.set("description", description);
537
- return this;
538
- }
539
-
540
- headers(headers) {
541
- this.set("headers", mapHeaders(headers));
542
- return this;
543
- }
544
-
545
- content(content) {
546
- this.set("content", toJsonMapCollection(content, JsonMedia));
547
- return this;
548
- }
549
-
550
- getContent() {
551
- return this.get("content");
552
- }
553
-
554
- getMedia(mediaType, create = true) {
555
- var _this$getContent;
556
-
557
- create && this.addMedia(mediaType);
558
- return (_this$getContent = this.getContent()) == null ? void 0 : _this$getContent.get(mediaType);
559
- }
560
-
561
- addMedia(mediaType) {
562
- const content = this.get("content");
563
-
564
- if (!content.has(mediaType)) {
565
- content.set(mediaType, new JsonMedia());
566
- }
567
-
568
- return this;
569
- }
570
-
571
- toJSON(options = {}) {
572
- const response = super.toJSON(options);
573
-
574
- if (this.status === 204) {
575
- delete response.content;
576
- }
577
-
578
- if (options.specType === SpecTypes.OPENAPI && response.headers) {
579
- Object.entries(response.headers).forEach(([key, _ref]) => {
580
- let {
581
- type
582
- } = _ref,
583
- props = _objectWithoutPropertiesLoose(_ref, _excluded$7);
584
-
585
- response.headers[key] = _extends({}, props, {
586
- schema: {
587
- type
588
- }
589
- });
590
- });
591
- }
592
-
593
- if (options.specType !== SpecTypes.OPENAPI && response.content) {
594
- const key = Object.keys(response.content)[0];
595
- return cleanObject(_extends({}, response, response.content[key], {
596
- content: undefined
597
- }));
598
- }
599
-
600
- return response;
601
- }
602
-
603
- }
604
-
605
- /**
606
- * @ignore
607
- */
608
-
609
- function getComputedType(target) {
610
- if (isPromise(target)) {
611
- return Object;
612
- }
613
-
614
- if (isClass(target) || isSymbol(target) || isPrimitiveOrPrimitiveClass(target) || isClassObject(target) || isDate(target) || isCollection(target)) {
615
- return classOf(target);
616
- }
617
-
618
- if (isArrowFn(target)) {
619
- return target();
620
- }
621
-
622
- return target;
623
- }
624
-
625
- /**
626
- * @ignore
627
- */
603
+ /**
604
+ * @ignore
605
+ */
628
606
 
629
607
  const JSON_TYPES = ["string", "number", "integer", "boolean", "object", "array", "null", "any"];
630
608
  function getJsonType(value) {
@@ -697,7 +675,7 @@ function mapToJsonSchema(item) {
697
675
  }
698
676
 
699
677
  if (classOf(item) !== Object && isClass(item)) {
700
- return getJsonEntityStore(item).schema;
678
+ return JsonEntityStore.from(item).schema;
701
679
  }
702
680
 
703
681
  if (isObject(item)) {
@@ -1526,318 +1504,222 @@ class JsonSchema extends Map {
1526
1504
 
1527
1505
  }
1528
1506
 
1529
- const _excluded$6 = ["schema", "in"];
1507
+ /**
1508
+ * Declare a new JsonEntityStore class for a specific decorator type.
1509
+ *
1510
+ * @ignore
1511
+ * @param type
1512
+ * @decorator
1513
+ */
1530
1514
 
1531
- var _status = /*#__PURE__*/_classPrivateFieldLooseKey("status");
1515
+ function JsonEntityComponent(type) {
1516
+ return target => {
1517
+ JsonEntitiesContainer.set(type, target);
1518
+ };
1519
+ }
1532
1520
 
1533
- var _redirection = /*#__PURE__*/_classPrivateFieldLooseKey("redirection");
1521
+ let JsonClassStore = class JsonClassStore extends JsonEntityStore {
1522
+ constructor() {
1523
+ super(...arguments);
1524
+ /**
1525
+ * List of children JsonEntityStore (properties or methods or params)
1526
+ */
1534
1527
 
1535
- class JsonOperation extends JsonMap {
1536
- constructor(obj = {}) {
1537
- super(_extends({
1538
- parameters: [],
1539
- responses: new JsonMap()
1540
- }, obj));
1541
- Object.defineProperty(this, _status, {
1542
- writable: true,
1543
- value: void 0
1544
- });
1545
- Object.defineProperty(this, _redirection, {
1546
- writable: true,
1547
- value: void 0
1548
- });
1549
- this.operationPaths = new Map();
1550
- _classPrivateFieldLooseBase(this, _redirection)[_redirection] = false;
1528
+ this.children = new Map();
1551
1529
  }
1552
1530
 
1553
- get response() {
1554
- return this.getResponses().get(this.getStatus().toString());
1531
+ get path() {
1532
+ return this.store.get("path", "/");
1555
1533
  }
1556
1534
 
1557
- get status() {
1558
- return _classPrivateFieldLooseBase(this, _status)[_status];
1535
+ set path(path) {
1536
+ this.store.set("path", path);
1559
1537
  }
1560
1538
 
1561
- tags(tags) {
1562
- super.set("tags", tags);
1563
- return this;
1564
- }
1539
+ build() {
1540
+ if (!this._type) {
1541
+ this.buildType(this.target);
1542
+ }
1565
1543
 
1566
- addTags(tags) {
1567
- tags = uniqBy([...(this.get("tags") || []), ...tags], "name");
1568
- return this.tags(tags);
1544
+ this._type = this._type || Object;
1545
+ this._schema = JsonSchema.from({
1546
+ type: this.type
1547
+ });
1569
1548
  }
1570
1549
 
1571
- summary(summary) {
1572
- super.set("summary", summary);
1573
- return this;
1574
- }
1550
+ };
1551
+ JsonClassStore = __decorate([JsonEntityComponent(DecoratorTypes.CLASS)], JsonClassStore);
1575
1552
 
1576
- operationId(operationId) {
1577
- this.set("operationId", operationId);
1578
- return this;
1553
+ let JsonPropertyStore = class JsonPropertyStore extends JsonEntityStore {
1554
+ constructor() {
1555
+ super(...arguments);
1556
+ this.parent = JsonEntityStore.from(this.target);
1579
1557
  }
1558
+ /**
1559
+ * Return the required state.
1560
+ * @returns {boolean}
1561
+ */
1580
1562
 
1581
- responses(responses) {
1582
- this.set("responses", responses);
1583
- return this;
1584
- }
1585
1563
 
1586
- defaultStatus(status) {
1587
- _classPrivateFieldLooseBase(this, _status)[_status] = status;
1588
- return this;
1564
+ get required() {
1565
+ return this.parent.schema.isRequired(this.propertyKey);
1589
1566
  }
1567
+ /**
1568
+ * Change the state of the required data.
1569
+ * @param value
1570
+ */
1590
1571
 
1591
- getStatus() {
1592
- return _classPrivateFieldLooseBase(this, _status)[_status] || 200;
1572
+
1573
+ set required(value) {
1574
+ if (value) {
1575
+ this.parent.schema.addRequired(this.propertyKey);
1576
+ } else {
1577
+ this.parent.schema.removeRequired(this.propertyKey);
1578
+ }
1593
1579
  }
1594
1580
 
1595
- setRedirection(status = 302) {
1596
- _classPrivateFieldLooseBase(this, _redirection)[_redirection] = true;
1597
- _classPrivateFieldLooseBase(this, _status)[_status] = status;
1598
- return this;
1581
+ get allowedRequiredValues() {
1582
+ return this.schema.$allow;
1599
1583
  }
1584
+ /**
1585
+ * Check precondition between value, required and allowedRequiredValues to know if the entity is required.
1586
+ * @param value
1587
+ * @returns {boolean}
1588
+ */
1600
1589
 
1601
- isRedirection(status) {
1602
- if (_classPrivateFieldLooseBase(this, _redirection)[_redirection]) {
1603
- if (status) {
1604
- return isRedirectionStatus(status);
1605
- }
1606
- }
1607
1590
 
1608
- return _classPrivateFieldLooseBase(this, _redirection)[_redirection];
1591
+ isRequired(value) {
1592
+ return this.required && [undefined, null, ""].includes(value) && !this.allowedRequiredValues.includes(value);
1609
1593
  }
1610
1594
 
1611
- addResponse(statusCode, response) {
1612
- if ((isSuccessStatus(statusCode) || isRedirectionStatus(statusCode)) && !_classPrivateFieldLooseBase(this, _status)[_status]) {
1613
- const res = this.getResponseOf(200);
1614
- this.getResponses().set(statusCode.toString(), res).delete("200");
1615
- this.defaultStatus(Number(statusCode));
1595
+ build() {
1596
+ if (!this._type) {
1597
+ this.buildType(Metadata.getType(prototypeOf(this.target), this.propertyKey));
1616
1598
  }
1617
1599
 
1618
- const currentCode = statusCode === "default" ? this.getStatus().toString() : statusCode.toString();
1619
- const currentResponse = this.getResponses().get(currentCode);
1600
+ this._type = this._type || Object;
1601
+ const properties = this.parent.schema.get("properties");
1602
+ let schema = properties[this.propertyName];
1620
1603
 
1621
- if (!currentResponse) {
1622
- response.status = Number(currentCode);
1623
- this.getResponses().set(currentCode, response);
1624
- } else {
1625
- response.forEach((value, key) => {
1626
- if (!["content"].includes(key)) {
1627
- currentResponse.set(key, deepMerge(currentResponse.get(key), value));
1628
- }
1604
+ if (!schema) {
1605
+ this.parent.children.set(this.propertyName, this);
1606
+ schema = JsonSchema.from({
1607
+ type: this.collectionType || this.type
1629
1608
  });
1630
- currentResponse.status = Number(currentCode);
1609
+
1610
+ if (this.collectionType) {
1611
+ schema.itemSchema(this.type);
1612
+ }
1631
1613
  }
1632
1614
 
1633
- return this;
1615
+ this.parent.schema.addProperty(this.propertyName, schema);
1616
+ this._schema = schema;
1634
1617
  }
1635
1618
 
1636
- getResponses() {
1637
- return this.get("responses");
1638
- }
1619
+ };
1620
+ JsonPropertyStore = __decorate([JsonEntityComponent(DecoratorTypes.PROP)], JsonPropertyStore);
1639
1621
 
1640
- getResponseOf(status) {
1641
- return (status === "default" ? this.response : this.getResponses().get(String(status))) || new JsonResponse();
1642
- }
1622
+ const _excluded$8 = ["genericLabels", "genericTypes"];
1643
1623
 
1644
- ensureResponseOf(status) {
1645
- this.addResponse(status, this.getResponseOf(status));
1646
- return this.getResponseOf(status);
1647
- }
1624
+ /**
1625
+ * @ignore
1626
+ * @param genericLabels
1627
+ * @param genericTypes
1628
+ */
1629
+ function getGenericsMap(genericLabels, genericTypes) {
1630
+ return genericLabels.reduce((map, item, index) => map.set(item, genericTypes[index]), new Map());
1631
+ }
1632
+ /**
1633
+ * @ignore
1634
+ * @param options
1635
+ */
1648
1636
 
1649
- getHeadersOf(status) {
1650
- return this.getResponseOf(status).get("headers") || {};
1651
- }
1637
+ function mapGenericsOptions(options) {
1638
+ if (options.genericLabels && options.genericTypes) {
1639
+ const {
1640
+ genericLabels,
1641
+ genericTypes
1642
+ } = options,
1643
+ ops = _objectWithoutPropertiesLoose(options, _excluded$8);
1652
1644
 
1653
- getContentTypeOf(status) {
1654
- return [...this.getResponseOf(status).get("content").keys()].slice(-1)[0];
1645
+ return _extends({}, ops, {
1646
+ generics: getGenericsMap(genericLabels, genericTypes)
1647
+ });
1655
1648
  }
1656
1649
 
1657
- security(security) {
1658
- this.set("security", security);
1659
- return this;
1660
- }
1650
+ return options;
1651
+ }
1652
+ /**
1653
+ * @ignore
1654
+ * @param value
1655
+ */
1661
1656
 
1662
- addSecurityScopes(name, scopes) {
1663
- const security = this.get("security") || {};
1664
- security[name] = uniq([...(security[name] || []), ...scopes]);
1665
- return this.security(security);
1666
- }
1657
+ function popGenerics(value) {
1658
+ const [genericTypes, ...out] = value.nestedGenerics;
1659
+ return {
1660
+ genericTypes,
1661
+ nestedGenerics: out
1662
+ };
1663
+ }
1667
1664
 
1668
- description(description) {
1669
- super.set("description", description);
1670
- return this;
1665
+ class JsonMap extends Map {
1666
+ constructor(obj = {}) {
1667
+ super();
1668
+ this.assign(obj);
1671
1669
  }
1672
1670
 
1673
- deprecated(deprecated) {
1674
- super.set("deprecated", deprecated);
1671
+ assign(obj = {}) {
1672
+ Object.entries(obj).forEach(([key, value]) => {
1673
+ if (isFunction(this[key])) {
1674
+ this[key](value);
1675
+ } else {
1676
+ this.set(key, value);
1677
+ }
1678
+ });
1675
1679
  return this;
1676
1680
  }
1677
1681
 
1678
- parameters(parameters) {
1679
- super.set("parameters", parameters);
1680
- return this;
1682
+ toJSON(options = {}) {
1683
+ return execMapper("map", this, options);
1681
1684
  }
1682
1685
 
1683
- addParameter(index, parameter) {
1684
- if (index === -1) {
1685
- index = this.get("parameters").length;
1686
- }
1686
+ }
1687
1687
 
1688
- this.get("parameters")[index] = parameter;
1689
- }
1688
+ var JsonParameterTypes;
1690
1689
 
1691
- consumes(consumes) {
1692
- super.set("consumes", consumes);
1693
- return this;
1694
- }
1690
+ (function (JsonParameterTypes) {
1691
+ JsonParameterTypes["BODY"] = "body";
1692
+ JsonParameterTypes["PATH"] = "path";
1693
+ JsonParameterTypes["QUERY"] = "query";
1694
+ JsonParameterTypes["HEADER"] = "header";
1695
+ JsonParameterTypes["COOKIES"] = "cookie";
1696
+ JsonParameterTypes["FILES"] = "files";
1697
+ })(JsonParameterTypes || (JsonParameterTypes = {}));
1698
+ /**
1699
+ * @ignore
1700
+ */
1695
1701
 
1696
- produces(produces) {
1697
- super.set("produces", produces);
1698
- return this;
1699
- }
1700
1702
 
1701
- addProduce(produce) {
1702
- const produces = uniq([].concat(this.get("produces"), produce)).filter(Boolean);
1703
- this.set("produces", produces);
1704
- }
1703
+ function formatParameterType(type) {
1704
+ return String(type).toLowerCase().replace("raw_", "").replace("cookies", "cookie");
1705
+ }
1706
+ /**
1707
+ * @ignore
1708
+ */
1705
1709
 
1706
- addOperationPath(method, path, options = {}) {
1707
- this.operationPaths.set(String(method) + String(path), _extends({}, options, {
1708
- method,
1709
- path
1710
- }));
1711
- return this;
1712
- }
1710
+ function isParameterType(type) {
1711
+ return Object.values(JsonParameterTypes).includes(formatParameterType(type));
1712
+ }
1713
1713
 
1714
- toJSON(options = {}) {
1715
- const operation = super.toJSON(_extends({}, options, {
1716
- ignore: ["parameters"]
1717
- }));
1718
- const bodyParameters = [];
1719
- const parameters = [];
1714
+ var SpecTypes;
1720
1715
 
1721
- if (operation.security) {
1722
- operation.security = [].concat(operation.security);
1723
- }
1724
-
1725
- this.get("parameters").forEach(parameter => {
1726
- if (!isParameterType(this.get("in"))) {
1727
- if (parameter.get("in")) {
1728
- if ([JsonParameterTypes.BODY, JsonParameterTypes.FILES].includes(parameter.get("in"))) {
1729
- bodyParameters.push(parameter);
1730
- } else {
1731
- parameters.push(...[].concat(parameter.toJSON(options)));
1732
- }
1733
- }
1734
- }
1735
- });
1736
- operation.parameters = parameters.filter(Boolean);
1737
-
1738
- if (this.get("responses").size === 0) {
1739
- operation.responses = {
1740
- "200": {
1741
- description: HTTP_STATUS_MESSAGES[200]
1742
- }
1743
- };
1744
- }
1745
-
1746
- if (bodyParameters.length) {
1747
- const parameter = buildSchemaFromBodyParameters(bodyParameters, options);
1748
-
1749
- if (options.specType === SpecTypes.OPENAPI) {
1750
- operation.requestBody = toRequestBody(this, parameter).toJSON(options);
1751
- } else {
1752
- operation.parameters.push(toJsonParameter(parameter));
1753
- }
1754
- }
1755
-
1756
- if (options.specType === SpecTypes.OPENAPI) {
1757
- delete operation.consumes;
1758
- delete operation.produces;
1759
- }
1760
-
1761
- return operation;
1762
- }
1763
-
1764
- }
1765
-
1766
- function toRequestBody(operation, _ref) {
1767
- var _operation$get;
1768
-
1769
- let {
1770
- schema
1771
- } = _ref,
1772
- props = _objectWithoutPropertiesLoose(_ref, _excluded$6);
1773
-
1774
- const requestBody = new JsonRequestBody(props);
1775
- const consumes = (_operation$get = operation.get("consumes")) != null && _operation$get.length ? operation.get("consumes") : ["application/json"];
1776
- consumes.forEach(consume => {
1777
- requestBody.addContent(consume, schema);
1778
- });
1779
- return requestBody;
1780
- }
1781
-
1782
- function toJsonParameter(parameter) {
1783
- return _extends({
1784
- in: JsonParameterTypes.BODY,
1785
- name: JsonParameterTypes.BODY
1786
- }, parameter);
1787
- }
1788
-
1789
- function buildSchemaFromBodyParameters(parameters, options) {
1790
- let schema = new JsonSchema();
1791
- const props = {};
1792
- const refs = [];
1793
- let propsLength = 0;
1794
- parameters.forEach(parameter => {
1795
- const name = parameter.getName();
1796
- Array.from(parameter.entries()).filter(([key]) => !["in", "name"].includes(key)).forEach(([key, value]) => {
1797
- if (props[key] === undefined) {
1798
- props[key] = value;
1799
- }
1800
- });
1801
- const jsonParameter = parameter.toJSON(options);
1802
-
1803
- if (name) {
1804
- schema.addProperty(name, jsonParameter.schema || {
1805
- type: jsonParameter.type
1806
- });
1807
-
1808
- if (parameter.get("required")) {
1809
- schema.addRequired(name);
1810
- }
1811
-
1812
- propsLength++;
1813
- } else {
1814
- refs.push(jsonParameter);
1815
- }
1816
- });
1817
-
1818
- if (propsLength) {
1819
- schema.type("object");
1820
- return _extends({
1821
- schema: schema.toJSON(options),
1822
- required: false
1823
- }, props);
1824
- }
1825
-
1826
- if (refs.length === 1) {
1827
- return refs[0];
1828
- }
1829
-
1830
- if (refs.length > 0) {
1831
- schema.allOf(refs);
1832
- }
1833
-
1834
- return _extends({
1835
- schema: schema.toJSON(options),
1836
- required: false
1837
- }, props);
1838
- }
1716
+ (function (SpecTypes) {
1717
+ SpecTypes["JSON"] = "jsonschema";
1718
+ SpecTypes["SWAGGER"] = "swagger2";
1719
+ SpecTypes["OPENAPI"] = "openapi3";
1720
+ })(SpecTypes || (SpecTypes = {}));
1839
1721
 
1840
- const _excluded$5 = ["type", "schema"],
1722
+ const _excluded$7 = ["type", "schema"],
1841
1723
  _excluded2 = ["minLength"],
1842
1724
  _excluded3 = ["description"];
1843
1725
  const IGNORE_OS2_PROPS = ["example", "examples", "title"];
@@ -1901,7 +1783,7 @@ class JsonParameter extends JsonMap {
1901
1783
 
1902
1784
  build(options, schemasContainer) {
1903
1785
  const _super$toJSON = super.toJSON(options),
1904
- parameter = _objectWithoutPropertiesLoose(_super$toJSON, _excluded$5);
1786
+ parameter = _objectWithoutPropertiesLoose(_super$toJSON, _excluded$7);
1905
1787
 
1906
1788
  const jsonSchema = execMapper("item", this.$schema, _extends({}, options, popGenerics(this)));
1907
1789
  parameter.required = parameter.required || this.get("in") === JsonParameterTypes.PATH;
@@ -2000,202 +1882,607 @@ class JsonParameter extends JsonMap {
2000
1882
 
2001
1883
  }
2002
1884
 
2003
- const getSchema = type => {
2004
- if (isCollection(type) || !isClass(type)) {
2005
- return JsonSchema.from({
2006
- type
2007
- });
2008
- }
2009
-
2010
- return getJsonEntityStore(type).schema;
2011
- };
2012
-
2013
- class JsonEntityStore extends Entity {
2014
- constructor(options) {
2015
- super(options);
2016
- this.isStore = true;
1885
+ let JsonParameterStore = class JsonParameterStore extends JsonEntityStore {
1886
+ constructor() {
1887
+ super(...arguments);
2017
1888
  /**
2018
- * List of children JsonEntityStore (properties or methods or params)
1889
+ * Ref to JsonParameter when the decorated object is a parameter.
2019
1890
  */
2020
1891
 
2021
- this.children = new Map();
2022
- this.store = options.store;
2023
- /* istanbul ignore next */
2024
-
2025
- if (options.children) {
2026
- this.children = options.children;
2027
- }
2028
-
2029
- this.build();
2030
- }
2031
-
2032
- get path() {
2033
- return this.store.get("path", "/");
1892
+ this.parameter = new JsonParameter();
1893
+ this.parent = JsonEntityStore.fromMethod(this.target, this.propertyKey);
2034
1894
  }
2035
1895
 
2036
- set path(path) {
2037
- this.store.set("path", path);
1896
+ get nestedGenerics() {
1897
+ return this.parameter.nestedGenerics;
2038
1898
  }
2039
- /**
2040
- * Return the JsonSchema
2041
- */
2042
-
2043
1899
 
2044
- get schema() {
2045
- return this._schema;
1900
+ set nestedGenerics(nestedGenerics) {
1901
+ this.parameter.nestedGenerics = nestedGenerics;
2046
1902
  }
2047
1903
  /**
2048
- * Return the JsonOperation
1904
+ * Return the required state.
1905
+ * @returns {boolean}
2049
1906
  */
2050
1907
 
2051
1908
 
2052
- get operation() {
2053
- return this._operation;
1909
+ get required() {
1910
+ return !!this.parameter.get("required");
2054
1911
  }
2055
- /**
2056
- * Return the JsonParameter
2057
- */
2058
-
2059
1912
 
2060
- get parameter() {
2061
- return this._parameter;
1913
+ set required(value) {
1914
+ this.parameter.required(value);
2062
1915
  }
2063
1916
 
2064
- get nestedGenerics() {
2065
- switch (this.decoratorType) {
2066
- case DecoratorTypes.PARAM:
2067
- return this.parameter.nestedGenerics;
2068
-
2069
- default:
2070
- return this.schema.nestedGenerics;
2071
- }
1917
+ get allowedRequiredValues() {
1918
+ return this.schema.$allow;
2072
1919
  }
2073
1920
 
2074
- set nestedGenerics(nestedGenerics) {
2075
- switch (this.decoratorType) {
2076
- case DecoratorTypes.PARAM:
2077
- this.parameter.nestedGenerics = nestedGenerics;
2078
- break;
1921
+ static getParams(target, propertyKey) {
1922
+ const params = [];
1923
+ const klass = ancestorsOf(target).reverse().find(target => {
1924
+ return isMethodDescriptor(target, propertyKey) && JsonEntityStore.fromMethod(target, propertyKey).children.size;
1925
+ });
2079
1926
 
2080
- default:
2081
- this.schema.nestedGenerics = nestedGenerics;
2082
- break;
1927
+ if (klass) {
1928
+ JsonEntityStore.fromMethod(klass, propertyKey).children.forEach((param, index) => {
1929
+ params[+index] = param;
1930
+ });
1931
+ return params;
2083
1932
  }
2084
- }
2085
- /**
2086
- *
2087
- * @returns {Type<any>}
2088
- */
2089
1933
 
2090
-
2091
- get type() {
2092
- return this._type;
1934
+ return [];
2093
1935
  }
2094
1936
  /**
2095
- * Get original type without transformation
1937
+ * Check precondition between value, required and allowedRequiredValues to know if the entity is required.
2096
1938
  * @param value
1939
+ * @returns {boolean}
2097
1940
  */
2098
1941
 
2099
1942
 
2100
- set type(value) {
2101
- this._type = value;
2102
- this.build();
1943
+ isRequired(value) {
1944
+ return this.required && [undefined, null, ""].includes(value) && !this.allowedRequiredValues.includes(value);
2103
1945
  }
2104
- /**
2105
- * Return the itemSchema computed type. if the type is a function used for recursive model, the function will be called to
2106
- * get the right type.
2107
- */
2108
1946
 
1947
+ getSchema(type) {
1948
+ if (isCollection(type) || !isClass(type)) {
1949
+ return JsonSchema.from({
1950
+ type
1951
+ });
1952
+ }
2109
1953
 
2110
- get computedType() {
2111
- return this.itemSchema.getComputedType();
1954
+ return JsonEntityStore.from(type).schema;
2112
1955
  }
2113
1956
 
2114
- get itemSchema() {
2115
- return this.isCollection ? this.schema.itemSchema() : this.schema;
2116
- }
1957
+ build() {
1958
+ if (!this._type) {
1959
+ const type = Metadata.getParamTypes(prototypeOf(this.target), this.propertyKey)[this.index];
1960
+ this.buildType(type);
1961
+ }
2117
1962
 
2118
- get parentSchema() {
2119
- return this.parent.schema;
2120
- }
1963
+ this._type = this._type || Object;
2121
1964
 
2122
- get parent() {
2123
- const {
2124
- target,
2125
- propertyKey,
2126
- decoratorType
2127
- } = this;
1965
+ if (!this._schema) {
1966
+ this.parent.children.set(this.index, this);
1967
+ this._schema = this.getSchema(this.collectionType || this.type);
1968
+ this.parameter.schema(this._schema);
2128
1969
 
2129
- switch (decoratorType) {
2130
- case DecoratorTypes.PARAM:
2131
- return JsonEntityStore.fromMethod(target, propertyKey);
1970
+ if (this.collectionType) {
1971
+ this._schema.itemSchema(this.getSchema(this.type));
1972
+ }
2132
1973
 
2133
- case DecoratorTypes.METHOD:
2134
- case DecoratorTypes.PROP:
2135
- return JsonEntityStore.from(target);
1974
+ this.parent.operation.addParameter(this.index, this.parameter);
2136
1975
  }
2137
-
2138
- return this;
2139
1976
  }
2140
- /**
2141
- * Return the required state.
2142
- * @returns {boolean}
2143
- */
2144
1977
 
1978
+ };
1979
+ JsonParameterStore = __decorate([JsonEntityComponent(DecoratorTypes.PARAM)], JsonParameterStore);
1980
+
1981
+ const isSuccessStatus = code => Number(code) && 200 <= Number(code) && Number(code) < 300;
1982
+ const isRedirectionStatus = code => Number(code) && 300 <= Number(code) && Number(code) < 400;
2145
1983
 
2146
- get required() {
2147
- switch (this.decoratorType) {
2148
- case DecoratorTypes.PROP:
2149
- return this.parent.schema.isRequired(this.propertyKey);
1984
+ /**
1985
+ * @ignore
1986
+ */
2150
1987
 
2151
- case DecoratorTypes.PARAM:
2152
- return this.parameter.get("required");
2153
- }
1988
+ function toJsonMapCollection(content, klass = JsonMap) {
1989
+ return Object.entries(content).reduce((content, [key, value]) => {
1990
+ content.set(key, new klass(value));
1991
+ return content;
1992
+ }, new JsonMap());
1993
+ }
2154
1994
 
2155
- return false;
1995
+ class JsonRequestBody extends JsonMap {
1996
+ constructor(obj = {}) {
1997
+ super(obj);
1998
+ this.content(obj.content || {});
2156
1999
  }
2157
- /**
2158
- * Change the state of the required data.
2159
- * @param value
2160
- */
2161
2000
 
2001
+ description(description) {
2002
+ this.set("description", description);
2003
+ return this;
2004
+ }
2162
2005
 
2163
- set required(value) {
2164
- switch (this.decoratorType) {
2165
- case DecoratorTypes.PROP:
2166
- if (value) {
2167
- this.parent.schema.addRequired(this.propertyKey);
2168
- } else {
2169
- this.parent.schema.removeRequired(this.propertyKey);
2170
- }
2006
+ content(content) {
2007
+ this.set("content", toJsonMapCollection(content));
2008
+ return this;
2009
+ }
2171
2010
 
2172
- break;
2011
+ addContent(mediaType, schema) {
2012
+ const content = this.get("content");
2013
+ const mediaContent = new JsonMap();
2014
+ mediaContent.set("schema", schema);
2015
+ content.set(mediaType, mediaContent);
2016
+ return this;
2017
+ }
2173
2018
 
2174
- case DecoratorTypes.PARAM:
2175
- this.parameter.required(value);
2176
- break;
2019
+ required(required) {
2020
+ this.set("required", required);
2021
+ return this;
2022
+ }
2023
+
2024
+ }
2025
+
2026
+ /**
2027
+ * Map input header to a standard open spec header
2028
+ * @param headers
2029
+ * @ignore
2030
+ */
2031
+
2032
+ function mapHeaders(headers) {
2033
+ return Object.keys(headers).reduce((newHeaders, key) => {
2034
+ const value = headers[key];
2035
+ let type = typeof value;
2036
+ let options = {
2037
+ example: value
2038
+ };
2039
+
2040
+ if (type === "object") {
2041
+ options = value;
2042
+ options.example = options.value === undefined ? options.example : options.value;
2043
+ delete options.value;
2044
+ type = typeof options.example;
2177
2045
  }
2046
+
2047
+ options.type = options.type || type;
2048
+ newHeaders[key] = cleanObject(options);
2049
+ return newHeaders;
2050
+ }, {});
2051
+ }
2052
+
2053
+ const _excluded$6 = ["type"];
2054
+ class JsonMedia extends JsonMap {
2055
+ constructor() {
2056
+ super(...arguments);
2057
+ this.groups = [];
2178
2058
  }
2179
2059
 
2180
- get allowedRequiredValues() {
2181
- return this.schema.$allow;
2182
- }
2183
- /**
2184
- *
2185
- * @param args
2186
- */
2060
+ schema(schema) {
2061
+ this.set("schema", schema);
2062
+ return this;
2063
+ }
2064
+
2065
+ examples(examples) {
2066
+ this.set("examples", examples);
2067
+ return this;
2068
+ }
2069
+
2070
+ toJSON(options = {}) {
2071
+ return super.toJSON(_extends({}, options, {
2072
+ groups: this.groups
2073
+ }));
2074
+ }
2075
+
2076
+ }
2077
+ class JsonResponse extends JsonMap {
2078
+ constructor(obj = {}) {
2079
+ super(obj);
2080
+ this.content(obj.content || {});
2081
+ }
2082
+
2083
+ description(description) {
2084
+ this.set("description", description);
2085
+ return this;
2086
+ }
2087
+
2088
+ headers(headers) {
2089
+ this.set("headers", mapHeaders(headers));
2090
+ return this;
2091
+ }
2092
+
2093
+ content(content) {
2094
+ this.set("content", toJsonMapCollection(content, JsonMedia));
2095
+ return this;
2096
+ }
2097
+
2098
+ getContent() {
2099
+ return this.get("content");
2100
+ }
2101
+
2102
+ getMedia(mediaType, create = true) {
2103
+ var _this$getContent;
2104
+
2105
+ create && this.addMedia(mediaType);
2106
+ return (_this$getContent = this.getContent()) == null ? void 0 : _this$getContent.get(mediaType);
2107
+ }
2108
+
2109
+ addMedia(mediaType) {
2110
+ const content = this.get("content");
2111
+
2112
+ if (!content.has(mediaType)) {
2113
+ content.set(mediaType, new JsonMedia());
2114
+ }
2115
+
2116
+ return this;
2117
+ }
2118
+
2119
+ toJSON(options = {}) {
2120
+ const response = super.toJSON(options);
2121
+
2122
+ if (this.status === 204) {
2123
+ delete response.content;
2124
+ }
2125
+
2126
+ if (options.specType === SpecTypes.OPENAPI && response.headers) {
2127
+ Object.entries(response.headers).forEach(([key, _ref]) => {
2128
+ let {
2129
+ type
2130
+ } = _ref,
2131
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$6);
2132
+
2133
+ response.headers[key] = _extends({}, props, {
2134
+ schema: {
2135
+ type
2136
+ }
2137
+ });
2138
+ });
2139
+ }
2140
+
2141
+ if (options.specType !== SpecTypes.OPENAPI && response.content) {
2142
+ const key = Object.keys(response.content)[0];
2143
+ return cleanObject(_extends({}, response, response.content[key], {
2144
+ content: undefined
2145
+ }));
2146
+ }
2147
+
2148
+ return response;
2149
+ }
2150
+
2151
+ }
2152
+
2153
+ const _excluded$5 = ["schema", "in"];
2154
+
2155
+ var _status = /*#__PURE__*/_classPrivateFieldLooseKey("status");
2156
+
2157
+ var _redirection = /*#__PURE__*/_classPrivateFieldLooseKey("redirection");
2158
+
2159
+ class JsonOperation extends JsonMap {
2160
+ constructor(obj = {}) {
2161
+ super(_extends({
2162
+ parameters: [],
2163
+ responses: new JsonMap()
2164
+ }, obj));
2165
+ Object.defineProperty(this, _status, {
2166
+ writable: true,
2167
+ value: void 0
2168
+ });
2169
+ Object.defineProperty(this, _redirection, {
2170
+ writable: true,
2171
+ value: void 0
2172
+ });
2173
+ this.operationPaths = new Map();
2174
+ _classPrivateFieldLooseBase(this, _redirection)[_redirection] = false;
2175
+ }
2176
+
2177
+ get response() {
2178
+ return this.getResponses().get(this.getStatus().toString());
2179
+ }
2180
+
2181
+ get status() {
2182
+ return _classPrivateFieldLooseBase(this, _status)[_status];
2183
+ }
2184
+
2185
+ tags(tags) {
2186
+ super.set("tags", tags);
2187
+ return this;
2188
+ }
2189
+
2190
+ addTags(tags) {
2191
+ tags = uniqBy([...(this.get("tags") || []), ...tags], "name");
2192
+ return this.tags(tags);
2193
+ }
2194
+
2195
+ summary(summary) {
2196
+ super.set("summary", summary);
2197
+ return this;
2198
+ }
2199
+
2200
+ operationId(operationId) {
2201
+ this.set("operationId", operationId);
2202
+ return this;
2203
+ }
2204
+
2205
+ responses(responses) {
2206
+ this.set("responses", responses);
2207
+ return this;
2208
+ }
2209
+
2210
+ defaultStatus(status) {
2211
+ _classPrivateFieldLooseBase(this, _status)[_status] = status;
2212
+ return this;
2213
+ }
2214
+
2215
+ getStatus() {
2216
+ return _classPrivateFieldLooseBase(this, _status)[_status] || 200;
2217
+ }
2218
+
2219
+ setRedirection(status = 302) {
2220
+ _classPrivateFieldLooseBase(this, _redirection)[_redirection] = true;
2221
+ _classPrivateFieldLooseBase(this, _status)[_status] = status;
2222
+ return this;
2223
+ }
2224
+
2225
+ isRedirection(status) {
2226
+ if (_classPrivateFieldLooseBase(this, _redirection)[_redirection]) {
2227
+ if (status) {
2228
+ return isRedirectionStatus(status);
2229
+ }
2230
+ }
2231
+
2232
+ return _classPrivateFieldLooseBase(this, _redirection)[_redirection];
2233
+ }
2234
+
2235
+ addResponse(statusCode, response) {
2236
+ if ((isSuccessStatus(statusCode) || isRedirectionStatus(statusCode)) && !_classPrivateFieldLooseBase(this, _status)[_status]) {
2237
+ const res = this.getResponseOf(200);
2238
+ this.getResponses().set(statusCode.toString(), res).delete("200");
2239
+ this.defaultStatus(Number(statusCode));
2240
+ }
2241
+
2242
+ const currentCode = statusCode === "default" ? this.getStatus().toString() : statusCode.toString();
2243
+ const currentResponse = this.getResponses().get(currentCode);
2244
+
2245
+ if (!currentResponse) {
2246
+ response.status = Number(currentCode);
2247
+ this.getResponses().set(currentCode, response);
2248
+ } else {
2249
+ response.forEach((value, key) => {
2250
+ if (!["content"].includes(key)) {
2251
+ currentResponse.set(key, deepMerge(currentResponse.get(key), value));
2252
+ }
2253
+ });
2254
+ currentResponse.status = Number(currentCode);
2255
+ }
2256
+
2257
+ return this;
2258
+ }
2259
+
2260
+ getResponses() {
2261
+ return this.get("responses");
2262
+ }
2263
+
2264
+ getResponseOf(status) {
2265
+ return (status === "default" ? this.response : this.getResponses().get(String(status))) || new JsonResponse();
2266
+ }
2267
+
2268
+ ensureResponseOf(status) {
2269
+ this.addResponse(status, this.getResponseOf(status));
2270
+ return this.getResponseOf(status);
2271
+ }
2272
+
2273
+ getHeadersOf(status) {
2274
+ return this.getResponseOf(status).get("headers") || {};
2275
+ }
2276
+
2277
+ getContentTypeOf(status) {
2278
+ return [...this.getResponseOf(status).get("content").keys()].slice(-1)[0];
2279
+ }
2280
+
2281
+ security(security) {
2282
+ this.set("security", security);
2283
+ return this;
2284
+ }
2285
+
2286
+ addSecurityScopes(name, scopes) {
2287
+ const security = this.get("security") || {};
2288
+ security[name] = uniq([...(security[name] || []), ...scopes]);
2289
+ return this.security(security);
2290
+ }
2291
+
2292
+ description(description) {
2293
+ super.set("description", description);
2294
+ return this;
2295
+ }
2296
+
2297
+ deprecated(deprecated) {
2298
+ super.set("deprecated", deprecated);
2299
+ return this;
2300
+ }
2301
+
2302
+ parameters(parameters) {
2303
+ super.set("parameters", parameters);
2304
+ return this;
2305
+ }
2306
+
2307
+ addParameter(index, parameter) {
2308
+ if (index === -1) {
2309
+ index = this.get("parameters").length;
2310
+ }
2311
+
2312
+ this.get("parameters")[index] = parameter;
2313
+ }
2314
+
2315
+ consumes(consumes) {
2316
+ super.set("consumes", consumes);
2317
+ return this;
2318
+ }
2319
+
2320
+ produces(produces) {
2321
+ super.set("produces", produces);
2322
+ return this;
2323
+ }
2324
+
2325
+ addProduce(produce) {
2326
+ const produces = uniq([].concat(this.get("produces"), produce)).filter(Boolean);
2327
+ this.set("produces", produces);
2328
+ }
2329
+
2330
+ addOperationPath(method, path, options = {}) {
2331
+ this.operationPaths.set(String(method) + String(path), _extends({}, options, {
2332
+ method,
2333
+ path
2334
+ }));
2335
+ return this;
2336
+ }
2337
+
2338
+ toJSON(options = {}) {
2339
+ const operation = super.toJSON(_extends({}, options, {
2340
+ ignore: ["parameters"]
2341
+ }));
2342
+ const bodyParameters = [];
2343
+ const parameters = [];
2344
+
2345
+ if (operation.security) {
2346
+ operation.security = [].concat(operation.security);
2347
+ }
2348
+
2349
+ this.get("parameters").forEach(parameter => {
2350
+ if (!isParameterType(this.get("in"))) {
2351
+ if (parameter.get("in")) {
2352
+ if ([JsonParameterTypes.BODY, JsonParameterTypes.FILES].includes(parameter.get("in"))) {
2353
+ bodyParameters.push(parameter);
2354
+ } else {
2355
+ parameters.push(...[].concat(parameter.toJSON(options)));
2356
+ }
2357
+ }
2358
+ }
2359
+ });
2360
+ operation.parameters = parameters.filter(Boolean);
2361
+
2362
+ if (this.get("responses").size === 0) {
2363
+ operation.responses = {
2364
+ "200": {
2365
+ description: getStatusMessage(200)
2366
+ }
2367
+ };
2368
+ }
2369
+
2370
+ if (bodyParameters.length) {
2371
+ const parameter = buildSchemaFromBodyParameters(bodyParameters, options);
2372
+
2373
+ if (options.specType === SpecTypes.OPENAPI) {
2374
+ operation.requestBody = toRequestBody(this, parameter).toJSON(options);
2375
+ } else {
2376
+ operation.parameters.push(toJsonParameter(parameter));
2377
+ }
2378
+ }
2379
+
2380
+ if (options.specType === SpecTypes.OPENAPI) {
2381
+ delete operation.consumes;
2382
+ delete operation.produces;
2383
+ }
2384
+
2385
+ return operation;
2386
+ }
2387
+
2388
+ }
2389
+
2390
+ function toRequestBody(operation, _ref) {
2391
+ var _operation$get;
2392
+
2393
+ let {
2394
+ schema
2395
+ } = _ref,
2396
+ props = _objectWithoutPropertiesLoose(_ref, _excluded$5);
2397
+
2398
+ const requestBody = new JsonRequestBody(props);
2399
+ const consumes = (_operation$get = operation.get("consumes")) != null && _operation$get.length ? operation.get("consumes") : ["application/json"];
2400
+ consumes.forEach(consume => {
2401
+ requestBody.addContent(consume, schema);
2402
+ });
2403
+ return requestBody;
2404
+ }
2405
+
2406
+ function toJsonParameter(parameter) {
2407
+ return _extends({
2408
+ in: JsonParameterTypes.BODY,
2409
+ name: JsonParameterTypes.BODY
2410
+ }, parameter);
2411
+ }
2412
+
2413
+ function buildSchemaFromBodyParameters(parameters, options) {
2414
+ let schema = new JsonSchema();
2415
+ const props = {};
2416
+ const refs = [];
2417
+ let propsLength = 0;
2418
+ parameters.forEach(parameter => {
2419
+ const name = parameter.getName();
2420
+ Array.from(parameter.entries()).filter(([key]) => !["in", "name"].includes(key)).forEach(([key, value]) => {
2421
+ if (props[key] === undefined) {
2422
+ props[key] = value;
2423
+ }
2424
+ });
2425
+ const jsonParameter = parameter.toJSON(options);
2426
+
2427
+ if (name) {
2428
+ schema.addProperty(name, jsonParameter.schema || {
2429
+ type: jsonParameter.type
2430
+ });
2431
+
2432
+ if (parameter.get("required")) {
2433
+ schema.addRequired(name);
2434
+ }
2435
+
2436
+ propsLength++;
2437
+ } else {
2438
+ refs.push(jsonParameter);
2439
+ }
2440
+ });
2441
+
2442
+ if (propsLength) {
2443
+ schema.type("object");
2444
+ return _extends({
2445
+ schema: schema.toJSON(options),
2446
+ required: false
2447
+ }, props);
2448
+ }
2449
+
2450
+ if (refs.length === 1) {
2451
+ return refs[0];
2452
+ }
2453
+
2454
+ if (refs.length > 0) {
2455
+ schema.allOf(refs);
2456
+ }
2457
+
2458
+ return _extends({
2459
+ schema: schema.toJSON(options),
2460
+ required: false
2461
+ }, props);
2462
+ }
2463
+
2464
+ let JsonMethodStore = class JsonMethodStore extends JsonEntityStore {
2465
+ constructor() {
2466
+ super(...arguments);
2467
+ this.parent = JsonEntityStore.from(this.target);
2468
+ /**
2469
+ * Ref to JsonOperation when the decorated object is a method.
2470
+ */
2187
2471
 
2472
+ this.operation = new JsonOperation();
2473
+ /**
2474
+ * List of children JsonEntityStore (properties or methods or params)
2475
+ */
2188
2476
 
2189
- static from(...args) {
2190
- return getJsonEntityStore(...args);
2477
+ this.children = new Map();
2191
2478
  }
2192
2479
 
2193
- static fromMethod(target, propertyKey) {
2194
- return this.from(target, propertyKey, descriptorOf(target, propertyKey));
2480
+ get parameters() {
2481
+ return [...this.children.values()];
2195
2482
  }
2196
2483
 
2197
- get(key, defaultValue) {
2198
- return this.store.get(key, defaultValue);
2484
+ get operationPaths() {
2485
+ return this.operation.operationPaths;
2199
2486
  }
2200
2487
 
2201
2488
  getResponseOptions(status, contentType = "application/json") {
@@ -2215,150 +2502,165 @@ class JsonEntityStore extends Entity {
2215
2502
  type: this.type
2216
2503
  };
2217
2504
  }
2218
- /**
2219
- * Check precondition between value, required and allowedRequiredValues to know if the entity is required.
2220
- * @param value
2221
- * @returns {boolean}
2222
- */
2223
-
2224
-
2225
- isRequired(value) {
2226
- return this.required && [undefined, null, ""].includes(value) && !this.allowedRequiredValues.includes(value);
2227
- }
2228
2505
 
2229
2506
  build() {
2230
2507
  if (!this._type) {
2231
- let type;
2232
-
2233
- switch (this.decoratorType) {
2234
- case DecoratorTypes.PARAM:
2235
- type = Metadata.getParamTypes(this.target, this.propertyKey)[this.index];
2236
- break;
2508
+ let type = Metadata.getReturnType(this.target, this.propertyKey);
2509
+ type = isPromise(type) ? undefined : type;
2510
+ this.buildType(type);
2511
+ }
2237
2512
 
2238
- case DecoratorTypes.CLASS:
2239
- type = this.target;
2240
- break;
2513
+ this._type = this._type || Object;
2514
+ this.parent.children.set(this.propertyName, this);
2241
2515
 
2242
- case DecoratorTypes.PROP:
2243
- type = Metadata.getType(this.target, this.propertyKey);
2244
- break;
2516
+ if (isCollection(this._type)) {
2517
+ this.collectionType = this._type; // @ts-ignore
2245
2518
 
2246
- case DecoratorTypes.METHOD:
2247
- type = Metadata.getReturnType(this.target, this.propertyKey);
2248
- type = isPromise(type) ? undefined : type;
2249
- break;
2250
- }
2519
+ delete this._type;
2520
+ }
2251
2521
 
2252
- if (isCollection(type)) {
2253
- this.collectionType = type;
2254
- } else {
2255
- this._type = type; // issue #1534: Enum metadata stored as plain object instead of String (see: https://github.com/tsedio/tsed/issues/1534)
2522
+ this._schema = JsonSchema.from({
2523
+ type: this.collectionType || this.type
2524
+ });
2256
2525
 
2257
- if (this._type && isPlainObject(this._type)) {
2258
- this._type = String;
2259
- }
2260
- }
2526
+ if (this.collectionType) {
2527
+ this._schema.itemSchema(this.type);
2261
2528
  }
2262
2529
 
2263
- this._type = this._type || Object;
2530
+ this.parent.schema.addProperty(this.propertyName, this.schema);
2531
+ }
2264
2532
 
2265
- switch (this.decoratorType) {
2266
- default:
2267
- this._schema = JsonSchema.from();
2268
- break;
2533
+ };
2534
+ JsonMethodStore = __decorate([JsonEntityComponent(DecoratorTypes.METHOD)], JsonMethodStore);
2269
2535
 
2270
- case DecoratorTypes.CLASS:
2271
- this._schema = JsonSchema.from({
2272
- type: this.type
2273
- });
2274
- break;
2536
+ JsonEntitiesContainer.set(DecoratorTypes.CLASS, JsonClassStore);
2537
+ JsonEntitiesContainer.set(DecoratorTypes.PROP, JsonPropertyStore);
2538
+ JsonEntitiesContainer.set(DecoratorTypes.PARAM, JsonParameterStore);
2539
+ JsonEntitiesContainer.set(DecoratorTypes.METHOD, JsonMethodStore);
2540
+ function getJsonEntityStore(...args) {
2541
+ return JsonEntityStore.from(...args);
2542
+ }
2275
2543
 
2276
- case DecoratorTypes.METHOD:
2277
- this._operation = this.createOperation();
2278
- break;
2544
+ class JsonLazyRef {
2545
+ constructor(getType) {
2546
+ this.getType = getType;
2547
+ this.isLazyRef = true;
2548
+ }
2279
2549
 
2280
- case DecoratorTypes.PARAM:
2281
- this._parameter = this.createParameter();
2282
- break;
2550
+ get target() {
2551
+ return this.getType();
2552
+ }
2283
2553
 
2284
- case DecoratorTypes.PROP:
2285
- this._schema = this.createProperty();
2286
- break;
2287
- }
2554
+ get schema() {
2555
+ return getJsonEntityStore(this.getType()).schema;
2288
2556
  }
2289
2557
 
2290
- createProperty() {
2291
- const parentStore = this.parent;
2292
- const properties = parentStore.schema.get("properties");
2293
- let schema = properties[this.propertyName];
2558
+ get name() {
2559
+ return nameOf(this.getType());
2560
+ }
2294
2561
 
2295
- if (!schema) {
2296
- parentStore.children.set(this.propertyName, this);
2297
- schema = JsonSchema.from({
2298
- type: this.collectionType || this.type
2299
- });
2562
+ toJSON(options) {
2563
+ return this.getType() && execMapper("schema", this.schema, options);
2564
+ }
2300
2565
 
2301
- if (this.collectionType) {
2302
- schema.itemSchema(this.type);
2303
- }
2304
- }
2566
+ }
2305
2567
 
2306
- parentStore.schema.addProperty(this.propertyName, schema);
2307
- return schema;
2308
- }
2568
+ /**
2569
+ * ignore
2570
+ * @param options
2571
+ */
2309
2572
 
2310
- createOperation() {
2311
- const parentStore = this.parent; // response schema of the method
2573
+ function getHost(options) {
2574
+ const {
2575
+ host = `#/${options.specType === "openapi3" ? "components/schemas" : "definitions"}`
2576
+ } = options;
2577
+ return host;
2578
+ }
2579
+ /**
2580
+ * @ignore
2581
+ */
2312
2582
 
2313
- let operation = this.operation;
2314
2583
 
2315
- if (!operation) {
2316
- operation = new JsonOperation();
2317
- parentStore.children.set(this.propertyName, this);
2318
- }
2584
+ function createRefName(name, options) {
2585
+ if (options.groups && options.groups.length) {
2586
+ return pascalCase(`${name} ${options.groups.join(" ")}`);
2587
+ }
2319
2588
 
2320
- if (isCollection(this._type)) {
2321
- this.collectionType = this._type; // @ts-ignore
2589
+ return name;
2590
+ }
2591
+ /**
2592
+ * @ignore
2593
+ */
2322
2594
 
2323
- delete this._type;
2324
- }
2595
+ function createRef(name, schema, options) {
2596
+ const host = getHost(options);
2597
+ const ref = {
2598
+ $ref: `${host}/${name}`
2599
+ };
2600
+ const nullable = schema.nullable;
2601
+ const readOnly = schema.get ? schema.get("readOnly") : undefined;
2325
2602
 
2326
- this._schema = JsonSchema.from({
2327
- type: this.collectionType || this.type
2328
- });
2603
+ if (nullable || readOnly) {
2604
+ switch (options.specType) {
2605
+ case SpecTypes.OPENAPI:
2606
+ return cleanObject({
2607
+ nullable: nullable ? true : undefined,
2608
+ readOnly: readOnly ? true : undefined,
2609
+ allOf: [ref]
2610
+ });
2329
2611
 
2330
- if (this.collectionType) {
2331
- this._schema.itemSchema(this.type);
2332
- }
2612
+ case SpecTypes.JSON:
2613
+ return cleanObject({
2614
+ readOnly,
2615
+ oneOf: [nullable && {
2616
+ type: "null"
2617
+ }, ref].filter(Boolean)
2618
+ });
2333
2619
 
2334
- parentStore.schema.addProperty(this.propertyName, this.schema);
2335
- return operation;
2620
+ case SpecTypes.SWAGGER:
2621
+ // unsupported
2622
+ if (readOnly) {
2623
+ return {
2624
+ readOnly,
2625
+ allOf: [ref]
2626
+ };
2627
+ }
2628
+
2629
+ break;
2630
+ }
2336
2631
  }
2337
2632
 
2338
- createParameter() {
2339
- const parentStore = this.parent;
2340
- let parameter = this.parameter;
2633
+ return ref;
2634
+ }
2635
+ /**
2636
+ * @ignore
2637
+ */
2341
2638
 
2342
- if (!parameter) {
2343
- var _parentStore$operatio;
2639
+ function toRef(value, schema, options) {
2640
+ const name = createRefName(value.getName(), options);
2641
+ options.schemas[value.getName()] = schema;
2642
+ return createRef(name, value, options);
2643
+ }
2344
2644
 
2345
- parameter = new JsonParameter();
2346
- parentStore.children.set(this.index, this);
2347
- this._schema = getSchema(this.collectionType || this.type);
2348
- parameter.schema(this._schema);
2645
+ function anyMapper(input, options = {}) {
2646
+ options.schemas = options.schemas || {};
2349
2647
 
2350
- if (this.collectionType) {
2351
- this._schema.itemSchema(getSchema(this.type));
2352
- }
2648
+ if (typeof input !== "object" || input === null) {
2649
+ return input;
2650
+ }
2353
2651
 
2354
- (_parentStore$operatio = parentStore.operation) == null ? void 0 : _parentStore$operatio.addParameter(this.index, parameter);
2355
- }
2652
+ if (input instanceof JsonLazyRef) {
2653
+ return execMapper("lazyRef", input, options);
2654
+ }
2356
2655
 
2357
- return parameter;
2656
+ if ("toJSON" in input) {
2657
+ const schema = input.toJSON(mapGenericsOptions(options));
2658
+ return input.canRef ? toRef(input, schema, options) : schema;
2358
2659
  }
2359
2660
 
2661
+ return execMapper("object", input, options);
2360
2662
  }
2361
- JsonEntitiesContainer.set("default", JsonEntityStore);
2663
+ registerJsonSchemaMapper("any", anyMapper);
2362
2664
 
2363
2665
  const _excluded$4 = ["type", "properties", "additionalProperties", "items"];
2364
2666
  function classMapper(value, options = {}) {
@@ -2979,20 +3281,17 @@ function getOperationsStores(target) {
2979
3281
  const store = target.isStore ? target : getJsonEntityStore(target);
2980
3282
 
2981
3283
  if (!store.$operations) {
2982
- const stores = getInheritedStores(store);
2983
3284
  const operationPaths = new JsonOperationPathsMap();
2984
3285
  store.$operations = new Map();
2985
- stores.forEach(currentStore => {
3286
+ getInheritedStores(store).forEach(currentStore => {
2986
3287
  currentStore.children.forEach(propStore => {
2987
- if (propStore.operation && !store.$operations.has(propStore.propertyKey)) {
3288
+ if (propStore instanceof JsonMethodStore && !store.$operations.has(propStore.propertyKey)) {
2988
3289
  store.$operations.set(propStore.propertyKey, propStore);
2989
3290
  }
2990
3291
  });
2991
3292
  });
2992
3293
  store.$operations.forEach(store => {
2993
- var _store$operation;
2994
-
2995
- (_store$operation = store.operation) == null ? void 0 : _store$operation.operationPaths.forEach(operationPath => {
3294
+ store.operation.operationPaths.forEach(operationPath => {
2996
3295
  operationPaths.setOperationPath(operationPath);
2997
3296
  });
2998
3297
  });
@@ -3011,6 +3310,10 @@ class JsonOperationRoute {
3011
3310
  Object.assign(this, options);
3012
3311
  }
3013
3312
 
3313
+ get url() {
3314
+ return this.fullPath;
3315
+ }
3316
+
3014
3317
  get path() {
3015
3318
  var _this$operationPath;
3016
3319
 
@@ -3033,14 +3336,42 @@ class JsonOperationRoute {
3033
3336
  return !!((_this$operationPath3 = this.operationPath) != null && _this$operationPath3.isFinal);
3034
3337
  }
3035
3338
 
3339
+ get name() {
3340
+ return `${this.endpoint.targetName}.${this.methodClassName}()`;
3341
+ }
3342
+
3343
+ get className() {
3344
+ return this.endpoint.targetName;
3345
+ }
3346
+
3347
+ get methodClassName() {
3348
+ return this.propertyKey;
3349
+ }
3350
+
3351
+ get parameters() {
3352
+ return this.endpoint.parameters;
3353
+ }
3354
+
3036
3355
  get propertyKey() {
3037
- return this.endpoint.propertyKey;
3356
+ return String(this.endpoint.propertyKey);
3357
+ }
3358
+
3359
+ get propertyName() {
3360
+ return this.endpoint.propertyName;
3038
3361
  }
3039
3362
 
3040
3363
  get store() {
3041
3364
  return this.endpoint.store;
3042
3365
  }
3043
3366
 
3367
+ get operation() {
3368
+ return this.endpoint.operation;
3369
+ }
3370
+
3371
+ get operationId() {
3372
+ return this.operation.get("operationId") || this.endpoint.propertyKey;
3373
+ }
3374
+
3044
3375
  }
3045
3376
 
3046
3377
  function getOperationsRoutes(token, options = {}) {
@@ -4502,7 +4833,7 @@ class DecoratorContext extends Map {
4502
4833
  }
4503
4834
 
4504
4835
  onMapKey(key, value) {
4505
- this.entity.store.set(key, value);
4836
+ this.entity.set(key, value);
4506
4837
  }
4507
4838
 
4508
4839
  runActions() {
@@ -4563,8 +4894,8 @@ class ReturnDecoratorContext extends DecoratorContext {
4563
4894
  status(status) {
4564
4895
  this.set("status", status);
4565
4896
 
4566
- if (status && HTTP_STATUS_MESSAGES[status] && !this.get("description")) {
4567
- this.set("description", HTTP_STATUS_MESSAGES[status]);
4897
+ if (status && getStatusMessage(status) && !this.get("description")) {
4898
+ this.set("description", getStatusMessage(status));
4568
4899
 
4569
4900
  if (!this.get("model")) {
4570
4901
  this.model(getStatusModel(+status));
@@ -4689,9 +5020,6 @@ class ReturnDecoratorContext extends DecoratorContext {
4689
5020
  this.decoratorType = DecoratorTypes.CLASS;
4690
5021
  decorateMethodsOf(args[0], decorator);
4691
5022
  break;
4692
-
4693
- default:
4694
- throw new UnsupportedDecoratorType(Returns, args);
4695
5023
  }
4696
5024
  }
4697
5025
 
@@ -5322,16 +5650,24 @@ function matchGroups(groups, compareWith = []) {
5322
5650
  return false;
5323
5651
  }
5324
5652
 
5653
+ /**
5654
+ * @ignore
5655
+ */
5656
+
5657
+ function groupsClass(groups, entity) {
5658
+ const entries = Object.entries(groups[0]);
5659
+ entity.children.forEach(propEntity => {
5660
+ const groups = entries.filter(([, props]) => props.includes(propEntity.propertyName)).map(([key]) => key);
5661
+ const decorator = Groups(...groups);
5662
+ decorator(propEntity.target, propEntity.propertyKey);
5663
+ });
5664
+ }
5665
+
5325
5666
  function Groups(...groups) {
5326
5667
  return JsonEntityFn(entity => {
5327
5668
  switch (entity.decoratorType) {
5328
5669
  case DecoratorTypes.CLASS:
5329
- const entries = Object.entries(groups[0]);
5330
- entity.children.forEach(propEntity => {
5331
- const groups = entries.filter(([, props]) => props.includes(propEntity.propertyName)).map(([key]) => key);
5332
- const decorator = Groups(...groups);
5333
- decorator(propEntity.target, propEntity.propertyKey);
5334
- });
5670
+ groupsClass(groups, entity);
5335
5671
  break;
5336
5672
 
5337
5673
  case DecoratorTypes.PROP:
@@ -5716,17 +6052,12 @@ function Allow(...values) {
5716
6052
  return useDecorators(model && Property(model), JsonEntityFn((store, args) => {
5717
6053
  store.schema.allow(...values);
5718
6054
 
5719
- switch (store.decoratorType) {
5720
- case DecoratorTypes.PARAM:
5721
- store.parameter.required(true);
5722
- break;
5723
-
5724
- case DecoratorTypes.PROP:
5725
- store.parentSchema.addRequired(store.propertyName);
5726
- break;
6055
+ if (store.decoratorType === DecoratorTypes.PARAM) {
6056
+ store.required = true;
6057
+ }
5727
6058
 
5728
- default:
5729
- throw new UnsupportedDecoratorType(Allow, args);
6059
+ if (store.decoratorType === DecoratorTypes.PROP) {
6060
+ store.parentSchema.addRequired(store.propertyName);
5730
6061
  }
5731
6062
  }));
5732
6063
  }
@@ -6008,7 +6339,7 @@ function Default(defaultValue) {
6008
6339
 
6009
6340
  function Description(description) {
6010
6341
  return JsonEntityFn((store, args) => {
6011
- var _store$parameter, _store$operation;
6342
+ var _store$operation;
6012
6343
 
6013
6344
  switch (decoratorTypeOf(args)) {
6014
6345
  case DecoratorTypes.PROP:
@@ -6017,15 +6348,12 @@ function Description(description) {
6017
6348
  break;
6018
6349
 
6019
6350
  case DecoratorTypes.PARAM:
6020
- (_store$parameter = store.parameter) == null ? void 0 : _store$parameter.description(description);
6351
+ store.parameter.description(description);
6021
6352
  break;
6022
6353
 
6023
6354
  case DecoratorTypes.METHOD:
6024
6355
  (_store$operation = store.operation) == null ? void 0 : _store$operation.description(description);
6025
6356
  break;
6026
-
6027
- default:
6028
- throw new UnsupportedDecoratorType(Description, args);
6029
6357
  }
6030
6358
  });
6031
6359
  }
@@ -6042,18 +6370,8 @@ function Description(description) {
6042
6370
  */
6043
6371
 
6044
6372
  function Example(...examples) {
6045
- return JsonEntityFn((store, args) => {
6046
- switch (decoratorTypeOf(args)) {
6047
- case DecoratorTypes.CLASS:
6048
- case DecoratorTypes.PROP:
6049
- case DecoratorTypes.PARAM:
6050
- case DecoratorTypes.METHOD:
6051
- store.schema.examples(examples);
6052
- break;
6053
-
6054
- default:
6055
- throw new UnsupportedDecoratorType(Example, args);
6056
- }
6373
+ return JsonEntityFn(store => {
6374
+ store.schema.examples(examples);
6057
6375
  });
6058
6376
  }
6059
6377
 
@@ -7515,18 +7833,15 @@ function Name(name) {
7515
7833
  */
7516
7834
 
7517
7835
  function Optional() {
7518
- return JsonEntityFn((store, args) => {
7836
+ return JsonEntityFn(store => {
7519
7837
  switch (store.decoratorType) {
7520
7838
  case DecoratorTypes.PARAM:
7521
- store.parameter.required(false);
7839
+ store.required = false;
7522
7840
  break;
7523
7841
 
7524
7842
  case DecoratorTypes.PROP:
7525
7843
  store.parentSchema.removeRequired(store.propertyName);
7526
7844
  break;
7527
-
7528
- default:
7529
- throw new UnsupportedDecoratorType(Optional, args);
7530
7845
  }
7531
7846
  });
7532
7847
  }
@@ -7911,19 +8226,5 @@ function Nullable(type, ...types) {
7911
8226
  return useDecorators(types.length === 1 && Property(types[0]), Any(null, ...types));
7912
8227
  }
7913
8228
 
7914
- /**
7915
- * Declare a new JsonEntityStore class for a specific decorator type.
7916
- *
7917
- * @ignore
7918
- * @param type
7919
- * @decorator
7920
- */
7921
-
7922
- function JsonEntityComponent(type) {
7923
- return target => {
7924
- JsonEntitiesContainer.set(type, target);
7925
- };
7926
- }
7927
-
7928
- export { AdditionalProperties, All, AllOf, Allow, Any, AnyOf, ArrayOf, Children, CollectionContains, CollectionOf, Const, Consumes, ContentType, CustomKey, CustomKeys, DateFormat, DateTime, Default, Delete, Deprecated, Description, Email, Enum, Example, Examples, ExclusiveMaximum, ExclusiveMinimum, For, Format, ForwardGroups, GenericOf, Generics, Get, Groups, HTTP_METHODS, HTTP_STATUS_MESSAGES, Head, Header, Hidden, Ignore, In, Integer, JSON_TYPES, JsonEntityComponent, JsonEntityFn, JsonEntityStore, JsonFormatTypes, JsonLazyRef, JsonMap, JsonMedia, JsonOperation, JsonOperationRoute, JsonParameter, JsonParameterTypes, JsonRequestBody, JsonResponse, JsonSchema, Location, MapOf, Max, MaxItems, MaxLength, MaxProperties, Maximum, Min, MinItems, MinLength, MinProperties, Minimum, MultipleOf, Name, Nullable, OneOf, OperationId, OperationMethods, OperationPath, Optional, Options, Partial, Patch, Path, Pattern, Post, Produces, Property, Put, ReadOnly, Redirect, Required, RequiredGroups, Returns, Route, Schema, Security, SpecTypes, Status, Summary, Tags, TimeFormat, Title, UniqueItems, Uri, Url, WriteOnly, allOf, alterIgnore, any, anyOf, array, boolean, concatPath, date, datetime, defineStatusModel, email, formatParameterType, from, getGenericsMap, getJsonSchema, getJsonType, getOperationsRoutes, getOperationsStores, getProperties, getPropertiesStores, getSpec, getStatusConstant, getStatusMessage, getStatusModel, integer, isParameterType, isRedirectionStatus, isSuccessStatus, lazyRef, map, mapGenericsOptions, mapHeaders, mergeSpec, number, object, oneOf, parameters, popGenerics, schemesReducer, security, set, string, tagsReducer, time, uri, url };
8229
+ export { AdditionalProperties, All, AllOf, Allow, Any, AnyOf, ArrayOf, Children, CollectionContains, CollectionOf, Const, Consumes, ContentType, CustomKey, CustomKeys, DateFormat, DateTime, Default, Delete, Deprecated, Description, Email, Enum, Example, Examples, ExclusiveMaximum, ExclusiveMinimum, For, Format, ForwardGroups, GenericOf, Generics, Get, Groups, HTTP_METHODS, HTTP_STATUS_MESSAGES, Head, Header, Hidden, Ignore, In, Integer, JSON_TYPES, JsonClassStore, JsonEntitiesContainer, JsonEntityComponent, JsonEntityFn, JsonEntityStore, JsonFormatTypes, JsonLazyRef, JsonMap, JsonMedia, JsonMethodStore, JsonOperation, JsonOperationRoute, JsonParameter, JsonParameterStore, JsonParameterTypes, JsonPropertyStore, JsonRequestBody, JsonResponse, JsonSchema, Location, MapOf, Max, MaxItems, MaxLength, MaxProperties, Maximum, Min, MinItems, MinLength, MinProperties, Minimum, MultipleOf, Name, Nullable, OneOf, OperationId, OperationMethods, OperationPath, Optional, Options, Partial, Patch, Path, Pattern, Post, Produces, Property, Put, ReadOnly, Redirect, Required, RequiredGroups, Returns, Route, Schema, Security, SpecTypes, Status, Summary, Tags, TimeFormat, Title, UniqueItems, Uri, Url, WriteOnly, allOf, alterIgnore, any, anyOf, array, boolean, concatPath, date, datetime, defineStatusModel, email, formatParameterType, from, getGenericsMap, getJsonSchema, getJsonType, getOperationsRoutes, getOperationsStores, getProperties, getPropertiesStores, getSpec, getStatusConstant, getStatusMessage, getStatusModel, integer, isParameterType, isRedirectionStatus, isSuccessStatus, lazyRef, map, mapGenericsOptions, mapHeaders, mergeSpec, number, object, oneOf, parameters, popGenerics, schemesReducer, security, set, string, tagsReducer, time, uri, url };
7929
8230
  //# sourceMappingURL=index.modern.js.map