moonflower 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/.eslintrc.js +26 -0
  2. package/.prettierrc.js +7 -0
  3. package/README.md +383 -0
  4. package/cli/cli.ts +59 -0
  5. package/cli/entry.cjs +3 -0
  6. package/cli/prettyprint.ts +16 -0
  7. package/dist/cli/cli.d.ts +2 -0
  8. package/dist/cli/cli.d.ts.map +1 -0
  9. package/dist/cli/cli.js +79 -0
  10. package/dist/cli/prettyprint.d.ts +4 -0
  11. package/dist/cli/prettyprint.d.ts.map +1 -0
  12. package/dist/cli/prettyprint.js +18 -0
  13. package/dist/src/errors/BaseHttpError.d.ts +13 -0
  14. package/dist/src/errors/BaseHttpError.d.ts.map +1 -0
  15. package/dist/src/errors/BaseHttpError.js +13 -0
  16. package/dist/src/errors/HttpErrorHandler.d.ts +3 -0
  17. package/dist/src/errors/HttpErrorHandler.d.ts.map +1 -0
  18. package/dist/src/errors/HttpErrorHandler.js +23 -0
  19. package/dist/src/errors/UserFacingErrors.d.ts +11 -0
  20. package/dist/src/errors/UserFacingErrors.d.ts.map +1 -0
  21. package/dist/src/errors/UserFacingErrors.js +23 -0
  22. package/dist/src/hooks/authentication/useAuth.d.ts +3 -0
  23. package/dist/src/hooks/authentication/useAuth.d.ts.map +1 -0
  24. package/dist/src/hooks/authentication/useAuth.js +7 -0
  25. package/dist/src/hooks/authentication/useOptionalAuth.d.ts +3 -0
  26. package/dist/src/hooks/authentication/useOptionalAuth.d.ts.map +1 -0
  27. package/dist/src/hooks/authentication/useOptionalAuth.js +16 -0
  28. package/dist/src/hooks/useApiEndpoint.d.ts +8 -0
  29. package/dist/src/hooks/useApiEndpoint.d.ts.map +1 -0
  30. package/dist/src/hooks/useApiEndpoint.js +7 -0
  31. package/dist/src/hooks/useApiHeader/index.d.ts +2 -0
  32. package/dist/src/hooks/useApiHeader/index.d.ts.map +1 -0
  33. package/dist/src/hooks/useApiHeader/index.js +17 -0
  34. package/dist/src/hooks/useApiHeader/useApiHeader.d.ts +3 -0
  35. package/dist/src/hooks/useApiHeader/useApiHeader.d.ts.map +1 -0
  36. package/dist/src/hooks/useApiHeader/useApiHeader.js +6 -0
  37. package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.d.ts +2 -0
  38. package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.d.ts.map +1 -0
  39. package/dist/src/hooks/useApiHeader/useApiHeader.spec.data.js +22 -0
  40. package/dist/src/hooks/useCookieParams.d.ts +9 -0
  41. package/dist/src/hooks/useCookieParams.d.ts.map +1 -0
  42. package/dist/src/hooks/useCookieParams.js +50 -0
  43. package/dist/src/hooks/useExposeApiModel/index.d.ts +2 -0
  44. package/dist/src/hooks/useExposeApiModel/index.d.ts.map +1 -0
  45. package/dist/src/hooks/useExposeApiModel/index.js +17 -0
  46. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.d.ts +3 -0
  47. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.d.ts.map +1 -0
  48. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.js +9 -0
  49. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.d.ts +2 -0
  50. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.d.ts.map +1 -0
  51. package/dist/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.js +16 -0
  52. package/dist/src/hooks/useHeaderParams.d.ts +12 -0
  53. package/dist/src/hooks/useHeaderParams.d.ts.map +1 -0
  54. package/dist/src/hooks/useHeaderParams.js +52 -0
  55. package/dist/src/hooks/usePathParams.d.ts +22 -0
  56. package/dist/src/hooks/usePathParams.d.ts.map +1 -0
  57. package/dist/src/hooks/usePathParams.js +46 -0
  58. package/dist/src/hooks/useQueryParams.d.ts +9 -0
  59. package/dist/src/hooks/useQueryParams.d.ts.map +1 -0
  60. package/dist/src/hooks/useQueryParams.js +50 -0
  61. package/dist/src/hooks/useRequestBody.d.ts +9 -0
  62. package/dist/src/hooks/useRequestBody.d.ts.map +1 -0
  63. package/dist/src/hooks/useRequestBody.js +59 -0
  64. package/dist/src/hooks/useRequestRawBody.d.ts +7 -0
  65. package/dist/src/hooks/useRequestRawBody.d.ts.map +1 -0
  66. package/dist/src/hooks/useRequestRawBody.js +34 -0
  67. package/dist/src/index.d.ts +18 -0
  68. package/dist/src/index.d.ts.map +1 -0
  69. package/dist/src/index.js +33 -0
  70. package/dist/src/openapi/analyzerModule/analyzerModule.d.ts +18 -0
  71. package/dist/src/openapi/analyzerModule/analyzerModule.d.ts.map +1 -0
  72. package/dist/src/openapi/analyzerModule/analyzerModule.js +192 -0
  73. package/dist/src/openapi/analyzerModule/nodeParsers.d.ts +19 -0
  74. package/dist/src/openapi/analyzerModule/nodeParsers.d.ts.map +1 -0
  75. package/dist/src/openapi/analyzerModule/nodeParsers.js +521 -0
  76. package/dist/src/openapi/analyzerModule/parseEndpoint.d.ts +4 -0
  77. package/dist/src/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -0
  78. package/dist/src/openapi/analyzerModule/parseEndpoint.js +246 -0
  79. package/dist/src/openapi/analyzerModule/parseExposedModels.d.ts +5 -0
  80. package/dist/src/openapi/analyzerModule/parseExposedModels.d.ts.map +1 -0
  81. package/dist/src/openapi/analyzerModule/parseExposedModels.js +32 -0
  82. package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.d.ts +2 -0
  83. package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.d.ts.map +1 -0
  84. package/dist/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.js +400 -0
  85. package/dist/src/openapi/analyzerModule/types.d.ts +53 -0
  86. package/dist/src/openapi/analyzerModule/types.d.ts.map +1 -0
  87. package/dist/src/openapi/analyzerModule/types.js +2 -0
  88. package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.d.ts +8 -0
  89. package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.d.ts.map +1 -0
  90. package/dist/src/openapi/discoveryModule/discoverImports/discoverImports.js +33 -0
  91. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.d.ts +4 -0
  92. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.d.ts.map +1 -0
  93. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.js +8 -0
  94. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.d.ts +4 -0
  95. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.d.ts.map +1 -0
  96. package/dist/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.js +8 -0
  97. package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.d.ts +17 -0
  98. package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.d.ts.map +1 -0
  99. package/dist/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.js +80 -0
  100. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.d.ts +6 -0
  101. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.d.ts.map +1 -0
  102. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.js +31 -0
  103. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.d.ts +5 -0
  104. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.d.ts.map +1 -0
  105. package/dist/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.js +38 -0
  106. package/dist/src/openapi/discoveryModule/index.d.ts +3 -0
  107. package/dist/src/openapi/discoveryModule/index.d.ts.map +1 -0
  108. package/dist/src/openapi/discoveryModule/index.js +18 -0
  109. package/dist/src/openapi/generatorModule/generateComponentSchemas.d.ts +4 -0
  110. package/dist/src/openapi/generatorModule/generateComponentSchemas.d.ts.map +1 -0
  111. package/dist/src/openapi/generatorModule/generateComponentSchemas.js +12 -0
  112. package/dist/src/openapi/generatorModule/generatePaths.d.ts +10 -0
  113. package/dist/src/openapi/generatorModule/generatePaths.d.ts.map +1 -0
  114. package/dist/src/openapi/generatorModule/generatePaths.js +116 -0
  115. package/dist/src/openapi/generatorModule/generatorModule.d.ts +16 -0
  116. package/dist/src/openapi/generatorModule/generatorModule.d.ts.map +1 -0
  117. package/dist/src/openapi/generatorModule/generatorModule.js +18 -0
  118. package/dist/src/openapi/generatorModule/getSchema.d.ts +36 -0
  119. package/dist/src/openapi/generatorModule/getSchema.d.ts.map +1 -0
  120. package/dist/src/openapi/generatorModule/getSchema.js +133 -0
  121. package/dist/src/openapi/generatorModule/index.d.ts +5 -0
  122. package/dist/src/openapi/generatorModule/index.d.ts.map +1 -0
  123. package/dist/src/openapi/generatorModule/index.js +20 -0
  124. package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.d.ts +515 -0
  125. package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.d.ts.map +1 -0
  126. package/dist/src/openapi/generatorModule/test/openApiGenerator.spec.data.js +1119 -0
  127. package/dist/src/openapi/initOpenApiEngine.d.ts +4 -0
  128. package/dist/src/openapi/initOpenApiEngine.d.ts.map +1 -0
  129. package/dist/src/openapi/initOpenApiEngine.js +14 -0
  130. package/dist/src/openapi/manager/OpenApiManager.d.ts +67 -0
  131. package/dist/src/openapi/manager/OpenApiManager.d.ts.map +1 -0
  132. package/dist/src/openapi/manager/OpenApiManager.js +86 -0
  133. package/dist/src/openapi/router/OpenApiRouter.d.ts +4 -0
  134. package/dist/src/openapi/router/OpenApiRouter.d.ts.map +1 -0
  135. package/dist/src/openapi/router/OpenApiRouter.js +11 -0
  136. package/dist/src/openapi/types.d.ts +81 -0
  137. package/dist/src/openapi/types.d.ts.map +1 -0
  138. package/dist/src/openapi/types.js +2 -0
  139. package/dist/src/router/Router.d.ts +23 -0
  140. package/dist/src/router/Router.d.ts.map +1 -0
  141. package/dist/src/router/Router.js +81 -0
  142. package/dist/src/router/responseValueToJson.d.ts +2 -0
  143. package/dist/src/router/responseValueToJson.d.ts.map +1 -0
  144. package/dist/src/router/responseValueToJson.js +10 -0
  145. package/dist/src/setupTests.d.ts +1 -0
  146. package/dist/src/setupTests.d.ts.map +1 -0
  147. package/dist/src/setupTests.js +3 -0
  148. package/dist/src/test/TestAppRouter.d.ts +8 -0
  149. package/dist/src/test/TestAppRouter.d.ts.map +1 -0
  150. package/dist/src/test/TestAppRouter.js +58 -0
  151. package/dist/src/test/app.d.ts +3 -0
  152. package/dist/src/test/app.d.ts.map +1 -0
  153. package/dist/src/test/app.js +41 -0
  154. package/dist/src/utils/TypeUtils.d.ts +22 -0
  155. package/dist/src/utils/TypeUtils.d.ts.map +1 -0
  156. package/dist/src/utils/TypeUtils.js +2 -0
  157. package/dist/src/utils/fromZodSchema.d.ts +2 -0
  158. package/dist/src/utils/fromZodSchema.d.ts.map +1 -0
  159. package/dist/src/utils/fromZodSchema.js +6 -0
  160. package/dist/src/utils/loadTestData.d.ts +2 -0
  161. package/dist/src/utils/loadTestData.d.ts.map +1 -0
  162. package/dist/src/utils/loadTestData.js +39 -0
  163. package/dist/src/utils/mockContext.d.ts +20 -0
  164. package/dist/src/utils/mockContext.d.ts.map +1 -0
  165. package/dist/src/utils/mockContext.js +85 -0
  166. package/dist/src/utils/nameOf.d.ts +5 -0
  167. package/dist/src/utils/nameOf.d.ts.map +1 -0
  168. package/dist/src/utils/nameOf.js +7 -0
  169. package/dist/src/utils/object.d.ts +7 -0
  170. package/dist/src/utils/object.d.ts.map +1 -0
  171. package/dist/src/utils/object.js +21 -0
  172. package/dist/src/utils/printers.d.ts +6 -0
  173. package/dist/src/utils/printers.d.ts.map +1 -0
  174. package/dist/src/utils/printers.js +76 -0
  175. package/dist/src/utils/validationMessages.d.ts +18 -0
  176. package/dist/src/utils/validationMessages.d.ts.map +1 -0
  177. package/dist/src/utils/validationMessages.js +43 -0
  178. package/dist/src/validators/BuiltInValidators.d.ts +61 -0
  179. package/dist/src/validators/BuiltInValidators.d.ts.map +1 -0
  180. package/dist/src/validators/BuiltInValidators.js +66 -0
  181. package/dist/src/validators/InternalParamWrappers.d.ts +5 -0
  182. package/dist/src/validators/InternalParamWrappers.d.ts.map +1 -0
  183. package/dist/src/validators/InternalParamWrappers.js +5 -0
  184. package/dist/src/validators/ParamWrappers.d.ts +11 -0
  185. package/dist/src/validators/ParamWrappers.d.ts.map +1 -0
  186. package/dist/src/validators/ParamWrappers.js +9 -0
  187. package/dist/src/validators/types.d.ts +18 -0
  188. package/dist/src/validators/types.d.ts.map +1 -0
  189. package/dist/src/validators/types.js +2 -0
  190. package/dist/tsconfig.build.tsbuildinfo +1 -0
  191. package/package.json +59 -0
  192. package/src/errors/BaseHttpError.ts +16 -0
  193. package/src/errors/HttpErrorHandler.ts +20 -0
  194. package/src/errors/UserFacingErrors.ts +39 -0
  195. package/src/hooks/authentication/useAuth.ts +8 -0
  196. package/src/hooks/authentication/useOptionalAuth.ts +17 -0
  197. package/src/hooks/useApiEndpoint.spec.ts +11 -0
  198. package/src/hooks/useApiEndpoint.ts +10 -0
  199. package/src/hooks/useApiHeader/index.ts +1 -0
  200. package/src/hooks/useApiHeader/useApiHeader.spec.data.ts +22 -0
  201. package/src/hooks/useApiHeader/useApiHeader.spec.ts +34 -0
  202. package/src/hooks/useApiHeader/useApiHeader.ts +6 -0
  203. package/src/hooks/useCookieParams.spec.ts +174 -0
  204. package/src/hooks/useCookieParams.ts +73 -0
  205. package/src/hooks/useExposeApiModel/index.ts +1 -0
  206. package/src/hooks/useExposeApiModel/useExposeApiModel.spec.data.ts +48 -0
  207. package/src/hooks/useExposeApiModel/useExposeApiModel.spec.ts +388 -0
  208. package/src/hooks/useExposeApiModel/useExposeApiModel.ts +9 -0
  209. package/src/hooks/useHeaderParams.spec.ts +186 -0
  210. package/src/hooks/useHeaderParams.ts +83 -0
  211. package/src/hooks/usePathParams.spec.ts +161 -0
  212. package/src/hooks/usePathParams.ts +89 -0
  213. package/src/hooks/useQueryParams.spec.ts +224 -0
  214. package/src/hooks/useQueryParams.ts +73 -0
  215. package/src/hooks/useRequestBody.spec.ts +215 -0
  216. package/src/hooks/useRequestBody.ts +94 -0
  217. package/src/hooks/useRequestRawBody.spec.ts +154 -0
  218. package/src/hooks/useRequestRawBody.ts +56 -0
  219. package/src/index.ts +17 -0
  220. package/src/openapi/analyzerModule/analyzerModule.ts +228 -0
  221. package/src/openapi/analyzerModule/nodeParsers.ts +648 -0
  222. package/src/openapi/analyzerModule/parseEndpoint.ts +305 -0
  223. package/src/openapi/analyzerModule/parseExposedModels.ts +34 -0
  224. package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.ts +521 -0
  225. package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.ts +1043 -0
  226. package/src/openapi/analyzerModule/types.ts +72 -0
  227. package/src/openapi/discoveryModule/discoverImports/discoverImports.ts +43 -0
  228. package/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterA.spec.data.ts +7 -0
  229. package/src/openapi/discoveryModule/discoverRouterFiles/data/testRouterB.spec.data.ts +7 -0
  230. package/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.spec.ts +36 -0
  231. package/src/openapi/discoveryModule/discoverRouterFiles/discoverRouterFiles.ts +80 -0
  232. package/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.data.ts +42 -0
  233. package/src/openapi/discoveryModule/discoverRouters/discoverRouters.spec.ts +18 -0
  234. package/src/openapi/discoveryModule/discoverRouters/discoverRouters.ts +39 -0
  235. package/src/openapi/discoveryModule/index.ts +2 -0
  236. package/src/openapi/generatorModule/generateComponentSchemas.ts +12 -0
  237. package/src/openapi/generatorModule/generatePaths.ts +138 -0
  238. package/src/openapi/generatorModule/generatorModule.ts +17 -0
  239. package/src/openapi/generatorModule/getSchema.ts +169 -0
  240. package/src/openapi/generatorModule/index.ts +4 -0
  241. package/src/openapi/generatorModule/test/openApiGenerator.spec.data.ts +1119 -0
  242. package/src/openapi/generatorModule/test/openApiGenerator.spec.ts +783 -0
  243. package/src/openapi/initOpenApiEngine.ts +20 -0
  244. package/src/openapi/manager/OpenApiManager.ts +153 -0
  245. package/src/openapi/router/OpenApiRouter.ts +11 -0
  246. package/src/openapi/types.ts +86 -0
  247. package/src/router/Router.ts +123 -0
  248. package/src/router/responseValueToJson.ts +6 -0
  249. package/src/setupTests.ts +3 -0
  250. package/src/test/TestAppRouter.ts +76 -0
  251. package/src/test/app.spec.ts +130 -0
  252. package/src/test/app.ts +43 -0
  253. package/src/utils/TypeUtils.ts +51 -0
  254. package/src/utils/loadTestData.ts +15 -0
  255. package/src/utils/mockContext.ts +86 -0
  256. package/src/utils/nameOf.ts +7 -0
  257. package/src/utils/object.spec.ts +27 -0
  258. package/src/utils/object.ts +17 -0
  259. package/src/utils/printers.spec.ts +103 -0
  260. package/src/utils/printers.ts +49 -0
  261. package/src/utils/validationMessages.ts +65 -0
  262. package/src/validators/BuiltInValidators.ts +64 -0
  263. package/src/validators/InternalParamWrappers.ts +14 -0
  264. package/src/validators/ParamWrappers.ts +22 -0
  265. package/src/validators/types.ts +35 -0
  266. package/tsconfig.build.json +15 -0
  267. package/tsconfig.json +29 -0
  268. package/vite.config.ts +16 -0
@@ -0,0 +1,1043 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { Project, SyntaxKind } from 'ts-morph'
3
+
4
+ import { loadTestData } from '../../../utils/loadTestData'
5
+ import { StringValidator } from '../../../validators/BuiltInValidators'
6
+ import { discoverRouters } from '../../discoveryModule/discoverRouters/discoverRouters'
7
+ import { OpenApiManager } from '../../manager/OpenApiManager'
8
+ import { analyzeSourceFileEndpoints } from '../analyzerModule'
9
+ import { getValidatorPropertyShape, getValidatorPropertyStringValue } from '../nodeParsers'
10
+
11
+ describe('OpenApi Analyzer', () => {
12
+ describe('when analyzing a test data file', () => {
13
+ const dataFile = loadTestData('openApiAnalyzer.spec.data.ts')
14
+ let analysisResult: ReturnType<typeof analyzeSourceFileEndpoints>
15
+
16
+ const analyzeEndpointById = (id: string) => {
17
+ analysisResult = analyzeSourceFileEndpoints(
18
+ {
19
+ fileName: 'test',
20
+ sourceFile: dataFile,
21
+ routers: discoverRouters(dataFile),
22
+ },
23
+ [`/test/${id}`]
24
+ )
25
+ const endpoint = analysisResult.find((endpoint) => endpoint.path.startsWith(`/test/${id}`))
26
+ if (!endpoint) {
27
+ throw new Error(`No endpoint with id ${id} found!`)
28
+ }
29
+ return endpoint
30
+ }
31
+
32
+ const analyzeMultiEndpointById = (id: string) => {
33
+ analysisResult = analyzeSourceFileEndpoints(
34
+ {
35
+ fileName: 'test',
36
+ sourceFile: dataFile,
37
+ routers: discoverRouters(dataFile),
38
+ },
39
+ [`/test/${id}`]
40
+ )
41
+ const endpoints = analysisResult.filter((endpoint) => endpoint.path.startsWith(`/test/${id}`))
42
+ if (endpoints.length === 0) {
43
+ throw new Error(`No endpoint with id ${id} found!`)
44
+ }
45
+ return endpoints
46
+ }
47
+
48
+ describe('useApiEndpoint', () => {
49
+ it('parses useApiEndpoint values correctly', () => {
50
+ const endpoint = analyzeEndpointById('908c3e74-cf67-4ec7-a281-66a79f95d44d')
51
+
52
+ expect(endpoint.name).toEqual('Test endpoint name')
53
+ expect(endpoint.summary).toEqual('Test endpoint summary')
54
+ expect(endpoint.description).toEqual('Test endpoint description')
55
+ expect(endpoint.tags).toEqual(['one', 'two', 'three'])
56
+ })
57
+
58
+ it('parses aliased tags correctly', () => {
59
+ const endpoint = analyzeEndpointById('f2473a55-0ac6-46a0-b3c6-aae060dbe0ab')
60
+
61
+ expect(endpoint.tags).toEqual(['one', 'two'])
62
+ })
63
+
64
+ it('parses property access tags correctly', () => {
65
+ const endpoint = analyzeEndpointById('b504a196-d31d-40a4-a901-38a0f34f6ea7')
66
+
67
+ expect(endpoint.tags).toEqual(['one', 'two'])
68
+ })
69
+ })
70
+
71
+ describe('usePathParams', () => {
72
+ it('parses inline usePathParams validators correctly', () => {
73
+ const endpoint = analyzeEndpointById('bf6147f2-a1dc-4cc2-8327-e6f041f828bf')
74
+
75
+ expect(endpoint.requestPathParams[0].identifier).toEqual('firstParam')
76
+ expect(endpoint.requestPathParams[0].signature).toEqual('string')
77
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
78
+ expect(endpoint.requestPathParams[1].identifier).toEqual('secondParam')
79
+ expect(endpoint.requestPathParams[1].signature).toEqual('boolean')
80
+ expect(endpoint.requestPathParams[1].optional).toEqual(false)
81
+ expect(endpoint.requestPathParams[2].identifier).toEqual('optionalParam')
82
+ expect(endpoint.requestPathParams[2].signature).toEqual('number')
83
+ expect(endpoint.requestPathParams[2].optional).toEqual(true)
84
+ })
85
+
86
+ it('parses built-in usePathParams validators correctly', () => {
87
+ const endpoint = analyzeEndpointById('ef25ef5e-0f8f-4732-bf59-8825f94a5287')
88
+
89
+ expect(endpoint.requestPathParams[0].identifier).toEqual('firstParam')
90
+ expect(endpoint.requestPathParams[0].signature).toEqual('string')
91
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
92
+ expect(endpoint.requestPathParams[1].identifier).toEqual('secondParam')
93
+ expect(endpoint.requestPathParams[1].signature).toEqual('boolean')
94
+ expect(endpoint.requestPathParams[1].optional).toEqual(false)
95
+ expect(endpoint.requestPathParams[2].identifier).toEqual('optionalParam')
96
+ expect(endpoint.requestPathParams[2].signature).toEqual('number')
97
+ expect(endpoint.requestPathParams[2].optional).toEqual(true)
98
+ })
99
+
100
+ it('parses complex usePathParams validator correctly', () => {
101
+ const endpoint = analyzeEndpointById('5ab5dd0d-b241-4378-bea1-a2dd696d699a')
102
+
103
+ expect(endpoint.requestPathParams[0].identifier).toEqual('firstParam')
104
+ expect(endpoint.requestPathParams[0].signature).toEqual([
105
+ {
106
+ role: 'property',
107
+ identifier: 'foo',
108
+ shape: 'string',
109
+ optional: false,
110
+ },
111
+ {
112
+ role: 'property',
113
+ identifier: 'bar',
114
+ shape: 'string',
115
+ optional: false,
116
+ },
117
+ ])
118
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
119
+ expect(endpoint.requestPathParams[1].identifier).toEqual('secondParam')
120
+ expect(endpoint.requestPathParams[1].signature).toEqual([
121
+ {
122
+ role: 'property',
123
+ identifier: 'foo',
124
+ shape: 'string',
125
+ optional: false,
126
+ },
127
+ {
128
+ role: 'property',
129
+ identifier: 'bar',
130
+ shape: 'string',
131
+ optional: false,
132
+ },
133
+ ])
134
+ expect(endpoint.requestPathParams[1].optional).toEqual(false)
135
+ })
136
+
137
+ it('parses usePathParams validator with optional types correctly', () => {
138
+ const endpoint = analyzeEndpointById('209df2a1-55f9-4859-bc31-3277547c7d88')
139
+
140
+ expect(endpoint.requestPathParams[0].identifier).toEqual('firstParam')
141
+ expect(endpoint.requestPathParams[0].signature).toEqual([
142
+ {
143
+ identifier: 'foo',
144
+ optional: true,
145
+ role: 'property',
146
+ shape: 'string',
147
+ },
148
+ ])
149
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
150
+ expect(endpoint.requestPathParams[1].identifier).toEqual('secondParam')
151
+ expect(endpoint.requestPathParams[1].signature).toEqual([
152
+ {
153
+ identifier: 'foo',
154
+ optional: true,
155
+ role: 'property',
156
+ shape: 'string',
157
+ },
158
+ ])
159
+ expect(endpoint.requestPathParams[1].optional).toEqual(false)
160
+ })
161
+
162
+ it('parses usePathParams validator with union types correctly', () => {
163
+ const endpoint = analyzeEndpointById('89d961f1-7d36-4271-8bd3-665ee0992590')
164
+
165
+ expect(endpoint.requestPathParams[0].identifier).toEqual('firstParam')
166
+ expect(endpoint.requestPathParams[0].signature).toEqual([
167
+ {
168
+ identifier: 'foo',
169
+ optional: false,
170
+ role: 'property',
171
+ shape: [
172
+ {
173
+ role: 'union',
174
+ optional: false,
175
+ shape: [
176
+ {
177
+ role: 'union_entry',
178
+ shape: 'string',
179
+ optional: false,
180
+ },
181
+ {
182
+ role: 'union_entry',
183
+ shape: 'number',
184
+ optional: false,
185
+ },
186
+ ],
187
+ },
188
+ ],
189
+ },
190
+ ])
191
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
192
+ expect(endpoint.requestPathParams[1].identifier).toEqual('secondParam')
193
+ expect(endpoint.requestPathParams[1].signature).toEqual([
194
+ {
195
+ identifier: 'foo',
196
+ optional: false,
197
+ role: 'property',
198
+ shape: [
199
+ {
200
+ role: 'union',
201
+ optional: false,
202
+ shape: [
203
+ {
204
+ role: 'union_entry',
205
+ shape: 'string',
206
+ optional: false,
207
+ },
208
+ {
209
+ role: 'union_entry',
210
+ shape: 'number',
211
+ optional: false,
212
+ },
213
+ ],
214
+ },
215
+ ],
216
+ },
217
+ ])
218
+ expect(endpoint.requestPathParams[1].optional).toEqual(false)
219
+ })
220
+
221
+ it('parses params with destructuring correctly', () => {
222
+ const endpoint = analyzeEndpointById('39669151-c529-4bcd-86a5-a10de7834104')
223
+
224
+ expect(endpoint.requestPathParams).toEqual([
225
+ { identifier: 'foo', optional: false, signature: 'string', description: '', errorMessage: '' },
226
+ ])
227
+ })
228
+ })
229
+
230
+ describe('useQueryParams', () => {
231
+ it('parses inline useQueryParams validators correctly', () => {
232
+ const endpoint = analyzeEndpointById('f89310d9-25ac-4005-93e4-614179d3bbd4')
233
+
234
+ expect(endpoint.requestQuery[0].identifier).toEqual('firstParam')
235
+ expect(endpoint.requestQuery[0].signature).toEqual('string')
236
+ expect(endpoint.requestQuery[0].optional).toEqual(false)
237
+ expect(endpoint.requestQuery[1].identifier).toEqual('secondParam')
238
+ expect(endpoint.requestQuery[1].signature).toEqual('boolean')
239
+ expect(endpoint.requestQuery[1].optional).toEqual(true)
240
+ expect(endpoint.requestQuery[2].identifier).toEqual('thirdParam')
241
+ expect(endpoint.requestQuery[2].signature).toEqual('number')
242
+ expect(endpoint.requestQuery[2].optional).toEqual(true)
243
+ })
244
+
245
+ it('parses enum union query type correctly', () => {
246
+ const endpoint = analyzeEndpointById('7c51de80-1ff1-4511-b0d3-8a75c296c507')
247
+
248
+ expect(endpoint.requestQuery[0].signature).toEqual([
249
+ {
250
+ role: 'union',
251
+ shape: [
252
+ {
253
+ role: 'union_entry',
254
+ shape: [{ role: 'literal_string', shape: 'dec', optional: false }],
255
+ optional: false,
256
+ },
257
+ {
258
+ role: 'union_entry',
259
+ shape: [{ role: 'literal_string', shape: 'hex', optional: false }],
260
+ optional: false,
261
+ },
262
+ {
263
+ role: 'union_entry',
264
+ shape: [{ role: 'literal_string', shape: 'bin', optional: false }],
265
+ optional: false,
266
+ },
267
+ ],
268
+ optional: false,
269
+ },
270
+ ])
271
+ expect(endpoint.responses.length).toEqual(1)
272
+ })
273
+
274
+ it('parses null query type correctly', () => {
275
+ const endpoint = analyzeEndpointById('2c5483d3-7b21-421a-92a8-34e54a008b82')
276
+
277
+ expect(endpoint.requestQuery[0].signature).toEqual([
278
+ {
279
+ role: 'union',
280
+ shape: [
281
+ {
282
+ role: 'union_entry',
283
+ shape: 'null',
284
+ optional: false,
285
+ },
286
+ {
287
+ role: 'union_entry',
288
+ shape: 'string',
289
+ optional: false,
290
+ },
291
+ ],
292
+ optional: false,
293
+ },
294
+ ])
295
+ expect(endpoint.responses.length).toEqual(1)
296
+ })
297
+
298
+ it('parses enum query type correctly', () => {
299
+ const endpoint = analyzeEndpointById('724a56ef-32f9-4c59-b22c-60bd33e45242')
300
+
301
+ expect(endpoint.requestQuery[0].signature).toEqual([
302
+ { role: 'literal_string', shape: 'hello world', optional: false },
303
+ ])
304
+ expect(endpoint.responses.length).toEqual(1)
305
+ })
306
+
307
+ it('parses validator with description correctly', () => {
308
+ const endpoint = analyzeEndpointById('2b9a53fa-4418-4303-9202-3f8e46f73aed')
309
+
310
+ expect(endpoint.requestQuery[0].description).toEqual('Test description')
311
+ })
312
+
313
+ it('parses validator with error message correctly', () => {
314
+ const endpoint = analyzeEndpointById('685ac7fb-18ee-4ace-b68e-a6ee354ad4db')
315
+
316
+ expect(endpoint.requestQuery[0].errorMessage).toEqual('Test error message')
317
+ })
318
+
319
+ it('parses validator with tuple type correctly', () => {
320
+ const endpoint = analyzeEndpointById('d8b07b26-5202-434c-9ff6-3fe792dad40f')
321
+
322
+ expect(endpoint.requestQuery[0].identifier).toEqual('foo')
323
+ expect(endpoint.requestQuery[0].signature).toEqual([
324
+ {
325
+ identifier: 'tuple',
326
+ optional: false,
327
+ role: 'property',
328
+ shape: [
329
+ {
330
+ optional: false,
331
+ role: 'tuple',
332
+ shape: [
333
+ { optional: false, role: 'tuple_entry', shape: 'number' },
334
+ { optional: false, role: 'tuple_entry', shape: 'string' },
335
+ { optional: false, role: 'tuple_entry', shape: 'boolean' },
336
+ ],
337
+ },
338
+ ],
339
+ },
340
+ ])
341
+ })
342
+ })
343
+
344
+ describe('useHeaderParams', () => {
345
+ it('parses inline validators correctly', () => {
346
+ const endpoint = analyzeEndpointById('03c247cb-96c0-4748-bb6a-9569c7bdb436')
347
+
348
+ expect(endpoint.requestHeaders[0].identifier).toEqual('firstParam')
349
+ expect(endpoint.requestHeaders[0].signature).toEqual('string')
350
+ expect(endpoint.requestHeaders[0].optional).toEqual(false)
351
+ expect(endpoint.requestHeaders[1].identifier).toEqual('secondParam')
352
+ expect(endpoint.requestHeaders[1].signature).toEqual('boolean')
353
+ expect(endpoint.requestHeaders[1].optional).toEqual(true)
354
+ expect(endpoint.requestHeaders[2].identifier).toEqual('thirdParam')
355
+ expect(endpoint.requestHeaders[2].signature).toEqual('number')
356
+ expect(endpoint.requestHeaders[2].optional).toEqual(true)
357
+ })
358
+
359
+ it('parses validator with dashes correctly', () => {
360
+ const endpoint = analyzeEndpointById('e563aa37-803e-4b79-a3e8-af0d01d024ae')
361
+
362
+ expect(endpoint.requestHeaders[0].identifier).toEqual('header-with-dashes')
363
+ expect(endpoint.requestHeaders[0].signature).toEqual('string')
364
+ expect(endpoint.requestHeaders[0].optional).toEqual(false)
365
+ })
366
+
367
+ it('parses validator with description correctly', () => {
368
+ const endpoint = analyzeEndpointById('a3e79aaa-2d0f-4481-9226-a10904e76354')
369
+
370
+ expect(endpoint.requestHeaders[0].description).toEqual('Test description')
371
+ })
372
+
373
+ it('parses validator with error message correctly', () => {
374
+ const endpoint = analyzeEndpointById('219c5c4e-1558-4d0b-85be-9753dfc14083')
375
+
376
+ expect(endpoint.requestHeaders[0].errorMessage).toEqual('Test error message')
377
+ })
378
+
379
+ it('parses info from built-in validator correctly', () => {
380
+ const endpoint = analyzeEndpointById('1ea8bc2f-3f66-4409-ba4a-289f33bcc8fd')
381
+
382
+ expect(endpoint.requestHeaders[0].description).toEqual(StringValidator.description)
383
+ expect(endpoint.requestHeaders[0].errorMessage).toEqual(StringValidator.errorMessage)
384
+ })
385
+
386
+ it('parses info from built-in wrapped validator correctly', () => {
387
+ const endpoint = analyzeEndpointById('c679c01e-a403-4a5c-8097-3abbe891a625')
388
+
389
+ expect(endpoint.requestHeaders[0].description).toEqual(StringValidator.description)
390
+ expect(endpoint.requestHeaders[0].errorMessage).toEqual(StringValidator.errorMessage)
391
+ })
392
+ })
393
+
394
+ describe('useRequestRawBody', () => {
395
+ it('parses inline useRequestRawBody validator correctly', () => {
396
+ const endpoint = analyzeEndpointById('6040cd01-a0c6-4b70-9901-b647f19b19a7')
397
+
398
+ const body = endpoint.rawBody
399
+ if (!body) {
400
+ throw new Error('No body definition found')
401
+ }
402
+ expect(body.signature).toEqual([
403
+ {
404
+ identifier: 'foo',
405
+ role: 'property',
406
+ shape: 'string',
407
+ optional: false,
408
+ },
409
+ {
410
+ identifier: 'bar',
411
+ role: 'property',
412
+ shape: 'number',
413
+ optional: true,
414
+ },
415
+ ])
416
+ expect(body.optional).toEqual(false)
417
+ })
418
+
419
+ it('parses inline useRequestRawBody validator correctly with alternative typing', () => {
420
+ const endpoint = analyzeEndpointById('f3754325-6d9c-42b6-becf-4a9e72bd2c4e')
421
+
422
+ const body = endpoint.rawBody
423
+ if (!body) {
424
+ throw new Error('No body definition found')
425
+ }
426
+ expect(body.signature).toEqual([
427
+ {
428
+ identifier: 'foo',
429
+ role: 'property',
430
+ shape: 'string',
431
+ optional: false,
432
+ },
433
+ {
434
+ identifier: 'bar',
435
+ role: 'property',
436
+ shape: 'number',
437
+ optional: true,
438
+ },
439
+ ])
440
+ expect(body.optional).toEqual(false)
441
+ })
442
+
443
+ it('parses optional useRequestRawBody validator correctly', () => {
444
+ const endpoint = analyzeEndpointById('1ab973ff-9937-4e2d-b432-ff43a9df42cb')
445
+
446
+ const body = endpoint.rawBody
447
+ if (!body) {
448
+ throw new Error('No body definition found')
449
+ }
450
+ expect(body.signature).toEqual([
451
+ {
452
+ identifier: 'foo',
453
+ role: 'property',
454
+ shape: 'string',
455
+ optional: false,
456
+ },
457
+ {
458
+ identifier: 'bar',
459
+ role: 'property',
460
+ shape: 'number',
461
+ optional: true,
462
+ },
463
+ ])
464
+ expect(body.optional).toEqual(true)
465
+ })
466
+
467
+ it('parses optional built-in useRequestRawBody validator correctly', () => {
468
+ const endpoint = analyzeEndpointById('f74f6003-2aba-4f8c-855e-c0149f4217b7')
469
+
470
+ const body = endpoint.rawBody
471
+ if (!body) {
472
+ throw new Error('No body definition found')
473
+ }
474
+ expect(body.signature).toEqual('boolean')
475
+ expect(body.optional).toEqual(true)
476
+ })
477
+
478
+ it('parses description from inline validator correctly', () => {
479
+ const endpoint = analyzeEndpointById('54768e53-4094-4e2e-96bf-8891235f264b')
480
+
481
+ expect(endpoint.rawBody?.description).toEqual('Test description')
482
+ })
483
+
484
+ it('parses errorMessage from inline validator correctly', () => {
485
+ const endpoint = analyzeEndpointById('87a1470c-3fec-492a-bc4c-ff35fc95524a')
486
+
487
+ expect(endpoint.rawBody?.errorMessage).toEqual('Test error message')
488
+ })
489
+
490
+ it('parses info from built-in validator correctly', () => {
491
+ const endpoint = analyzeEndpointById('32f51057-743a-4c37-9647-476f9a8581f3')
492
+
493
+ expect(endpoint.rawBody?.description).toEqual(StringValidator.description)
494
+ expect(endpoint.rawBody?.errorMessage).toEqual(StringValidator.errorMessage)
495
+ })
496
+
497
+ it('parses info from built-in optional validator correctly', () => {
498
+ const endpoint = analyzeEndpointById('2fbc419b-2f1c-4782-9113-ef4125dd813b')
499
+
500
+ expect(endpoint.rawBody?.description).toEqual(StringValidator.description)
501
+ expect(endpoint.rawBody?.errorMessage).toEqual(StringValidator.errorMessage)
502
+ })
503
+ })
504
+
505
+ describe('useRequestBody', () => {
506
+ it('parses inline useRequestBody validators correctly', () => {
507
+ const endpoint = analyzeEndpointById('e8e5496b-11a0-41e3-a68d-f03d524e413c')
508
+
509
+ expect(endpoint.objectBody[0].identifier).toEqual('firstParam')
510
+ expect(endpoint.objectBody[0].signature).toEqual('string')
511
+ expect(endpoint.objectBody[0].optional).toEqual(false)
512
+ expect(endpoint.objectBody[1].identifier).toEqual('secondParam')
513
+ expect(endpoint.objectBody[1].signature).toEqual('boolean')
514
+ expect(endpoint.objectBody[1].optional).toEqual(true)
515
+ expect(endpoint.objectBody[2].identifier).toEqual('thirdParam')
516
+ expect(endpoint.objectBody[2].signature).toEqual('number')
517
+ expect(endpoint.objectBody[2].optional).toEqual(true)
518
+ })
519
+
520
+ it('parses optional validator correctly', () => {
521
+ const endpoint = analyzeEndpointById('c9a2301c-babd-4512-935c-b9664803e720')
522
+
523
+ expect(endpoint.objectBody[0].identifier).toEqual('firstParam')
524
+ expect(endpoint.objectBody[0].signature).toEqual('string')
525
+ expect(endpoint.objectBody[0].optional).toEqual(true)
526
+ })
527
+
528
+ it('parses validator with bigint correctly', () => {
529
+ const endpoint = analyzeEndpointById('b3b9aec9-f58e-4c4b-8cf6-ca2fe11c5331')
530
+
531
+ expect(endpoint.objectBody[0].identifier).toEqual('firstParam')
532
+ expect(endpoint.objectBody[0].signature).toEqual('bigint')
533
+ })
534
+ })
535
+
536
+ describe('endpoint return value', () => {
537
+ it('parses simple return value correctly', () => {
538
+ const endpoint = analyzeEndpointById('e1bedf55-6d3a-4c01-9c66-6ec74cc66c3b')
539
+
540
+ expect(endpoint.responses[0].status).toEqual(200)
541
+ expect(endpoint.responses[0].signature).toEqual('string')
542
+ expect(endpoint.responses.length).toEqual(1)
543
+ })
544
+
545
+ it('parses multiple return values correctly', () => {
546
+ const endpoint = analyzeEndpointById('78ad5fba-f4e2-4924-b28a-23e39dd146f7')
547
+
548
+ expect(endpoint.responses[0].status).toEqual(200)
549
+ expect(endpoint.responses[0].signature).toEqual('string')
550
+ expect(endpoint.responses[1].status).toEqual(200)
551
+ expect(endpoint.responses[1].signature).toEqual('number')
552
+ expect(endpoint.responses[2].status).toEqual(200)
553
+ expect(endpoint.responses[2].signature).toEqual('boolean')
554
+ expect(endpoint.responses.length).toEqual(3)
555
+ })
556
+
557
+ it('parses type inferred return value object correctly', () => {
558
+ const endpoint = analyzeEndpointById('c542cb10-538c-44eb-8d13-5111e273ead0')
559
+
560
+ expect(endpoint.responses[0].status).toEqual(200)
561
+ expect(endpoint.responses[0].signature).toEqual([
562
+ {
563
+ role: 'property',
564
+ identifier: 'foo',
565
+ shape: 'string',
566
+ optional: false,
567
+ },
568
+ {
569
+ role: 'property',
570
+ identifier: 'bar',
571
+ shape: 'number',
572
+ optional: false,
573
+ },
574
+ ])
575
+ expect(endpoint.responses.length).toEqual(1)
576
+ })
577
+
578
+ it('parses return value object with optional values correctly', () => {
579
+ const endpoint = analyzeEndpointById('03888127-6b97-42df-b429-87a6588ab2a4')
580
+
581
+ expect(endpoint.responses[0].status).toEqual(200)
582
+ expect(endpoint.responses[0].signature).toEqual([
583
+ {
584
+ role: 'property',
585
+ identifier: 'foo',
586
+ shape: 'string',
587
+ optional: true,
588
+ },
589
+ {
590
+ role: 'property',
591
+ identifier: 'bar',
592
+ shape: 'number',
593
+ optional: true,
594
+ },
595
+ ])
596
+ expect(endpoint.responses.length).toEqual(1)
597
+ })
598
+
599
+ it('parses return value object with union values correctly', () => {
600
+ const endpoint = analyzeEndpointById('b73347dc-c16f-4272-95b4-bf1716bf9c14')
601
+
602
+ expect(endpoint.responses[0].status).toEqual(200)
603
+ expect(endpoint.responses[0].signature).toEqual([
604
+ {
605
+ identifier: 'foo',
606
+ optional: false,
607
+ role: 'property',
608
+ shape: [
609
+ {
610
+ optional: false,
611
+ role: 'union',
612
+ shape: [
613
+ { optional: false, role: 'union_entry', shape: 'string' },
614
+ { optional: false, role: 'union_entry', shape: 'number' },
615
+ { optional: false, role: 'union_entry', shape: 'boolean' },
616
+ ],
617
+ },
618
+ ],
619
+ },
620
+ ])
621
+ expect(endpoint.responses.length).toEqual(1)
622
+ })
623
+
624
+ it('parses return value object with union values in async function correctly', () => {
625
+ const endpoint = analyzeEndpointById('666b9ed1-62db-447a-80a7-8f35ec50ab02')
626
+
627
+ expect(endpoint.responses[0].status).toEqual(200)
628
+ expect(endpoint.responses[0].signature).toEqual([
629
+ {
630
+ identifier: 'foo',
631
+ optional: false,
632
+ role: 'property',
633
+ shape: 'number',
634
+ },
635
+ ])
636
+ expect(endpoint.responses.length).toEqual(1)
637
+ })
638
+
639
+ it('parses return of query params correctly', () => {
640
+ const endpoint = analyzeEndpointById('97bb5db8-1871-4c1d-998e-a724c04c5741')
641
+
642
+ expect(endpoint.responses[0].status).toEqual(200)
643
+ expect(endpoint.responses[0].signature).toEqual([
644
+ {
645
+ identifier: 'foo',
646
+ optional: false,
647
+ role: 'property',
648
+ shape: 'string',
649
+ },
650
+ {
651
+ identifier: 'bar',
652
+ optional: true,
653
+ role: 'property',
654
+ shape: 'boolean',
655
+ },
656
+ {
657
+ identifier: 'baz',
658
+ optional: true,
659
+ role: 'property',
660
+ shape: 'number',
661
+ },
662
+ ])
663
+ expect(endpoint.responses.length).toEqual(1)
664
+ })
665
+
666
+ it('parses return of union type query params correctly', () => {
667
+ const endpoint = analyzeEndpointById('4188ebf2-eae6-4994-8732-c7f43d4da861')
668
+
669
+ expect(endpoint.responses[0].status).toEqual(200)
670
+ expect(endpoint.responses[0].signature).toEqual([
671
+ {
672
+ identifier: 'test',
673
+ optional: false,
674
+ role: 'property',
675
+ shape: 'string',
676
+ },
677
+ ])
678
+ expect(endpoint.responses[1].status).toEqual(200)
679
+ expect(endpoint.responses[1].signature).toEqual([
680
+ {
681
+ identifier: 'foo',
682
+ optional: false,
683
+ role: 'property',
684
+ shape: 'string',
685
+ },
686
+ {
687
+ identifier: 'bar',
688
+ optional: true,
689
+ role: 'property',
690
+ shape: 'boolean',
691
+ },
692
+ {
693
+ identifier: 'baz',
694
+ optional: true,
695
+ role: 'property',
696
+ shape: 'number',
697
+ },
698
+ ])
699
+ expect(endpoint.responses.length).toEqual(2)
700
+ })
701
+
702
+ it('parses return record type correctly', () => {
703
+ const endpoint = analyzeEndpointById('32f18a25-2408-46cf-9519-f9a8d855bf84')
704
+
705
+ expect(endpoint.responses[0].status).toEqual(200)
706
+ expect(endpoint.responses[0].signature).toEqual([
707
+ {
708
+ role: 'record',
709
+ shape: [
710
+ {
711
+ identifier: 'foo',
712
+ optional: false,
713
+ role: 'property',
714
+ shape: 'string',
715
+ },
716
+ {
717
+ identifier: 'bar',
718
+ optional: false,
719
+ role: 'property',
720
+ shape: 'string',
721
+ },
722
+ ],
723
+ optional: false,
724
+ },
725
+ ])
726
+ expect(endpoint.responses.length).toEqual(1)
727
+ })
728
+
729
+ it('parses no-return endpoint correctly', () => {
730
+ const endpoint = analyzeEndpointById('196f2937-e369-435f-b239-62eaacaa6fbd')
731
+
732
+ expect(endpoint.responses[0].status).toEqual(204)
733
+ expect(endpoint.responses[0].signature).toEqual('void')
734
+ expect(endpoint.responses.length).toEqual(1)
735
+ })
736
+
737
+ it('parses circular dependency correctly', () => {
738
+ const endpoint = analyzeEndpointById('33a0f888-396e-4c4d-b1d9-4cf6600ab88d')
739
+
740
+ expect(endpoint.responses[0].status).toEqual(200)
741
+ expect(endpoint.responses[0].signature).toEqual('string')
742
+ expect(endpoint.responses[1].status).toEqual(200)
743
+ expect(endpoint.responses[1].signature).toEqual([
744
+ { role: 'array', shape: 'circular', optional: false },
745
+ ])
746
+ expect(endpoint.responses.length).toEqual(2)
747
+ })
748
+
749
+ it('parses array return type correctly', () => {
750
+ const endpoint = analyzeEndpointById('e3659429-1a05-4590-a5a6-dc80a30878e6')
751
+
752
+ expect(endpoint.responses[0].status).toEqual(200)
753
+ expect(endpoint.responses[0].signature).toEqual([
754
+ {
755
+ role: 'array',
756
+ shape: 'string',
757
+ optional: false,
758
+ },
759
+ ])
760
+ expect(endpoint.responses.length).toEqual(1)
761
+ })
762
+
763
+ it('parses intersection return type correctly', () => {
764
+ const endpoint = analyzeEndpointById('9470a1f7-1781-43ea-aa32-4d7d71eddf4f')
765
+
766
+ expect(endpoint.responses[0].status).toEqual(200)
767
+ expect(endpoint.responses[0].signature).toEqual([
768
+ {
769
+ role: 'property',
770
+ identifier: 'foo',
771
+ shape: 'string',
772
+ optional: false,
773
+ },
774
+ {
775
+ role: 'property',
776
+ identifier: 'bar',
777
+ shape: 'string',
778
+ optional: false,
779
+ },
780
+ ])
781
+ expect(endpoint.responses.length).toEqual(1)
782
+ })
783
+
784
+ it('parses intersection of union return types correctly', () => {
785
+ const endpoint = analyzeEndpointById('be7205a2-3bc3-490e-be25-988d7ab65f20')
786
+
787
+ expect(endpoint.responses[0].status).toEqual(200)
788
+ expect(endpoint.responses[0].signature).toEqual([
789
+ {
790
+ identifier: 'afoo',
791
+ optional: false,
792
+ role: 'property',
793
+ shape: 'string',
794
+ },
795
+ {
796
+ identifier: 'befoo',
797
+ optional: false,
798
+ role: 'property',
799
+ shape: 'string',
800
+ },
801
+ ])
802
+ expect(endpoint.responses[1].status).toEqual(200)
803
+ expect(endpoint.responses[1].signature).toEqual([
804
+ {
805
+ identifier: 'afoo',
806
+ optional: false,
807
+ role: 'property',
808
+ shape: 'string',
809
+ },
810
+ {
811
+ identifier: 'beebar',
812
+ optional: false,
813
+ role: 'property',
814
+ shape: 'string',
815
+ },
816
+ ])
817
+ expect(endpoint.responses[2].status).toEqual(200)
818
+ expect(endpoint.responses[2].signature).toEqual([
819
+ {
820
+ identifier: 'abar',
821
+ optional: false,
822
+ role: 'property',
823
+ shape: 'string',
824
+ },
825
+ {
826
+ identifier: 'befoo',
827
+ optional: false,
828
+ role: 'property',
829
+ shape: 'string',
830
+ },
831
+ ])
832
+ expect(endpoint.responses[3].status).toEqual(200)
833
+ expect(endpoint.responses[3].signature).toEqual([
834
+ {
835
+ identifier: 'abar',
836
+ optional: false,
837
+ role: 'property',
838
+ shape: 'string',
839
+ },
840
+ {
841
+ identifier: 'beebar',
842
+ optional: false,
843
+ role: 'property',
844
+ shape: 'string',
845
+ },
846
+ ])
847
+ expect(endpoint.responses.length).toEqual(4)
848
+ })
849
+
850
+ it('handles null union type correctly', () => {
851
+ const endpoint = analyzeEndpointById('006b4d53-15a4-405e-b94d-1fa3abbd19aa')
852
+
853
+ expect(endpoint.responses[0].status).toEqual(204)
854
+ expect(endpoint.responses[0].signature).toEqual('null')
855
+ expect(endpoint.responses[1].status).toEqual(200)
856
+ expect(endpoint.responses[1].signature).toEqual('string')
857
+ expect(endpoint.responses.length).toEqual(2)
858
+ })
859
+
860
+ it('handles complex null union type correctly', () => {
861
+ const endpoint = analyzeEndpointById('a8f4e5f7-ed58-4de6-8877-b14bf14ae176')
862
+
863
+ expect(endpoint.responses[0].status).toEqual(204)
864
+ expect(endpoint.responses[0].signature).toEqual('null')
865
+ expect(endpoint.responses[1].status).toEqual(200)
866
+ expect(endpoint.responses[1].signature).toEqual('string')
867
+ expect(endpoint.responses[2].status).toEqual(200)
868
+ expect(endpoint.responses[2].signature).toEqual('number')
869
+ expect(endpoint.responses.length).toEqual(3)
870
+ })
871
+
872
+ it('handles object with nullable param correctly', () => {
873
+ const endpoint = analyzeEndpointById('b9fae12a-be41-4aef-9250-f6d67cd0aee6')
874
+
875
+ expect(endpoint.responses[0].status).toEqual(200)
876
+ expect(endpoint.responses[0].signature).toEqual([
877
+ {
878
+ identifier: 'foo',
879
+ optional: true,
880
+ role: 'property',
881
+ shape: [
882
+ {
883
+ role: 'union',
884
+ optional: false,
885
+ shape: [
886
+ {
887
+ role: 'union_entry',
888
+ shape: 'null',
889
+ optional: false,
890
+ },
891
+ {
892
+ role: 'union_entry',
893
+ shape: 'string',
894
+ optional: false,
895
+ },
896
+ ],
897
+ },
898
+ ],
899
+ },
900
+ ])
901
+ expect(endpoint.responses.length).toEqual(1)
902
+ })
903
+
904
+ it('handles object with Date param correctly', () => {
905
+ const endpoint = analyzeEndpointById('dba70b93-8e8f-4731-8869-285831d18fcb')
906
+
907
+ expect(endpoint.responses[0].status).toEqual(200)
908
+ expect(endpoint.responses[0].signature).toEqual([
909
+ {
910
+ identifier: 'foo',
911
+ optional: false,
912
+ role: 'property',
913
+ shape: 'Date',
914
+ },
915
+ ])
916
+ expect(endpoint.responses.length).toEqual(1)
917
+ })
918
+
919
+ it('handles object with bigint param correctly', () => {
920
+ const endpoint = analyzeEndpointById('79207cfa-916a-4474-9d98-45196d2451b5')
921
+
922
+ expect(endpoint.responses[0].status).toEqual(200)
923
+ expect(endpoint.responses[0].signature).toEqual([
924
+ {
925
+ identifier: 'foo',
926
+ optional: false,
927
+ role: 'property',
928
+ shape: 'bigint',
929
+ },
930
+ ])
931
+ expect(endpoint.responses.length).toEqual(1)
932
+ })
933
+
934
+ it('handles object with inferred bigint param correctly', () => {
935
+ const endpoint = analyzeEndpointById('19207cfa-916a-4474-9d98-45196d2451b6')
936
+
937
+ expect(endpoint.responses[0].status).toEqual(200)
938
+ expect(endpoint.responses[0].signature).toEqual([
939
+ {
940
+ identifier: 'foo',
941
+ optional: false,
942
+ role: 'property',
943
+ shape: 'bigint',
944
+ },
945
+ ])
946
+ expect(endpoint.responses.length).toEqual(1)
947
+ })
948
+ })
949
+
950
+ describe('when using an exposed model', () => {
951
+ beforeEach(() => {
952
+ OpenApiManager.getInstance().setExposedModels([
953
+ {
954
+ name: 'FooBarObject',
955
+ shape: 'string',
956
+ },
957
+ ])
958
+ })
959
+
960
+ it('places a reference to the model for type inferred validator', () => {
961
+ const endpoint = analyzeEndpointById('e917e982-b5ce-4a8f-804e-13466e7a00a2')
962
+
963
+ expect(endpoint.requestQuery[0].identifier).toEqual('foo')
964
+ expect(endpoint.requestQuery[0].signature).toEqual([
965
+ {
966
+ role: 'ref',
967
+ shape: 'FooBarObject',
968
+ optional: false,
969
+ },
970
+ ])
971
+ })
972
+
973
+ it('places a reference to the model for explicit validator', () => {
974
+ const endpoint = analyzeEndpointById('af22e5ff-7cbf-4aa3-8ea9-fd538a747c01')
975
+
976
+ expect(endpoint.requestQuery[0].identifier).toEqual('foo')
977
+ expect(endpoint.requestQuery[0].signature).toEqual([
978
+ {
979
+ role: 'ref',
980
+ shape: 'FooBarObject',
981
+ optional: false,
982
+ },
983
+ ])
984
+ })
985
+
986
+ afterEach(() => {
987
+ OpenApiManager.getInstance().reset()
988
+ })
989
+ })
990
+
991
+ describe('when the same endpoint path has multiple methods', () => {
992
+ it('adds all to the spec', () => {
993
+ const endpoints = analyzeMultiEndpointById('e349c3c6-990b-4d97-9bde-f3bf133d2df7')
994
+
995
+ expect(endpoints.length).toEqual(4)
996
+ expect(endpoints[0].method).toEqual('GET')
997
+ expect(endpoints[1].method).toEqual('POST')
998
+ expect(endpoints[2].method).toEqual('PATCH')
999
+ expect(endpoints[3].method).toEqual('DELETE')
1000
+ })
1001
+ })
1002
+ })
1003
+
1004
+ describe('when validator is imported from another package', () => {
1005
+ let project: Project
1006
+
1007
+ beforeAll(() => {
1008
+ project = new Project({
1009
+ useInMemoryFileSystem: true,
1010
+ })
1011
+ })
1012
+
1013
+ it('parses shape correctly', () => {
1014
+ const sourceFile = project.createSourceFile(
1015
+ '/test-file',
1016
+ `
1017
+ export declare const StringValidator: import("./types").Validator<string> & {
1018
+ description: "Any string value.";
1019
+ errorMessage: "Must be a valid string.";
1020
+ } & {
1021
+ optional: false;
1022
+ };
1023
+ `
1024
+ )
1025
+
1026
+ const node = sourceFile
1027
+ .getFirstChild()!
1028
+ .getFirstChildByKind(SyntaxKind.VariableStatement)!
1029
+ .getFirstChildByKind(SyntaxKind.VariableDeclarationList)!
1030
+ .getFirstChildByKind(SyntaxKind.SyntaxList)!
1031
+ .getFirstChildByKind(SyntaxKind.VariableDeclaration)!
1032
+ .getFirstChildByKind(SyntaxKind.IntersectionType)!
1033
+
1034
+ if (!node) {
1035
+ throw new Error('Node not found')
1036
+ }
1037
+
1038
+ expect(getValidatorPropertyShape(node)).toEqual('string')
1039
+ expect(getValidatorPropertyStringValue(node, 'description')).toEqual('Any string value.')
1040
+ expect(getValidatorPropertyStringValue(node, 'errorMessage')).toEqual('Must be a valid string.')
1041
+ })
1042
+ })
1043
+ })