@tsed/schema 8.0.0 → 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,17 @@
1
+ import {JsonEntityStore} from "../../domain/JsonEntityStore.js";
2
+ import {JsonEntityFn} from "./jsonEntityFn.js";
3
+ /**
4
+ * Set the property as readOnly.
5
+ *
6
+ * @returns {Function}
7
+ * @decorator
8
+ * @validation
9
+ * @property
10
+ * @parameter
11
+ * @schema
12
+ */
13
+ export function ReadOnly(readOnly: boolean = true) {
14
+ return JsonEntityFn((store: JsonEntityStore) => {
15
+ store.itemSchema.readOnly(readOnly);
16
+ });
17
+ }
@@ -0,0 +1,41 @@
1
+ import {getJsonSchema} from "../../index.js";
2
+ import {RecordOf} from "./recordOf.js";
3
+
4
+ describe("RecordOf()", () => {
5
+ it("should store data", () => {
6
+ type keys = "one" | "two";
7
+
8
+ class Part {
9
+ prop: string;
10
+ }
11
+
12
+ type Parts = Record<keys, Part>;
13
+
14
+ class Test {
15
+ @RecordOf(Part, "one", "two")
16
+ parts: Parts;
17
+ }
18
+
19
+ expect(getJsonSchema(Test)).toEqual({
20
+ definitions: {
21
+ Part: {
22
+ type: "object"
23
+ }
24
+ },
25
+ type: "object",
26
+ properties: {
27
+ parts: {
28
+ properties: {
29
+ one: {
30
+ $ref: "#/definitions/Part"
31
+ },
32
+ two: {
33
+ $ref: "#/definitions/Part"
34
+ }
35
+ },
36
+ type: "object"
37
+ }
38
+ }
39
+ });
40
+ });
41
+ });
@@ -0,0 +1,59 @@
1
+ import {Schema} from "./schema.js";
2
+
3
+ /**
4
+ * Constructs a json schema object type whose property keys are keys and whose property values are type.
5
+ *
6
+ * ## Example
7
+ *
8
+ * ```typescript
9
+ * type keys = 'one' | 'two';
10
+ *
11
+ * class Part {
12
+ * prop: string;
13
+ * }
14
+ *
15
+ * type Parts = Record<keys, Part>;
16
+ *
17
+ * class Test {
18
+ * @RecordOf(Part, 'one', 'two')
19
+ * parts: Parts;
20
+ * }
21
+ * ```
22
+ *
23
+ * Will produce:
24
+ *
25
+ * ```json
26
+ * {
27
+ * "type": "object",
28
+ * "properties": {
29
+ * "one": {
30
+ * "$ref": "#/components/schemas/Part"
31
+ * },
32
+ * "two": {
33
+ * "$ref": "#/components/schemas/Part"
34
+ * },
35
+ * },
36
+ * }
37
+ * ```
38
+ *
39
+ * @param model
40
+ * @param keys
41
+ * @decorator
42
+ * @validation
43
+ * @swagger
44
+ * @schema
45
+ * @classDecorator
46
+ * @input
47
+ */
48
+ export function RecordOf(model: any, ...keys: string[]) {
49
+ return Schema({
50
+ properties: {
51
+ ...keys.reduce((initial, key) => {
52
+ return {
53
+ ...initial,
54
+ [key]: model
55
+ };
56
+ }, {})
57
+ }
58
+ });
59
+ }
@@ -0,0 +1,188 @@
1
+ import {Ajv} from "ajv";
2
+
3
+ import {validateModel} from "../../../test/helpers/validateModel.js";
4
+ import {JsonEntityStore} from "../../domain/JsonEntityStore.js";
5
+ import {getJsonSchema, MinLength} from "../../index.js";
6
+ import {Property} from "../common/property.js";
7
+ import {Required} from "./required.js";
8
+
9
+ describe("@Required", () => {
10
+ it("should declare required field", () => {
11
+ // WHEN
12
+ class Model {
13
+ @Required()
14
+ num: number;
15
+ }
16
+
17
+ // THEN
18
+ const classSchema = JsonEntityStore.from(Model);
19
+
20
+ expect(classSchema.schema.toJSON()).toEqual({
21
+ properties: {
22
+ num: {
23
+ type: "number"
24
+ }
25
+ },
26
+ required: ["num"],
27
+ type: "object"
28
+ });
29
+ });
30
+ it("should declare required field (false)", () => {
31
+ // WHEN
32
+ class Model {
33
+ @Required(false)
34
+ num: number;
35
+ }
36
+
37
+ // THEN
38
+ const classSchema = JsonEntityStore.from(Model);
39
+
40
+ expect(classSchema.schema.toJSON()).toEqual({
41
+ properties: {
42
+ num: {
43
+ type: "number"
44
+ }
45
+ },
46
+ type: "object"
47
+ });
48
+ });
49
+ it("should declare required field on string property", () => {
50
+ // WHEN
51
+ class Model {
52
+ @Required()
53
+ prop: string;
54
+ }
55
+
56
+ // THEN
57
+ const classSchema = JsonEntityStore.from(Model);
58
+
59
+ expect(classSchema.schema.toJSON()).toEqual({
60
+ properties: {
61
+ prop: {
62
+ minLength: 1,
63
+ type: "string"
64
+ }
65
+ },
66
+ required: ["prop"],
67
+ type: "object"
68
+ });
69
+ });
70
+ it("should declare required field on string property (minLength 3)", () => {
71
+ // WHEN
72
+ class Model {
73
+ @Required()
74
+ @MinLength(3)
75
+ prop: string;
76
+ }
77
+
78
+ // THEN
79
+ const classSchema = JsonEntityStore.from(Model);
80
+
81
+ expect(classSchema.schema.toJSON()).toEqual({
82
+ properties: {
83
+ prop: {
84
+ minLength: 3,
85
+ type: "string"
86
+ }
87
+ },
88
+ required: ["prop"],
89
+ type: "object"
90
+ });
91
+ });
92
+ it("should declare required field with a model an null", () => {
93
+ // WHEN
94
+ class NestedModel {
95
+ @Property()
96
+ prop: string;
97
+ }
98
+
99
+ class Model {
100
+ @Required(true, null, NestedModel)
101
+ allow: NestedModel | null;
102
+ }
103
+
104
+ // THEN
105
+ const spec = getJsonSchema(Model);
106
+
107
+ expect(spec).toEqual({
108
+ definitions: {
109
+ NestedModel: {
110
+ properties: {
111
+ prop: {
112
+ type: "string"
113
+ }
114
+ },
115
+ type: "object"
116
+ }
117
+ },
118
+ properties: {
119
+ allow: {
120
+ anyOf: [
121
+ {
122
+ type: "null"
123
+ },
124
+ {
125
+ $ref: "#/definitions/NestedModel"
126
+ }
127
+ ]
128
+ }
129
+ },
130
+ required: ["allow"],
131
+ type: "object"
132
+ });
133
+
134
+ const validate = new Ajv().compile(spec);
135
+ expect(validate({allow: null})).toBe(true);
136
+ expect(validate({})).toBe(false);
137
+ });
138
+ it("should declare required field with custom error message", () => {
139
+ // WHEN
140
+ class Model {
141
+ @(Required().Error("custom message"))
142
+ num: number;
143
+ }
144
+
145
+ // THEN
146
+ const schema = getJsonSchema(Model, {customKeys: true});
147
+
148
+ expect(schema).toEqual({
149
+ errorMessage: {
150
+ required: {
151
+ num: "custom message"
152
+ }
153
+ },
154
+ properties: {
155
+ num: {
156
+ type: "number"
157
+ }
158
+ },
159
+ required: ["num"],
160
+ type: "object"
161
+ });
162
+
163
+ const result = validateModel({}, Model);
164
+
165
+ expect(result).toEqual([
166
+ {
167
+ instancePath: "",
168
+ keyword: "errorMessage",
169
+ message: "custom message",
170
+ params: {
171
+ errors: [
172
+ {
173
+ emUsed: true,
174
+ instancePath: "",
175
+ keyword: "required",
176
+ message: "must have required property 'num'",
177
+ params: {
178
+ missingProperty: "num"
179
+ },
180
+ schemaPath: "#/required"
181
+ }
182
+ ]
183
+ },
184
+ schemaPath: "#/errorMessage"
185
+ }
186
+ ]);
187
+ });
188
+ });
@@ -0,0 +1,50 @@
1
+ import {withErrorMsg} from "../../utils/withErrorMsg.js";
2
+ import {Allow} from "./allow.js";
3
+ import {Optional} from "./optional.js";
4
+
5
+ /**
6
+ * Add required annotation on Property or Parameter.
7
+ *
8
+ * The @@Required@@ decorator can be used on two cases.
9
+ *
10
+ * To decorate a parameters:
11
+ *
12
+ * ```typescript
13
+ * @Post("/")
14
+ * async method(@Required() @BodyParams("field") field: string) {}
15
+ * ```
16
+ *
17
+ * To decorate a model:
18
+ *
19
+ * ```typescript
20
+ * class Model {
21
+ * @Required()
22
+ * field: string;
23
+ * }
24
+ * ```
25
+ *
26
+ * ::: tip
27
+ * Required will throw a BadRequest when the given value is `null`, an empty string or `undefined`.
28
+ * :::
29
+ *
30
+ * ### Allow values
31
+ *
32
+ * In some case, you didn't want trigger a BadRequest when the value is an empty string for example.
33
+ * The decorator `@Allow()`, allow you to configure a value list for which there will be no exception.
34
+ *
35
+ * ```typescript
36
+ * class Model {
37
+ * @Allow("") // add automatically required flag
38
+ * field: string;
39
+ * }
40
+ * ```
41
+ *
42
+ * @decorator
43
+ * @validation
44
+ * @swagger
45
+ * @schema
46
+ * @input
47
+ */
48
+ export const Required = withErrorMsg("required", (required: boolean = true, ...allowedRequiredValues: any[]) => {
49
+ return required ? Allow(...allowedRequiredValues) : Optional();
50
+ });
@@ -0,0 +1,127 @@
1
+ import {getJsonSchema, Required} from "../../index.js";
2
+ import {Groups} from "./groups.js";
3
+ import {RequiredGroups} from "./requiredGroups.js";
4
+
5
+ class MyModel {
6
+ @Groups("!creation")
7
+ id: string;
8
+
9
+ @Required()
10
+ prop1: string;
11
+
12
+ @RequiredGroups("!patch")
13
+ @Required()
14
+ prop2: string;
15
+
16
+ @RequiredGroups("patch")
17
+ @Required()
18
+ prop3: string;
19
+ }
20
+
21
+ describe("@RequiredGroups", () => {
22
+ it("should have required fields filtered by groups (groups: false)", () => {
23
+ const spec = getJsonSchema(MyModel, {
24
+ groups: false
25
+ });
26
+
27
+ expect(spec).toEqual({
28
+ properties: {
29
+ id: {
30
+ type: "string"
31
+ },
32
+ prop1: {
33
+ minLength: 1,
34
+ type: "string"
35
+ },
36
+ prop2: {
37
+ minLength: 1,
38
+ type: "string"
39
+ },
40
+ prop3: {
41
+ minLength: 1,
42
+ type: "string"
43
+ }
44
+ },
45
+ required: ["prop1", "prop2", "prop3"],
46
+ type: "object"
47
+ });
48
+ });
49
+ it("should have required fields filtered by groups (groups: [])", () => {
50
+ const spec = getJsonSchema(MyModel, {
51
+ groups: []
52
+ });
53
+
54
+ expect(spec).toEqual({
55
+ properties: {
56
+ id: {
57
+ type: "string"
58
+ },
59
+ prop1: {
60
+ minLength: 1,
61
+ type: "string"
62
+ },
63
+ prop2: {
64
+ minLength: 1,
65
+ type: "string"
66
+ },
67
+ prop3: {
68
+ minLength: 1,
69
+ type: "string"
70
+ }
71
+ },
72
+ required: ["prop1", "prop2"],
73
+ type: "object"
74
+ });
75
+ });
76
+ it("should have required fields filtered by groups (groups: ['patch'])", () => {
77
+ const spec = getJsonSchema(MyModel, {
78
+ groups: ["patch"]
79
+ });
80
+
81
+ expect(spec).toEqual({
82
+ properties: {
83
+ id: {
84
+ type: "string"
85
+ },
86
+ prop1: {
87
+ minLength: 1,
88
+ type: "string"
89
+ },
90
+ prop2: {
91
+ minLength: 1,
92
+ type: "string"
93
+ },
94
+ prop3: {
95
+ minLength: 1,
96
+ type: "string"
97
+ }
98
+ },
99
+ required: ["prop1", "prop3"],
100
+ type: "object"
101
+ });
102
+ });
103
+ it("should have required fields filtered by groups (groups: ['!patch'])", () => {
104
+ const spec = getJsonSchema(MyModel, {
105
+ groups: ["!patch"]
106
+ });
107
+
108
+ expect(spec).toEqual({
109
+ properties: {
110
+ prop1: {
111
+ minLength: 1,
112
+ type: "string"
113
+ },
114
+ prop2: {
115
+ minLength: 1,
116
+ type: "string"
117
+ },
118
+ prop3: {
119
+ minLength: 1,
120
+ type: "string"
121
+ }
122
+ },
123
+ required: ["prop1", "prop2"],
124
+ type: "object"
125
+ });
126
+ });
127
+ });
@@ -0,0 +1,23 @@
1
+ import {matchGroups} from "../../utils/matchGroups.js";
2
+ import {JsonEntityFn} from "./jsonEntityFn.js";
3
+
4
+ /**
5
+ * Apply groups validation strategy for required property.
6
+ *
7
+ * @decorator
8
+ * @validation
9
+ * @swagger
10
+ * @schema
11
+ * @input
12
+ */
13
+ export function RequiredGroups(...groups: string[]): PropertyDecorator {
14
+ return JsonEntityFn((entity) => {
15
+ entity.parent.schema.$hooks.on("requiredGroups", (required: string[], givenGroups: string[]) => {
16
+ if (matchGroups(groups, givenGroups)) {
17
+ return required.filter((key: string) => key !== entity.propertyKey);
18
+ }
19
+
20
+ return required;
21
+ });
22
+ });
23
+ }
@@ -0,0 +1,23 @@
1
+ import {getJsonSchema} from "../../index.js";
2
+ import {Schema} from "./schema.js";
3
+
4
+ describe("Schema()", () => {
5
+ it("should store data", () => {
6
+ class Test {
7
+ @Schema({
8
+ pattern: "a|b"
9
+ })
10
+ test: string;
11
+ }
12
+
13
+ expect(getJsonSchema(Test)).toEqual({
14
+ properties: {
15
+ test: {
16
+ pattern: "a|b",
17
+ type: "string"
18
+ }
19
+ },
20
+ type: "object"
21
+ });
22
+ });
23
+ });
@@ -0,0 +1,64 @@
1
+ import {JsonSchema, JsonSchemaObject} from "../../domain/JsonSchema.js";
2
+ import {SpecTypes} from "../../domain/SpecTypes.js";
3
+ import {JsonEntityFn} from "./jsonEntityFn.js";
4
+
5
+ /**
6
+ * Write data formatted to JsonSchema.
7
+ *
8
+ * ## Example
9
+ *
10
+ * ```typescript
11
+ * @Schema({title: "test"})
12
+ * class Model {
13
+ * @Schema({formatMinimum: "1987-10-24"})
14
+ * @Format("date")
15
+ * birthDate: Date
16
+ * }
17
+ * ```
18
+ *
19
+ * Will produce:
20
+ *
21
+ * ```json
22
+ * {
23
+ * "type": "object",
24
+ * "title": "test",
25
+ * "properties": {
26
+ * "birthdate": {
27
+ * "type": "string",
28
+ * "format": "date",
29
+ * "formatMinimum": "1987-10-24"
30
+ * }
31
+ * }
32
+ * }
33
+ * ```
34
+ *
35
+ * @param partialSchema
36
+ * @decorator
37
+ * @validation
38
+ * @swagger
39
+ * @schema
40
+ * @classDecorator
41
+ * @input
42
+ */
43
+ export function Schema(partialSchema: Partial<JsonSchemaObject> | JsonSchema) {
44
+ return JsonEntityFn((entity) => {
45
+ entity.schema.assign(partialSchema);
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Apply specific schema depending on the spec version
51
+ * @param specType
52
+ * @param schema
53
+ * @decorator
54
+ * @validation
55
+ * @swagger
56
+ * @schema
57
+ * @classDecorator
58
+ * @input
59
+ */
60
+ export function For(specType: SpecTypes, schema: any) {
61
+ return JsonEntityFn((entity) => {
62
+ entity.schema.set(specType, schema);
63
+ });
64
+ }
@@ -0,0 +1,20 @@
1
+ import {getJsonSchema, Title} from "../../index.js";
2
+
3
+ describe("Title()", () => {
4
+ it("should store data", () => {
5
+ class Test {
6
+ @Title("Title")
7
+ test: string;
8
+ }
9
+
10
+ expect(getJsonSchema(Test)).toEqual({
11
+ properties: {
12
+ test: {
13
+ title: "Title",
14
+ type: "string"
15
+ }
16
+ },
17
+ type: "object"
18
+ });
19
+ });
20
+ });
@@ -0,0 +1,45 @@
1
+ import {JsonEntityFn} from "./jsonEntityFn.js";
2
+
3
+ /**
4
+ * Add title metadata on the decorated element.
5
+ *
6
+ * ::: warning
7
+ * For v6 user, use @@Title@@ from @tsed/schema instead of @tsed/platform-http.
8
+ * :::
9
+ *
10
+ * ## Example
11
+ *
12
+ * ```typescript
13
+ * class Model {
14
+ * @Title("title")
15
+ * id: string;
16
+ * }
17
+ * ```
18
+ *
19
+ * Will produce:
20
+ *
21
+ * ```json
22
+ * {
23
+ * "type": "object",
24
+ * "properties": {
25
+ * "id": {
26
+ * "type": "string",
27
+ * "title": "title"
28
+ * }
29
+ * }
30
+ * }
31
+ * ```
32
+ *
33
+ * @param {string} title
34
+ * @decorator
35
+ * @validation
36
+ * @swagger
37
+ * @schema
38
+ * @classDecorator
39
+ * @input
40
+ */
41
+ export function Title(title: string) {
42
+ return JsonEntityFn((entity) => {
43
+ entity.schema.title(title);
44
+ });
45
+ }
@@ -0,0 +1,22 @@
1
+ import {getJsonSchema} from "../../utils/getJsonSchema.js";
2
+ import {TypeError} from "./typeError.js";
3
+
4
+ describe("@TypeError", () => {
5
+ it("should declare type error message", () => {
6
+ // WHEN
7
+ @TypeError("foo should be a string")
8
+ class Model {
9
+ property: number;
10
+ }
11
+
12
+ // THEN
13
+ const schema = getJsonSchema(Model, {customKeys: true});
14
+
15
+ expect(schema).toEqual({
16
+ type: "object",
17
+ errorMessage: {
18
+ type: "foo should be a string"
19
+ }
20
+ });
21
+ });
22
+ });
@@ -0,0 +1,15 @@
1
+ import {useDecorators} from "@tsed/core";
2
+
3
+ import {ErrorMsg} from "./errorMsg.js";
4
+ import {JsonEntityFn} from "./jsonEntityFn.js";
5
+
6
+ /**
7
+ * Create a new custom formats validator
8
+ * @param name
9
+ * @param options
10
+ * @decorator
11
+ * @ajv
12
+ */
13
+ export function TypeError(msg: string): ClassDecorator {
14
+ return JsonEntityFn(() => useDecorators(ErrorMsg({type: msg})));
15
+ }