moonflower 1.2.0 → 1.3.1

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 (435) hide show
  1. package/cli/entry.cjs +1 -1
  2. package/dist/cli/cli.cjs +2 -0
  3. package/dist/cli/cli.cjs.map +1 -0
  4. package/dist/cli/cli.d.ts +2 -0
  5. package/dist/cli/cli.d.ts.map +1 -0
  6. package/dist/cli/cli.mjs +62 -0
  7. package/dist/cli/cli.mjs.map +1 -0
  8. package/dist/cli/prettyprint.cjs +2 -0
  9. package/dist/cli/prettyprint.cjs.map +1 -0
  10. package/dist/cli/prettyprint.d.ts +5 -0
  11. package/dist/cli/prettyprint.d.ts.map +1 -0
  12. package/dist/cli/prettyprint.mjs +15 -0
  13. package/dist/cli/prettyprint.mjs.map +1 -0
  14. package/dist/errors/UserFacingErrors.cjs +1 -1
  15. package/dist/errors/UserFacingErrors.cjs.map +1 -1
  16. package/dist/errors/UserFacingErrors.d.ts +27 -0
  17. package/dist/errors/UserFacingErrors.d.ts.map +1 -1
  18. package/dist/errors/UserFacingErrors.mjs +67 -13
  19. package/dist/errors/UserFacingErrors.mjs.map +1 -1
  20. package/dist/hooks/usePathParams.cjs +1 -1
  21. package/dist/hooks/usePathParams.cjs.map +1 -1
  22. package/dist/hooks/usePathParams.d.ts.map +1 -1
  23. package/dist/hooks/usePathParams.mjs +20 -27
  24. package/dist/hooks/usePathParams.mjs.map +1 -1
  25. package/dist/hooks/useQueryParams.cjs +1 -1
  26. package/dist/hooks/useQueryParams.cjs.map +1 -1
  27. package/dist/hooks/useQueryParams.d.ts +4 -3
  28. package/dist/hooks/useQueryParams.d.ts.map +1 -1
  29. package/dist/hooks/useQueryParams.mjs +24 -33
  30. package/dist/hooks/useQueryParams.mjs.map +1 -1
  31. package/dist/hooks/useRequestBody.cjs +1 -1
  32. package/dist/hooks/useRequestBody.cjs.map +1 -1
  33. package/dist/hooks/useRequestBody.d.ts +4 -3
  34. package/dist/hooks/useRequestBody.d.ts.map +1 -1
  35. package/dist/hooks/useRequestBody.mjs +23 -34
  36. package/dist/hooks/useRequestBody.mjs.map +1 -1
  37. package/dist/index.cjs +1 -1
  38. package/dist/index.mjs +64 -55
  39. package/dist/node_modules/zod/index.cjs +2 -0
  40. package/dist/node_modules/zod/index.cjs.map +1 -0
  41. package/dist/node_modules/zod/index.mjs +6 -0
  42. package/dist/node_modules/zod/index.mjs.map +1 -0
  43. package/dist/node_modules/zod/v4/classic/checks.cjs +2 -0
  44. package/dist/node_modules/zod/v4/classic/checks.cjs.map +1 -0
  45. package/dist/node_modules/zod/v4/classic/checks.mjs +34 -0
  46. package/dist/node_modules/zod/v4/classic/checks.mjs.map +1 -0
  47. package/dist/node_modules/zod/v4/classic/coerce.cjs +2 -0
  48. package/dist/node_modules/zod/v4/classic/coerce.cjs.map +1 -0
  49. package/dist/node_modules/zod/v4/classic/coerce.mjs +26 -0
  50. package/dist/node_modules/zod/v4/classic/coerce.mjs.map +1 -0
  51. package/dist/node_modules/zod/v4/classic/compat.cjs +2 -0
  52. package/dist/node_modules/zod/v4/classic/compat.cjs.map +1 -0
  53. package/dist/node_modules/zod/v4/classic/compat.mjs +35 -0
  54. package/dist/node_modules/zod/v4/classic/compat.mjs.map +1 -0
  55. package/dist/node_modules/zod/v4/classic/errors.cjs +2 -0
  56. package/dist/node_modules/zod/v4/classic/errors.cjs.map +1 -0
  57. package/dist/node_modules/zod/v4/classic/errors.mjs +41 -0
  58. package/dist/node_modules/zod/v4/classic/errors.mjs.map +1 -0
  59. package/dist/node_modules/zod/v4/classic/external.cjs +2 -0
  60. package/dist/node_modules/zod/v4/classic/external.cjs.map +1 -0
  61. package/dist/node_modules/zod/v4/classic/external.mjs +260 -0
  62. package/dist/node_modules/zod/v4/classic/external.mjs.map +1 -0
  63. package/dist/node_modules/zod/v4/classic/from-json-schema.cjs +2 -0
  64. package/dist/node_modules/zod/v4/classic/from-json-schema.cjs.map +1 -0
  65. package/dist/node_modules/zod/v4/classic/from-json-schema.mjs +287 -0
  66. package/dist/node_modules/zod/v4/classic/from-json-schema.mjs.map +1 -0
  67. package/dist/node_modules/zod/v4/classic/iso.cjs +2 -0
  68. package/dist/node_modules/zod/v4/classic/iso.cjs.map +1 -0
  69. package/dist/node_modules/zod/v4/classic/iso.mjs +40 -0
  70. package/dist/node_modules/zod/v4/classic/iso.mjs.map +1 -0
  71. package/dist/node_modules/zod/v4/classic/parse.cjs +2 -0
  72. package/dist/node_modules/zod/v4/classic/parse.cjs.map +1 -0
  73. package/dist/node_modules/zod/v4/classic/parse.mjs +19 -0
  74. package/dist/node_modules/zod/v4/classic/parse.mjs.map +1 -0
  75. package/dist/node_modules/zod/v4/classic/schemas.cjs +2 -0
  76. package/dist/node_modules/zod/v4/classic/schemas.cjs.map +1 -0
  77. package/dist/node_modules/zod/v4/classic/schemas.mjs +912 -0
  78. package/dist/node_modules/zod/v4/classic/schemas.mjs.map +1 -0
  79. package/dist/node_modules/zod/v4/core/api.cjs +2 -0
  80. package/dist/node_modules/zod/v4/core/api.cjs.map +1 -0
  81. package/dist/node_modules/zod/v4/core/api.mjs +1110 -0
  82. package/dist/node_modules/zod/v4/core/api.mjs.map +1 -0
  83. package/dist/node_modules/zod/v4/core/checks.cjs +2 -0
  84. package/dist/node_modules/zod/v4/core/checks.cjs.map +1 -0
  85. package/dist/node_modules/zod/v4/core/checks.mjs +421 -0
  86. package/dist/node_modules/zod/v4/core/checks.mjs.map +1 -0
  87. package/dist/node_modules/zod/v4/core/core.cjs +2 -0
  88. package/dist/node_modules/zod/v4/core/core.cjs.map +1 -0
  89. package/dist/node_modules/zod/v4/core/core.mjs +62 -0
  90. package/dist/node_modules/zod/v4/core/core.mjs.map +1 -0
  91. package/dist/node_modules/zod/v4/core/doc.cjs +4 -0
  92. package/dist/node_modules/zod/v4/core/doc.cjs.map +1 -0
  93. package/dist/node_modules/zod/v4/core/doc.mjs +27 -0
  94. package/dist/node_modules/zod/v4/core/doc.mjs.map +1 -0
  95. package/dist/node_modules/zod/v4/core/errors.cjs +3 -0
  96. package/dist/node_modules/zod/v4/core/errors.cjs.map +1 -0
  97. package/dist/node_modules/zod/v4/core/errors.mjs +89 -0
  98. package/dist/node_modules/zod/v4/core/errors.mjs.map +1 -0
  99. package/dist/node_modules/zod/v4/core/index.cjs +2 -0
  100. package/dist/node_modules/zod/v4/core/index.cjs.map +1 -0
  101. package/dist/node_modules/zod/v4/core/index.mjs +293 -0
  102. package/dist/node_modules/zod/v4/core/index.mjs.map +1 -0
  103. package/dist/node_modules/zod/v4/core/json-schema-generator.cjs +2 -0
  104. package/dist/node_modules/zod/v4/core/json-schema-generator.cjs.map +1 -0
  105. package/dist/node_modules/zod/v4/core/json-schema-generator.mjs +66 -0
  106. package/dist/node_modules/zod/v4/core/json-schema-generator.mjs.map +1 -0
  107. package/dist/node_modules/zod/v4/core/json-schema-processors.cjs +2 -0
  108. package/dist/node_modules/zod/v4/core/json-schema-processors.cjs.map +1 -0
  109. package/dist/node_modules/zod/v4/core/json-schema-processors.mjs +346 -0
  110. package/dist/node_modules/zod/v4/core/json-schema-processors.mjs.map +1 -0
  111. package/dist/node_modules/zod/v4/core/json-schema.cjs +2 -0
  112. package/dist/node_modules/zod/v4/core/json-schema.cjs.map +1 -0
  113. package/dist/node_modules/zod/v4/core/json-schema.mjs +2 -0
  114. package/dist/node_modules/zod/v4/core/json-schema.mjs.map +1 -0
  115. package/dist/node_modules/zod/v4/core/parse.cjs +2 -0
  116. package/dist/node_modules/zod/v4/core/parse.cjs.map +1 -0
  117. package/dist/node_modules/zod/v4/core/parse.mjs +75 -0
  118. package/dist/node_modules/zod/v4/core/parse.mjs.map +1 -0
  119. package/dist/node_modules/zod/v4/core/regexes.cjs +2 -0
  120. package/dist/node_modules/zod/v4/core/regexes.cjs.map +1 -0
  121. package/dist/node_modules/zod/v4/core/regexes.mjs +94 -0
  122. package/dist/node_modules/zod/v4/core/regexes.mjs.map +1 -0
  123. package/dist/node_modules/zod/v4/core/registries.cjs +2 -0
  124. package/dist/node_modules/zod/v4/core/registries.cjs.map +1 -0
  125. package/dist/node_modules/zod/v4/core/registries.mjs +44 -0
  126. package/dist/node_modules/zod/v4/core/registries.mjs.map +1 -0
  127. package/dist/node_modules/zod/v4/core/schemas.cjs +36 -0
  128. package/dist/node_modules/zod/v4/core/schemas.cjs.map +1 -0
  129. package/dist/node_modules/zod/v4/core/schemas.mjs +1319 -0
  130. package/dist/node_modules/zod/v4/core/schemas.mjs.map +1 -0
  131. package/dist/node_modules/zod/v4/core/to-json-schema.cjs +4 -0
  132. package/dist/node_modules/zod/v4/core/to-json-schema.cjs.map +1 -0
  133. package/dist/node_modules/zod/v4/core/to-json-schema.mjs +244 -0
  134. package/dist/node_modules/zod/v4/core/to-json-schema.mjs.map +1 -0
  135. package/dist/node_modules/zod/v4/core/util.cjs +2 -0
  136. package/dist/node_modules/zod/v4/core/util.cjs.map +1 -0
  137. package/dist/node_modules/zod/v4/core/util.mjs +523 -0
  138. package/dist/node_modules/zod/v4/core/util.mjs.map +1 -0
  139. package/dist/node_modules/zod/v4/core/versions.cjs +2 -0
  140. package/dist/node_modules/zod/v4/core/versions.cjs.map +1 -0
  141. package/dist/node_modules/zod/v4/core/versions.mjs +9 -0
  142. package/dist/node_modules/zod/v4/core/versions.mjs.map +1 -0
  143. package/dist/node_modules/zod/v4/locales/ar.cjs +2 -0
  144. package/dist/node_modules/zod/v4/locales/ar.cjs.map +1 -0
  145. package/dist/node_modules/zod/v4/locales/ar.mjs +87 -0
  146. package/dist/node_modules/zod/v4/locales/ar.mjs.map +1 -0
  147. package/dist/node_modules/zod/v4/locales/az.cjs +2 -0
  148. package/dist/node_modules/zod/v4/locales/az.cjs.map +1 -0
  149. package/dist/node_modules/zod/v4/locales/az.mjs +87 -0
  150. package/dist/node_modules/zod/v4/locales/az.mjs.map +1 -0
  151. package/dist/node_modules/zod/v4/locales/be.cjs +2 -0
  152. package/dist/node_modules/zod/v4/locales/be.cjs.map +1 -0
  153. package/dist/node_modules/zod/v4/locales/be.mjs +129 -0
  154. package/dist/node_modules/zod/v4/locales/be.mjs.map +1 -0
  155. package/dist/node_modules/zod/v4/locales/bg.cjs +2 -0
  156. package/dist/node_modules/zod/v4/locales/bg.cjs.map +1 -0
  157. package/dist/node_modules/zod/v4/locales/bg.mjs +98 -0
  158. package/dist/node_modules/zod/v4/locales/bg.mjs.map +1 -0
  159. package/dist/node_modules/zod/v4/locales/ca.cjs +2 -0
  160. package/dist/node_modules/zod/v4/locales/ca.cjs.map +1 -0
  161. package/dist/node_modules/zod/v4/locales/ca.mjs +88 -0
  162. package/dist/node_modules/zod/v4/locales/ca.mjs.map +1 -0
  163. package/dist/node_modules/zod/v4/locales/cs.cjs +2 -0
  164. package/dist/node_modules/zod/v4/locales/cs.cjs.map +1 -0
  165. package/dist/node_modules/zod/v4/locales/cs.mjs +91 -0
  166. package/dist/node_modules/zod/v4/locales/cs.mjs.map +1 -0
  167. package/dist/node_modules/zod/v4/locales/da.cjs +2 -0
  168. package/dist/node_modules/zod/v4/locales/da.cjs.map +1 -0
  169. package/dist/node_modules/zod/v4/locales/da.mjs +94 -0
  170. package/dist/node_modules/zod/v4/locales/da.mjs.map +1 -0
  171. package/dist/node_modules/zod/v4/locales/de.cjs +2 -0
  172. package/dist/node_modules/zod/v4/locales/de.cjs.map +1 -0
  173. package/dist/node_modules/zod/v4/locales/de.mjs +89 -0
  174. package/dist/node_modules/zod/v4/locales/de.mjs.map +1 -0
  175. package/dist/node_modules/zod/v4/locales/en.cjs +2 -0
  176. package/dist/node_modules/zod/v4/locales/en.cjs.map +1 -0
  177. package/dist/node_modules/zod/v4/locales/en.mjs +91 -0
  178. package/dist/node_modules/zod/v4/locales/en.mjs.map +1 -0
  179. package/dist/node_modules/zod/v4/locales/eo.cjs +2 -0
  180. package/dist/node_modules/zod/v4/locales/eo.cjs.map +1 -0
  181. package/dist/node_modules/zod/v4/locales/eo.mjs +90 -0
  182. package/dist/node_modules/zod/v4/locales/eo.mjs.map +1 -0
  183. package/dist/node_modules/zod/v4/locales/es.cjs +2 -0
  184. package/dist/node_modules/zod/v4/locales/es.cjs.map +1 -0
  185. package/dist/node_modules/zod/v4/locales/es.mjs +111 -0
  186. package/dist/node_modules/zod/v4/locales/es.mjs.map +1 -0
  187. package/dist/node_modules/zod/v4/locales/fa.cjs +2 -0
  188. package/dist/node_modules/zod/v4/locales/fa.cjs.map +1 -0
  189. package/dist/node_modules/zod/v4/locales/fa.mjs +89 -0
  190. package/dist/node_modules/zod/v4/locales/fa.mjs.map +1 -0
  191. package/dist/node_modules/zod/v4/locales/fi.cjs +2 -0
  192. package/dist/node_modules/zod/v4/locales/fi.cjs.map +1 -0
  193. package/dist/node_modules/zod/v4/locales/fi.mjs +91 -0
  194. package/dist/node_modules/zod/v4/locales/fi.mjs.map +1 -0
  195. package/dist/node_modules/zod/v4/locales/fr-CA.cjs +2 -0
  196. package/dist/node_modules/zod/v4/locales/fr-CA.cjs.map +1 -0
  197. package/dist/node_modules/zod/v4/locales/fr-CA.mjs +87 -0
  198. package/dist/node_modules/zod/v4/locales/fr-CA.mjs.map +1 -0
  199. package/dist/node_modules/zod/v4/locales/fr.cjs +2 -0
  200. package/dist/node_modules/zod/v4/locales/fr.cjs.map +1 -0
  201. package/dist/node_modules/zod/v4/locales/fr.mjs +89 -0
  202. package/dist/node_modules/zod/v4/locales/fr.mjs.map +1 -0
  203. package/dist/node_modules/zod/v4/locales/he.cjs +2 -0
  204. package/dist/node_modules/zod/v4/locales/he.cjs.map +1 -0
  205. package/dist/node_modules/zod/v4/locales/he.mjs +152 -0
  206. package/dist/node_modules/zod/v4/locales/he.mjs.map +1 -0
  207. package/dist/node_modules/zod/v4/locales/hu.cjs +2 -0
  208. package/dist/node_modules/zod/v4/locales/hu.cjs.map +1 -0
  209. package/dist/node_modules/zod/v4/locales/hu.mjs +89 -0
  210. package/dist/node_modules/zod/v4/locales/hu.mjs.map +1 -0
  211. package/dist/node_modules/zod/v4/locales/hy.cjs +2 -0
  212. package/dist/node_modules/zod/v4/locales/hy.cjs.map +1 -0
  213. package/dist/node_modules/zod/v4/locales/hy.mjs +130 -0
  214. package/dist/node_modules/zod/v4/locales/hy.mjs.map +1 -0
  215. package/dist/node_modules/zod/v4/locales/id.cjs +2 -0
  216. package/dist/node_modules/zod/v4/locales/id.cjs.map +1 -0
  217. package/dist/node_modules/zod/v4/locales/id.mjs +87 -0
  218. package/dist/node_modules/zod/v4/locales/id.mjs.map +1 -0
  219. package/dist/node_modules/zod/v4/locales/index.cjs +2 -0
  220. package/dist/node_modules/zod/v4/locales/index.cjs.map +1 -0
  221. package/dist/node_modules/zod/v4/locales/index.mjs +101 -0
  222. package/dist/node_modules/zod/v4/locales/index.mjs.map +1 -0
  223. package/dist/node_modules/zod/v4/locales/is.cjs +2 -0
  224. package/dist/node_modules/zod/v4/locales/is.cjs.map +1 -0
  225. package/dist/node_modules/zod/v4/locales/is.mjs +89 -0
  226. package/dist/node_modules/zod/v4/locales/is.mjs.map +1 -0
  227. package/dist/node_modules/zod/v4/locales/it.cjs +2 -0
  228. package/dist/node_modules/zod/v4/locales/it.cjs.map +1 -0
  229. package/dist/node_modules/zod/v4/locales/it.mjs +89 -0
  230. package/dist/node_modules/zod/v4/locales/it.mjs.map +1 -0
  231. package/dist/node_modules/zod/v4/locales/ja.cjs +2 -0
  232. package/dist/node_modules/zod/v4/locales/ja.cjs.map +1 -0
  233. package/dist/node_modules/zod/v4/locales/ja.mjs +89 -0
  234. package/dist/node_modules/zod/v4/locales/ja.mjs.map +1 -0
  235. package/dist/node_modules/zod/v4/locales/ka.cjs +2 -0
  236. package/dist/node_modules/zod/v4/locales/ka.cjs.map +1 -0
  237. package/dist/node_modules/zod/v4/locales/ka.mjs +92 -0
  238. package/dist/node_modules/zod/v4/locales/ka.mjs.map +1 -0
  239. package/dist/node_modules/zod/v4/locales/kh.cjs +2 -0
  240. package/dist/node_modules/zod/v4/locales/kh.cjs.map +1 -0
  241. package/dist/node_modules/zod/v4/locales/kh.mjs +8 -0
  242. package/dist/node_modules/zod/v4/locales/kh.mjs.map +1 -0
  243. package/dist/node_modules/zod/v4/locales/km.cjs +2 -0
  244. package/dist/node_modules/zod/v4/locales/km.cjs.map +1 -0
  245. package/dist/node_modules/zod/v4/locales/km.mjs +90 -0
  246. package/dist/node_modules/zod/v4/locales/km.mjs.map +1 -0
  247. package/dist/node_modules/zod/v4/locales/ko.cjs +2 -0
  248. package/dist/node_modules/zod/v4/locales/ko.cjs.map +1 -0
  249. package/dist/node_modules/zod/v4/locales/ko.mjs +87 -0
  250. package/dist/node_modules/zod/v4/locales/ko.mjs.map +1 -0
  251. package/dist/node_modules/zod/v4/locales/lt.cjs +2 -0
  252. package/dist/node_modules/zod/v4/locales/lt.cjs.map +1 -0
  253. package/dist/node_modules/zod/v4/locales/lt.mjs +178 -0
  254. package/dist/node_modules/zod/v4/locales/lt.mjs.map +1 -0
  255. package/dist/node_modules/zod/v4/locales/mk.cjs +2 -0
  256. package/dist/node_modules/zod/v4/locales/mk.cjs.map +1 -0
  257. package/dist/node_modules/zod/v4/locales/mk.mjs +89 -0
  258. package/dist/node_modules/zod/v4/locales/mk.mjs.map +1 -0
  259. package/dist/node_modules/zod/v4/locales/ms.cjs +2 -0
  260. package/dist/node_modules/zod/v4/locales/ms.cjs.map +1 -0
  261. package/dist/node_modules/zod/v4/locales/ms.mjs +88 -0
  262. package/dist/node_modules/zod/v4/locales/ms.mjs.map +1 -0
  263. package/dist/node_modules/zod/v4/locales/nl.cjs +2 -0
  264. package/dist/node_modules/zod/v4/locales/nl.cjs.map +1 -0
  265. package/dist/node_modules/zod/v4/locales/nl.mjs +88 -0
  266. package/dist/node_modules/zod/v4/locales/nl.mjs.map +1 -0
  267. package/dist/node_modules/zod/v4/locales/no.cjs +2 -0
  268. package/dist/node_modules/zod/v4/locales/no.cjs.map +1 -0
  269. package/dist/node_modules/zod/v4/locales/no.mjs +89 -0
  270. package/dist/node_modules/zod/v4/locales/no.mjs.map +1 -0
  271. package/dist/node_modules/zod/v4/locales/ota.cjs +2 -0
  272. package/dist/node_modules/zod/v4/locales/ota.cjs.map +1 -0
  273. package/dist/node_modules/zod/v4/locales/ota.mjs +90 -0
  274. package/dist/node_modules/zod/v4/locales/ota.mjs.map +1 -0
  275. package/dist/node_modules/zod/v4/locales/pl.cjs +2 -0
  276. package/dist/node_modules/zod/v4/locales/pl.cjs.map +1 -0
  277. package/dist/node_modules/zod/v4/locales/pl.mjs +89 -0
  278. package/dist/node_modules/zod/v4/locales/pl.mjs.map +1 -0
  279. package/dist/node_modules/zod/v4/locales/ps.cjs +2 -0
  280. package/dist/node_modules/zod/v4/locales/ps.cjs.map +1 -0
  281. package/dist/node_modules/zod/v4/locales/ps.mjs +89 -0
  282. package/dist/node_modules/zod/v4/locales/ps.mjs.map +1 -0
  283. package/dist/node_modules/zod/v4/locales/pt.cjs +2 -0
  284. package/dist/node_modules/zod/v4/locales/pt.cjs.map +1 -0
  285. package/dist/node_modules/zod/v4/locales/pt.mjs +89 -0
  286. package/dist/node_modules/zod/v4/locales/pt.mjs.map +1 -0
  287. package/dist/node_modules/zod/v4/locales/ru.cjs +2 -0
  288. package/dist/node_modules/zod/v4/locales/ru.cjs.map +1 -0
  289. package/dist/node_modules/zod/v4/locales/ru.mjs +129 -0
  290. package/dist/node_modules/zod/v4/locales/ru.mjs.map +1 -0
  291. package/dist/node_modules/zod/v4/locales/sl.cjs +2 -0
  292. package/dist/node_modules/zod/v4/locales/sl.cjs.map +1 -0
  293. package/dist/node_modules/zod/v4/locales/sl.mjs +89 -0
  294. package/dist/node_modules/zod/v4/locales/sl.mjs.map +1 -0
  295. package/dist/node_modules/zod/v4/locales/sv.cjs +2 -0
  296. package/dist/node_modules/zod/v4/locales/sv.cjs.map +1 -0
  297. package/dist/node_modules/zod/v4/locales/sv.mjs +89 -0
  298. package/dist/node_modules/zod/v4/locales/sv.mjs.map +1 -0
  299. package/dist/node_modules/zod/v4/locales/ta.cjs +2 -0
  300. package/dist/node_modules/zod/v4/locales/ta.cjs.map +1 -0
  301. package/dist/node_modules/zod/v4/locales/ta.mjs +90 -0
  302. package/dist/node_modules/zod/v4/locales/ta.mjs.map +1 -0
  303. package/dist/node_modules/zod/v4/locales/th.cjs +2 -0
  304. package/dist/node_modules/zod/v4/locales/th.cjs.map +1 -0
  305. package/dist/node_modules/zod/v4/locales/th.mjs +90 -0
  306. package/dist/node_modules/zod/v4/locales/th.mjs.map +1 -0
  307. package/dist/node_modules/zod/v4/locales/tr.cjs +2 -0
  308. package/dist/node_modules/zod/v4/locales/tr.cjs.map +1 -0
  309. package/dist/node_modules/zod/v4/locales/tr.mjs +87 -0
  310. package/dist/node_modules/zod/v4/locales/tr.mjs.map +1 -0
  311. package/dist/node_modules/zod/v4/locales/ua.cjs +2 -0
  312. package/dist/node_modules/zod/v4/locales/ua.cjs.map +1 -0
  313. package/dist/node_modules/zod/v4/locales/ua.mjs +8 -0
  314. package/dist/node_modules/zod/v4/locales/ua.mjs.map +1 -0
  315. package/dist/node_modules/zod/v4/locales/uk.cjs +2 -0
  316. package/dist/node_modules/zod/v4/locales/uk.cjs.map +1 -0
  317. package/dist/node_modules/zod/v4/locales/uk.mjs +89 -0
  318. package/dist/node_modules/zod/v4/locales/uk.mjs.map +1 -0
  319. package/dist/node_modules/zod/v4/locales/ur.cjs +2 -0
  320. package/dist/node_modules/zod/v4/locales/ur.cjs.map +1 -0
  321. package/dist/node_modules/zod/v4/locales/ur.mjs +90 -0
  322. package/dist/node_modules/zod/v4/locales/ur.mjs.map +1 -0
  323. package/dist/node_modules/zod/v4/locales/uz.cjs +2 -0
  324. package/dist/node_modules/zod/v4/locales/uz.cjs.map +1 -0
  325. package/dist/node_modules/zod/v4/locales/uz.mjs +90 -0
  326. package/dist/node_modules/zod/v4/locales/uz.mjs.map +1 -0
  327. package/dist/node_modules/zod/v4/locales/vi.cjs +2 -0
  328. package/dist/node_modules/zod/v4/locales/vi.cjs.map +1 -0
  329. package/dist/node_modules/zod/v4/locales/vi.mjs +89 -0
  330. package/dist/node_modules/zod/v4/locales/vi.mjs.map +1 -0
  331. package/dist/node_modules/zod/v4/locales/yo.cjs +2 -0
  332. package/dist/node_modules/zod/v4/locales/yo.cjs.map +1 -0
  333. package/dist/node_modules/zod/v4/locales/yo.mjs +89 -0
  334. package/dist/node_modules/zod/v4/locales/yo.mjs.map +1 -0
  335. package/dist/node_modules/zod/v4/locales/zh-CN.cjs +2 -0
  336. package/dist/node_modules/zod/v4/locales/zh-CN.cjs.map +1 -0
  337. package/dist/node_modules/zod/v4/locales/zh-CN.mjs +90 -0
  338. package/dist/node_modules/zod/v4/locales/zh-CN.mjs.map +1 -0
  339. package/dist/node_modules/zod/v4/locales/zh-TW.cjs +2 -0
  340. package/dist/node_modules/zod/v4/locales/zh-TW.cjs.map +1 -0
  341. package/dist/node_modules/zod/v4/locales/zh-TW.mjs +87 -0
  342. package/dist/node_modules/zod/v4/locales/zh-TW.mjs.map +1 -0
  343. package/dist/openapi/analyzerModule/analyzerModule.cjs +1 -1
  344. package/dist/openapi/analyzerModule/analyzerModule.cjs.map +1 -1
  345. package/dist/openapi/analyzerModule/analyzerModule.d.ts.map +1 -1
  346. package/dist/openapi/analyzerModule/analyzerModule.mjs +42 -42
  347. package/dist/openapi/analyzerModule/analyzerModule.mjs.map +1 -1
  348. package/dist/openapi/analyzerModule/nodeParsers.cjs +1 -1
  349. package/dist/openapi/analyzerModule/nodeParsers.cjs.map +1 -1
  350. package/dist/openapi/analyzerModule/nodeParsers.d.ts +1 -0
  351. package/dist/openapi/analyzerModule/nodeParsers.d.ts.map +1 -1
  352. package/dist/openapi/analyzerModule/nodeParsers.mjs +261 -206
  353. package/dist/openapi/analyzerModule/nodeParsers.mjs.map +1 -1
  354. package/dist/openapi/analyzerModule/parseEndpoint.cjs +1 -1
  355. package/dist/openapi/analyzerModule/parseEndpoint.cjs.map +1 -1
  356. package/dist/openapi/analyzerModule/parseEndpoint.d.ts.map +1 -1
  357. package/dist/openapi/analyzerModule/parseEndpoint.mjs +62 -62
  358. package/dist/openapi/analyzerModule/parseEndpoint.mjs.map +1 -1
  359. package/dist/openapi/analyzerModule/test/TestCase.d.ts +9 -0
  360. package/dist/openapi/analyzerModule/test/TestCase.d.ts.map +1 -0
  361. package/dist/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.d.ts +2 -0
  362. package/dist/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.d.ts.map +1 -0
  363. package/dist/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.data.d.ts +2 -0
  364. package/dist/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.data.d.ts.map +1 -0
  365. package/dist/openapi/initOpenApiEngine.cjs +1 -1
  366. package/dist/openapi/initOpenApiEngine.cjs.map +1 -1
  367. package/dist/openapi/initOpenApiEngine.d.ts +7 -2
  368. package/dist/openapi/initOpenApiEngine.d.ts.map +1 -1
  369. package/dist/openapi/initOpenApiEngine.mjs +13 -7
  370. package/dist/openapi/initOpenApiEngine.mjs.map +1 -1
  371. package/dist/openapi/manager/OpenApiManager.cjs +1 -1
  372. package/dist/openapi/manager/OpenApiManager.cjs.map +1 -1
  373. package/dist/openapi/manager/OpenApiManager.d.ts +4 -0
  374. package/dist/openapi/manager/OpenApiManager.d.ts.map +1 -1
  375. package/dist/openapi/manager/OpenApiManager.mjs +11 -2
  376. package/dist/openapi/manager/OpenApiManager.mjs.map +1 -1
  377. package/dist/openapi/router/OpenApiRouter.cjs +1 -1
  378. package/dist/openapi/router/OpenApiRouter.cjs.map +1 -1
  379. package/dist/openapi/router/OpenApiRouter.d.ts.map +1 -1
  380. package/dist/openapi/router/OpenApiRouter.mjs +9 -6
  381. package/dist/openapi/router/OpenApiRouter.mjs.map +1 -1
  382. package/dist/utils/getValueAsNullableString.cjs +2 -0
  383. package/dist/utils/getValueAsNullableString.cjs.map +1 -0
  384. package/dist/utils/getValueAsNullableString.d.ts +2 -0
  385. package/dist/utils/getValueAsNullableString.d.ts.map +1 -0
  386. package/dist/utils/getValueAsNullableString.mjs +7 -0
  387. package/dist/utils/getValueAsNullableString.mjs.map +1 -0
  388. package/dist/utils/validationMessages.cjs +1 -1
  389. package/dist/utils/validationMessages.cjs.map +1 -1
  390. package/dist/utils/validationMessages.d.ts +1 -1
  391. package/dist/utils/validationMessages.d.ts.map +1 -1
  392. package/dist/utils/validationMessages.mjs +8 -8
  393. package/dist/utils/validationMessages.mjs.map +1 -1
  394. package/dist/validators/types.d.ts +4 -0
  395. package/dist/validators/types.d.ts.map +1 -1
  396. package/dist/validators/validateMissingParams.cjs +2 -0
  397. package/dist/validators/validateMissingParams.cjs.map +1 -0
  398. package/dist/validators/validateMissingParams.d.ts +7 -0
  399. package/dist/validators/validateMissingParams.d.ts.map +1 -0
  400. package/dist/validators/validateMissingParams.mjs +17 -0
  401. package/dist/validators/validateMissingParams.mjs.map +1 -0
  402. package/dist/validators/validateParam.cjs +2 -0
  403. package/dist/validators/validateParam.cjs.map +1 -0
  404. package/dist/validators/validateParam.d.ts +8 -0
  405. package/dist/validators/validateParam.d.ts.map +1 -0
  406. package/dist/validators/validateParam.mjs +41 -0
  407. package/dist/validators/validateParam.mjs.map +1 -0
  408. package/package.json +12 -5
  409. package/{cli → src/cli}/cli.ts +26 -6
  410. package/{cli → src/cli}/prettyprint.ts +2 -2
  411. package/src/errors/UserFacingErrors.ts +54 -0
  412. package/src/hooks/usePathParams.spec.ts +27 -0
  413. package/src/hooks/usePathParams.ts +5 -13
  414. package/src/hooks/useQueryParams.spec.ts +99 -0
  415. package/src/hooks/useQueryParams.ts +16 -25
  416. package/src/hooks/useRequestBody.spec.ts +99 -0
  417. package/src/hooks/useRequestBody.ts +16 -35
  418. package/src/openapi/analyzerModule/analyzerModule.ts +2 -3
  419. package/src/openapi/analyzerModule/nodeParsers.ts +113 -8
  420. package/src/openapi/analyzerModule/parseEndpoint.ts +2 -2
  421. package/src/openapi/analyzerModule/test/TestCase.ts +8 -0
  422. package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.data.ts +9 -0
  423. package/src/openapi/analyzerModule/test/openApiAnalyzer.spec.ts +21 -0
  424. package/src/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.data.ts +87 -0
  425. package/src/openapi/analyzerModule/test/openApiAnalyzer.zod.spec.ts +178 -0
  426. package/src/openapi/initOpenApiEngine.ts +48 -6
  427. package/src/openapi/manager/OpenApiManager.ts +16 -0
  428. package/src/openapi/router/OpenApiRouter.ts +6 -1
  429. package/src/test/app.spec.ts +27 -0
  430. package/src/utils/getValueAsNullableString.ts +8 -0
  431. package/src/utils/validationMessages.ts +4 -0
  432. package/src/validators/types.ts +5 -0
  433. package/src/validators/validateMissingParams.ts +27 -0
  434. package/src/validators/validateParam.ts +69 -0
  435. package/vite.config.ts +3 -0
@@ -1,14 +1,20 @@
1
1
  import { ParameterizedContext } from 'koa'
2
+ import z from 'zod'
2
3
 
3
4
  import { ValidationError } from '../errors/UserFacingErrors'
4
5
  import { keysOf } from '../utils/object'
5
- import { getMissingParamMessage, getValidationResultMessage } from '../utils/validationMessages'
6
+ import { getValidationResultMessage } from '../utils/validationMessages'
6
7
  import { Validator } from '../validators/types'
8
+ import { validateMissingParams } from '../validators/validateMissingParams'
9
+ import { validateParam } from '../validators/validateParam'
7
10
 
8
11
  type CheckIfOptional<T, B extends boolean | undefined> = B extends false ? T : T | undefined
9
12
 
10
- type ValidatedData<T extends Record<string, Validator<any>>> = {
11
- [K in keyof T]: CheckIfOptional<ReturnType<T[K]['parse']>, T[K]['optional']>
13
+ type ValidatedData<T extends Record<string, Validator<any> | z.ZodType<any>>> = {
14
+ [K in keyof T]: CheckIfOptional<
15
+ ReturnType<T[K] extends Validator<any> ? T[K]['parse'] : T[K]['parse']>,
16
+ T[K] extends Validator<any> ? T[K]['optional'] : false
17
+ >
12
18
  }
13
19
 
14
20
  /**
@@ -22,7 +28,7 @@ type ValidatedData<T extends Record<string, Validator<any>>> = {
22
28
  * @param validators Validator definitions
23
29
  * @returns Validated parameters
24
30
  */
25
- export const useRequestBody = <ValidatorsT extends Record<string, Validator<any>>>(
31
+ export const useRequestBody = <ValidatorsT extends Record<string, Validator<any> | z.ZodType<any>>>(
26
32
  ctx: ParameterizedContext,
27
33
  validators: ValidatorsT,
28
34
  ): ValidatedData<ValidatorsT> => {
@@ -32,44 +38,19 @@ export const useRequestBody = <ValidatorsT extends Record<string, Validator<any>
32
38
  validator: validators[name],
33
39
  }))
34
40
 
35
- const missingParams = params.filter(
36
- (param) => providedParams[param.name] === undefined && !validators[param.name].optional,
37
- )
38
-
39
- if (missingParams.length > 0) {
40
- throw new ValidationError(
41
- `Missing body params: ${missingParams.map((param) => getMissingParamMessage(param)).join(', ')}`,
42
- )
43
- }
41
+ validateMissingParams(params, providedParams, validators, 'body')
44
42
 
45
43
  const validationResults = params.map((param) => {
46
44
  const paramValue = providedParams[param.name]
47
45
 
48
46
  // Param is optional and is not provided - skip validation
49
47
  if (paramValue === undefined) {
50
- return { param, validated: true }
48
+ return { param, validated: true, parsedValue: undefined, exception: null }
51
49
  }
52
50
 
53
- try {
54
- const convertedValue = (() => {
55
- if (paramValue === null) {
56
- return null
57
- } else if (typeof paramValue === 'object') {
58
- return JSON.stringify(paramValue)
59
- }
60
- return String(paramValue)
61
- })()
62
- const validatorObject = param.validator
63
- const prevalidatorSuccess = !validatorObject.prevalidate || validatorObject.prevalidate(convertedValue)
64
- const parsedValue = validatorObject.parse(convertedValue)
65
- const validatorSuccess = !validatorObject.validate || validatorObject.validate(parsedValue)
66
- return {
67
- param,
68
- validated: prevalidatorSuccess && validatorSuccess,
69
- parsedValue,
70
- }
71
- } catch {
72
- return { param, validated: false }
51
+ return {
52
+ ...validateParam(param.validator, paramValue),
53
+ param,
73
54
  }
74
55
  })
75
56
 
@@ -78,7 +59,7 @@ export const useRequestBody = <ValidatorsT extends Record<string, Validator<any>
78
59
  if (failedValidations.length > 0) {
79
60
  throw new ValidationError(
80
61
  `Failed body param validation: ${failedValidations
81
- .map((result) => getValidationResultMessage(result.param))
62
+ .map((result) => getValidationResultMessage(result.param, result.exception))
82
63
  .join(', ')}`,
83
64
  )
84
65
  }
@@ -12,7 +12,7 @@ import { discoverRouters } from '../discoveryModule/discoverRouters/discoverRout
12
12
  import { ApiDocsHeader, OpenApiManager } from '../manager/OpenApiManager'
13
13
  import { EndpointData, ExposedModelData } from '../types'
14
14
  import { getSourceFileTimestamp, TimestampCache } from './getSourceFileTimestamp'
15
- import { getValuesOfObjectLiteral } from './nodeParsers'
15
+ import { getValuesOfObjectLiteral, resolveEndpointPath } from './nodeParsers'
16
16
  import { parseEndpoint } from './parseEndpoint'
17
17
  import { parseExposedModel, parseNamedExposedModels } from './parseExposedModels'
18
18
  import { SourceFileCache } from './sourceFileCache'
@@ -214,8 +214,7 @@ export const analyzeSourceFileEndpoints = (
214
214
  const routerPattern = new RegExp(`${routerName}\\.(?:${joinedOperations})`)
215
215
 
216
216
  if (routerPattern.test(nodeText)) {
217
- const endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)?.getText() ?? ''
218
- const endpointPath = endpointText.slice(1, -1)
217
+ const endpointPath = resolveEndpointPath(node) ?? ''
219
218
 
220
219
  if (filterEndpointPaths && !filterEndpointPaths.some((path) => endpointPath.includes(path))) {
221
220
  return
@@ -253,7 +253,87 @@ export const getShapeOfValidatorLiteral = (
253
253
  return properties || []
254
254
  }
255
255
 
256
+ const isZodCallExpression = (node: Node): boolean => {
257
+ const callExpression = node.asKind(SyntaxKind.CallExpression)
258
+ if (!callExpression) {
259
+ return false
260
+ }
261
+ const returnType = callExpression.getReturnType()
262
+ const typeName = returnType.getSymbol()?.getName() ?? ''
263
+ return typeName.startsWith('Zod')
264
+ }
265
+
266
+ const getZodCallShape = (node: Node): ShapeOfType['shape'] => {
267
+ const callExpression = node.asKind(SyntaxKind.CallExpression)!
268
+ const returnType = callExpression.getReturnType()
269
+ const typeName = returnType.getSymbol()?.getName() ?? ''
270
+
271
+ if (typeName === 'ZodNumber') {
272
+ return 'number'
273
+ }
274
+ if (typeName === 'ZodString') {
275
+ return 'string'
276
+ }
277
+ if (typeName === 'ZodBoolean') {
278
+ return 'boolean'
279
+ }
280
+ if (typeName === 'ZodBigInt') {
281
+ return 'bigint'
282
+ }
283
+
284
+ if (typeName === 'ZodObject') {
285
+ const argNode = callExpression.getFirstChildByKind(SyntaxKind.SyntaxList)?.getFirstChild()
286
+ const objectLiteral = argNode?.asKind(SyntaxKind.ObjectLiteralExpression)
287
+ if (!objectLiteral) {
288
+ return 'unknown_zod_object'
289
+ }
290
+ const syntaxList = objectLiteral.getFirstChildByKind(SyntaxKind.SyntaxList)
291
+ if (!syntaxList) {
292
+ return []
293
+ }
294
+ const properties = syntaxList.getChildrenOfKind(SyntaxKind.PropertyAssignment)
295
+ return properties.map((prop) => {
296
+ const identifier = prop.getFirstChildByKind(SyntaxKind.Identifier)!.getText()
297
+ const valueNode = prop.getLastChild()!
298
+ return {
299
+ role: 'property' as const,
300
+ identifier,
301
+ shape: isZodCallExpression(valueNode)
302
+ ? getZodCallShape(valueNode)
303
+ : getValidatorPropertyShape(valueNode),
304
+ optional: false,
305
+ }
306
+ })
307
+ }
308
+
309
+ if (typeName === 'ZodArray') {
310
+ const argNode = callExpression.getFirstChildByKind(SyntaxKind.SyntaxList)?.getFirstChild()
311
+ if (!argNode) {
312
+ return 'unknown_zod_array'
313
+ }
314
+ const elementShape = isZodCallExpression(argNode)
315
+ ? getZodCallShape(argNode)
316
+ : getValidatorPropertyShape(argNode)
317
+ return [
318
+ {
319
+ role: 'array' as const,
320
+ shape: elementShape,
321
+ optional: false,
322
+ },
323
+ ]
324
+ }
325
+
326
+ const fileName = node.getSourceFile().getFilePath().split('/').pop()
327
+ Logger.warn(`[${fileName}] Unknown zod type: ${typeName}`)
328
+ return 'unknown_zod'
329
+ }
330
+
256
331
  export const getValidatorPropertyShape = (innerLiteralNode: Node): ShapeOfType['shape'] => {
332
+ // Zod validator (e.g. z.number(), z.string(), z.object({...}), z.array(...))
333
+ if (isZodCallExpression(innerLiteralNode)) {
334
+ return getZodCallShape(innerLiteralNode)
335
+ }
336
+
257
337
  // Inline definition with `as Validator<...>` clause
258
338
  const inlineValidatorAsExpression = innerLiteralNode
259
339
  .getParent()!
@@ -360,6 +440,10 @@ export const getValidatorPropertyShape = (innerLiteralNode: Node): ShapeOfType['
360
440
  }
361
441
 
362
442
  export const getValidatorPropertyOptionality = (node: Node): boolean => {
443
+ if (isZodCallExpression(node)) {
444
+ return false
445
+ }
446
+
363
447
  const callExpressionNode = node.asKind(SyntaxKind.CallExpression)
364
448
  if (callExpressionNode) {
365
449
  const identifierNode = callExpressionNode.getFirstChildByKind(SyntaxKind.Identifier)
@@ -393,6 +477,10 @@ export const getValidatorPropertyStringValue = (
393
477
  nodeOrReference: Node,
394
478
  name: 'description' | 'errorMessage',
395
479
  ): string => {
480
+ if (isZodCallExpression(nodeOrReference)) {
481
+ return ''
482
+ }
483
+
396
484
  const node = findNodeImplementation(nodeOrReference)
397
485
 
398
486
  const callExpressionNode = node.asKind(SyntaxKind.CallExpression)
@@ -571,14 +659,16 @@ export const getProperTypeShape = (
571
659
  }
572
660
 
573
661
  if (type.isObject() && type.getProperties().length === 0) {
574
- const targetType = type.getAliasTypeArguments()[1]
575
- return [
576
- {
577
- role: 'record' as const,
578
- shape: getProperTypeShape(targetType, atLocation, nextStack),
579
- optional: false,
580
- },
581
- ]
662
+ const targetType = type.getAliasTypeArguments()[1] ?? type.getStringIndexType()
663
+ if (targetType) {
664
+ return [
665
+ {
666
+ role: 'record' as const,
667
+ shape: getProperTypeShape(targetType, atLocation, nextStack),
668
+ optional: false,
669
+ },
670
+ ]
671
+ }
582
672
  }
583
673
 
584
674
  if (type.isObject()) {
@@ -680,6 +770,21 @@ const getLiteralValueOfNode = (node: Node): string | string[] | unknown[] => {
680
770
  return 'unknown_6'
681
771
  }
682
772
 
773
+ export const resolveEndpointPath = (node: Node): string | null => {
774
+ const callExpression = node.getFirstDescendantByKind(SyntaxKind.CallExpression)
775
+ if (!callExpression) return null
776
+
777
+ const firstArg = callExpression.getArguments()[0]
778
+ if (!firstArg) return null
779
+
780
+ const argType = firstArg.getType()
781
+ if (argType.isStringLiteral()) {
782
+ return argType.getLiteralValue() as string
783
+ }
784
+
785
+ return null
786
+ }
787
+
683
788
  export const getValuesOfObjectLiteral = (objectLiteralNode: Node<ts.ObjectLiteralExpression>) => {
684
789
  const syntaxListNode = objectLiteralNode.getFirstDescendantByKind(SyntaxKind.SyntaxList)!
685
790
  const assignmentNodes = syntaxListNode.getChildrenOfKind(SyntaxKind.PropertyAssignment)!
@@ -11,6 +11,7 @@ import {
11
11
  getValidatorPropertyShape,
12
12
  getValidatorPropertyStringValue,
13
13
  getValuesOfObjectLiteral,
14
+ resolveEndpointPath,
14
15
  } from './nodeParsers'
15
16
 
16
17
  export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
@@ -22,8 +23,7 @@ export const parseEndpoint = (node: Node<ts.Node>, sourceFilePath: string) => {
22
23
 
23
24
  const endpointMethod = parsedEndpointMethod === 'DEL' ? 'DELETE' : parsedEndpointMethod
24
25
 
25
- const endpointText = node.getFirstDescendantByKind(SyntaxKind.StringLiteral)!.getText() ?? ''
26
- const endpointPath = endpointText.substring(1, endpointText.length - 1)
26
+ const endpointPath = resolveEndpointPath(node) ?? ''
27
27
 
28
28
  const endpointData: EndpointData = {
29
29
  method: endpointMethod as 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
@@ -0,0 +1,8 @@
1
+ export const TestCase = {
2
+ parsesInlineZodNumber: 'parses-inline-zod-number',
3
+ parsesInlineZodString: 'parses-inline-zod-string',
4
+ parsesInlineZodObject: 'parses-inline-zod-object',
5
+ parsesInlineZodNumberArray: 'parses-inline-zod-number-array',
6
+ parsesInlineZodObjectArray: 'parses-inline-zod-object-array',
7
+ parsedAliasedZodSchema: 'parses-aliased-zod-schema',
8
+ } as const
@@ -550,3 +550,12 @@ router.get('/test/2ec01787-13d0-4512-9cf3-468f409508b7', () => {
550
550
  value: 'foo',
551
551
  }
552
552
  })
553
+
554
+ // Mimics Prisma's JsonValue / JsonObject: an object with an index signature and no own properties
555
+ type JsonValue = string | number | boolean | JsonObject | JsonArray | null
556
+ type JsonObject = { [Key in string]?: JsonValue }
557
+ type JsonArray = JsonValue[]
558
+
559
+ router.get('/test/c4a1e7b2-9f3d-4e8a-b5c6-7d2f1a3e4b5c', () => {
560
+ return {} as { data: JsonObject }
561
+ })
@@ -725,6 +725,27 @@ describe('OpenApi Analyzer', () => {
725
725
  expect(endpoint.responses.length).toEqual(1)
726
726
  })
727
727
 
728
+ it('parses return type with index signature object (like Prisma JsonObject) correctly', () => {
729
+ const endpoint = analyzeEndpointById('c4a1e7b2-9f3d-4e8a-b5c6-7d2f1a3e4b5c')
730
+
731
+ expect(endpoint.responses[0].status).toEqual(200)
732
+ expect(endpoint.responses[0].signature).toEqual([
733
+ {
734
+ role: 'property',
735
+ identifier: 'data',
736
+ shape: [
737
+ {
738
+ role: 'record',
739
+ shape: expect.anything(),
740
+ optional: false,
741
+ },
742
+ ],
743
+ optional: false,
744
+ },
745
+ ])
746
+ expect(endpoint.responses.length).toEqual(1)
747
+ })
748
+
728
749
  it('parses no-return endpoint correctly', () => {
729
750
  const endpoint = analyzeEndpointById('196f2937-e369-435f-b239-62eaacaa6fbd')
730
751
 
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod'
2
+ import { z as valibot } from 'zod'
3
+
4
+ import { usePathParams } from '../../../hooks/usePathParams'
5
+ import { useRequestBody } from '../../../hooks/useRequestBody'
6
+ import { Router } from '../../../router/Router'
7
+ import { TestCase } from './TestCase'
8
+
9
+ const router = new Router()
10
+
11
+ router.post(`/test/${TestCase.parsesInlineZodNumber}/:id`, (ctx) => {
12
+ usePathParams(ctx, {
13
+ id: z.number(),
14
+ })
15
+
16
+ useRequestBody(ctx, {
17
+ data: z.number(),
18
+ })
19
+ })
20
+
21
+ router.post(`/test/${TestCase.parsesInlineZodString}/:id`, (ctx) => {
22
+ usePathParams(ctx, {
23
+ id: z.string(),
24
+ })
25
+
26
+ useRequestBody(ctx, {
27
+ data: z.string(),
28
+ })
29
+ })
30
+
31
+ router.post(`/test/${TestCase.parsesInlineZodObject}/:id`, (ctx) => {
32
+ usePathParams(ctx, {
33
+ id: z.object({
34
+ value: z.number(),
35
+ }),
36
+ })
37
+
38
+ useRequestBody(ctx, {
39
+ data: z.object({
40
+ value: z.number(),
41
+ }),
42
+ })
43
+ })
44
+
45
+ router.post(`/test/${TestCase.parsesInlineZodNumberArray}/:id`, (ctx) => {
46
+ usePathParams(ctx, {
47
+ id: z.array(z.number()),
48
+ })
49
+
50
+ useRequestBody(ctx, {
51
+ data: z.array(z.number()),
52
+ })
53
+ })
54
+
55
+ router.post(`/test/${TestCase.parsesInlineZodObjectArray}/:id`, (ctx) => {
56
+ usePathParams(ctx, {
57
+ id: z.array(
58
+ z.object({
59
+ value: z.number(),
60
+ }),
61
+ ),
62
+ })
63
+
64
+ useRequestBody(ctx, {
65
+ data: z.array(
66
+ z.object({
67
+ value: z.number(),
68
+ }),
69
+ ),
70
+ })
71
+ })
72
+
73
+ router.post(`/test/${TestCase.parsedAliasedZodSchema}/:id`, (ctx) => {
74
+ const schema = valibot.array(
75
+ valibot.object({
76
+ value: valibot.number(),
77
+ }),
78
+ )
79
+
80
+ usePathParams(ctx, {
81
+ id: schema,
82
+ })
83
+
84
+ useRequestBody(ctx, {
85
+ data: schema,
86
+ })
87
+ })
@@ -0,0 +1,178 @@
1
+ import { loadTestData } from '../../../utils/loadTestData'
2
+ import { discoverRouters } from '../../discoveryModule/discoverRouters/discoverRouters'
3
+ import { analyzeSourceFileEndpoints } from '../analyzerModule'
4
+ import { TestCase } from './TestCase'
5
+
6
+ describe('OpenApi Analyzer (Zod Validator)', () => {
7
+ describe('when analyzing a test data file', () => {
8
+ const dataFile = loadTestData('openApiAnalyzer.zod.spec.data.ts')
9
+ let analysisResult: ReturnType<typeof analyzeSourceFileEndpoints>
10
+
11
+ const analyzeEndpointById = (id: string) => {
12
+ analysisResult = analyzeSourceFileEndpoints(
13
+ {
14
+ fileName: 'test',
15
+ sourceFile: dataFile,
16
+ routers: discoverRouters(dataFile),
17
+ },
18
+ [`/test/${id}`],
19
+ )
20
+ const endpoint = analysisResult.find((endpoint) => endpoint.path.startsWith(`/test/${id}`))
21
+ if (!endpoint) {
22
+ throw new Error(`No endpoint with id ${id} found!`)
23
+ }
24
+ return endpoint
25
+ }
26
+
27
+ describe('zod validators', () => {
28
+ it('parses inline zod number validators', () => {
29
+ const endpoint = analyzeEndpointById(TestCase.parsesInlineZodNumber)
30
+
31
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
32
+ expect(endpoint.requestPathParams[0].signature).toEqual('number')
33
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
34
+
35
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
36
+ expect(endpoint.objectBody[0].signature).toEqual('number')
37
+ expect(endpoint.objectBody[0].optional).toEqual(false)
38
+ })
39
+
40
+ it('parses inline zod string validators', () => {
41
+ const endpoint = analyzeEndpointById(TestCase.parsesInlineZodString)
42
+
43
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
44
+ expect(endpoint.requestPathParams[0].signature).toEqual('string')
45
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
46
+
47
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
48
+ expect(endpoint.objectBody[0].signature).toEqual('string')
49
+ expect(endpoint.objectBody[0].optional).toEqual(false)
50
+ })
51
+
52
+ it('parses inline zod object validators', () => {
53
+ const endpoint = analyzeEndpointById(TestCase.parsesInlineZodObject)
54
+
55
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
56
+ expect(endpoint.requestPathParams[0].signature).toEqual([
57
+ {
58
+ identifier: 'value',
59
+ optional: false,
60
+ role: 'property',
61
+ shape: 'number',
62
+ },
63
+ ])
64
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
65
+
66
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
67
+ expect(endpoint.objectBody[0].signature).toEqual([
68
+ {
69
+ identifier: 'value',
70
+ optional: false,
71
+ role: 'property',
72
+ shape: 'number',
73
+ },
74
+ ])
75
+ expect(endpoint.objectBody[0].optional).toEqual(false)
76
+ })
77
+
78
+ it('parses inline zod number array validators', () => {
79
+ const endpoint = analyzeEndpointById(TestCase.parsesInlineZodNumberArray)
80
+
81
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
82
+ expect(endpoint.requestPathParams[0].signature).toEqual([
83
+ {
84
+ role: 'array',
85
+ shape: 'number',
86
+ optional: false,
87
+ },
88
+ ])
89
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
90
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
91
+ expect(endpoint.objectBody[0].signature).toEqual([
92
+ {
93
+ role: 'array',
94
+ shape: 'number',
95
+ optional: false,
96
+ },
97
+ ])
98
+ expect(endpoint.objectBody[0].optional).toEqual(false)
99
+ })
100
+
101
+ it('parses inline zod object array validators', () => {
102
+ const endpoint = analyzeEndpointById(TestCase.parsesInlineZodObjectArray)
103
+
104
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
105
+ expect(endpoint.requestPathParams[0].signature).toEqual([
106
+ {
107
+ role: 'array',
108
+ shape: [
109
+ {
110
+ identifier: 'value',
111
+ optional: false,
112
+ role: 'property',
113
+ shape: 'number',
114
+ },
115
+ ],
116
+ optional: false,
117
+ },
118
+ ])
119
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
120
+
121
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
122
+ expect(endpoint.objectBody[0].signature).toEqual([
123
+ {
124
+ role: 'array',
125
+ shape: [
126
+ {
127
+ identifier: 'value',
128
+ optional: false,
129
+ role: 'property',
130
+ shape: 'number',
131
+ },
132
+ ],
133
+ optional: false,
134
+ },
135
+ ])
136
+ expect(endpoint.objectBody[0].optional).toEqual(false)
137
+ })
138
+
139
+ it('parses aliased zod object array validators', () => {
140
+ const endpoint = analyzeEndpointById(TestCase.parsedAliasedZodSchema)
141
+
142
+ expect(endpoint.requestPathParams[0].identifier).toEqual('id')
143
+ expect(endpoint.requestPathParams[0].signature).toEqual([
144
+ {
145
+ role: 'array',
146
+ shape: [
147
+ {
148
+ identifier: 'value',
149
+ optional: false,
150
+ role: 'property',
151
+ shape: 'number',
152
+ },
153
+ ],
154
+ optional: false,
155
+ },
156
+ ])
157
+ expect(endpoint.requestPathParams[0].optional).toEqual(false)
158
+
159
+ expect(endpoint.objectBody[0].identifier).toEqual('data')
160
+ expect(endpoint.objectBody[0].signature).toEqual([
161
+ {
162
+ role: 'array',
163
+ shape: [
164
+ {
165
+ identifier: 'value',
166
+ optional: false,
167
+ role: 'property',
168
+ shape: 'number',
169
+ },
170
+ ],
171
+ optional: false,
172
+ },
173
+ ])
174
+ expect(endpoint.objectBody[0].optional).toEqual(false)
175
+ })
176
+ })
177
+ })
178
+ })
@@ -1,20 +1,62 @@
1
+ import * as fs from 'fs'
1
2
  import Koa from 'koa'
2
3
 
3
- import { prepareOpenApiSpec } from './analyzerModule/analyzerModule'
4
+ import type * as AnalyzerModule from './analyzerModule/analyzerModule'
5
+ import { OpenApiManager } from './manager/OpenApiManager'
4
6
  import { OpenApiRouter } from './router/OpenApiRouter'
5
7
 
8
+ type AnalyzerProps = Parameters<typeof AnalyzerModule.prepareOpenApiSpec>[0]
9
+
10
+ type PrebuiltSpecProps = {
11
+ /**
12
+ * Path to a pre-built OpenAPI spec JSON file.
13
+ * When provided, the analyzer is skipped entirely and the spec is served from this file.
14
+ * Use this in production to avoid running the TypeScript analyzer on startup.
15
+ *
16
+ * Generate the spec file at build time using the CLI:
17
+ * ```
18
+ * moonflower openapi ./openapi-spec.json
19
+ * ```
20
+ */
21
+ specPath: string
22
+ }
23
+
6
24
  /**
7
25
  * Middleware to initialize the openApi engine.
8
26
  * Can be at any position in the middleware execution order.
9
- * All files with routers or exposed models must be included in `props.sourceFilePaths`.
10
- * @param props Paths to files to analyze, relative to project root.
27
+ *
28
+ * In development, pass analyzer options to generate the spec on startup:
29
+ * ```
30
+ * initOpenApiEngine({ tsconfigPath: 'tsconfig.json', sourceFileDiscovery: true })
31
+ * ```
32
+ *
33
+ * In production, pass a pre-built spec file to skip analysis:
34
+ * ```
35
+ * initOpenApiEngine({ specPath: './openapi-spec.json' })
36
+ * ```
11
37
  */
12
- export const initOpenApiEngine = (props: Parameters<typeof prepareOpenApiSpec>[0]) => {
13
- prepareOpenApiSpec(props)
38
+ export const initOpenApiEngine = (props: AnalyzerProps | PrebuiltSpecProps) => {
39
+ const ready =
40
+ 'specPath' in props
41
+ ? loadPrebuiltSpec(props.specPath)
42
+ : import('./analyzerModule/analyzerModule').then(({ prepareOpenApiSpec }) => prepareOpenApiSpec(props))
14
43
 
15
44
  const builtInRoutes = OpenApiRouter.routes()
16
45
  const builtInAllowedMethods = OpenApiRouter.allowedMethods()
17
- return (ctx: Koa.ParameterizedContext<any, any>, next: Koa.Next) => {
46
+ return async (ctx: Koa.ParameterizedContext<any, any>, next: Koa.Next) => {
47
+ await ready
18
48
  return builtInRoutes(ctx, () => builtInAllowedMethods(ctx, next))
19
49
  }
20
50
  }
51
+
52
+ const loadPrebuiltSpec = (specPath: string) => {
53
+ const manager = OpenApiManager.getInstance()
54
+ if (manager.isReady()) {
55
+ return
56
+ }
57
+
58
+ const content = fs.readFileSync(specPath, 'utf-8')
59
+ const spec = JSON.parse(content)
60
+ manager.setPrebuiltSpec(spec)
61
+ manager.markAsReady()
62
+ }