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,648 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import {
3
+ Node,
4
+ PropertyAccessExpression,
5
+ PropertyAssignment,
6
+ PropertySignature,
7
+ ShorthandPropertyAssignment,
8
+ SyntaxKind,
9
+ ts,
10
+ Type,
11
+ TypeReferenceNode,
12
+ } from 'ts-morph'
13
+
14
+ import { OpenApiManager } from '../manager/OpenApiManager'
15
+ import { ShapeOfProperty, ShapeOfType, ShapeOfUnionEntry } from './types'
16
+
17
+ export const findNodeImplementation = (node: Node): Node => {
18
+ if (node.getKind() === SyntaxKind.Identifier) {
19
+ const implementationNode = node.asKind(SyntaxKind.Identifier)!.getImplementations()[0]?.getNode()
20
+ if (implementationNode) {
21
+ const implementationParentNode = implementationNode.getParent()!
22
+ const assignmentValueNode = implementationParentNode.getLastChild()!
23
+ if (assignmentValueNode === node) {
24
+ throw new Error('Recursive implementation found')
25
+ }
26
+ return findNodeImplementation(assignmentValueNode)
27
+ }
28
+
29
+ const definitionNode = node.asKind(SyntaxKind.Identifier)!.getDefinitions()[0]?.getNode()
30
+ if (definitionNode) {
31
+ const definitionParentNode = definitionNode.getParent()!
32
+ const assignmentValueNode = definitionParentNode.getLastChild()!
33
+ if (assignmentValueNode === node) {
34
+ throw new Error('Recursive implementation found')
35
+ }
36
+ return findNodeImplementation(assignmentValueNode)
37
+ }
38
+ throw new Error('No implementation nor definition available')
39
+ }
40
+
41
+ return node
42
+ }
43
+
44
+ export const findPropertyAssignmentValueNode = (
45
+ node:
46
+ | PropertyAssignment
47
+ | TypeReferenceNode
48
+ | PropertySignature
49
+ | PropertyAccessExpression
50
+ | ShorthandPropertyAssignment
51
+ ): Node => {
52
+ const identifierChildren = node.getChildrenOfKind(SyntaxKind.Identifier)
53
+ if (identifierChildren.length === 2) {
54
+ return findNodeImplementation(identifierChildren[1])
55
+ }
56
+ const lastMatchingChild = node.getChildren().reverse()
57
+ return lastMatchingChild.find(
58
+ (child) =>
59
+ child.getKind() !== SyntaxKind.GreaterThanToken &&
60
+ child.getKind() !== SyntaxKind.CommaToken &&
61
+ child.getKind() !== SyntaxKind.SemicolonToken
62
+ )!
63
+ }
64
+
65
+ export const getTypeReferenceShape = (node: TypeReferenceNode): ShapeOfType['shape'] => {
66
+ const firstChild = node.getFirstChild()!
67
+ if (firstChild.isKind(SyntaxKind.SyntaxList)) {
68
+ return getRecursiveNodeShape(firstChild.getFirstChild()!)
69
+ } else {
70
+ return getRecursiveNodeShape(firstChild)
71
+ }
72
+ }
73
+
74
+ export const getRecursiveNodeShape = (nodeOrReference: Node): ShapeOfType['shape'] => {
75
+ const typeName = nodeOrReference.getSymbol()?.getName()
76
+ if (typeName && OpenApiManager.getInstance().hasExposedModel(typeName)) {
77
+ return [
78
+ {
79
+ role: 'ref',
80
+ shape: typeName,
81
+ optional: false,
82
+ },
83
+ ]
84
+ }
85
+
86
+ const node = findNodeImplementation(nodeOrReference)
87
+
88
+ // Undefined
89
+ const undefinedNode = node.asKind(SyntaxKind.UndefinedKeyword)
90
+ if (undefinedNode) {
91
+ return 'undefined'
92
+ }
93
+
94
+ // Literal type
95
+ const literalNode = node.asKind(SyntaxKind.LiteralType)
96
+ if (literalNode) {
97
+ if (literalNode.getFirstChildByKind(SyntaxKind.TrueKeyword)) {
98
+ return 'true'
99
+ }
100
+ if (literalNode.getFirstChildByKind(SyntaxKind.FalseKeyword)) {
101
+ return 'false'
102
+ }
103
+ }
104
+
105
+ // Boolean literal
106
+ const booleanLiteralNode =
107
+ node.asKind(SyntaxKind.BooleanKeyword) ||
108
+ node.asKind(SyntaxKind.TrueKeyword) ||
109
+ node.asKind(SyntaxKind.FalseKeyword)
110
+ if (booleanLiteralNode) {
111
+ return 'boolean'
112
+ }
113
+
114
+ // String literal
115
+ const stringLiteralNode = node.asKind(SyntaxKind.StringKeyword) || node.asKind(SyntaxKind.StringLiteral)
116
+ if (stringLiteralNode) {
117
+ return 'string'
118
+ }
119
+
120
+ // Number literal
121
+ const numberLiteralNode = node.asKind(SyntaxKind.NumberKeyword) || node.asKind(SyntaxKind.NumericLiteral)
122
+ if (numberLiteralNode) {
123
+ return 'number'
124
+ }
125
+
126
+ // BigInt literal
127
+ const bigIntNode = node.asKind(SyntaxKind.BigIntKeyword) || node.asKind(SyntaxKind.BigIntLiteral)
128
+ if (bigIntNode) {
129
+ return 'bigint'
130
+ }
131
+
132
+ // Type literal
133
+ const typeLiteralNode = node.asKind(SyntaxKind.TypeLiteral)
134
+ if (typeLiteralNode) {
135
+ const properties = typeLiteralNode
136
+ .getFirstChildByKind(SyntaxKind.SyntaxList)!
137
+ .getChildrenOfKind(SyntaxKind.PropertySignature)
138
+
139
+ const propertyShapes = properties.map((propNode) => {
140
+ const identifier = propNode.getFirstChildByKind(SyntaxKind.Identifier)!
141
+ const valueNode = findPropertyAssignmentValueNode(propNode)
142
+ const questionMarkToken = identifier.getNextSiblingIfKind(SyntaxKind.QuestionToken)
143
+ return {
144
+ role: 'property' as const,
145
+ identifier: identifier.getText(),
146
+ shape: getRecursiveNodeShape(valueNode),
147
+ optional: valueNode.getType().isNullable() || !!questionMarkToken,
148
+ }
149
+ })
150
+ return propertyShapes
151
+ }
152
+
153
+ // Type reference
154
+ const typeReferenceNode = node.asKind(SyntaxKind.TypeReference)
155
+ if (typeReferenceNode) {
156
+ return getRecursiveNodeShape(typeReferenceNode.getFirstChild()!)
157
+ }
158
+
159
+ // Property access expression
160
+ const propertyAccessNode = node.asKind(SyntaxKind.PropertyAccessExpression)
161
+ if (propertyAccessNode) {
162
+ const lastChild = findNodeImplementation(node.getLastChild()!)
163
+ return getProperTypeShape(lastChild.asKind(SyntaxKind.CallExpression)!.getReturnType(), lastChild)
164
+ }
165
+
166
+ // Union type
167
+ const unionTypeNode = node.asKind(SyntaxKind.UnionType)
168
+ if (unionTypeNode) {
169
+ return getProperTypeShape(unionTypeNode.getType(), node)
170
+ }
171
+
172
+ // Typeof query
173
+ const typeQueryNode = node.asKind(SyntaxKind.TypeQuery)
174
+ if (typeQueryNode) {
175
+ return getRecursiveNodeShape(typeQueryNode.getLastChild()!)
176
+ }
177
+
178
+ // Qualified name
179
+ const qualifiedNameNode = node.asKind(SyntaxKind.QualifiedName)
180
+ if (qualifiedNameNode) {
181
+ return getRecursiveNodeShape(qualifiedNameNode.getLastChild()!)
182
+ }
183
+
184
+ // Call expression
185
+ const callExpressionNode = node.asKind(SyntaxKind.CallExpression)
186
+ if (callExpressionNode) {
187
+ return getProperTypeShape(callExpressionNode.getReturnType(), callExpressionNode)
188
+ }
189
+
190
+ // Await expression
191
+ const awaitExpressionNode = node.asKind(SyntaxKind.AwaitExpression)
192
+ if (awaitExpressionNode) {
193
+ return getRecursiveNodeShape(awaitExpressionNode.getChildAtIndex(1)!)
194
+ }
195
+
196
+ // 'As' Expression
197
+ const asExpressionNode = node.asKind(SyntaxKind.AsExpression)
198
+ if (asExpressionNode) {
199
+ return getRecursiveNodeShape(asExpressionNode.getChildAtIndex(2)!)
200
+ }
201
+
202
+ // TODO
203
+ return 'unknown_1'
204
+ }
205
+
206
+ export const getShapeOfValidatorLiteral = (
207
+ objectLiteralNode: Node<ts.ObjectLiteralExpression>
208
+ ): (ShapeOfProperty & { description: string; errorMessage: string })[] => {
209
+ const syntaxListNode = objectLiteralNode.getFirstDescendantByKind(SyntaxKind.SyntaxList)!
210
+ const assignmentNodes = syntaxListNode.getChildrenOfKind(SyntaxKind.PropertyAssignment)!
211
+
212
+ const properties = assignmentNodes.map((node) => {
213
+ const identifierNode = node.getFirstChild()!
214
+ const identifierName = (() => {
215
+ if (identifierNode.isKind(SyntaxKind.Identifier)) {
216
+ return identifierNode.getText()
217
+ }
218
+ if (identifierNode.isKind(SyntaxKind.StringLiteral)) {
219
+ return identifierNode.getLiteralText()
220
+ }
221
+ return 'unknown_30'
222
+ })()
223
+
224
+ const assignmentValueNode = node.getLastChild()!
225
+ const innerLiteralNode = findNodeImplementation(assignmentValueNode)
226
+
227
+ return {
228
+ role: 'property' as const,
229
+ identifier: identifierName,
230
+ shape: getValidatorPropertyShape(innerLiteralNode),
231
+ optional: getValidatorPropertyOptionality(innerLiteralNode),
232
+ description: getValidatorPropertyStringValue(innerLiteralNode, 'description'),
233
+ errorMessage: getValidatorPropertyStringValue(innerLiteralNode, 'errorMessage'),
234
+ }
235
+ })
236
+
237
+ return properties || []
238
+ }
239
+
240
+ export const getValidatorPropertyShape = (innerLiteralNode: Node): ShapeOfType['shape'] => {
241
+ // Inline definition with `as Validator<...>` clause
242
+ const inlineValidatorAsExpression = innerLiteralNode
243
+ .getParent()!
244
+ .getFirstChildByKind(SyntaxKind.AsExpression)
245
+ if (inlineValidatorAsExpression) {
246
+ const typeReference = inlineValidatorAsExpression.getLastChildByKind(SyntaxKind.TypeReference)!
247
+ return getTypeReferenceShape(typeReference)
248
+ }
249
+
250
+ // Variable with `: Validator<...>` clause
251
+ const childTypeReferenceNode = innerLiteralNode.getParent()!.getFirstChildByKind(SyntaxKind.TypeReference)
252
+ if (childTypeReferenceNode) {
253
+ return getTypeReferenceShape(childTypeReferenceNode)
254
+ }
255
+
256
+ // `RequiredParam<...>` inline call expression
257
+ if (innerLiteralNode.getParent()!.getChildrenOfKind(SyntaxKind.SyntaxList).length >= 2) {
258
+ const typeNode = innerLiteralNode
259
+ .getParent()!
260
+ .getFirstChildByKind(SyntaxKind.SyntaxList)!
261
+ .getFirstChild()!
262
+ return getRecursiveNodeShape(typeNode)
263
+ }
264
+
265
+ // `RequestParam | RequiredParam | OptionalParam` call expression
266
+ const childCallExpressionNode = innerLiteralNode.getParent()!.getFirstChildByKind(SyntaxKind.CallExpression)
267
+ if (childCallExpressionNode) {
268
+ const callExpressionArgument = findNodeImplementation(
269
+ childCallExpressionNode.getFirstChildByKind(SyntaxKind.SyntaxList)!.getFirstChild()!
270
+ )
271
+
272
+ // Param is a type reference
273
+ const typeReferenceNode = callExpressionArgument
274
+ .getParent()!
275
+ .getFirstChildByKind(SyntaxKind.TypeReference)!
276
+ if (typeReferenceNode) {
277
+ return getProperTypeShape(typeReferenceNode.getType(), typeReferenceNode, [])
278
+ }
279
+
280
+ const thingyNode = callExpressionArgument
281
+ .getParent()!
282
+ .getFirstChildByKind(SyntaxKind.ObjectLiteralExpression)!
283
+ if (thingyNode) {
284
+ return getValidatorPropertyShape(thingyNode)
285
+ }
286
+
287
+ if (callExpressionArgument.getKind() === SyntaxKind.CallExpression) {
288
+ return getValidatorPropertyShape(callExpressionArgument)
289
+ }
290
+
291
+ if (callExpressionArgument.getKind() === SyntaxKind.IntersectionType) {
292
+ return getValidatorPropertyShape(callExpressionArgument)
293
+ }
294
+ return 'unknown_3'
295
+ }
296
+
297
+ // Attempting to infer type from `parse` function
298
+ const innerNodePropertyAssignments = innerLiteralNode
299
+ .getFirstChildByKind(SyntaxKind.SyntaxList)!
300
+ .getChildrenOfKind(SyntaxKind.PropertyAssignment)
301
+ const parsePropertyAssignment = innerNodePropertyAssignments.find((prop) => {
302
+ return prop.getFirstChildByKind(SyntaxKind.Identifier)?.getText() === 'parse'
303
+ })
304
+ if (parsePropertyAssignment) {
305
+ const returnType = findPropertyAssignmentValueNode(parsePropertyAssignment)
306
+ .asKind(SyntaxKind.ArrowFunction)!
307
+ .getReturnType()
308
+ return getProperTypeShape(returnType, parsePropertyAssignment)
309
+ }
310
+
311
+ // Import statement
312
+ const importTypeNode = innerLiteralNode
313
+ .getFirstChildByKind(SyntaxKind.SyntaxList)
314
+ ?.getFirstChildByKind(SyntaxKind.ImportType)
315
+ if (importTypeNode) {
316
+ const indexOfGreaterThanToken = importTypeNode
317
+ .getLastChildByKind(SyntaxKind.GreaterThanToken)!
318
+ .getChildIndex()
319
+ const targetSyntaxList = importTypeNode.getChildAtIndex(indexOfGreaterThanToken - 1)
320
+ return getRecursiveNodeShape(targetSyntaxList.getFirstChild()!)
321
+ }
322
+
323
+ return 'unknown_2'
324
+ }
325
+
326
+ export const getValidatorPropertyOptionality = (node: Node): boolean => {
327
+ const callExpressionNode = node.asKind(SyntaxKind.CallExpression)
328
+ if (callExpressionNode) {
329
+ const identifierNode = callExpressionNode.getFirstChildByKind(SyntaxKind.Identifier)
330
+ if (identifierNode?.getText() === 'OptionalParam') {
331
+ return true
332
+ } else if (identifierNode?.getText() === 'RequiredParam') {
333
+ return false
334
+ }
335
+
336
+ const syntaxListNode = callExpressionNode.getFirstChildByKind(SyntaxKind.SyntaxList)!
337
+ const literalExpression = findNodeImplementation(syntaxListNode.getFirstChild()!)
338
+ return getValidatorPropertyOptionality(literalExpression)
339
+ }
340
+
341
+ const syntaxListNode = node.getFirstDescendantByKind(SyntaxKind.SyntaxList)!
342
+ const assignmentNodes = syntaxListNode.getChildrenOfKind(SyntaxKind.PropertyAssignment)!
343
+
344
+ return assignmentNodes.some((node) => {
345
+ const identifierNode = node.getFirstDescendantByKind(SyntaxKind.Identifier)!
346
+ const identifierName = identifierNode.getText()
347
+
348
+ if (identifierName === 'optional') {
349
+ const value = findPropertyAssignmentValueNode(node)
350
+ return value.getKind() === SyntaxKind.TrueKeyword
351
+ }
352
+ return false
353
+ })
354
+ }
355
+
356
+ export const getValidatorPropertyStringValue = (
357
+ nodeOrReference: Node,
358
+ name: 'description' | 'errorMessage'
359
+ ): string => {
360
+ const node = findNodeImplementation(nodeOrReference)
361
+
362
+ const callExpressionNode = node.asKind(SyntaxKind.CallExpression)
363
+ if (callExpressionNode) {
364
+ const targetChild = callExpressionNode.getLastChildByKind(SyntaxKind.SyntaxList)!
365
+ return getValidatorPropertyStringValue(targetChild, name)
366
+ }
367
+
368
+ const syntaxListNode = node.asKind(SyntaxKind.SyntaxList)
369
+ if (syntaxListNode) {
370
+ const children = syntaxListNode.getChildren().map((c) => getValidatorPropertyStringValue(c, name))
371
+ return children.find((value) => !!value && value !== 'unknown_25') || ''
372
+ }
373
+
374
+ const objectLiteralNode = node.asKind(SyntaxKind.ObjectLiteralExpression)
375
+ if (objectLiteralNode) {
376
+ const values = getValuesOfObjectLiteral(objectLiteralNode)
377
+ const targetValue = values.find((value) => value.identifier === name)
378
+ if (!targetValue) {
379
+ return ''
380
+ }
381
+ if (Array.isArray(targetValue.value)) {
382
+ return 'array'
383
+ }
384
+ return targetValue.value || ''
385
+ }
386
+
387
+ const intersectionTypeNode = node.asKind(SyntaxKind.IntersectionType)
388
+ if (intersectionTypeNode) {
389
+ return (
390
+ intersectionTypeNode
391
+ .getTypeNodes()
392
+ .flatMap((t) => getValidatorPropertyStringValue(t, name))
393
+ .filter((v) => !!v && v !== 'unknown_25')[0] || 'unknown_27'
394
+ )
395
+ }
396
+
397
+ const typeLiteralNode = node.asKind(SyntaxKind.TypeLiteral)
398
+ if (typeLiteralNode) {
399
+ return getValidatorPropertyStringValue(typeLiteralNode.getFirstChildByKind(SyntaxKind.SyntaxList)!, name)
400
+ }
401
+
402
+ const propertySignatureNode = node.asKind(SyntaxKind.PropertySignature)
403
+ if (propertySignatureNode) {
404
+ const identifier = node.getFirstDescendantByKind(SyntaxKind.Identifier)!
405
+ if (identifier.getText() === name) {
406
+ const targetNode = findPropertyAssignmentValueNode(propertySignatureNode).getFirstDescendantByKind(
407
+ SyntaxKind.StringLiteral
408
+ )!
409
+ return targetNode.getLiteralText()
410
+ }
411
+ }
412
+
413
+ return 'unknown_25'
414
+ }
415
+
416
+ const isPromise = (type: Type) => {
417
+ const symbol = type.getSymbol()
418
+ if (!type.isObject() || !symbol) {
419
+ return false
420
+ }
421
+ const args = type.getTypeArguments()
422
+ return symbol.getName() === 'Promise' && args.length === 1
423
+ }
424
+
425
+ export const getProperTypeShape = (
426
+ typeOrPromise: Type,
427
+ atLocation: Node,
428
+ stack: Type[] = []
429
+ ): ShapeOfType['shape'] => {
430
+ const typeName = typeOrPromise.getAliasSymbol()?.getName()
431
+ if (typeName && OpenApiManager.getInstance().hasExposedModel(typeName)) {
432
+ return [
433
+ {
434
+ role: 'ref',
435
+ shape: typeName,
436
+ optional: false,
437
+ },
438
+ ]
439
+ }
440
+
441
+ const type = isPromise(typeOrPromise) ? typeOrPromise.getTypeArguments()[0] : typeOrPromise
442
+
443
+ if (stack.some((previousType) => previousType === type)) {
444
+ return 'circular'
445
+ }
446
+
447
+ const nextStack = stack.concat(type)
448
+
449
+ if (type.getText() === 'void') {
450
+ return 'void'
451
+ }
452
+
453
+ if (type.isAny()) {
454
+ return 'any'
455
+ }
456
+
457
+ if (type.isNull()) {
458
+ return 'null'
459
+ }
460
+
461
+ if (type.isUndefined()) {
462
+ return 'undefined'
463
+ }
464
+
465
+ if (type.isBoolean() || type.isBooleanLiteral()) {
466
+ return 'boolean'
467
+ }
468
+
469
+ if (type.isStringLiteral()) {
470
+ return [
471
+ {
472
+ role: 'literal_string' as const,
473
+ shape: String(type.getLiteralValue()!),
474
+ optional: false,
475
+ },
476
+ ]
477
+ }
478
+
479
+ if (type.isNumberLiteral()) {
480
+ return [
481
+ {
482
+ role: 'literal_number' as const,
483
+ shape: String(type.getLiteralValue()!),
484
+ optional: false,
485
+ },
486
+ ]
487
+ }
488
+
489
+ if (type.isString() || type.isTemplateLiteral()) {
490
+ return 'string'
491
+ }
492
+
493
+ if (type.isNumber()) {
494
+ return 'number'
495
+ }
496
+
497
+ if (type.getText() === 'bigint') {
498
+ return 'bigint'
499
+ }
500
+
501
+ if (type.isTuple()) {
502
+ return [
503
+ {
504
+ role: 'tuple' as const,
505
+ shape: type.getTupleElements().map((t) => ({
506
+ role: 'tuple_entry' as const,
507
+ shape: getProperTypeShape(t, atLocation, nextStack),
508
+ optional: false,
509
+ })),
510
+ optional: false,
511
+ },
512
+ ]
513
+ }
514
+
515
+ if (type.isArray()) {
516
+ return [
517
+ {
518
+ role: 'array' as const,
519
+ shape: getProperTypeShape(type.getArrayElementType()!, atLocation, nextStack),
520
+ optional: false,
521
+ },
522
+ ]
523
+ }
524
+
525
+ if (type.isObject() && type.getProperties().length === 0) {
526
+ const targetType = type.getAliasTypeArguments()[1]
527
+ return [
528
+ {
529
+ role: 'record' as const,
530
+ shape: getProperTypeShape(targetType, atLocation, nextStack),
531
+ optional: false,
532
+ },
533
+ ]
534
+ }
535
+
536
+ if (type.isObject()) {
537
+ if (type.getText() === 'Date') {
538
+ return 'Date'
539
+ }
540
+ return type
541
+ .getProperties()
542
+ .map((prop) => {
543
+ const valueDeclaration = prop.getValueDeclaration() || prop.getDeclarations()[0]!
544
+ if (!valueDeclaration) {
545
+ return {
546
+ role: 'property' as const,
547
+ identifier: prop.getName(),
548
+ shape: getProperTypeShape(prop.getTypeAtLocation(atLocation), atLocation, nextStack),
549
+ optional: false,
550
+ }
551
+ }
552
+ const valueDeclarationNode =
553
+ valueDeclaration.asKind(SyntaxKind.PropertySignature) ||
554
+ valueDeclaration.asKind(SyntaxKind.PropertyAssignment) ||
555
+ valueDeclaration.asKind(SyntaxKind.ShorthandPropertyAssignment)
556
+
557
+ if (!valueDeclarationNode) {
558
+ return {
559
+ role: 'property' as const,
560
+ identifier: prop.getName(),
561
+ shape: getProperTypeShape(prop.getTypeAtLocation(atLocation), atLocation, nextStack),
562
+ optional: false,
563
+ }
564
+ }
565
+
566
+ const isOptional = prop.getTypeAtLocation(atLocation).isNullable()
567
+
568
+ const shape = getProperTypeShape(prop.getTypeAtLocation(atLocation), atLocation, nextStack)
569
+ return {
570
+ role: 'property' as const,
571
+ identifier: prop.getName(),
572
+ shape: shape,
573
+ optional: isOptional,
574
+ }
575
+ })
576
+ .filter((val) => val.shape !== 'undefined')
577
+ }
578
+
579
+ if (type.isUnion()) {
580
+ const unfilteredShapes: ShapeOfUnionEntry[] = type.getUnionTypes().map((type) => ({
581
+ role: 'union_entry',
582
+ shape: getProperTypeShape(type, atLocation, nextStack),
583
+ optional: false,
584
+ }))
585
+
586
+ const dedupedShapes = unfilteredShapes.filter(
587
+ (type, index, arr) => !arr.find((dup, dupIndex) => dup.shape === type.shape && dupIndex > index)
588
+ )
589
+ const isNullable = dedupedShapes.some((shape) => shape.shape === 'undefined')
590
+ const shapes = dedupedShapes.filter((shape) => shape.shape !== 'undefined')
591
+ if (shapes.length === 1) {
592
+ return shapes[0].shape
593
+ }
594
+ return [
595
+ {
596
+ role: 'union',
597
+ shape: shapes,
598
+ optional: isNullable,
599
+ },
600
+ ]
601
+ }
602
+
603
+ if (type.isIntersection()) {
604
+ const children = type.getIntersectionTypes()
605
+ const shapesOfChildren = children
606
+ .map((child) => getProperTypeShape(child, atLocation, nextStack))
607
+ .filter((shape) => typeof shape !== 'string') as ShapeOfProperty[][]
608
+ return shapesOfChildren.reduce<ShapeOfType[]>((total, current) => [...total, ...current], [])
609
+ }
610
+
611
+ return 'unknown_5'
612
+ }
613
+
614
+ const getLiteralValueOfNode = (node: Node): string | string[] | unknown[] => {
615
+ if (node.isKind(SyntaxKind.Identifier)) {
616
+ return getLiteralValueOfNode(findNodeImplementation(node))
617
+ } else if (node.isKind(SyntaxKind.StringLiteral)) {
618
+ return node.getLiteralValue()
619
+ } else if (node.isKind(SyntaxKind.ArrayLiteralExpression)) {
620
+ return node.forEachChildAsArray().map((child) => getLiteralValueOfNode(child)) as string[]
621
+ } else if (node.isKind(SyntaxKind.PropertyAccessExpression)) {
622
+ return getLiteralValueOfNode(findPropertyAssignmentValueNode(node))
623
+ } else if (node.isKind(SyntaxKind.ObjectLiteralExpression)) {
624
+ return getValuesOfObjectLiteral(node)
625
+ }
626
+ return 'unknown_6'
627
+ }
628
+
629
+ export const getValuesOfObjectLiteral = (objectLiteralNode: Node<ts.ObjectLiteralExpression>) => {
630
+ const syntaxListNode = objectLiteralNode.getFirstDescendantByKind(SyntaxKind.SyntaxList)!
631
+ const assignmentNodes = syntaxListNode.getChildrenOfKind(SyntaxKind.PropertyAssignment)!
632
+
633
+ const properties = assignmentNodes.map((node) => {
634
+ const identifierNode = node.getFirstDescendantByKind(SyntaxKind.Identifier)!
635
+ const identifierName = identifierNode.getText()
636
+
637
+ const assignmentValueNode = node.getLastChild()!
638
+ const targetNode = findNodeImplementation(assignmentValueNode)
639
+ const value = getLiteralValueOfNode(targetNode)
640
+
641
+ return {
642
+ identifier: identifierName,
643
+ value,
644
+ }
645
+ })
646
+
647
+ return properties || []
648
+ }