@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,327 @@
1
+ import {catchError} from "@tsed/core";
2
+
3
+ import {JsonEntityStore} from "../../domain/JsonEntityStore.js";
4
+ import {array, map, string} from "../../utils/from.js";
5
+ import {getJsonSchema} from "../../utils/getJsonSchema.js";
6
+ import {Property} from "../common/property.js";
7
+ import {Schema} from "../common/schema.js";
8
+ import {In} from "../operations/in.js";
9
+ import {OperationPath} from "../operations/operationPath.js";
10
+ import {CollectionContains} from "./collectionContains.js";
11
+ import {ArrayOf, CollectionOf, MapOf} from "./collectionOf.js";
12
+ import {MaxItems} from "./maxItems.js";
13
+ import {MinItems} from "./minItems.js";
14
+
15
+ describe("@CollectionOf", () => {
16
+ it("should declare a collection and catch error (Array of)", () => {
17
+ // WHEN
18
+ const error = catchError(() => {
19
+ class Model {
20
+ @CollectionOf(undefined)
21
+ num: number[];
22
+ }
23
+ });
24
+
25
+ expect(error?.message).toEqual(
26
+ "A type is required on `@CollectionOf(type)` decorator. Please give a type or wrap it inside an arrow function if you have a circular reference."
27
+ );
28
+ });
29
+ it("should declare an array of map of string", () => {
30
+ const schema = array().items(map().additionalProperties(string()));
31
+
32
+ class Test {
33
+ @Schema(schema)
34
+ @CollectionOf(Map)
35
+ fields: Map<string, string>[] = [];
36
+ }
37
+
38
+ expect(getJsonSchema(Test)).toEqual({
39
+ properties: {
40
+ fields: {
41
+ items: {
42
+ additionalProperties: {
43
+ type: "string"
44
+ },
45
+ type: "object"
46
+ },
47
+ type: "array"
48
+ }
49
+ },
50
+ type: "object"
51
+ });
52
+ });
53
+ it("should declare a collection (Array of)", () => {
54
+ // WHEN
55
+ class Model {
56
+ @CollectionOf(Number)
57
+ num: number[];
58
+ }
59
+
60
+ // THEN
61
+ const classSchema = JsonEntityStore.from(Model);
62
+
63
+ expect(classSchema.schema.toJSON()).toEqual({
64
+ properties: {
65
+ num: {
66
+ items: {
67
+ type: "number"
68
+ },
69
+ type: "array"
70
+ }
71
+ },
72
+ type: "object"
73
+ });
74
+ });
75
+ it("should declare a collection (Array of Model)", () => {
76
+ // WHEN
77
+ class Nested {
78
+ @Property()
79
+ id: string;
80
+ }
81
+
82
+ class Model {
83
+ @MaxItems(10)
84
+ @CollectionOf(Nested)
85
+ @MinItems(1)
86
+ prop: Nested[];
87
+ }
88
+
89
+ // THEN
90
+ const entity = JsonEntityStore.from(Model, "prop");
91
+ const schema = getJsonSchema(Model);
92
+
93
+ expect(entity.schema.getTarget()).toEqual(Array);
94
+ expect(entity.schema.get("type")).toEqual("array");
95
+ expect(entity.itemSchema.getComputedType()).toEqual(Nested);
96
+
97
+ expect(schema).toEqual({
98
+ definitions: {
99
+ Nested: {
100
+ properties: {
101
+ id: {
102
+ type: "string"
103
+ }
104
+ },
105
+ type: "object"
106
+ }
107
+ },
108
+ properties: {
109
+ prop: {
110
+ items: {
111
+ $ref: "#/definitions/Nested"
112
+ },
113
+ minItems: 1,
114
+ maxItems: 10,
115
+ type: "array"
116
+ }
117
+ },
118
+ type: "object"
119
+ });
120
+ });
121
+ it("should declare a collection (Array of Model on param)", () => {
122
+ // WHEN
123
+ class Nested {
124
+ @Property()
125
+ id: string;
126
+ }
127
+
128
+ class Model {
129
+ @Property()
130
+ id: string;
131
+ @CollectionOf(Nested)
132
+ prop: Nested;
133
+ }
134
+
135
+ class Ctrl {
136
+ @OperationPath("POST", "/")
137
+ test(@In("body") @CollectionOf(Model) body: Model[]) {}
138
+ }
139
+
140
+ // THEN
141
+ const entity = JsonEntityStore.from(Ctrl.prototype, "test", 0);
142
+
143
+ expect(getJsonSchema(entity)).toEqual({
144
+ definitions: {
145
+ Model: {
146
+ properties: {
147
+ id: {
148
+ type: "string"
149
+ },
150
+ prop: {
151
+ $ref: "#/definitions/Nested"
152
+ }
153
+ },
154
+ type: "object"
155
+ },
156
+ Nested: {
157
+ properties: {
158
+ id: {
159
+ type: "string"
160
+ }
161
+ },
162
+ type: "object"
163
+ }
164
+ },
165
+ items: {
166
+ $ref: "#/definitions/Model"
167
+ },
168
+ type: "array"
169
+ });
170
+ });
171
+ it("should declare a collection (Map of)", () => {
172
+ // WHEN
173
+ class Model {
174
+ @(CollectionOf(Number).MinProperties(2).MaxProperties(5))
175
+ num: Map<string, number>;
176
+ }
177
+
178
+ // THEN
179
+ const classSchema = JsonEntityStore.from(Model);
180
+
181
+ expect(classSchema.schema.toJSON()).toEqual({
182
+ properties: {
183
+ num: {
184
+ additionalProperties: {
185
+ type: "number"
186
+ },
187
+ maxProperties: 5,
188
+ minProperties: 2,
189
+ type: "object"
190
+ }
191
+ },
192
+ type: "object"
193
+ });
194
+ });
195
+ it("should declare a collection (Set of)", () => {
196
+ // WHEN
197
+ class Model {
198
+ @CollectionOf(Number)
199
+ num: Set<number>;
200
+ }
201
+
202
+ // THEN
203
+ const classSchema = JsonEntityStore.from(Model);
204
+
205
+ expect(classSchema.schema.toJSON()).toEqual({
206
+ properties: {
207
+ num: {
208
+ items: {
209
+ type: "number"
210
+ },
211
+ type: "array",
212
+ uniqueItems: true
213
+ }
214
+ },
215
+ type: "object"
216
+ });
217
+ });
218
+ it("should declare collection with additional props", () => {
219
+ // WHEN
220
+ class Model {
221
+ @(CollectionOf(String).MinItems(0).MaxItems(10).UniqueItems())
222
+ words: string[];
223
+ }
224
+
225
+ // THEN
226
+ const classSchema = JsonEntityStore.from(Model);
227
+
228
+ expect(classSchema.schema.toJSON()).toEqual({
229
+ properties: {
230
+ words: {
231
+ type: "array",
232
+ items: {
233
+ type: "string"
234
+ },
235
+ maxItems: 10,
236
+ minItems: 0,
237
+ uniqueItems: true
238
+ }
239
+ },
240
+ type: "object"
241
+ });
242
+ });
243
+ it("should declare collection with additional props and contains", () => {
244
+ // WHEN
245
+ class Model {
246
+ @(CollectionContains(String).MinItems(0).MaxItems(10))
247
+ words: string[];
248
+ }
249
+
250
+ // THEN
251
+ const classSchema = JsonEntityStore.from(Model);
252
+
253
+ expect(classSchema.schema.toJSON()).toEqual({
254
+ properties: {
255
+ words: {
256
+ type: "array",
257
+ contains: {
258
+ type: "string"
259
+ },
260
+ maxItems: 10,
261
+ minItems: 0
262
+ }
263
+ },
264
+ type: "object"
265
+ });
266
+ });
267
+ });
268
+
269
+ describe("@ArrayOf", () => {
270
+ interface ArrayList<T> extends Array<T> {
271
+ pull(query: any): this;
272
+ }
273
+
274
+ it("should declare a collection (Array of)", () => {
275
+ // WHEN
276
+ class Model {
277
+ @ArrayOf(Number)
278
+ num: ArrayList<number>;
279
+ }
280
+
281
+ // THEN
282
+ const classSchema = JsonEntityStore.from(Model);
283
+
284
+ expect(classSchema.schema.toJSON()).toEqual({
285
+ properties: {
286
+ num: {
287
+ items: {
288
+ type: "number"
289
+ },
290
+ type: "array"
291
+ }
292
+ },
293
+ type: "object"
294
+ });
295
+ });
296
+ });
297
+
298
+ describe("@MapOf", () => {
299
+ interface MapCollection<K, V> extends Map<K, V> {
300
+ take(query: any): V;
301
+ }
302
+
303
+ it("should declare a collection (Map of)", () => {
304
+ // WHEN
305
+ class Model {
306
+ @(MapOf(Number).MinProperties(2).MaxProperties(5))
307
+ num: MapCollection<string, number>;
308
+ }
309
+
310
+ // THEN
311
+ const classSchema = JsonEntityStore.from(Model);
312
+
313
+ expect(classSchema.schema.toJSON()).toEqual({
314
+ properties: {
315
+ num: {
316
+ additionalProperties: {
317
+ type: "number"
318
+ },
319
+ maxProperties: 5,
320
+ minProperties: 2,
321
+ type: "object"
322
+ }
323
+ },
324
+ type: "object"
325
+ });
326
+ });
327
+ });
@@ -0,0 +1,182 @@
1
+ import {JsonEntityStore} from "../../domain/JsonEntityStore.js";
2
+
3
+ export interface ArrayOfChainedDecorators {
4
+ (...args: any): any;
5
+
6
+ /**
7
+ * An array instance is valid against `minItems` if its size is greater than, or equal to, the value of this keyword.
8
+ *
9
+ * ::: warning
10
+ * The value `minItems` MUST be a non-negative integer.
11
+ * :::
12
+ *
13
+ * ::: tip
14
+ * Omitting this keyword has the same behavior as a value of 0.
15
+ * :::
16
+ */
17
+ MinItems(minItems: number): this;
18
+
19
+ /**
20
+ * The value `maxItems` MUST be a non-negative integer.
21
+ *
22
+ * An array instance is valid against `maxItems` if its size is less than, or equal to, the value of this keyword.
23
+ *
24
+ * :: warning
25
+ * The value `maxItems` MUST be a non-negative integer.
26
+ * :::
27
+ */
28
+ MaxItems(maxItems: number): this;
29
+
30
+ /**
31
+ * Set the type of the item collection. The possible value is String, Boolean, Number, Date, Object, Class, etc...
32
+ *
33
+ * The array instance will be valid against "contains" if at least one of its elements is valid against the given schema.
34
+ */
35
+ Contains(): this;
36
+
37
+ /**
38
+ * If this keyword has boolean value false, the instance validates successfully. If it has boolean value true, the instance validates successfully if all of its elements are unique.
39
+ */
40
+ UniqueItems(uniqueItems?: boolean): this;
41
+ }
42
+
43
+ export interface MapOfChainedDecorators {
44
+ (...args: any): any;
45
+
46
+ /**
47
+ * An object instance is valid against `minProperties` if its number of properties is less than, or equal to, the value of this keyword.
48
+ *
49
+ * ::: warning
50
+ * The value of this keyword MUST be a non-negative integer.
51
+ * :::
52
+ */
53
+ MinProperties(minProperties: number): this;
54
+
55
+ /**
56
+ * An object instance is valid against `maxProperties` if its number of properties is less than, or equal to, the value of this keyword.
57
+ *
58
+ * ::: warning
59
+ * The value of this keyword MUST be a non-negative integer.
60
+ * :::
61
+ */
62
+ MaxProperties(maxProperties: number): this;
63
+ }
64
+
65
+ export interface CollectionOfChainedDecorators extends MapOfChainedDecorators, ArrayOfChainedDecorators {}
66
+
67
+ /**
68
+ * Set the type of the item collection. The possible value is String, Boolean, Number, Date, Object, Class, etc...
69
+ *
70
+ * ```typescript
71
+ * class Model {
72
+ * @CollectionOf(String).MinLength(0).MaxLength(0)
73
+ * property: string[];
74
+ * }
75
+ * ```
76
+ * ::: warning
77
+ * You mustn't use the `type Type = string | number` as parameters Type.
78
+ *
79
+ * This example doesn't work:
80
+ *
81
+ * ```typescript
82
+ * type Type = "string" | "number"
83
+ * class Model {
84
+ * @CollectionOf(Type)
85
+ * property: Type[];
86
+ * }
87
+ * ```
88
+ * :::
89
+ *
90
+ * @param {Type<any>} type
91
+ * @param collectionType
92
+ * @decorator
93
+ * @validation
94
+ * @swagger
95
+ * @schema
96
+ * @input
97
+ * @collections
98
+ */
99
+ export function CollectionOf(type: any, collectionType?: any): CollectionOfChainedDecorators {
100
+ if (!type) {
101
+ throw new Error(
102
+ "A type is required on `@CollectionOf(type)` decorator. Please give a type or wrap it inside an arrow function if you have a circular reference."
103
+ );
104
+ }
105
+
106
+ const schema: any = {};
107
+ let contains: boolean = false;
108
+
109
+ const decorator = (...args: any) => {
110
+ const store = JsonEntityStore.from(...args);
111
+
112
+ if (collectionType) {
113
+ store.collectionType = collectionType;
114
+ store.schema.type(collectionType);
115
+ }
116
+
117
+ store.type = type;
118
+ store.itemSchema.type(type);
119
+
120
+ store.schema.assign(schema);
121
+
122
+ if (store.isArray && contains) {
123
+ store.schema.set("contains", store.schema.get("items"));
124
+ store.schema.delete("items");
125
+ }
126
+ };
127
+
128
+ decorator.MinItems = (minItems: number) => {
129
+ schema.minItems = minItems;
130
+
131
+ return decorator;
132
+ };
133
+
134
+ decorator.MaxItems = (maxItems: number) => {
135
+ schema.maxItems = maxItems;
136
+
137
+ return decorator;
138
+ };
139
+ decorator.MinProperties = (minProperties: number) => {
140
+ schema.minProperties = minProperties;
141
+
142
+ return decorator;
143
+ };
144
+
145
+ decorator.MaxProperties = (maxProperties: number) => {
146
+ schema.maxProperties = maxProperties;
147
+
148
+ return decorator;
149
+ };
150
+
151
+ decorator.Contains = () => {
152
+ contains = true;
153
+
154
+ return decorator;
155
+ };
156
+
157
+ decorator.UniqueItems = (uniqueItems = true) => {
158
+ schema.uniqueItems = uniqueItems;
159
+
160
+ return decorator;
161
+ };
162
+
163
+ return decorator;
164
+ }
165
+
166
+ /**
167
+ * Alias of @@GenericOf@@ decorator.
168
+ * @param type
169
+ * @decorator
170
+ */
171
+ export function ArrayOf(type: any): ArrayOfChainedDecorators {
172
+ return CollectionOf(type, Array);
173
+ }
174
+
175
+ /**
176
+ * Alias of @@GenericOf@@ decorator.
177
+ * @param type
178
+ * @decorator
179
+ */
180
+ export function MapOf(type: any): MapOfChainedDecorators {
181
+ return CollectionOf(type, Map);
182
+ }
@@ -0,0 +1,40 @@
1
+ import {getJsonSchema} from "../../utils/getJsonSchema.js";
2
+ import {CollectionOf} from "./collectionOf.js";
3
+ import {MaxItems} from "./maxItems.js";
4
+
5
+ describe("@MaxItems", () => {
6
+ it("should declare a prop", () => {
7
+ // WHEN
8
+ class Model {
9
+ @CollectionOf(Number)
10
+ @MaxItems(10)
11
+ num: number[];
12
+ }
13
+
14
+ // THEN
15
+ expect(getJsonSchema(Model)).toEqual({
16
+ properties: {
17
+ num: {
18
+ items: {
19
+ type: "number"
20
+ },
21
+ maxItems: 10,
22
+ type: "array"
23
+ }
24
+ },
25
+ type: "object"
26
+ });
27
+ });
28
+ it("should throw error", () => {
29
+ // WHEN
30
+ let actualError: any;
31
+ try {
32
+ MaxItems(-1);
33
+ } catch (er) {
34
+ actualError = er;
35
+ }
36
+
37
+ // THEN
38
+ expect(actualError.message).toBe("The value of maxItems MUST be a non-negative integer.");
39
+ });
40
+ });
@@ -0,0 +1,59 @@
1
+ import {withErrorMsg} from "../../utils/withErrorMsg.js";
2
+ import {JsonEntityFn} from "../common/jsonEntityFn.js";
3
+
4
+ /**
5
+ * The value `maxItems` MUST be a non-negative integer.
6
+ *
7
+ * An array instance is valid against `maxItems` if its size is less than, or equal to, the value of this keyword.
8
+ *
9
+ * :: warning
10
+ * The value `maxItems` MUST be a non-negative integer.
11
+ * :::
12
+ *
13
+ * :: warning
14
+ * This decorator will be removed in v7.
15
+ * For v6 user, use @@MaxItems@@ from @tsed/schema instead of @tsed/platform-http.
16
+ * :::
17
+ *
18
+ * ## Example
19
+ *
20
+ * ```typescript
21
+ * class Model {
22
+ * @CollectionOf(String)
23
+ * @MaxItems(10)
24
+ * property: string[];
25
+ * }
26
+ * ```
27
+ *
28
+ * Will produce:
29
+ *
30
+ * ```json
31
+ * {
32
+ * "type": "object",
33
+ * "properties": {
34
+ * "property": {
35
+ * "type": "number",
36
+ * "maxItems": 10
37
+ * }
38
+ * }
39
+ * }
40
+ * ```
41
+ *
42
+ * @param {number} maxItems
43
+ * @decorator
44
+ * @validation
45
+ * @swagger
46
+ * @schema
47
+ * @input
48
+ * @collections
49
+ * @ajv-errors
50
+ */
51
+ export const MaxItems = withErrorMsg("maxItems", (maxItems: number) => {
52
+ if (maxItems < 0) {
53
+ throw new Error("The value of maxItems MUST be a non-negative integer.");
54
+ }
55
+
56
+ return JsonEntityFn((storedJson) => {
57
+ storedJson.schema.maxItems(maxItems);
58
+ });
59
+ });
@@ -0,0 +1,109 @@
1
+ import {SpecTypes} from "../../domain/SpecTypes.js";
2
+ import {getJsonSchema} from "../../utils/getJsonSchema.js";
3
+ import {getSpec} from "../../utils/getSpec.js";
4
+ import {In} from "../operations/in.js";
5
+ import {OperationPath} from "../operations/operationPath.js";
6
+ import {MaxProperties} from "./maxProperties.js";
7
+
8
+ describe("@MaxProperties", () => {
9
+ it("should declare max value (any)", () => {
10
+ // WHEN
11
+ class Model {
12
+ @MaxProperties(10)
13
+ prop: any;
14
+ }
15
+
16
+ // THEN
17
+ expect(getJsonSchema(Model)).toEqual({
18
+ properties: {
19
+ prop: {
20
+ maxProperties: 10,
21
+ type: "object"
22
+ }
23
+ },
24
+ type: "object"
25
+ });
26
+ });
27
+ it("should declare max value (Map<any>)", () => {
28
+ // WHEN
29
+ class Model {
30
+ @MaxProperties(10)
31
+ prop: Map<string, any>;
32
+ }
33
+
34
+ // THEN
35
+ expect(getJsonSchema(Model)).toEqual({
36
+ properties: {
37
+ prop: {
38
+ maxProperties: 10,
39
+ type: "object"
40
+ }
41
+ },
42
+ type: "object"
43
+ });
44
+ });
45
+ it("should declare max value on class", () => {
46
+ // WHEN
47
+ @MaxProperties(10)
48
+ class Model {}
49
+
50
+ // THEN
51
+ expect(getJsonSchema(Model)).toEqual({
52
+ maxProperties: 10,
53
+ type: "object"
54
+ });
55
+ });
56
+ it("should declare max value on param", () => {
57
+ // WHEN
58
+ class MyController {
59
+ @OperationPath("POST", "/")
60
+ method(@In("body") @MaxProperties(10) test: any) {}
61
+ }
62
+
63
+ // THEN
64
+ expect(getSpec(MyController, {specType: SpecTypes.OPENAPI})).toEqual({
65
+ paths: {
66
+ "/": {
67
+ post: {
68
+ operationId: "myControllerMethod",
69
+ parameters: [],
70
+ requestBody: {
71
+ content: {
72
+ "application/json": {
73
+ schema: {
74
+ maxProperties: 10,
75
+ type: "object"
76
+ }
77
+ }
78
+ },
79
+ required: false
80
+ },
81
+ responses: {
82
+ "200": {
83
+ description: "Success"
84
+ }
85
+ },
86
+ tags: ["MyController"]
87
+ }
88
+ }
89
+ },
90
+ tags: [
91
+ {
92
+ name: "MyController"
93
+ }
94
+ ]
95
+ });
96
+ });
97
+ it("should throw an error when the given parameters is as negative integer", () => {
98
+ // WHEN
99
+ let actualError: any;
100
+ try {
101
+ MaxProperties(-1);
102
+ } catch (er) {
103
+ actualError = er;
104
+ }
105
+
106
+ // THEN
107
+ expect(actualError.message).toBe("The value of maxProperties MUST be a non-negative integer.");
108
+ });
109
+ });