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