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,783 @@
1
+ import { OpenApiManager } from '../../manager/OpenApiManager'
2
+ import { EndpointData, ExposedModelData } from '../../types'
3
+ import { generateOpenApiSpec } from '../generatorModule'
4
+ import { manyEndpointsData, manyEndpointsResults } from './openApiGenerator.spec.data'
5
+
6
+ describe('OpenApi Generator', () => {
7
+ const createManager = (models: ExposedModelData[], endpoints: EndpointData[]): OpenApiManager => {
8
+ return new OpenApiManager(
9
+ {
10
+ title: 'Default title',
11
+ version: '1.0.0',
12
+ },
13
+ models,
14
+ endpoints,
15
+ {
16
+ allowOptionalPathParams: false,
17
+ },
18
+ {
19
+ discoveredRouterFiles: [],
20
+ explicitRouterFiles: [],
21
+ }
22
+ )
23
+ }
24
+
25
+ const createManagerWithEndpoints = (endpoints: EndpointData[]): OpenApiManager => {
26
+ return new OpenApiManager(
27
+ {
28
+ title: 'Default title',
29
+ version: '1.0.0',
30
+ },
31
+ [],
32
+ endpoints,
33
+ {
34
+ allowOptionalPathParams: false,
35
+ },
36
+ {
37
+ discoveredRouterFiles: [],
38
+ explicitRouterFiles: [],
39
+ }
40
+ )
41
+ }
42
+
43
+ const createManagerWithModels = (models: ExposedModelData[]): OpenApiManager => {
44
+ return new OpenApiManager(
45
+ {
46
+ title: 'Default title',
47
+ version: '1.0.0',
48
+ },
49
+ models,
50
+ [],
51
+ {
52
+ allowOptionalPathParams: false,
53
+ },
54
+ {
55
+ discoveredRouterFiles: [],
56
+ explicitRouterFiles: [],
57
+ }
58
+ )
59
+ }
60
+
61
+ const minimalEndpointData: EndpointData = {
62
+ method: 'GET',
63
+ path: '/test/path',
64
+ requestPathParams: [],
65
+ requestQuery: [],
66
+ requestHeaders: [],
67
+ objectBody: [],
68
+ responses: [],
69
+ sourceFilePath: '/root/test',
70
+ }
71
+
72
+ it('does not include responses field if no responses are available', () => {
73
+ const manager = createManagerWithEndpoints([
74
+ {
75
+ ...minimalEndpointData,
76
+ responses: [
77
+ {
78
+ status: 204,
79
+ signature: 'void',
80
+ },
81
+ ],
82
+ },
83
+ ])
84
+ const spec = generateOpenApiSpec(manager)
85
+
86
+ expect(spec.paths['/test/path'].get?.responses[204].content).toEqual(undefined)
87
+ })
88
+
89
+ it('handles bigint type correctly', () => {
90
+ const manager = createManagerWithEndpoints([
91
+ {
92
+ ...minimalEndpointData,
93
+ responses: [
94
+ {
95
+ status: 200,
96
+ signature: 'bigint',
97
+ },
98
+ ],
99
+ },
100
+ ])
101
+ const spec = generateOpenApiSpec(manager)
102
+
103
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
104
+ 'application/json': {
105
+ schema: {
106
+ oneOf: [
107
+ {
108
+ type: 'string',
109
+ format: 'bigint',
110
+ },
111
+ ],
112
+ },
113
+ },
114
+ })
115
+ })
116
+
117
+ it('includes record response correctly', () => {
118
+ const manager = createManagerWithEndpoints([
119
+ {
120
+ ...minimalEndpointData,
121
+ responses: [
122
+ {
123
+ status: 200,
124
+ signature: [
125
+ {
126
+ role: 'record',
127
+ shape: [
128
+ {
129
+ identifier: 'foo',
130
+ optional: false,
131
+ role: 'property',
132
+ shape: 'string',
133
+ },
134
+ {
135
+ identifier: 'bar',
136
+ optional: true,
137
+ role: 'property',
138
+ shape: 'boolean',
139
+ },
140
+ ],
141
+ optional: false,
142
+ },
143
+ ],
144
+ },
145
+ ],
146
+ },
147
+ ])
148
+ const spec = generateOpenApiSpec(manager)
149
+
150
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
151
+ 'application/json': {
152
+ schema: {
153
+ oneOf: [
154
+ {
155
+ type: 'object',
156
+ additionalProperties: {
157
+ type: 'object',
158
+ properties: { bar: { type: 'boolean' }, foo: { type: 'string' } },
159
+ required: ['foo'],
160
+ },
161
+ },
162
+ ],
163
+ },
164
+ },
165
+ })
166
+ })
167
+
168
+ it('generates correct spec for many endpoints', () => {
169
+ const manager = createManagerWithEndpoints(manyEndpointsData)
170
+ const spec = generateOpenApiSpec(manager)
171
+
172
+ expect(spec).toEqual(manyEndpointsResults)
173
+ })
174
+
175
+ it('generates correct spec for circular dependency', () => {
176
+ const manager = createManagerWithEndpoints([
177
+ {
178
+ ...minimalEndpointData,
179
+ responses: [
180
+ {
181
+ status: 200,
182
+ signature: [
183
+ {
184
+ role: 'property',
185
+ identifier: 'foo',
186
+ shape: 'circular',
187
+ optional: false,
188
+ },
189
+ ],
190
+ },
191
+ ],
192
+ },
193
+ ])
194
+ const spec = generateOpenApiSpec(manager)
195
+
196
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
197
+ 'application/json': {
198
+ schema: {
199
+ oneOf: [
200
+ {
201
+ type: 'object',
202
+ properties: {
203
+ foo: {
204
+ oneOf: [
205
+ { type: 'string' },
206
+ { type: 'boolean' },
207
+ { type: 'number' },
208
+ { type: 'object' },
209
+ { type: 'array' },
210
+ ],
211
+ },
212
+ },
213
+ required: ['foo'],
214
+ },
215
+ ],
216
+ },
217
+ },
218
+ })
219
+ })
220
+
221
+ it('generates correct spec for array in responses', () => {
222
+ const manager = createManagerWithEndpoints([
223
+ {
224
+ ...minimalEndpointData,
225
+ responses: [
226
+ {
227
+ status: 200,
228
+ signature: [
229
+ {
230
+ role: 'array',
231
+ shape: 'string',
232
+ optional: false,
233
+ },
234
+ ],
235
+ },
236
+ ],
237
+ },
238
+ ])
239
+ const spec = generateOpenApiSpec(manager)
240
+
241
+ expect(spec.paths['/test/path'].get).toEqual({
242
+ description: '',
243
+ parameters: [],
244
+ responses: {
245
+ '200': {
246
+ description: '',
247
+ content: {
248
+ 'application/json': {
249
+ schema: {
250
+ oneOf: [
251
+ {
252
+ type: 'array',
253
+ items: {
254
+ type: 'string',
255
+ },
256
+ },
257
+ ],
258
+ },
259
+ },
260
+ },
261
+ },
262
+ },
263
+ })
264
+ })
265
+
266
+ it('generates correct spec for any in responses', () => {
267
+ const manager = createManagerWithEndpoints([
268
+ {
269
+ ...minimalEndpointData,
270
+ responses: [
271
+ {
272
+ status: 200,
273
+ signature: [
274
+ {
275
+ identifier: 'foo',
276
+ role: 'property',
277
+ shape: 'any',
278
+ optional: false,
279
+ },
280
+ ],
281
+ },
282
+ ],
283
+ },
284
+ ])
285
+ const spec = generateOpenApiSpec(manager)
286
+
287
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
288
+ 'application/json': {
289
+ schema: {
290
+ oneOf: [
291
+ {
292
+ type: 'object',
293
+ properties: {
294
+ foo: {
295
+ oneOf: [
296
+ { type: 'string' },
297
+ { type: 'boolean' },
298
+ { type: 'number' },
299
+ { type: 'object' },
300
+ { type: 'array' },
301
+ ],
302
+ },
303
+ },
304
+ required: ['foo'],
305
+ },
306
+ ],
307
+ },
308
+ },
309
+ })
310
+ })
311
+
312
+ it('generates correct spec for string literal union', () => {
313
+ const manager = createManagerWithEndpoints([
314
+ {
315
+ ...minimalEndpointData,
316
+ responses: [
317
+ {
318
+ status: 200,
319
+ signature: [
320
+ {
321
+ role: 'union',
322
+ shape: [
323
+ {
324
+ role: 'union_entry',
325
+ shape: [{ role: 'literal_string', shape: 'bin', optional: false }],
326
+ optional: false,
327
+ },
328
+ {
329
+ role: 'union_entry',
330
+ shape: [{ role: 'literal_string', shape: 'hex', optional: false }],
331
+ optional: false,
332
+ },
333
+ {
334
+ role: 'union_entry',
335
+ shape: [{ role: 'literal_number', shape: '10', optional: false }],
336
+ optional: false,
337
+ },
338
+ ],
339
+ optional: false,
340
+ },
341
+ ],
342
+ },
343
+ ],
344
+ },
345
+ ])
346
+ const spec = generateOpenApiSpec(manager)
347
+
348
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
349
+ 'application/json': {
350
+ schema: {
351
+ oneOf: [
352
+ {
353
+ oneOf: [
354
+ { type: 'string', enum: ['bin'] },
355
+ { type: 'string', enum: ['hex'] },
356
+ { type: 'number', enum: ['10'] },
357
+ ],
358
+ },
359
+ ],
360
+ },
361
+ },
362
+ })
363
+ })
364
+
365
+ it('generates correct spec for string literal', () => {
366
+ const manager = createManagerWithEndpoints([
367
+ {
368
+ ...minimalEndpointData,
369
+ responses: [
370
+ {
371
+ status: 200,
372
+ signature: [{ role: 'literal_string', shape: 'hello world', optional: false }],
373
+ },
374
+ ],
375
+ },
376
+ ])
377
+ const spec = generateOpenApiSpec(manager)
378
+
379
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
380
+ 'application/json': { schema: { oneOf: [{ type: 'string', enum: ['hello world'] }] } },
381
+ })
382
+ })
383
+
384
+ it('generates correct spec for request headers', () => {
385
+ const manager = createManagerWithEndpoints([
386
+ {
387
+ ...minimalEndpointData,
388
+ requestHeaders: [
389
+ {
390
+ identifier: 'x-auth',
391
+ signature: 'string',
392
+ optional: false,
393
+ },
394
+ ],
395
+ },
396
+ ])
397
+ const spec = generateOpenApiSpec(manager)
398
+
399
+ expect(spec.paths['/test/path'].get?.parameters[0]).toEqual({
400
+ name: 'x-auth',
401
+ in: 'header',
402
+ description: '',
403
+ required: true,
404
+ schema: {
405
+ type: 'string',
406
+ },
407
+ })
408
+ })
409
+
410
+ it('includes descriptions if provided in request headers', () => {
411
+ const manager = createManagerWithEndpoints([
412
+ {
413
+ ...minimalEndpointData,
414
+ requestHeaders: [
415
+ {
416
+ identifier: 'x-auth',
417
+ signature: 'string',
418
+ optional: false,
419
+ description: 'Test description',
420
+ },
421
+ ],
422
+ },
423
+ ])
424
+ const spec = generateOpenApiSpec(manager)
425
+
426
+ expect(spec.paths['/test/path'].get?.parameters[0].in).toEqual('header')
427
+ expect(spec.paths['/test/path'].get?.parameters[0].description).toEqual('Test description')
428
+ })
429
+
430
+ it('includes descriptions if provided in request path params', () => {
431
+ const manager = createManagerWithEndpoints([
432
+ {
433
+ ...minimalEndpointData,
434
+ requestPathParams: [
435
+ {
436
+ identifier: 'pathParam',
437
+ signature: 'string',
438
+ optional: false,
439
+ description: 'Test description',
440
+ },
441
+ ],
442
+ },
443
+ ])
444
+ const spec = generateOpenApiSpec(manager)
445
+
446
+ expect(spec.paths['/test/path'].get?.parameters[0].in).toEqual('path')
447
+ expect(spec.paths['/test/path'].get?.parameters[0].description).toEqual('Test description')
448
+ })
449
+
450
+ it('includes descriptions if provided in optional request path params', () => {
451
+ const manager = createManagerWithEndpoints([
452
+ {
453
+ ...minimalEndpointData,
454
+ requestPathParams: [
455
+ {
456
+ identifier: 'pathParam',
457
+ signature: 'string',
458
+ optional: true,
459
+ description: 'Test description',
460
+ },
461
+ ],
462
+ },
463
+ ])
464
+ const spec = generateOpenApiSpec(manager)
465
+
466
+ expect(spec.paths['/test/path'].get?.parameters[0].in).toEqual('path')
467
+ expect(spec.paths['/test/path'].get?.parameters[0].description).toEqual(
468
+ '(Optional parameter) Test description'
469
+ )
470
+ })
471
+
472
+ it('includes descriptions if provided in request path params', () => {
473
+ const manager = createManagerWithEndpoints([
474
+ {
475
+ ...minimalEndpointData,
476
+ requestQuery: [
477
+ {
478
+ identifier: 'pathParam',
479
+ signature: 'string',
480
+ optional: false,
481
+ description: 'Test description',
482
+ },
483
+ ],
484
+ },
485
+ ])
486
+ const spec = generateOpenApiSpec(manager)
487
+
488
+ expect(spec.paths['/test/path'].get?.parameters[0].in).toEqual('query')
489
+ expect(spec.paths['/test/path'].get?.parameters[0].description).toEqual('Test description')
490
+ })
491
+
492
+ it('includes descriptions if provided in response', () => {
493
+ const manager = createManagerWithEndpoints([
494
+ {
495
+ ...minimalEndpointData,
496
+ responses: [
497
+ {
498
+ status: 200,
499
+ signature: 'string',
500
+ description: 'Test description',
501
+ },
502
+ ],
503
+ },
504
+ ])
505
+ const spec = generateOpenApiSpec(manager)
506
+
507
+ expect(spec.paths['/test/path'].get?.responses[200].description).toEqual('Test description')
508
+ })
509
+
510
+ it('includes exposed models as references', () => {
511
+ const manager = createManager(
512
+ [
513
+ {
514
+ name: 'FooBarObject',
515
+ shape: [
516
+ {
517
+ role: 'property',
518
+ identifier: 'foo',
519
+ shape: 'string',
520
+ optional: false,
521
+ },
522
+ {
523
+ role: 'property',
524
+ identifier: 'bar',
525
+ shape: 'string',
526
+ optional: false,
527
+ },
528
+ ],
529
+ },
530
+ ],
531
+ [
532
+ {
533
+ ...minimalEndpointData,
534
+ requestQuery: [
535
+ {
536
+ identifier: 'pathParam',
537
+ signature: [
538
+ {
539
+ role: 'ref',
540
+ shape: 'FooBarObject',
541
+ optional: false,
542
+ },
543
+ ],
544
+ optional: false,
545
+ },
546
+ ],
547
+ },
548
+ ]
549
+ )
550
+ const spec = generateOpenApiSpec(manager)
551
+
552
+ expect(spec.paths['/test/path'].get?.parameters[0]).toEqual({
553
+ name: 'pathParam',
554
+ in: 'query',
555
+ description: '',
556
+ required: true,
557
+ schema: {
558
+ $ref: '#/components/schemas/FooBarObject',
559
+ },
560
+ })
561
+ })
562
+
563
+ it('includes exposed models as component schemas', () => {
564
+ const manager = createManagerWithModels([
565
+ {
566
+ name: 'FooBarObject',
567
+ shape: [
568
+ {
569
+ role: 'property',
570
+ identifier: 'foo',
571
+ shape: 'string',
572
+ optional: false,
573
+ },
574
+ {
575
+ role: 'property',
576
+ identifier: 'bar',
577
+ shape: 'string',
578
+ optional: false,
579
+ },
580
+ ],
581
+ },
582
+ ])
583
+ const spec = generateOpenApiSpec(manager)
584
+
585
+ expect(spec.components.schemas['FooBarObject']).toEqual({
586
+ type: 'object',
587
+ properties: {
588
+ ['foo']: {
589
+ type: 'string',
590
+ },
591
+ ['bar']: {
592
+ type: 'string',
593
+ },
594
+ },
595
+ required: ['foo', 'bar'],
596
+ })
597
+ })
598
+
599
+ it('generates correct spec for tuple', () => {
600
+ const manager = createManagerWithEndpoints([
601
+ {
602
+ ...minimalEndpointData,
603
+ requestQuery: [
604
+ {
605
+ identifier: 'foo',
606
+ signature: [
607
+ {
608
+ role: 'tuple',
609
+ shape: [
610
+ { optional: false, role: 'tuple_entry', shape: 'number' },
611
+ { optional: false, role: 'tuple_entry', shape: 'string' },
612
+ { optional: false, role: 'tuple_entry', shape: 'boolean' },
613
+ ],
614
+ optional: false,
615
+ },
616
+ ],
617
+ optional: false,
618
+ },
619
+ ],
620
+ },
621
+ ])
622
+ const spec = generateOpenApiSpec(manager)
623
+
624
+ expect(spec.paths['/test/path'].get?.parameters[0]).toEqual({
625
+ name: 'foo',
626
+ in: 'query',
627
+ description: '',
628
+ required: true,
629
+ schema: {
630
+ type: 'array',
631
+ items: {
632
+ oneOf: [{ type: 'number' }, { type: 'string' }, { type: 'boolean' }],
633
+ },
634
+ minItems: 3,
635
+ maxItems: 3,
636
+ },
637
+ })
638
+ })
639
+
640
+ it('generates correct spec for nullable value', () => {
641
+ const manager = createManagerWithEndpoints([
642
+ {
643
+ ...minimalEndpointData,
644
+ requestQuery: [
645
+ {
646
+ identifier: 'foo',
647
+ optional: true,
648
+ signature: [
649
+ {
650
+ role: 'union',
651
+ optional: false,
652
+ shape: [
653
+ {
654
+ role: 'union_entry',
655
+ shape: 'null',
656
+ optional: false,
657
+ },
658
+ {
659
+ role: 'union_entry',
660
+ shape: 'string',
661
+ optional: false,
662
+ },
663
+ ],
664
+ },
665
+ ],
666
+ },
667
+ ],
668
+ },
669
+ ])
670
+ const spec = generateOpenApiSpec(manager)
671
+
672
+ expect(spec.paths['/test/path'].get?.parameters[0]).toEqual({
673
+ name: 'foo',
674
+ in: 'query',
675
+ description: '',
676
+ required: false,
677
+ schema: { oneOf: [{ type: 'null' }, { type: 'string' }] },
678
+ })
679
+ })
680
+
681
+ it('generates correct spec for endpoint with multiple methods', () => {
682
+ const manager = createManagerWithEndpoints([
683
+ {
684
+ ...minimalEndpointData,
685
+ method: 'GET',
686
+ path: '/test/path/:id',
687
+ },
688
+ {
689
+ ...minimalEndpointData,
690
+ method: 'POST',
691
+ path: '/test/path/:id',
692
+ },
693
+ {
694
+ ...minimalEndpointData,
695
+ method: 'PUT',
696
+ path: '/test/path/:id',
697
+ },
698
+ {
699
+ ...minimalEndpointData,
700
+ method: 'DELETE',
701
+ path: '/test/path/:id',
702
+ },
703
+ ])
704
+ const spec = generateOpenApiSpec(manager)
705
+
706
+ expect(spec.paths['/test/path/{id}'].get).not.toBe(undefined)
707
+ expect(spec.paths['/test/path/{id}'].post).not.toBe(undefined)
708
+ expect(spec.paths['/test/path/{id}'].put).not.toBe(undefined)
709
+ expect(spec.paths['/test/path/{id}'].delete).not.toBe(undefined)
710
+ })
711
+
712
+ it('generates correct spec for endpoint with tags', () => {
713
+ const manager = createManagerWithEndpoints([
714
+ {
715
+ ...minimalEndpointData,
716
+ method: 'GET',
717
+ path: '/test/path/:id',
718
+ tags: ['one', 'two', 'three'],
719
+ },
720
+ ])
721
+ const spec = generateOpenApiSpec(manager)
722
+
723
+ expect(spec.paths['/test/path/{id}'].get?.tags).toEqual(['one', 'two', 'three'])
724
+ })
725
+
726
+ it('generates correct spec for endpoint that returns Date objects', () => {
727
+ const manager = createManagerWithEndpoints([
728
+ {
729
+ ...minimalEndpointData,
730
+ responses: [
731
+ {
732
+ status: 200,
733
+ signature: [
734
+ {
735
+ identifier: 'foo',
736
+ optional: false,
737
+ role: 'property',
738
+ shape: 'Date',
739
+ },
740
+ ],
741
+ },
742
+ ],
743
+ },
744
+ ])
745
+ const spec = generateOpenApiSpec(manager)
746
+
747
+ expect(spec.paths['/test/path'].get?.responses[200].content).toEqual({
748
+ 'application/json': {
749
+ schema: {
750
+ oneOf: [
751
+ {
752
+ type: 'object',
753
+ properties: {
754
+ foo: {
755
+ type: 'string',
756
+ format: 'date-time',
757
+ },
758
+ },
759
+ required: ['foo'],
760
+ },
761
+ ],
762
+ },
763
+ },
764
+ })
765
+ })
766
+
767
+ it('does not include body if endpoint is not expecting a body', () => {
768
+ const manager = createManagerWithEndpoints([
769
+ {
770
+ ...minimalEndpointData,
771
+ method: 'POST',
772
+ },
773
+ ])
774
+ const spec = generateOpenApiSpec(manager)
775
+
776
+ expect(spec.paths['/test/path'].post).toEqual({
777
+ description: '',
778
+ parameters: [],
779
+ requestBody: undefined,
780
+ responses: {},
781
+ })
782
+ })
783
+ })