@tsed/schema 8.0.1 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (291) hide show
  1. package/package.json +11 -10
  2. package/src/components/async-api/channelsMapper.ts +81 -0
  3. package/src/components/async-api/generate.ts +24 -0
  4. package/src/components/async-api/messageMapper.ts +62 -0
  5. package/src/components/async-api/payloadMapper.ts +61 -0
  6. package/src/components/async-api/responseMapper.ts +70 -0
  7. package/src/components/default/anyMapper.spec.ts +7 -0
  8. package/src/components/default/anyMapper.ts +33 -0
  9. package/src/components/default/classMapper.ts +55 -0
  10. package/src/components/default/discriminatorMappingMapper.ts +36 -0
  11. package/src/components/default/enumsMapper.spec.ts +64 -0
  12. package/src/components/default/enumsMapper.ts +17 -0
  13. package/src/components/default/genericsMapper.ts +70 -0
  14. package/src/components/default/inheritedClassMapper.ts +24 -0
  15. package/src/components/default/itemMapper.ts +8 -0
  16. package/src/components/default/lazyRefMapper.ts +21 -0
  17. package/src/components/default/mapMapper.ts +25 -0
  18. package/src/components/default/nullableMapper.ts +55 -0
  19. package/src/components/default/objectMapper.ts +36 -0
  20. package/src/components/default/ofMapper.ts +16 -0
  21. package/src/components/default/propertiesMapper.ts +25 -0
  22. package/src/components/default/requiredMapper.ts +69 -0
  23. package/src/components/default/schemaMapper.ts +151 -0
  24. package/src/components/index.ts +36 -0
  25. package/src/components/open-spec/discriminatorMappingMapper.ts +7 -0
  26. package/src/components/open-spec/enumsMapper.ts +20 -0
  27. package/src/components/open-spec/generate.ts +29 -0
  28. package/src/components/open-spec/nullableMapper.ts +51 -0
  29. package/src/components/open-spec/operationInFilesMapper.ts +32 -0
  30. package/src/components/open-spec/operationInParameterMapper.ts +56 -0
  31. package/src/components/open-spec/operationInParametersMapper.ts +9 -0
  32. package/src/components/open-spec/operationInQueryMapper.ts +74 -0
  33. package/src/components/open-spec/operationMapper.ts +65 -0
  34. package/src/components/open-spec/operationMediaMapper.ts +11 -0
  35. package/src/components/open-spec/operationRequestBodyMapper.ts +82 -0
  36. package/src/components/open-spec/operationResponseMapper.ts +26 -0
  37. package/src/components/open-spec/pathsMapper.ts +132 -0
  38. package/src/constants/OperationVerbs.ts +29 -0
  39. package/src/constants/httpStatusMessages.ts +21 -0
  40. package/src/constants/jsonSchemaProperties.ts +17 -0
  41. package/src/decorators/class/children.ts +22 -0
  42. package/src/decorators/class/discriminatorValue.ts +53 -0
  43. package/src/decorators/collections/collectionContains.ts +25 -0
  44. package/src/decorators/collections/collectionOf.spec.ts +327 -0
  45. package/src/decorators/collections/collectionOf.ts +182 -0
  46. package/src/decorators/collections/maxItems.spec.ts +40 -0
  47. package/src/decorators/collections/maxItems.ts +59 -0
  48. package/src/decorators/collections/maxProperties.spec.ts +109 -0
  49. package/src/decorators/collections/maxProperties.ts +82 -0
  50. package/src/decorators/collections/minItems.spec.ts +40 -0
  51. package/src/decorators/collections/minItems.ts +63 -0
  52. package/src/decorators/collections/minProperties.spec.ts +109 -0
  53. package/src/decorators/collections/minProperties.ts +81 -0
  54. package/src/decorators/collections/uniqueItems.spec.ts +28 -0
  55. package/src/decorators/collections/uniqueItems.ts +59 -0
  56. package/src/decorators/common/__snapshots__/groups.spec.ts.snap +321 -0
  57. package/src/decorators/common/additionalProperties.spec.ts +133 -0
  58. package/src/decorators/common/additionalProperties.ts +17 -0
  59. package/src/decorators/common/allOf.spec.ts +276 -0
  60. package/src/decorators/common/allOf.ts +19 -0
  61. package/src/decorators/common/allow.spec.ts +130 -0
  62. package/src/decorators/common/allow.ts +50 -0
  63. package/src/decorators/common/any.spec.ts +109 -0
  64. package/src/decorators/common/any.ts +45 -0
  65. package/src/decorators/common/anyOf.spec.ts +270 -0
  66. package/src/decorators/common/anyOf.ts +23 -0
  67. package/src/decorators/common/const.spec.ts +98 -0
  68. package/src/decorators/common/const.ts +68 -0
  69. package/src/decorators/common/customKey.spec.ts +105 -0
  70. package/src/decorators/common/customKey.ts +39 -0
  71. package/src/decorators/common/default.spec.ts +25 -0
  72. package/src/decorators/common/default.ts +47 -0
  73. package/src/decorators/common/defaultMsg.spec.ts +22 -0
  74. package/src/decorators/common/defaultMsg.ts +38 -0
  75. package/src/decorators/common/description.spec.ts +166 -0
  76. package/src/decorators/common/description.ts +77 -0
  77. package/src/decorators/common/discriminatorKey.ts +14 -0
  78. package/src/decorators/common/enum.spec.ts +305 -0
  79. package/src/decorators/common/enum.ts +111 -0
  80. package/src/decorators/common/errorMsg.spec.ts +57 -0
  81. package/src/decorators/common/errorMsg.ts +14 -0
  82. package/src/decorators/common/example.spec.ts +93 -0
  83. package/src/decorators/common/example.ts +18 -0
  84. package/src/decorators/common/examples.spec.ts +101 -0
  85. package/src/decorators/common/examples.ts +20 -0
  86. package/src/decorators/common/exclusiveMaximum.spec.ts +47 -0
  87. package/src/decorators/common/exclusiveMaximum.ts +75 -0
  88. package/src/decorators/common/exclusiveMinimum.spec.ts +47 -0
  89. package/src/decorators/common/exclusiveMinimum.ts +75 -0
  90. package/src/decorators/common/format.spec.ts +149 -0
  91. package/src/decorators/common/format.ts +486 -0
  92. package/src/decorators/common/forwardGroups.spec.ts +270 -0
  93. package/src/decorators/common/forwardGroups.ts +16 -0
  94. package/src/decorators/common/groups.spec.ts +968 -0
  95. package/src/decorators/common/groups.ts +66 -0
  96. package/src/decorators/common/hidden.spec.ts +52 -0
  97. package/src/decorators/common/hidden.ts +36 -0
  98. package/src/decorators/common/ignore.spec.ts +88 -0
  99. package/src/decorators/common/ignore.ts +66 -0
  100. package/src/decorators/common/integer.spec.ts +110 -0
  101. package/src/decorators/common/integer.ts +69 -0
  102. package/src/decorators/common/jsonEntityFn.spec.ts +16 -0
  103. package/src/decorators/common/jsonEntityFn.ts +33 -0
  104. package/src/decorators/common/maxLength.spec.ts +61 -0
  105. package/src/decorators/common/maxLength.ts +88 -0
  106. package/src/decorators/common/maximum.spec.ts +73 -0
  107. package/src/decorators/common/maximum.ts +146 -0
  108. package/src/decorators/common/minLength.spec.ts +186 -0
  109. package/src/decorators/common/minLength.ts +89 -0
  110. package/src/decorators/common/minimum.spec.ts +74 -0
  111. package/src/decorators/common/minimum.ts +145 -0
  112. package/src/decorators/common/multipleOf.spec.ts +33 -0
  113. package/src/decorators/common/multipleOf.ts +80 -0
  114. package/src/decorators/common/name.spec.ts +56 -0
  115. package/src/decorators/common/name.ts +50 -0
  116. package/src/decorators/common/nullable.spec.ts +818 -0
  117. package/src/decorators/common/nullable.ts +32 -0
  118. package/src/decorators/common/oneOf.spec.ts +301 -0
  119. package/src/decorators/common/oneOf.ts +24 -0
  120. package/src/decorators/common/optional.spec.ts +43 -0
  121. package/src/decorators/common/optional.ts +26 -0
  122. package/src/decorators/common/pattern.spec.ts +27 -0
  123. package/src/decorators/common/pattern.ts +102 -0
  124. package/src/decorators/common/property.ts +24 -0
  125. package/src/decorators/common/readOnly.spec.ts +135 -0
  126. package/src/decorators/common/readOnly.ts +17 -0
  127. package/src/decorators/common/recordOf.spec.ts +41 -0
  128. package/src/decorators/common/recordOf.ts +59 -0
  129. package/src/decorators/common/required.spec.ts +188 -0
  130. package/src/decorators/common/required.ts +50 -0
  131. package/src/decorators/common/requiredGroups.spec.ts +127 -0
  132. package/src/decorators/common/requiredGroups.ts +23 -0
  133. package/src/decorators/common/schema.spec.ts +23 -0
  134. package/src/decorators/common/schema.ts +64 -0
  135. package/src/decorators/common/title.spec.ts +20 -0
  136. package/src/decorators/common/title.ts +45 -0
  137. package/src/decorators/common/typeError.spec.ts +22 -0
  138. package/src/decorators/common/typeError.ts +15 -0
  139. package/src/decorators/common/writeOnly.spec.ts +105 -0
  140. package/src/decorators/common/writeOnly.ts +17 -0
  141. package/src/decorators/config/jsonEntityComponent.ts +16 -0
  142. package/src/decorators/generics/genericOf.spec.ts +246 -0
  143. package/src/decorators/generics/genericOf.ts +112 -0
  144. package/src/decorators/generics/generics.ts +22 -0
  145. package/src/decorators/operations/acceptMime.spec.ts +39 -0
  146. package/src/decorators/operations/acceptMime.ts +25 -0
  147. package/src/decorators/operations/consumes.spec.ts +89 -0
  148. package/src/decorators/operations/consumes.ts +37 -0
  149. package/src/decorators/operations/contentType.spec.ts +40 -0
  150. package/src/decorators/operations/contentType.ts +24 -0
  151. package/src/decorators/operations/deprecated.spec.ts +223 -0
  152. package/src/decorators/operations/deprecated.ts +49 -0
  153. package/src/decorators/operations/header.spec.ts +214 -0
  154. package/src/decorators/operations/header.ts +62 -0
  155. package/src/decorators/operations/in.spec.ts +321 -0
  156. package/src/decorators/operations/in.ts +141 -0
  157. package/src/decorators/operations/inFile.spec.ts +209 -0
  158. package/src/decorators/operations/inFile.ts +55 -0
  159. package/src/decorators/operations/location.spec.ts +51 -0
  160. package/src/decorators/operations/location.ts +26 -0
  161. package/src/decorators/operations/operation.ts +119 -0
  162. package/src/decorators/operations/operationId.spec.ts +43 -0
  163. package/src/decorators/operations/operationId.ts +22 -0
  164. package/src/decorators/operations/operationPath.spec.ts +42 -0
  165. package/src/decorators/operations/operationPath.ts +33 -0
  166. package/src/decorators/operations/partial.spec.ts +249 -0
  167. package/src/decorators/operations/partial.ts +14 -0
  168. package/src/decorators/operations/path.spec.ts +47 -0
  169. package/src/decorators/operations/path.ts +27 -0
  170. package/src/decorators/operations/produces.spec.ts +89 -0
  171. package/src/decorators/operations/produces.ts +44 -0
  172. package/src/decorators/operations/publish.spec.ts +26 -0
  173. package/src/decorators/operations/publish.ts +6 -0
  174. package/src/decorators/operations/redirect.spec.ts +146 -0
  175. package/src/decorators/operations/redirect.ts +82 -0
  176. package/src/decorators/operations/returns.spec.ts +1393 -0
  177. package/src/decorators/operations/returns.ts +662 -0
  178. package/src/decorators/operations/route.spec.ts +211 -0
  179. package/src/decorators/operations/route.ts +154 -0
  180. package/src/decorators/operations/security.spec.ts +162 -0
  181. package/src/decorators/operations/security.ts +83 -0
  182. package/src/decorators/operations/status.spec.ts +582 -0
  183. package/src/decorators/operations/status.ts +130 -0
  184. package/src/decorators/operations/subscribe.spec.ts +32 -0
  185. package/src/decorators/operations/subscribe.ts +6 -0
  186. package/src/decorators/operations/summary.spec.ts +45 -0
  187. package/src/decorators/operations/summary.ts +32 -0
  188. package/src/decorators/operations/tags.spec.ts +113 -0
  189. package/src/decorators/operations/tags.ts +53 -0
  190. package/src/decorators/operations/view.spec.ts +16 -0
  191. package/src/decorators/operations/view.ts +27 -0
  192. package/src/domain/DecoratorContext.ts +116 -0
  193. package/src/domain/JsonAliasMap.ts +19 -0
  194. package/src/domain/JsonClassStore.ts +35 -0
  195. package/src/domain/JsonDiscriminator.spec.ts +65 -0
  196. package/src/domain/JsonDiscriminator.ts +52 -0
  197. package/src/domain/JsonEntityStore.spec.ts +277 -0
  198. package/src/domain/JsonEntityStore.ts +284 -0
  199. package/src/domain/JsonFormatTypes.ts +17 -0
  200. package/src/domain/JsonLazyRef.ts +21 -0
  201. package/src/domain/JsonMap.spec.ts +15 -0
  202. package/src/domain/JsonMap.ts +33 -0
  203. package/src/domain/JsonMedia.ts +24 -0
  204. package/src/domain/JsonMethodStore.spec.ts +301 -0
  205. package/src/domain/JsonMethodStore.ts +212 -0
  206. package/src/domain/JsonOperation.spec.ts +126 -0
  207. package/src/domain/JsonOperation.ts +219 -0
  208. package/src/domain/JsonOperationPathsMap.ts +16 -0
  209. package/src/domain/JsonOperationRoute.spec.ts +109 -0
  210. package/src/domain/JsonOperationRoute.ts +75 -0
  211. package/src/domain/JsonParameter.ts +70 -0
  212. package/src/domain/JsonParameterStore.spec.ts +212 -0
  213. package/src/domain/JsonParameterStore.ts +138 -0
  214. package/src/domain/JsonParameterTypes.spec.ts +12 -0
  215. package/src/domain/JsonParameterTypes.ts +20 -0
  216. package/src/domain/JsonPropertyStore.spec.ts +177 -0
  217. package/src/domain/JsonPropertyStore.ts +92 -0
  218. package/src/domain/JsonRequestBody.ts +47 -0
  219. package/src/domain/JsonResponse.spec.ts +33 -0
  220. package/src/domain/JsonResponse.ts +64 -0
  221. package/src/domain/JsonSchema.spec.ts +1470 -0
  222. package/src/domain/JsonSchema.ts +1049 -0
  223. package/src/domain/SpecTypes.ts +6 -0
  224. package/src/hooks/alterIgnore.ts +25 -0
  225. package/src/hooks/alterOneOf.ts +67 -0
  226. package/src/hooks/alterRequiredGroups.ts +12 -0
  227. package/src/index.ts +185 -0
  228. package/src/interfaces/IgnoreCallback.ts +5 -0
  229. package/src/interfaces/JsonHookContext.ts +18 -0
  230. package/src/interfaces/JsonOpenSpec.ts +7 -0
  231. package/src/interfaces/JsonSchemaOptions.ts +35 -0
  232. package/src/registries/JsonSchemaMapperContainer.ts +52 -0
  233. package/src/registries/enumRegistries.ts +3 -0
  234. package/src/utils/__snapshots__/generateSpec.spec.ts.snap +109 -0
  235. package/src/utils/buildPath.ts +8 -0
  236. package/src/utils/concatParameters.ts +12 -0
  237. package/src/utils/concatPath.spec.ts +23 -0
  238. package/src/utils/concatPath.ts +24 -0
  239. package/src/utils/defineStatusModel.ts +11 -0
  240. package/src/utils/from.spec.ts +243 -0
  241. package/src/utils/from.ts +281 -0
  242. package/src/utils/generateSpec.spec.ts +1262 -0
  243. package/src/utils/generateSpec.ts +54 -0
  244. package/src/utils/generics.ts +83 -0
  245. package/src/utils/getComputedType.spec.ts +45 -0
  246. package/src/utils/getComputedType.ts +39 -0
  247. package/src/utils/getInheritedStores.spec.ts +47 -0
  248. package/src/utils/getInheritedStores.ts +23 -0
  249. package/src/utils/getJsonEntityStore.ts +36 -0
  250. package/src/utils/getJsonPathParameters.spec.ts +126 -0
  251. package/src/utils/getJsonPathParameters.ts +97 -0
  252. package/src/utils/getJsonSchema.spec.ts +695 -0
  253. package/src/utils/getJsonSchema.ts +69 -0
  254. package/src/utils/getJsonType.spec.ts +28 -0
  255. package/src/utils/getJsonType.ts +46 -0
  256. package/src/utils/getOperationsRoutes.spec.ts +284 -0
  257. package/src/utils/getOperationsRoutes.ts +56 -0
  258. package/src/utils/getOperationsStore.spec.ts +47 -0
  259. package/src/utils/getOperationsStores.ts +37 -0
  260. package/src/utils/getPropertiesStores.spec.ts +138 -0
  261. package/src/utils/getPropertiesStores.ts +66 -0
  262. package/src/utils/getSpec.spec.ts +610 -0
  263. package/src/utils/getSpec.ts +117 -0
  264. package/src/utils/getSpecType.spec.ts +16 -0
  265. package/src/utils/getSpecType.ts +19 -0
  266. package/src/utils/isSuccessStatus.spec.ts +22 -0
  267. package/src/utils/isSuccessStatus.ts +2 -0
  268. package/src/utils/mapHeaders.spec.ts +57 -0
  269. package/src/utils/mapHeaders.ts +33 -0
  270. package/src/utils/mapOpenSpec.ts +44 -0
  271. package/src/utils/mapOpenSpec2.ts +50 -0
  272. package/src/utils/mapOpenSpec3.ts +25 -0
  273. package/src/utils/mapOpenSpecInfo.ts +19 -0
  274. package/src/utils/mapOperationOptions.ts +34 -0
  275. package/src/utils/matchGroups.spec.ts +85 -0
  276. package/src/utils/matchGroups.ts +64 -0
  277. package/src/utils/mergeSpec.spec.ts +533 -0
  278. package/src/utils/mergeSpec.ts +54 -0
  279. package/src/utils/operationIdFormatter.spec.ts +11 -0
  280. package/src/utils/operationIdFormatter.ts +49 -0
  281. package/src/utils/ref.ts +65 -0
  282. package/src/utils/removeHiddenOperation.ts +5 -0
  283. package/src/utils/serializeEnumValues.ts +27 -0
  284. package/src/utils/somethingOf.ts +11 -0
  285. package/src/utils/toJsonMapCollection.spec.ts +18 -0
  286. package/src/utils/toJsonMapCollection.ts +12 -0
  287. package/src/utils/toJsonRegex.ts +7 -0
  288. package/src/utils/transformToOS2.spec.ts +177 -0
  289. package/src/utils/transformToOS2.ts +607 -0
  290. package/src/utils/withErrorMsg.spec.ts +16 -0
  291. package/src/utils/withErrorMsg.ts +56 -0
@@ -0,0 +1,1393 @@
1
+ import "@tsed/platform-exceptions";
2
+
3
+ import {OpenSpec3} from "@tsed/openspec";
4
+
5
+ import {SpecTypes} from "../../domain/SpecTypes.js";
6
+ import {getSpec} from "../../utils/getSpec.js";
7
+ import {CollectionOf} from "../collections/collectionOf.js";
8
+ import {Property} from "../common/property.js";
9
+ import {Generics} from "../generics/generics.js";
10
+ import {OperationPath} from "./operationPath.js";
11
+ import {Returns} from "./returns.js";
12
+
13
+ describe("@Returns", () => {
14
+ describe("Single contentType", () => {
15
+ it("should declare a return type with object", () => {
16
+ // WHEN
17
+ class Controller {
18
+ @OperationPath("POST", "/")
19
+ @(Returns(200, String).Description("description"))
20
+ method() {}
21
+ }
22
+
23
+ // THEN
24
+ const spec = getSpec(Controller);
25
+
26
+ expect(spec).toEqual({
27
+ paths: {
28
+ "/": {
29
+ post: {
30
+ operationId: "controllerMethod",
31
+ parameters: [],
32
+ responses: {
33
+ "200": {
34
+ content: {
35
+ "*/*": {
36
+ schema: {
37
+ type: "string"
38
+ }
39
+ }
40
+ },
41
+ description: "description"
42
+ }
43
+ },
44
+ tags: ["Controller"]
45
+ }
46
+ }
47
+ },
48
+ tags: [
49
+ {
50
+ name: "Controller"
51
+ }
52
+ ]
53
+ });
54
+ });
55
+ it("should declare a return type", () => {
56
+ // WHEN
57
+ class Controller {
58
+ @OperationPath("POST", "/")
59
+ @(Returns(200, String).Description("description"))
60
+ method() {}
61
+ }
62
+
63
+ // THEN
64
+ const spec = getSpec(Controller);
65
+
66
+ expect(spec).toEqual({
67
+ paths: {
68
+ "/": {
69
+ post: {
70
+ operationId: "controllerMethod",
71
+ parameters: [],
72
+ responses: {
73
+ "200": {
74
+ content: {
75
+ "*/*": {
76
+ schema: {
77
+ type: "string"
78
+ }
79
+ }
80
+ },
81
+ description: "description"
82
+ }
83
+ },
84
+ tags: ["Controller"]
85
+ }
86
+ }
87
+ },
88
+ tags: [
89
+ {
90
+ name: "Controller"
91
+ }
92
+ ]
93
+ });
94
+ });
95
+ it("should declare a return type (Status().Type())", () => {
96
+ // WHEN
97
+ class Controller {
98
+ @OperationPath("POST", "/")
99
+ @(Returns().Status(200).Type(String).Description("description"))
100
+ method() {}
101
+ }
102
+
103
+ // THEN
104
+ const spec = getSpec(Controller);
105
+
106
+ expect(spec).toEqual({
107
+ paths: {
108
+ "/": {
109
+ post: {
110
+ operationId: "controllerMethod",
111
+ parameters: [],
112
+ responses: {
113
+ "200": {
114
+ content: {
115
+ "*/*": {
116
+ schema: {
117
+ type: "string"
118
+ }
119
+ }
120
+ },
121
+ description: "description"
122
+ }
123
+ },
124
+ tags: ["Controller"]
125
+ }
126
+ }
127
+ },
128
+ tags: [
129
+ {
130
+ name: "Controller"
131
+ }
132
+ ]
133
+ });
134
+ });
135
+ it("should declare a return type with headers (openspec)", () => {
136
+ // WHEN
137
+ class Controller {
138
+ @OperationPath("POST", "/")
139
+ @(Returns(200, String)
140
+ .Description("description")
141
+ .Header("x-token", "token")
142
+ .Header("x-header", {
143
+ value: ""
144
+ })
145
+ .Examples({test: "Examples"})
146
+ .Schema({
147
+ minLength: 3
148
+ }))
149
+ method() {}
150
+ }
151
+
152
+ // THEN
153
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
154
+
155
+ expect(spec).toEqual({
156
+ paths: {
157
+ "/": {
158
+ post: {
159
+ operationId: "controllerMethod",
160
+ parameters: [],
161
+ responses: {
162
+ "200": {
163
+ content: {
164
+ "*/*": {
165
+ examples: {
166
+ test: "Examples"
167
+ },
168
+ schema: {
169
+ minLength: 3,
170
+ type: "string"
171
+ }
172
+ }
173
+ },
174
+ description: "description",
175
+ headers: {
176
+ "x-header": {
177
+ example: "",
178
+ schema: {
179
+ type: "string"
180
+ }
181
+ },
182
+ "x-token": {
183
+ example: "token",
184
+ schema: {
185
+ type: "string"
186
+ }
187
+ }
188
+ }
189
+ }
190
+ },
191
+ tags: ["Controller"]
192
+ }
193
+ }
194
+ },
195
+ tags: [
196
+ {
197
+ name: "Controller"
198
+ }
199
+ ]
200
+ });
201
+ });
202
+ it("should declare a return type with headers (openspec - header)", () => {
203
+ // WHEN
204
+ class Controller {
205
+ @OperationPath("POST", "/")
206
+ @(Returns(200, String).Description("description").Header("x-token").Examples({test: "Examples"}).Schema({
207
+ minLength: 3
208
+ }))
209
+ method() {}
210
+ }
211
+
212
+ // THEN
213
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
214
+
215
+ expect(spec).toEqual({
216
+ paths: {
217
+ "/": {
218
+ post: {
219
+ operationId: "controllerMethod",
220
+ parameters: [],
221
+ responses: {
222
+ "200": {
223
+ content: {
224
+ "*/*": {
225
+ examples: {
226
+ test: "Examples"
227
+ },
228
+ schema: {
229
+ minLength: 3,
230
+ type: "string"
231
+ }
232
+ }
233
+ },
234
+ description: "description",
235
+ headers: {
236
+ "x-token": {
237
+ schema: {
238
+ type: "string"
239
+ }
240
+ }
241
+ }
242
+ }
243
+ },
244
+ tags: ["Controller"]
245
+ }
246
+ }
247
+ },
248
+ tags: [
249
+ {
250
+ name: "Controller"
251
+ }
252
+ ]
253
+ });
254
+ });
255
+ it("should declare a return type with content-type", () => {
256
+ // WHEN
257
+ class Controller {
258
+ @OperationPath("POST", "/")
259
+ @(Returns(200, String).Description("description").ContentType("text/html").Examples("Examples"))
260
+ method() {}
261
+ }
262
+
263
+ // THEN
264
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
265
+
266
+ expect(spec).toEqual({
267
+ tags: [
268
+ {
269
+ name: "Controller"
270
+ }
271
+ ],
272
+ paths: {
273
+ "/": {
274
+ post: {
275
+ operationId: "controllerMethod",
276
+ parameters: [],
277
+ responses: {
278
+ "200": {
279
+ content: {
280
+ "text/html": {
281
+ schema: {
282
+ type: "string"
283
+ },
284
+ examples: ["Examples"]
285
+ }
286
+ },
287
+ description: "description"
288
+ }
289
+ },
290
+ tags: ["Controller"]
291
+ }
292
+ }
293
+ }
294
+ });
295
+ });
296
+ it("should declare error response", () => {
297
+ // WHEN
298
+ class Controller {
299
+ @OperationPath("POST", "/")
300
+ @(Returns(400).Description("Bad request"))
301
+ @Returns(401)
302
+ @(Returns(200).Description("Success"))
303
+ method() {}
304
+ }
305
+
306
+ // THEN
307
+ const spec = getSpec(Controller);
308
+
309
+ expect(spec).toEqual({
310
+ components: {
311
+ schemas: {
312
+ BadRequest: {
313
+ properties: {
314
+ errors: {
315
+ description: "A list of related errors",
316
+ items: {
317
+ $ref: "#/components/schemas/GenericError"
318
+ },
319
+ type: "array"
320
+ },
321
+ message: {
322
+ description: "An error message",
323
+ minLength: 1,
324
+ type: "string"
325
+ },
326
+ name: {
327
+ default: "BAD_REQUEST",
328
+ description: "The error name",
329
+ example: "BAD_REQUEST",
330
+ minLength: 1,
331
+ type: "string"
332
+ },
333
+ stack: {
334
+ description: "The stack trace (only in development mode)",
335
+ type: "string"
336
+ },
337
+ status: {
338
+ default: 400,
339
+ description: "The status code of the exception",
340
+ example: 400,
341
+ type: "number"
342
+ }
343
+ },
344
+ required: ["name", "message", "status"],
345
+ type: "object"
346
+ },
347
+ GenericError: {
348
+ additionalProperties: true,
349
+ properties: {
350
+ message: {
351
+ description: "An error message",
352
+ minLength: 1,
353
+ type: "string"
354
+ },
355
+ name: {
356
+ description: "The error name",
357
+ minLength: 1,
358
+ type: "string"
359
+ }
360
+ },
361
+ required: ["name", "message"],
362
+ type: "object"
363
+ },
364
+ Unauthorized: {
365
+ properties: {
366
+ errors: {
367
+ description: "A list of related errors",
368
+ items: {
369
+ $ref: "#/components/schemas/GenericError"
370
+ },
371
+ type: "array"
372
+ },
373
+ message: {
374
+ description: "An error message",
375
+ minLength: 1,
376
+ type: "string"
377
+ },
378
+ name: {
379
+ default: "UNAUTHORIZED",
380
+ description: "The error name",
381
+ example: "UNAUTHORIZED",
382
+ minLength: 1,
383
+ type: "string"
384
+ },
385
+ stack: {
386
+ description: "The stack trace (only in development mode)",
387
+ type: "string"
388
+ },
389
+ status: {
390
+ default: 401,
391
+ description: "The status code of the exception",
392
+ example: 401,
393
+ type: "number"
394
+ }
395
+ },
396
+ required: ["name", "message", "status"],
397
+ type: "object"
398
+ }
399
+ }
400
+ },
401
+ paths: {
402
+ "/": {
403
+ post: {
404
+ operationId: "controllerMethod",
405
+ parameters: [],
406
+ responses: {
407
+ "200": {
408
+ content: {
409
+ "*/*": {
410
+ schema: {
411
+ type: "object"
412
+ }
413
+ }
414
+ },
415
+ description: "Success"
416
+ },
417
+ "400": {
418
+ content: {
419
+ "application/json": {
420
+ schema: {
421
+ $ref: "#/components/schemas/BadRequest"
422
+ }
423
+ }
424
+ },
425
+ description: "Bad request"
426
+ },
427
+ "401": {
428
+ content: {
429
+ "application/json": {
430
+ schema: {
431
+ $ref: "#/components/schemas/Unauthorized"
432
+ }
433
+ }
434
+ },
435
+ description: "Unauthorized"
436
+ }
437
+ },
438
+ tags: ["Controller"]
439
+ }
440
+ }
441
+ },
442
+ tags: [
443
+ {
444
+ name: "Controller"
445
+ }
446
+ ]
447
+ });
448
+ });
449
+ it("should declare error response on class", () => {
450
+ // WHEN
451
+ @(Returns(400).Description("Bad request").Header("x-token", "token"))
452
+ @Returns(401)
453
+ class Controller {
454
+ @OperationPath("POST", "/")
455
+ @(Returns(200).Description("Success"))
456
+ @(Returns(400).Description("Bad request2").Header("x-token", "token2"))
457
+ method() {}
458
+ }
459
+
460
+ // THEN
461
+ const spec = getSpec(Controller);
462
+
463
+ expect(spec).toEqual({
464
+ components: {
465
+ schemas: {
466
+ BadRequest: {
467
+ properties: {
468
+ errors: {
469
+ description: "A list of related errors",
470
+ items: {
471
+ $ref: "#/components/schemas/GenericError"
472
+ },
473
+ type: "array"
474
+ },
475
+ message: {
476
+ description: "An error message",
477
+ minLength: 1,
478
+ type: "string"
479
+ },
480
+ name: {
481
+ default: "BAD_REQUEST",
482
+ description: "The error name",
483
+ example: "BAD_REQUEST",
484
+ minLength: 1,
485
+ type: "string"
486
+ },
487
+ stack: {
488
+ description: "The stack trace (only in development mode)",
489
+ type: "string"
490
+ },
491
+ status: {
492
+ default: 400,
493
+ description: "The status code of the exception",
494
+ example: 400,
495
+ type: "number"
496
+ }
497
+ },
498
+ required: ["name", "message", "status"],
499
+ type: "object"
500
+ },
501
+ GenericError: {
502
+ additionalProperties: true,
503
+ properties: {
504
+ message: {
505
+ description: "An error message",
506
+ minLength: 1,
507
+ type: "string"
508
+ },
509
+ name: {
510
+ description: "The error name",
511
+ minLength: 1,
512
+ type: "string"
513
+ }
514
+ },
515
+ required: ["name", "message"],
516
+ type: "object"
517
+ },
518
+ Unauthorized: {
519
+ properties: {
520
+ errors: {
521
+ description: "A list of related errors",
522
+ items: {
523
+ $ref: "#/components/schemas/GenericError"
524
+ },
525
+ type: "array"
526
+ },
527
+ message: {
528
+ description: "An error message",
529
+ minLength: 1,
530
+ type: "string"
531
+ },
532
+ name: {
533
+ default: "UNAUTHORIZED",
534
+ description: "The error name",
535
+ example: "UNAUTHORIZED",
536
+ minLength: 1,
537
+ type: "string"
538
+ },
539
+ stack: {
540
+ description: "The stack trace (only in development mode)",
541
+ type: "string"
542
+ },
543
+ status: {
544
+ default: 401,
545
+ description: "The status code of the exception",
546
+ example: 401,
547
+ type: "number"
548
+ }
549
+ },
550
+ required: ["name", "message", "status"],
551
+ type: "object"
552
+ }
553
+ }
554
+ },
555
+ paths: {
556
+ "/": {
557
+ post: {
558
+ operationId: "controllerMethod",
559
+ parameters: [],
560
+ responses: {
561
+ "200": {
562
+ content: {
563
+ "*/*": {
564
+ schema: {
565
+ type: "object"
566
+ }
567
+ }
568
+ },
569
+ description: "Success"
570
+ },
571
+ "400": {
572
+ content: {
573
+ "application/json": {
574
+ schema: {
575
+ $ref: "#/components/schemas/BadRequest"
576
+ }
577
+ }
578
+ },
579
+ description: "Bad request2",
580
+ headers: {
581
+ "x-token": {
582
+ example: "token2",
583
+ schema: {
584
+ type: "string"
585
+ }
586
+ }
587
+ }
588
+ },
589
+ "401": {
590
+ content: {
591
+ "application/json": {
592
+ schema: {
593
+ $ref: "#/components/schemas/Unauthorized"
594
+ }
595
+ }
596
+ },
597
+ description: "Unauthorized"
598
+ }
599
+ },
600
+ tags: ["Controller"]
601
+ }
602
+ }
603
+ },
604
+ tags: [
605
+ {
606
+ name: "Controller"
607
+ }
608
+ ]
609
+ });
610
+ });
611
+ it("should throw an error when using of with String", () => {
612
+ // WHEN
613
+ let actualError: any;
614
+ try {
615
+ class Controller {
616
+ @OperationPath("POST", "/")
617
+ @(Returns(200, String).Of(Array).Description("description"))
618
+ method() {}
619
+ }
620
+ } catch (er) {
621
+ actualError = er;
622
+ }
623
+
624
+ expect(actualError.message).toBe("Returns.Of cannot be used with the following primitive classes: String, Number, Boolean");
625
+ });
626
+ it("should throw an error when using of with Collection", () => {
627
+ // WHEN
628
+ let actualError: any;
629
+ try {
630
+ class Controller {
631
+ @OperationPath("POST", "/")
632
+ @(Returns(200, Array).Nested(Set).Description("description"))
633
+ method() {}
634
+ }
635
+ } catch (er) {
636
+ actualError = er;
637
+ }
638
+
639
+ expect(actualError.message).toBe(
640
+ "Returns.Nested cannot be used with the following classes: Map, Set, Array, String, Number, Boolean"
641
+ );
642
+ });
643
+ it("should declare an Array of string", () => {
644
+ // WHEN
645
+ class Controller {
646
+ @OperationPath("POST", "/")
647
+ @(Returns(200, Array).Of(String).Description("description"))
648
+ method() {}
649
+ }
650
+
651
+ // THEN
652
+ const spec = getSpec(Controller);
653
+
654
+ expect(spec).toEqual({
655
+ paths: {
656
+ "/": {
657
+ post: {
658
+ operationId: "controllerMethod",
659
+ parameters: [],
660
+ responses: {
661
+ "200": {
662
+ content: {
663
+ "application/json": {
664
+ schema: {
665
+ items: {
666
+ type: "string"
667
+ },
668
+ type: "array"
669
+ }
670
+ }
671
+ },
672
+ description: "description"
673
+ }
674
+ },
675
+ tags: ["Controller"]
676
+ }
677
+ }
678
+ },
679
+ tags: [
680
+ {
681
+ name: "Controller"
682
+ }
683
+ ]
684
+ });
685
+ });
686
+ it("should declare an Array of Model", () => {
687
+ // WHEN
688
+ class Model {
689
+ @Property()
690
+ id: string;
691
+ }
692
+
693
+ class Controller {
694
+ @OperationPath("POST", "/")
695
+ @(Returns(200, Array).Of(Model).Description("description"))
696
+ method() {}
697
+ }
698
+
699
+ // THEN
700
+ const spec = getSpec(Controller);
701
+
702
+ expect(spec).toEqual({
703
+ components: {
704
+ schemas: {
705
+ Model: {
706
+ properties: {
707
+ id: {
708
+ type: "string"
709
+ }
710
+ },
711
+ type: "object"
712
+ }
713
+ }
714
+ },
715
+ paths: {
716
+ "/": {
717
+ post: {
718
+ operationId: "controllerMethod",
719
+ parameters: [],
720
+ responses: {
721
+ "200": {
722
+ content: {
723
+ "application/json": {
724
+ schema: {
725
+ items: {
726
+ $ref: "#/components/schemas/Model"
727
+ },
728
+ type: "array"
729
+ }
730
+ }
731
+ },
732
+ description: "description"
733
+ }
734
+ },
735
+ tags: ["Controller"]
736
+ }
737
+ }
738
+ },
739
+ tags: [
740
+ {
741
+ name: "Controller"
742
+ }
743
+ ]
744
+ });
745
+ });
746
+ it("should declare an Generic of Model", () => {
747
+ // WHEN
748
+ @Generics("T")
749
+ class Pagination<T> {
750
+ @CollectionOf("T")
751
+ data: T[];
752
+
753
+ @Property()
754
+ totalCount: number;
755
+ }
756
+
757
+ @Generics("T")
758
+ class Submission<T> {
759
+ @Property()
760
+ _id: string;
761
+
762
+ @Property("T")
763
+ data: T;
764
+ }
765
+
766
+ class Product {
767
+ @Property()
768
+ title: string;
769
+ }
770
+
771
+ class Controller {
772
+ @OperationPath("POST", "/")
773
+ @(Returns(200, Pagination)
774
+ .Of(Submission)
775
+ .Nested(Product)
776
+ .Description("description")
777
+ .Examples({
778
+ Example1: {
779
+ value: [
780
+ {
781
+ totalCount: 0,
782
+ data: [
783
+ {
784
+ _id: "id",
785
+ data: {}
786
+ }
787
+ ]
788
+ }
789
+ ]
790
+ }
791
+ }))
792
+ method(): Promise<Pagination<Submission<Product>> | null> {
793
+ return null as never;
794
+ }
795
+ }
796
+
797
+ // THEN
798
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
799
+
800
+ expect(spec).toEqual({
801
+ components: {
802
+ schemas: {
803
+ Product: {
804
+ properties: {
805
+ title: {
806
+ type: "string"
807
+ }
808
+ },
809
+ type: "object"
810
+ }
811
+ }
812
+ },
813
+ paths: {
814
+ "/": {
815
+ post: {
816
+ operationId: "controllerMethod",
817
+ parameters: [],
818
+ responses: {
819
+ "200": {
820
+ content: {
821
+ "application/json": {
822
+ examples: {
823
+ Example1: {
824
+ value: [
825
+ {
826
+ data: [
827
+ {
828
+ _id: "id",
829
+ data: {}
830
+ }
831
+ ],
832
+ totalCount: 0
833
+ }
834
+ ]
835
+ }
836
+ },
837
+ schema: {
838
+ properties: {
839
+ data: {
840
+ items: {
841
+ properties: {
842
+ _id: {
843
+ type: "string"
844
+ },
845
+ data: {
846
+ $ref: "#/components/schemas/Product"
847
+ }
848
+ },
849
+ type: "object"
850
+ },
851
+ type: "array"
852
+ },
853
+ totalCount: {
854
+ type: "number"
855
+ }
856
+ },
857
+ type: "object"
858
+ }
859
+ }
860
+ },
861
+ description: "description"
862
+ }
863
+ },
864
+ tags: ["Controller"]
865
+ }
866
+ }
867
+ },
868
+ tags: [
869
+ {
870
+ name: "Controller"
871
+ }
872
+ ]
873
+ });
874
+ });
875
+ it("should declare an Generic of Model with enum (OS3)", () => {
876
+ // WHEN
877
+ @Generics("T")
878
+ class Submission<T> {
879
+ @Property()
880
+ _id: string;
881
+
882
+ @Property("T")
883
+ data: T;
884
+ }
885
+
886
+ enum MyEnum {
887
+ READ = "read",
888
+ WRITE = "write"
889
+ }
890
+
891
+ class Controller {
892
+ @OperationPath("POST", "/")
893
+ @(Returns(200, Submission).Of(MyEnum).Description("description"))
894
+ method(): Promise<Submission<MyEnum> | null> {
895
+ return Promise.resolve(null);
896
+ }
897
+ }
898
+
899
+ // THEN
900
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
901
+
902
+ expect(spec).toEqual({
903
+ paths: {
904
+ "/": {
905
+ post: {
906
+ operationId: "controllerMethod",
907
+ parameters: [],
908
+ responses: {
909
+ "200": {
910
+ content: {
911
+ "application/json": {
912
+ schema: {
913
+ properties: {
914
+ _id: {
915
+ type: "string"
916
+ },
917
+ data: {
918
+ enum: ["read", "write"],
919
+ type: "string"
920
+ }
921
+ },
922
+ type: "object"
923
+ }
924
+ }
925
+ },
926
+ description: "description"
927
+ }
928
+ },
929
+ tags: ["Controller"]
930
+ }
931
+ }
932
+ },
933
+ tags: [
934
+ {
935
+ name: "Controller"
936
+ }
937
+ ]
938
+ });
939
+ });
940
+ it("should declare an Generic of Model with enum with pagination(OS3)", () => {
941
+ // WHEN
942
+ @Generics("T")
943
+ class Pagination<T> {
944
+ @CollectionOf("T")
945
+ data: T[];
946
+
947
+ @Property()
948
+ totalCount: number;
949
+ }
950
+
951
+ @Generics("T")
952
+ class Submission<T> {
953
+ @Property()
954
+ _id: string;
955
+
956
+ @Property("T")
957
+ data: T;
958
+ }
959
+
960
+ enum MyEnum {
961
+ READ = "read",
962
+ WRITE = "write"
963
+ }
964
+
965
+ class Controller {
966
+ @OperationPath("POST", "/")
967
+ @(Returns(200, Pagination)
968
+ .Of(Submission)
969
+ .Nested(MyEnum)
970
+ .Description("description")
971
+ .Examples({
972
+ Example1: {
973
+ value: [
974
+ {
975
+ totalCount: 0,
976
+ data: [
977
+ {
978
+ _id: "id",
979
+ data: {}
980
+ }
981
+ ]
982
+ }
983
+ ]
984
+ }
985
+ }))
986
+ method(): Promise<Pagination<Submission<MyEnum>> | null> {
987
+ return null as never;
988
+ }
989
+ }
990
+
991
+ // THEN
992
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
993
+
994
+ expect(spec).toEqual({
995
+ paths: {
996
+ "/": {
997
+ post: {
998
+ operationId: "controllerMethod",
999
+ parameters: [],
1000
+ responses: {
1001
+ "200": {
1002
+ content: {
1003
+ "application/json": {
1004
+ examples: {
1005
+ Example1: {
1006
+ value: [
1007
+ {
1008
+ data: [
1009
+ {
1010
+ _id: "id",
1011
+ data: {}
1012
+ }
1013
+ ],
1014
+ totalCount: 0
1015
+ }
1016
+ ]
1017
+ }
1018
+ },
1019
+ schema: {
1020
+ properties: {
1021
+ data: {
1022
+ items: {
1023
+ properties: {
1024
+ _id: {
1025
+ type: "string"
1026
+ },
1027
+ data: {
1028
+ enum: ["read", "write"],
1029
+ type: "string"
1030
+ }
1031
+ },
1032
+ type: "object"
1033
+ },
1034
+ type: "array"
1035
+ },
1036
+ totalCount: {
1037
+ type: "number"
1038
+ }
1039
+ },
1040
+ type: "object"
1041
+ }
1042
+ }
1043
+ },
1044
+ description: "description"
1045
+ }
1046
+ },
1047
+ tags: ["Controller"]
1048
+ }
1049
+ }
1050
+ },
1051
+ tags: [
1052
+ {
1053
+ name: "Controller"
1054
+ }
1055
+ ]
1056
+ });
1057
+ });
1058
+ it("should apply application/json content type if OneOf/AnyOf/AllOf is used without base model", () => {
1059
+ class Model {
1060
+ @Property()
1061
+ id: string;
1062
+ }
1063
+
1064
+ class Model2 {
1065
+ @Property()
1066
+ id: string;
1067
+ }
1068
+
1069
+ class Controller {
1070
+ @OperationPath("POST", "/")
1071
+ @(Returns(200).OneOf(Model, Model2).Description("description"))
1072
+ method() {
1073
+ return {};
1074
+ }
1075
+ }
1076
+
1077
+ const result = getSpec(Controller, {specType: SpecTypes.OPENAPI});
1078
+
1079
+ expect(result).toEqual({
1080
+ components: {
1081
+ schemas: {
1082
+ Model: {
1083
+ properties: {
1084
+ id: {
1085
+ type: "string"
1086
+ }
1087
+ },
1088
+ type: "object"
1089
+ },
1090
+ Model2: {
1091
+ properties: {
1092
+ id: {
1093
+ type: "string"
1094
+ }
1095
+ },
1096
+ type: "object"
1097
+ }
1098
+ }
1099
+ },
1100
+ paths: {
1101
+ "/": {
1102
+ post: {
1103
+ operationId: "controllerMethod",
1104
+ parameters: [],
1105
+ responses: {
1106
+ "200": {
1107
+ content: {
1108
+ "application/json": {
1109
+ schema: {
1110
+ oneOf: [
1111
+ {
1112
+ $ref: "#/components/schemas/Model"
1113
+ },
1114
+ {
1115
+ $ref: "#/components/schemas/Model2"
1116
+ }
1117
+ ]
1118
+ }
1119
+ }
1120
+ },
1121
+ description: "description"
1122
+ }
1123
+ },
1124
+ tags: ["Controller"]
1125
+ }
1126
+ }
1127
+ },
1128
+ tags: [
1129
+ {
1130
+ name: "Controller"
1131
+ }
1132
+ ]
1133
+ });
1134
+ });
1135
+ });
1136
+ describe("Multiple contentType", () => {
1137
+ it("should manage multiple content and model", () => {
1138
+ // WHEN
1139
+ class Model {
1140
+ @Property()
1141
+ id: string;
1142
+ }
1143
+
1144
+ class Controller {
1145
+ @OperationPath("POST", "/")
1146
+ @(Returns(200, Model).Description("description"))
1147
+ @(Returns(200, String).ContentType("text/html"))
1148
+ @(Returns(200, String).ContentType("text/xml"))
1149
+ method() {}
1150
+ }
1151
+
1152
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
1153
+
1154
+ expect(spec).toEqual({
1155
+ components: {
1156
+ schemas: {
1157
+ Model: {
1158
+ properties: {
1159
+ id: {
1160
+ type: "string"
1161
+ }
1162
+ },
1163
+ type: "object"
1164
+ }
1165
+ }
1166
+ },
1167
+ paths: {
1168
+ "/": {
1169
+ post: {
1170
+ operationId: "controllerMethod",
1171
+ parameters: [],
1172
+ responses: {
1173
+ "200": {
1174
+ content: {
1175
+ "application/json": {
1176
+ schema: {
1177
+ $ref: "#/components/schemas/Model"
1178
+ }
1179
+ },
1180
+ "text/html": {
1181
+ schema: {
1182
+ type: "string"
1183
+ }
1184
+ },
1185
+ "text/xml": {
1186
+ schema: {
1187
+ type: "string"
1188
+ }
1189
+ }
1190
+ },
1191
+ description: "description"
1192
+ }
1193
+ },
1194
+ tags: ["Controller"]
1195
+ }
1196
+ }
1197
+ },
1198
+ tags: [
1199
+ {
1200
+ name: "Controller"
1201
+ }
1202
+ ]
1203
+ });
1204
+ });
1205
+ });
1206
+ describe("Title", () => {
1207
+ it("should declare an Generic of Model", () => {
1208
+ // WHEN
1209
+ @Generics("T")
1210
+ class Pagination<T> {
1211
+ @CollectionOf("T")
1212
+ data: T[];
1213
+
1214
+ @Property()
1215
+ totalCount: number;
1216
+ }
1217
+
1218
+ @Generics("T")
1219
+ class Submission<T> {
1220
+ @Property()
1221
+ _id: string;
1222
+
1223
+ @Property("T")
1224
+ data: T;
1225
+ }
1226
+
1227
+ class Product {
1228
+ @Property()
1229
+ title: string;
1230
+ }
1231
+
1232
+ class Controller {
1233
+ @OperationPath("POST", "/")
1234
+ @(Returns(200, Pagination).Of(Submission).Nested(Product).Title("PaginatedSubmissionProduct").Description("description"))
1235
+ method(): Promise<Pagination<Submission<Product>> | null> {
1236
+ return null as never;
1237
+ }
1238
+ }
1239
+
1240
+ // THEN
1241
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI});
1242
+
1243
+ expect(spec).toEqual({
1244
+ components: {
1245
+ schemas: {
1246
+ Product: {
1247
+ properties: {
1248
+ title: {
1249
+ type: "string"
1250
+ }
1251
+ },
1252
+ type: "object"
1253
+ },
1254
+ PaginatedSubmissionProduct: {
1255
+ properties: {
1256
+ data: {
1257
+ items: {
1258
+ properties: {
1259
+ _id: {
1260
+ type: "string"
1261
+ },
1262
+ data: {
1263
+ $ref: "#/components/schemas/Product"
1264
+ }
1265
+ },
1266
+ type: "object"
1267
+ },
1268
+ type: "array"
1269
+ },
1270
+ totalCount: {
1271
+ type: "number"
1272
+ }
1273
+ },
1274
+ type: "object"
1275
+ }
1276
+ }
1277
+ },
1278
+ paths: {
1279
+ "/": {
1280
+ post: {
1281
+ operationId: "controllerMethod",
1282
+ parameters: [],
1283
+ responses: {
1284
+ "200": {
1285
+ content: {
1286
+ "application/json": {
1287
+ schema: {
1288
+ $ref: "#/components/schemas/PaginatedSubmissionProduct"
1289
+ }
1290
+ }
1291
+ },
1292
+ description: "description"
1293
+ }
1294
+ },
1295
+ tags: ["Controller"]
1296
+ }
1297
+ }
1298
+ },
1299
+ tags: [
1300
+ {
1301
+ name: "Controller"
1302
+ }
1303
+ ]
1304
+ });
1305
+ });
1306
+ });
1307
+ describe("Multiple return types", () => {
1308
+ class ClassA {
1309
+ @Property()
1310
+ prop1: string;
1311
+
1312
+ @Property()
1313
+ prop2: string;
1314
+ }
1315
+
1316
+ class ClassB {
1317
+ @Property()
1318
+ prop3: string;
1319
+
1320
+ @Property()
1321
+ prop4: string;
1322
+ }
1323
+
1324
+ it("should return oneOf schema", () => {
1325
+ class Controller {
1326
+ @Returns(200, [ClassA, ClassB])
1327
+ @OperationPath("GET", "/")
1328
+ method() {}
1329
+ }
1330
+
1331
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI}) as Partial<OpenSpec3>;
1332
+
1333
+ expect(spec.paths!["/"].get!.responses["200"].content!["application/json"].schema).toEqual({
1334
+ oneOf: [
1335
+ {
1336
+ $ref: "#/components/schemas/ClassA"
1337
+ },
1338
+ {
1339
+ $ref: "#/components/schemas/ClassB"
1340
+ }
1341
+ ]
1342
+ });
1343
+ });
1344
+
1345
+ it("should return oneOf array schema", () => {
1346
+ class Controller {
1347
+ @(Returns(200, Array).OneOf(ClassA, ClassB))
1348
+ @OperationPath("GET", "/")
1349
+ method() {}
1350
+ }
1351
+
1352
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI}) as Partial<OpenSpec3>;
1353
+
1354
+ expect(spec.paths!["/"].get!.responses["200"].content!["application/json"].schema).toEqual({
1355
+ type: "array",
1356
+ items: {
1357
+ oneOf: [
1358
+ {
1359
+ $ref: "#/components/schemas/ClassA"
1360
+ },
1361
+ {
1362
+ $ref: "#/components/schemas/ClassB"
1363
+ }
1364
+ ]
1365
+ }
1366
+ });
1367
+ });
1368
+
1369
+ it("should return allOf array schema", () => {
1370
+ class Controller {
1371
+ @(Returns(200, Array).AllOf(ClassA, ClassB))
1372
+ @OperationPath("GET", "/")
1373
+ method() {}
1374
+ }
1375
+
1376
+ const spec = getSpec(Controller, {specType: SpecTypes.OPENAPI}) as Partial<OpenSpec3>;
1377
+
1378
+ expect(spec.paths!["/"].get!.responses["200"].content!["application/json"].schema).toEqual({
1379
+ type: "array",
1380
+ items: {
1381
+ allOf: [
1382
+ {
1383
+ $ref: "#/components/schemas/ClassA"
1384
+ },
1385
+ {
1386
+ $ref: "#/components/schemas/ClassB"
1387
+ }
1388
+ ]
1389
+ }
1390
+ });
1391
+ });
1392
+ });
1393
+ });