zudoku 0.26.0 → 0.27.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 (300) hide show
  1. package/dist/app/main.d.ts +1 -1
  2. package/dist/app/main.js +19 -7
  3. package/dist/app/main.js.map +1 -1
  4. package/dist/config/config.d.ts +1 -0
  5. package/dist/config/validators/InputSidebarSchema.d.ts +2 -2
  6. package/dist/config/validators/common.d.ts +78 -0
  7. package/dist/config/validators/common.js +6 -0
  8. package/dist/config/validators/common.js.map +1 -1
  9. package/dist/config/validators/validate.d.ts +34 -0
  10. package/dist/lib/authentication/providers/auth0.js +1 -1
  11. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  12. package/dist/lib/authentication/providers/openid.d.ts +1 -1
  13. package/dist/lib/authentication/providers/openid.js +10 -6
  14. package/dist/lib/authentication/providers/openid.js.map +1 -1
  15. package/dist/lib/components/AnchorLink.js +5 -2
  16. package/dist/lib/components/AnchorLink.js.map +1 -1
  17. package/dist/lib/components/Autocomplete.d.ts +12 -0
  18. package/dist/lib/components/Autocomplete.js +47 -0
  19. package/dist/lib/components/Autocomplete.js.map +1 -0
  20. package/dist/lib/components/Header.js +4 -4
  21. package/dist/lib/components/Header.js.map +1 -1
  22. package/dist/lib/components/Heading.d.ts +1 -1
  23. package/dist/lib/components/Markdown.d.ts +2 -2
  24. package/dist/lib/components/Markdown.js +3 -1
  25. package/dist/lib/components/Markdown.js.map +1 -1
  26. package/dist/lib/components/StatusPage.d.ts +7 -0
  27. package/dist/lib/components/StatusPage.js +71 -0
  28. package/dist/lib/components/StatusPage.js.map +1 -0
  29. package/dist/lib/components/SyntaxHighlight.d.ts +2 -1
  30. package/dist/lib/components/SyntaxHighlight.js +2 -2
  31. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  32. package/dist/lib/components/ThemeSwitch.js +4 -4
  33. package/dist/lib/components/ThemeSwitch.js.map +1 -1
  34. package/dist/lib/components/cache.d.ts +6 -0
  35. package/dist/lib/components/cache.js +13 -0
  36. package/dist/lib/components/cache.js.map +1 -0
  37. package/dist/lib/components/context/ViewportAnchorContext.js +16 -4
  38. package/dist/lib/components/context/ViewportAnchorContext.js.map +1 -1
  39. package/dist/lib/components/context/ZudokuContext.js +2 -1
  40. package/dist/lib/components/context/ZudokuContext.js.map +1 -1
  41. package/dist/lib/components/index.d.ts +9 -2
  42. package/dist/lib/components/index.js +5 -2
  43. package/dist/lib/components/index.js.map +1 -1
  44. package/dist/lib/core/RouteGuard.d.ts +1 -0
  45. package/dist/lib/core/RouteGuard.js +28 -0
  46. package/dist/lib/core/RouteGuard.js.map +1 -0
  47. package/dist/lib/core/ZudokuContext.d.ts +4 -2
  48. package/dist/lib/core/ZudokuContext.js +9 -7
  49. package/dist/lib/core/ZudokuContext.js.map +1 -1
  50. package/dist/lib/oas/graphql/circular.d.ts +3 -0
  51. package/dist/lib/oas/graphql/circular.js +27 -0
  52. package/dist/lib/oas/graphql/circular.js.map +1 -0
  53. package/dist/lib/oas/graphql/index.js +5 -6
  54. package/dist/lib/oas/graphql/index.js.map +1 -1
  55. package/dist/lib/oas/parser/dereference/index.d.ts +0 -1
  56. package/dist/lib/oas/parser/dereference/index.js +1 -1
  57. package/dist/lib/oas/parser/dereference/index.js.map +1 -1
  58. package/dist/lib/plugins/markdown/MdxPage.js +8 -2
  59. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  60. package/dist/lib/plugins/openapi/OperationListItem.js +1 -1
  61. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  62. package/dist/lib/plugins/openapi/ParameterListItem.js +1 -1
  63. package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
  64. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +3 -1
  65. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +3 -2
  66. package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
  67. package/dist/lib/plugins/openapi/Sidecar.js +3 -3
  68. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  69. package/dist/lib/plugins/openapi/index.js +4 -11
  70. package/dist/lib/plugins/openapi/index.js.map +1 -1
  71. package/dist/lib/plugins/openapi/interfaces.d.ts +7 -2
  72. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.d.ts +6 -0
  73. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js +12 -0
  74. package/dist/lib/plugins/openapi/playground/ExamplesDropdown.js.map +1 -0
  75. package/dist/lib/plugins/openapi/playground/Headers.js +67 -4
  76. package/dist/lib/plugins/openapi/playground/Headers.js.map +1 -1
  77. package/dist/lib/plugins/openapi/playground/ParamsGrid.d.ts +5 -0
  78. package/dist/lib/plugins/openapi/playground/ParamsGrid.js +4 -0
  79. package/dist/lib/plugins/openapi/playground/ParamsGrid.js.map +1 -0
  80. package/dist/lib/plugins/openapi/playground/PathParams.js +4 -12
  81. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  82. package/dist/lib/plugins/openapi/playground/Playground.d.ts +18 -1
  83. package/dist/lib/plugins/openapi/playground/Playground.js +53 -40
  84. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  85. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js +1 -1
  86. package/dist/lib/plugins/openapi/playground/PlaygroundDialog.js.map +1 -1
  87. package/dist/lib/plugins/openapi/playground/QueryParams.js +21 -30
  88. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  89. package/dist/lib/plugins/openapi/playground/SubmitButton.d.ts +7 -0
  90. package/dist/lib/plugins/openapi/playground/SubmitButton.js +22 -0
  91. package/dist/lib/plugins/openapi/playground/SubmitButton.js.map +1 -0
  92. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.d.ts +7 -0
  93. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js +11 -0
  94. package/dist/lib/plugins/openapi/playground/result-panel/RequestTab.js.map +1 -0
  95. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.d.ts +8 -0
  96. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js +95 -0
  97. package/dist/lib/plugins/openapi/playground/result-panel/ResponseTab.js.map +1 -0
  98. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.d.ts +7 -0
  99. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js +16 -0
  100. package/dist/lib/plugins/openapi/playground/result-panel/ResultPanel.js.map +1 -0
  101. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.d.ts +10 -0
  102. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js +32 -0
  103. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.js.map +1 -0
  104. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.d.ts +1 -0
  105. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js +56 -0
  106. package/dist/lib/plugins/openapi/playground/result-panel/convertToTypes.test.js.map +1 -0
  107. package/dist/lib/plugins/openapi/post-processors/removeExtensions.d.ts +2 -1
  108. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js +5 -3
  109. package/dist/lib/plugins/openapi/post-processors/removeExtensions.js.map +1 -1
  110. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js +49 -0
  111. package/dist/lib/plugins/openapi/post-processors/removeExtensions.test.js.map +1 -1
  112. package/dist/lib/plugins/openapi/post-processors/removeParameters.d.ts +10 -0
  113. package/dist/lib/plugins/openapi/post-processors/removeParameters.js +66 -0
  114. package/dist/lib/plugins/openapi/post-processors/removeParameters.js.map +1 -0
  115. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.d.ts +1 -0
  116. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js +131 -0
  117. package/dist/lib/plugins/openapi/post-processors/removeParameters.test.js.map +1 -0
  118. package/dist/lib/plugins/openapi/schema/SchemaComponents.js +1 -1
  119. package/dist/lib/plugins/openapi/schema/SchemaComponents.js.map +1 -1
  120. package/dist/lib/ui/Command.d.ts +9 -1
  121. package/dist/lib/ui/Command.js +5 -1
  122. package/dist/lib/ui/Command.js.map +1 -1
  123. package/dist/lib/ui/Select.js +2 -2
  124. package/dist/lib/ui/Select.js.map +1 -1
  125. package/dist/lib/util/MdxComponents.js +2 -2
  126. package/dist/lib/util/MdxComponents.js.map +1 -1
  127. package/dist/lib/util/joinUrl.d.ts +1 -0
  128. package/dist/lib/util/joinUrl.js +40 -0
  129. package/dist/lib/util/joinUrl.js.map +1 -0
  130. package/dist/lib/util/useScrollToAnchor.d.ts +1 -0
  131. package/dist/lib/util/useScrollToAnchor.js +26 -15
  132. package/dist/lib/util/useScrollToAnchor.js.map +1 -1
  133. package/dist/vite/build.js +10 -10
  134. package/dist/vite/build.js.map +1 -1
  135. package/dist/vite/config.js +4 -1
  136. package/dist/vite/config.js.map +1 -1
  137. package/dist/vite/dev-server.js +4 -1
  138. package/dist/vite/dev-server.js.map +1 -1
  139. package/dist/vite/plugin-api.d.ts +1 -1
  140. package/dist/vite/plugin-api.js +31 -7
  141. package/dist/vite/plugin-api.js.map +1 -1
  142. package/dist/vite/plugin-auth.js +4 -1
  143. package/dist/vite/plugin-auth.js.map +1 -1
  144. package/dist/vite/plugin-mdx.js +9 -4
  145. package/dist/vite/plugin-mdx.js.map +1 -1
  146. package/dist/vite/prerender.d.ts +2 -2
  147. package/dist/vite/prerender.js +5 -4
  148. package/dist/vite/prerender.js.map +1 -1
  149. package/dist/zuplo/enrich-with-zuplo.d.ts +5 -0
  150. package/dist/zuplo/enrich-with-zuplo.js +184 -0
  151. package/dist/zuplo/enrich-with-zuplo.js.map +1 -0
  152. package/dist/zuplo/env.d.ts +1 -0
  153. package/dist/zuplo/env.js +3 -0
  154. package/dist/zuplo/env.js.map +1 -1
  155. package/dist/zuplo/policy-types.d.ts +33 -0
  156. package/dist/zuplo/policy-types.js +8 -0
  157. package/dist/zuplo/policy-types.js.map +1 -0
  158. package/dist/zuplo/with-zuplo-processors.d.ts +3 -0
  159. package/dist/zuplo/with-zuplo-processors.js +26 -0
  160. package/dist/zuplo/with-zuplo-processors.js.map +1 -0
  161. package/dist/zuplo/with-zuplo.d.ts +1 -1
  162. package/dist/zuplo/with-zuplo.js +7 -26
  163. package/dist/zuplo/with-zuplo.js.map +1 -1
  164. package/lib/{AuthenticationPlugin-DNXBcsVN.js → AuthenticationPlugin-CO_YCd2x.js} +3 -3
  165. package/lib/{AuthenticationPlugin-DNXBcsVN.js.map → AuthenticationPlugin-CO_YCd2x.js.map} +1 -1
  166. package/lib/{Markdown-BrfrjEk_.js → Markdown-B8o9Qz4q.js} +1197 -1186
  167. package/lib/{Markdown-BrfrjEk_.js.map → Markdown-B8o9Qz4q.js.map} +1 -1
  168. package/lib/{MdxPage-LNZLj_A5.js → MdxPage-BxRt3Ly7.js} +63 -58
  169. package/lib/MdxPage-BxRt3Ly7.js.map +1 -0
  170. package/lib/OperationList-DH-zIgtq.js +5160 -0
  171. package/lib/OperationList-DH-zIgtq.js.map +1 -0
  172. package/lib/{Route-Pzk6qwIk.js → Route-DJ0ZlVq1.js} +3 -3
  173. package/lib/{Route-Pzk6qwIk.js.map → Route-DJ0ZlVq1.js.map} +1 -1
  174. package/lib/{Select-DkOpAG0c.js → Select-B7UXR0SB.js} +61 -61
  175. package/lib/Select-B7UXR0SB.js.map +1 -0
  176. package/lib/{SlotletProvider-DPbx9KdU.js → SlotletProvider-CtIp8rP3.js} +4 -4
  177. package/lib/{SlotletProvider-DPbx9KdU.js.map → SlotletProvider-CtIp8rP3.js.map} +1 -1
  178. package/lib/{Button-oroWHXAy.js → Spinner-BlzrEEk1.js} +15 -12
  179. package/lib/Spinner-BlzrEEk1.js.map +1 -0
  180. package/lib/{SyntaxHighlight-CJCSPG1F.js → SyntaxHighlight-C1w1QPdY.js} +300 -295
  181. package/lib/{SyntaxHighlight-CJCSPG1F.js.map → SyntaxHighlight-C1w1QPdY.js.map} +1 -1
  182. package/lib/{ZudokuContext-D3ayHjP-.js → ZudokuContext-8jts0fF3.js} +259 -248
  183. package/lib/ZudokuContext-8jts0fF3.js.map +1 -0
  184. package/lib/{chunk-SYFQ2XB5-KWlHsT7t.js → chunk-SYFQ2XB5-BPvC-soB.js} +6 -5
  185. package/lib/{chunk-SYFQ2XB5-KWlHsT7t.js.map → chunk-SYFQ2XB5-BPvC-soB.js.map} +1 -1
  186. package/lib/circular-Dgpd6AN-.js +15397 -0
  187. package/lib/circular-Dgpd6AN-.js.map +1 -0
  188. package/lib/{createServer-BcaswoFO.js → createServer-BV0tHzLK.js} +3450 -5577
  189. package/lib/createServer-BV0tHzLK.js.map +1 -0
  190. package/lib/{hook-DUyACbIK.js → hook-BG02esyv.js} +2 -2
  191. package/lib/{hook-DUyACbIK.js.map → hook-BG02esyv.js.map} +1 -1
  192. package/lib/index-B7mqiOei.js +509 -0
  193. package/lib/index-B7mqiOei.js.map +1 -0
  194. package/lib/index-DmqsUPcm.js +1915 -0
  195. package/lib/index-DmqsUPcm.js.map +1 -0
  196. package/lib/joinUrl-BTy9bvoK.js +20 -0
  197. package/lib/joinUrl-BTy9bvoK.js.map +1 -0
  198. package/lib/post-processors/removeExtensions.js +7 -7
  199. package/lib/post-processors/removeExtensions.js.map +1 -1
  200. package/lib/post-processors/removeParameters.js +48 -0
  201. package/lib/post-processors/removeParameters.js.map +1 -0
  202. package/lib/ui/ActionButton.js +10 -11
  203. package/lib/ui/ActionButton.js.map +1 -1
  204. package/lib/ui/Command.js +125 -13
  205. package/lib/ui/Command.js.map +1 -1
  206. package/lib/ui/Select.js +2 -2
  207. package/lib/ui/Select.js.map +1 -1
  208. package/lib/{useExposedProps-BBHR7aLM.js → useExposedProps-BLKFBylA.js} +2 -2
  209. package/lib/{useExposedProps-BBHR7aLM.js.map → useExposedProps-BLKFBylA.js.map} +1 -1
  210. package/lib/useScrollToAnchor-Bl6mz9_x.js +288 -0
  211. package/lib/useScrollToAnchor-Bl6mz9_x.js.map +1 -0
  212. package/lib/zudoku.auth-auth0.js +7 -9
  213. package/lib/zudoku.auth-auth0.js.map +1 -1
  214. package/lib/zudoku.auth-clerk.js +1 -1
  215. package/lib/zudoku.auth-openid.js +223 -219
  216. package/lib/zudoku.auth-openid.js.map +1 -1
  217. package/lib/zudoku.components.js +754 -992
  218. package/lib/zudoku.components.js.map +1 -1
  219. package/lib/zudoku.plugin-api-catalog.js +3 -3
  220. package/lib/zudoku.plugin-api-keys.js +5 -5
  221. package/lib/zudoku.plugin-custom-pages.js +2 -2
  222. package/lib/zudoku.plugin-markdown.js +1 -1
  223. package/lib/zudoku.plugin-openapi.js +4 -4
  224. package/lib/zudoku.plugin-redirect.js +1 -1
  225. package/package.json +2 -2
  226. package/src/app/main.css +50 -50
  227. package/src/app/main.tsx +26 -7
  228. package/src/lib/authentication/providers/auth0.tsx +1 -4
  229. package/src/lib/authentication/providers/openid.tsx +12 -5
  230. package/src/lib/components/AnchorLink.tsx +5 -2
  231. package/src/lib/components/Autocomplete.tsx +111 -0
  232. package/src/lib/components/Header.tsx +4 -4
  233. package/src/lib/components/Markdown.tsx +14 -15
  234. package/src/lib/components/StatusPage.tsx +91 -0
  235. package/src/lib/components/SyntaxHighlight.tsx +14 -0
  236. package/src/lib/components/ThemeSwitch.tsx +14 -15
  237. package/src/lib/components/cache.ts +15 -0
  238. package/src/lib/components/context/ViewportAnchorContext.tsx +20 -6
  239. package/src/lib/components/context/ZudokuContext.ts +3 -1
  240. package/src/lib/components/index.ts +9 -2
  241. package/src/lib/core/RouteGuard.tsx +35 -0
  242. package/src/lib/core/ZudokuContext.ts +9 -8
  243. package/src/lib/oas/graphql/circular.ts +29 -0
  244. package/src/lib/oas/graphql/index.ts +9 -9
  245. package/src/lib/oas/parser/dereference/index.ts +1 -2
  246. package/src/lib/plugins/markdown/MdxPage.tsx +9 -1
  247. package/src/lib/plugins/openapi/OperationListItem.tsx +0 -2
  248. package/src/lib/plugins/openapi/ParameterListItem.tsx +1 -0
  249. package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +5 -0
  250. package/src/lib/plugins/openapi/Sidecar.tsx +4 -2
  251. package/src/lib/plugins/openapi/index.tsx +9 -15
  252. package/src/lib/plugins/openapi/interfaces.ts +10 -2
  253. package/src/lib/plugins/openapi/playground/ExamplesDropdown.tsx +54 -0
  254. package/src/lib/plugins/openapi/playground/Headers.tsx +136 -39
  255. package/src/lib/plugins/openapi/playground/ParamsGrid.tsx +8 -0
  256. package/src/lib/plugins/openapi/playground/PathParams.tsx +34 -74
  257. package/src/lib/plugins/openapi/playground/Playground.tsx +219 -177
  258. package/src/lib/plugins/openapi/playground/PlaygroundDialog.tsx +1 -1
  259. package/src/lib/plugins/openapi/playground/QueryParams.tsx +90 -122
  260. package/src/lib/plugins/openapi/playground/SubmitButton.tsx +75 -0
  261. package/src/lib/plugins/openapi/playground/result-panel/RequestTab.tsx +73 -0
  262. package/src/lib/plugins/openapi/playground/result-panel/ResponseTab.tsx +210 -0
  263. package/src/lib/plugins/openapi/playground/result-panel/ResultPanel.tsx +101 -0
  264. package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.test.ts +64 -0
  265. package/src/lib/plugins/openapi/playground/result-panel/convertToTypes.ts +36 -0
  266. package/src/lib/plugins/openapi/post-processors/removeExtensions.test.ts +58 -0
  267. package/src/lib/plugins/openapi/post-processors/removeExtensions.ts +7 -4
  268. package/src/lib/plugins/openapi/post-processors/removeParameters.test.ts +148 -0
  269. package/src/lib/plugins/openapi/post-processors/removeParameters.ts +101 -0
  270. package/src/lib/plugins/openapi/schema/SchemaComponents.tsx +1 -1
  271. package/src/lib/ui/Command.tsx +20 -0
  272. package/src/lib/ui/Select.tsx +1 -1
  273. package/src/lib/util/MdxComponents.tsx +2 -1
  274. package/src/lib/util/joinUrl.ts +57 -0
  275. package/src/lib/util/useScrollToAnchor.ts +32 -15
  276. package/dist/lib/plugins/openapi/playground/EnumSelector.d.ts +0 -8
  277. package/dist/lib/plugins/openapi/playground/EnumSelector.js +0 -21
  278. package/dist/lib/plugins/openapi/playground/EnumSelector.js.map +0 -1
  279. package/dist/lib/plugins/openapi/playground/ResponseTab.d.ts +0 -4
  280. package/dist/lib/plugins/openapi/playground/ResponseTab.js +0 -42
  281. package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +0 -1
  282. package/lib/AnchorLink-_Vu02ceN.js +0 -34
  283. package/lib/AnchorLink-_Vu02ceN.js.map +0 -1
  284. package/lib/Button-oroWHXAy.js.map +0 -1
  285. package/lib/Command-D5DE0DD7.js +0 -611
  286. package/lib/Command-D5DE0DD7.js.map +0 -1
  287. package/lib/MdxPage-LNZLj_A5.js.map +0 -1
  288. package/lib/OperationList-PCwzTp1r.js +0 -5144
  289. package/lib/OperationList-PCwzTp1r.js.map +0 -1
  290. package/lib/Select-DkOpAG0c.js.map +0 -1
  291. package/lib/Spinner-C5gHXrVz.js +0 -7
  292. package/lib/Spinner-C5gHXrVz.js.map +0 -1
  293. package/lib/ZudokuContext-D3ayHjP-.js.map +0 -1
  294. package/lib/createServer-BcaswoFO.js.map +0 -1
  295. package/lib/index-CaILD1AV.js +0 -1292
  296. package/lib/index-CaILD1AV.js.map +0 -1
  297. package/lib/index-TaRXY2w1.js +0 -43
  298. package/lib/index-TaRXY2w1.js.map +0 -1
  299. package/src/lib/plugins/openapi/playground/EnumSelector.tsx +0 -86
  300. package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -76
@@ -1,6 +1,11 @@
1
1
  import { useMutation } from "@tanstack/react-query";
2
+ import { InfoIcon } from "lucide-react";
2
3
  import { Fragment, useEffect, useRef, useTransition } from "react";
3
4
  import { FormProvider, useForm } from "react-hook-form";
5
+ import { Alert, AlertDescription, AlertTitle } from "zudoku/ui/Alert.js";
6
+
7
+ import { Label } from "zudoku/ui/Label.js";
8
+ import { RadioGroup, RadioGroupItem } from "zudoku/ui/RadioGroup.js";
4
9
  import {
5
10
  Select,
6
11
  SelectContent,
@@ -8,39 +13,30 @@ import {
8
13
  SelectTrigger,
9
14
  SelectValue,
10
15
  } from "zudoku/ui/Select.js";
16
+ import { Textarea } from "zudoku/ui/Textarea.js";
11
17
  import { useSelectedServerStore } from "../../../authentication/state.js";
12
18
  import { useApiIdentities } from "../../../components/context/ZudokuContext.js";
13
- import { Spinner } from "../../../components/Spinner.js";
14
- import { Button } from "../../../ui/Button.js";
15
- import { Callout } from "../../../ui/Callout.js";
16
- import { Card, CardContent, CardHeader, CardTitle } from "../../../ui/Card.js";
19
+ import { Card } from "../../../ui/Card.js";
17
20
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../ui/Tabs.js";
21
+ import { cn } from "../../../util/cn.js";
18
22
  import { ColorizedParam } from "../ColorizedParam.js";
23
+ import { Content } from "../SidecarExamples.js";
19
24
  import { createUrl } from "./createUrl.js";
25
+ import ExamplesDropdown from "./ExamplesDropdown.js";
20
26
  import { Headers } from "./Headers.js";
21
27
  import { PathParams } from "./PathParams.js";
22
28
  import { QueryParams } from "./QueryParams.js";
23
- import { ResponseTab } from "./ResponseTab.js";
29
+ import { ResultPanel } from "./result-panel/ResultPanel.js";
30
+ import SubmitButton from "./SubmitButton.js";
24
31
 
25
32
  export const NO_IDENTITY = "__none";
26
33
 
27
- const statusCodeMap: Record<number, string> = {
28
- 200: "OK",
29
- 201: "Created",
30
- 202: "Accepted",
31
- 204: "No Content",
32
- 400: "Bad Request",
33
- 401: "Unauthorized",
34
- 403: "Forbidden",
35
- 404: "Not Found",
36
- 405: "Method Not Allowed",
37
- 500: "Internal Server Error",
38
- };
39
-
40
34
  export type Header = {
41
35
  name: string;
42
36
  defaultValue?: string;
37
+ defaultActive?: boolean;
43
38
  };
39
+
44
40
  export type QueryParam = {
45
41
  name: string;
46
42
  defaultValue?: string;
@@ -67,10 +63,25 @@ export type PlaygroundForm = {
67
63
  headers: Array<{
68
64
  name: string;
69
65
  value: string;
66
+ active: boolean;
70
67
  }>;
71
68
  identity?: string;
72
69
  };
73
70
 
71
+ export type PlaygroundResult = {
72
+ status: number;
73
+ headers: Array<[string, string]>;
74
+ size: number;
75
+ body: string;
76
+ time: number;
77
+ request: {
78
+ method: string;
79
+ url: string;
80
+ headers: Array<[string, string]>;
81
+ body?: string;
82
+ };
83
+ };
84
+
74
85
  export type PlaygroundContentProps = {
75
86
  server: string;
76
87
  servers?: string[];
@@ -80,6 +91,7 @@ export type PlaygroundContentProps = {
80
91
  queryParams?: QueryParam[];
81
92
  pathParams?: PathParam[];
82
93
  defaultBody?: string;
94
+ examples?: Content;
83
95
  };
84
96
 
85
97
  export const Playground = ({
@@ -91,6 +103,7 @@ export const Playground = ({
91
103
  queryParams = [],
92
104
  pathParams = [],
93
105
  defaultBody = "",
106
+ examples,
94
107
  }: PlaygroundContentProps) => {
95
108
  const { selectedServer, setSelectedServer } = useSelectedServerStore();
96
109
  const [, startTransition] = useTransition();
@@ -98,20 +111,38 @@ export const Playground = ({
98
111
  useForm<PlaygroundForm>({
99
112
  defaultValues: {
100
113
  body: defaultBody,
101
- queryParams: queryParams.map((param) => ({
102
- name: param.name,
103
- value: param.defaultValue ?? "",
104
- active: param.defaultActive ?? false,
105
- enum: param.enum ?? [],
106
- })),
114
+ queryParams: queryParams
115
+ .map((param) => ({
116
+ name: param.name,
117
+ value: param.defaultValue ?? "",
118
+ active: param.defaultActive ?? false,
119
+ enum: param.enum ?? [],
120
+ }))
121
+ .concat([
122
+ {
123
+ name: "",
124
+ value: "",
125
+ active: false,
126
+ enum: [],
127
+ },
128
+ ]),
107
129
  pathParams: pathParams.map((param) => ({
108
130
  name: param.name,
109
131
  value: param.defaultValue ?? "",
110
132
  })),
111
- headers: headers.map((header) => ({
112
- name: header.name,
113
- value: header.defaultValue ?? "",
114
- })),
133
+ headers: headers
134
+ .map((header) => ({
135
+ name: header.name,
136
+ value: header.defaultValue ?? "",
137
+ active: header.defaultActive ?? false,
138
+ }))
139
+ .concat([
140
+ {
141
+ name: "",
142
+ value: "",
143
+ active: false,
144
+ },
145
+ ]),
115
146
  identity: NO_IDENTITY,
116
147
  },
117
148
  });
@@ -128,20 +159,23 @@ export const Playground = ({
128
159
  }
129
160
  }, [setValue, identities.data]);
130
161
 
162
+ const formRef = useRef<HTMLFormElement>(null);
163
+
131
164
  const queryMutation = useMutation({
132
165
  mutationFn: async (data: PlaygroundForm) => {
133
- const requestUrl = createUrl(selectedServer ?? server, url, data);
134
166
  const start = performance.now();
135
-
136
- const request = new Request(requestUrl, {
137
- method: method.toUpperCase(),
138
- headers: Object.fromEntries(
139
- data.headers
140
- .filter((h) => h.name)
141
- .map((header) => [header.name, header.value]),
142
- ),
143
- body: data.body ? data.body : undefined,
144
- });
167
+ const request = new Request(
168
+ createUrl(selectedServer ?? server, url, data),
169
+ {
170
+ method: method.toUpperCase(),
171
+ headers: Object.fromEntries(
172
+ data.headers
173
+ .filter((h) => h.name && h.active)
174
+ .map((header) => [header.name, header.value]),
175
+ ),
176
+ body: data.body ? data.body : undefined,
177
+ },
178
+ );
145
179
 
146
180
  if (data.identity !== NO_IDENTITY) {
147
181
  identities.data
@@ -157,13 +191,25 @@ export const Playground = ({
157
191
 
158
192
  const body = await response.text();
159
193
 
194
+ const url = new URL(request.url);
195
+
160
196
  return {
161
197
  status: response.status,
162
- headers: response.headers,
198
+ headers: Array.from(response.headers.entries()),
163
199
  size: body.length,
164
200
  body,
165
201
  time,
166
- };
202
+ request: {
203
+ method: request.method.toUpperCase(),
204
+ url: request.url,
205
+ headers: [
206
+ ["Host", url.host],
207
+ ["User-Agent", "Zudoku Playground"],
208
+ ...Array.from(request.headers.entries()),
209
+ ],
210
+ body: data.body ? data.body : undefined,
211
+ },
212
+ } satisfies PlaygroundResult;
167
213
  } catch (error) {
168
214
  if (error instanceof TypeError) {
169
215
  throw new Error(
@@ -207,8 +253,6 @@ export const Playground = ({
207
253
  );
208
254
  });
209
255
 
210
- const headerEntries = Array.from(queryMutation.data?.headers.entries() ?? []);
211
-
212
256
  const urlQueryParams = formState.queryParams
213
257
  .filter((p) => p.active)
214
258
  .map((p, i, arr) => (
@@ -229,6 +273,7 @@ export const Playground = ({
229
273
  });
230
274
  }}
231
275
  value={selectedServer}
276
+ defaultValue={selectedServer}
232
277
  >
233
278
  <SelectTrigger className="p-0 border-none flex-row-reverse bg-transparent text-xs gap-0.5 h-auto">
234
279
  <SelectValue />
@@ -251,73 +296,55 @@ export const Playground = ({
251
296
  <FormProvider
252
297
  {...{ register, control, handleSubmit, watch, setValue, ...form }}
253
298
  >
254
- <form onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}>
255
- <div className="grid grid-cols-[8fr_7fr] text-sm h-full">
299
+ <form
300
+ onSubmit={handleSubmit((data) => queryMutation.mutateAsync(data))}
301
+ ref={formRef}
302
+ >
303
+ <div className="grid grid-cols-2 text-sm h-full">
256
304
  <div className="flex flex-col gap-4 p-4 after:bg-muted-foreground/20 relative after:absolute after:w-px after:inset-0 after:left-auto">
257
305
  <div className="flex gap-2 items-stretch">
258
306
  <div className="flex flex-1 items-center w-full border rounded-md">
259
- <div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono">
307
+ <div className="border-r p-2 bg-muted rounded-l-md self-stretch font-semibold font-mono flex items-center">
260
308
  {method.toUpperCase()}
261
309
  </div>
262
- <div className="flex items-center flex-wrap p-2 font-mono text-xs">
310
+ <div className="flex items-center flex-wrap p-2 font-mono text-xs break-all">
263
311
  {serverSelect}
264
312
  {path}
265
313
  {urlQueryParams.length > 0 ? "?" : ""}
266
314
  {urlQueryParams}
267
315
  </div>
268
316
  </div>
269
- <Button type="submit" className="h-auto flex gap-1">
270
- Send
271
- </Button>
317
+
318
+ <SubmitButton
319
+ identities={identities.data ?? []}
320
+ formRef={formRef}
321
+ disabled={form.formState.isSubmitting}
322
+ />
272
323
  </div>
273
- <Tabs
274
- defaultValue={
275
- queryParams.length + pathParams.length > 0
276
- ? "parameters"
277
- : "headers"
278
- }
279
- >
324
+ <Tabs defaultValue="parameters">
280
325
  <div className="flex flex-wrap gap-1 justify-between">
281
326
  <TabsList>
282
- {queryParams.length + pathParams.length > 0 && (
283
- <TabsTrigger value="parameters">Parameters</TabsTrigger>
284
- )}
327
+ <TabsTrigger value="parameters">
328
+ Parameters
329
+ {(formState.pathParams.some((p) => p.value !== "") ||
330
+ formState.queryParams.some((p) => p.active)) && (
331
+ <div className="w-2 h-2 rounded-full bg-blue-400 ml-2" />
332
+ )}
333
+ </TabsTrigger>
285
334
  <TabsTrigger value="headers">
286
- Headers{" "}
287
- {formState.headers.length > 0 &&
288
- `(${formState.headers.length})`}
335
+ Headers
336
+ {formState.headers.filter((h) => h.active).length > 0 && (
337
+ <div className="w-2 h-2 rounded-full bg-blue-400 ml-2" />
338
+ )}
289
339
  </TabsTrigger>
290
- <TabsTrigger
291
- value="body"
292
- disabled={
293
- !["POST", "PUT", "PATCH", "DELETE"].includes(
294
- method.toUpperCase(),
295
- )
296
- }
297
- >
298
- Body
340
+ <TabsTrigger value="auth">
341
+ Auth
342
+ {formState.identity !== NO_IDENTITY && (
343
+ <div className="w-2 h-2 rounded-full bg-blue-400 ml-2" />
344
+ )}
299
345
  </TabsTrigger>
346
+ <TabsTrigger value="body">Body</TabsTrigger>
300
347
  </TabsList>
301
- <div className="flex gap-2 items-center">
302
- Auth:
303
- <Select
304
- onValueChange={(value) => setValue("identity", value)}
305
- value={formState.identity}
306
- defaultValue={formState.identity}
307
- >
308
- <SelectTrigger className="w-[180px] flex">
309
- {identities.isPending ? <Spinner /> : <SelectValue />}
310
- </SelectTrigger>
311
- <SelectContent align="center">
312
- <SelectItem value={NO_IDENTITY}>None</SelectItem>
313
- {identities.data?.map((identity) => (
314
- <SelectItem key={identity.id} value={identity.id}>
315
- {identity.label}
316
- </SelectItem>
317
- ))}
318
- </SelectContent>
319
- </Select>
320
- </div>
321
348
  </div>
322
349
  <TabsContent value="headers">
323
350
  <Headers control={control} register={register} />
@@ -329,99 +356,114 @@ export const Playground = ({
329
356
  <PathParams control={control} />
330
357
  </div>
331
358
  )}
332
- {queryParams.length > 0 && (
333
- <div className="flex flex-col gap-4 my-4">
334
- <span className="font-semibold">Query Parameters</span>
335
- <QueryParams control={control} queryParams={queryParams} />
336
- </div>
337
- )}
359
+ <div className="flex flex-col gap-4 my-4">
360
+ <span className="font-semibold">Query Parameters</span>
361
+ <QueryParams control={control} queryParams={queryParams} />
362
+ </div>
338
363
  </TabsContent>
339
364
  <TabsContent value="body">
340
- <textarea
365
+ {!["POST", "PUT", "PATCH", "DELETE"].includes(
366
+ method.toUpperCase(),
367
+ ) && (
368
+ <Alert className="mb-2">
369
+ <InfoIcon className="w-4 h-4" />
370
+ <AlertTitle>Body</AlertTitle>
371
+ <AlertDescription>
372
+ Body is only supported for POST, PUT, PATCH, and DELETE
373
+ requests
374
+ </AlertDescription>
375
+ </Alert>
376
+ )}
377
+ <Textarea
341
378
  {...register("body")}
342
- className="border w-full rounded p-2 bg-muted h-40"
379
+ className={cn(
380
+ "border w-full rounded-lg p-2 bg-muted h-40 font-mono",
381
+ !["POST", "PUT", "PATCH", "DELETE"].includes(
382
+ method.toUpperCase(),
383
+ ) && "h-20",
384
+ )}
385
+ placeholder={
386
+ !["POST", "PUT", "PATCH", "DELETE"].includes(
387
+ method.toUpperCase(),
388
+ )
389
+ ? "This request does not support a body"
390
+ : undefined
391
+ }
392
+ disabled={
393
+ !["POST", "PUT", "PATCH", "DELETE"].includes(
394
+ method.toUpperCase(),
395
+ )
396
+ }
343
397
  />
344
- </TabsContent>
345
- </Tabs>
346
- </div>
347
- <div className="min-w-0 p-8 bg-muted/70">
348
- {queryMutation.error ? (
349
- <div className="flex flex-col gap-2">
350
- {formState.pathParams.some((p) => p.value === "") && (
351
- <Callout type="caution">
352
- Some path parameters are missing values. Please fill them in
353
- to ensure the request is sent correctly.
354
- </Callout>
398
+ {examples && (
399
+ <ExamplesDropdown
400
+ examples={examples}
401
+ onSelect={(example) =>
402
+ setValue("body", JSON.stringify(example.value, null, 2))
403
+ }
404
+ />
355
405
  )}
356
- <Card>
357
- <CardHeader>
358
- <CardTitle>Request failed</CardTitle>
359
- </CardHeader>
360
- <CardContent>
361
- Error:{" "}
362
- {queryMutation.error.message ||
363
- String(queryMutation.error) ||
364
- "Unexpected error"}
365
- </CardContent>
366
- </Card>
367
- </div>
368
- ) : queryMutation.data ? (
369
- <div className="flex flex-col gap-2">
370
- <div className="flex gap-2">
371
- <div className="flex text-xs gap-6">
372
- <div>
373
- Status: {queryMutation.data.status}{" "}
374
- {statusCodeMap[queryMutation.data.status] ?? ""}
375
- </div>
376
- <div>Time: {queryMutation.data.time.toFixed(0)}ms</div>
377
- <div>Size: {queryMutation.data.size} B</div>
406
+ </TabsContent>
407
+ <TabsContent value="auth">
408
+ <div className="flex flex-col gap-4 my-4">
409
+ {identities.data?.length === 0 && (
410
+ <Alert>
411
+ <InfoIcon className="w-4 h-4" />
412
+ <AlertTitle>Authentication</AlertTitle>
413
+ <AlertDescription>
414
+ No identities found. Please create an identity first.
415
+ </AlertDescription>
416
+ </Alert>
417
+ )}
418
+ <div className="flex flex-col items-center gap-2">
419
+ <Card className="w-full overflow-hidden">
420
+ <RadioGroup
421
+ onValueChange={(value) => setValue("identity", value)}
422
+ value={formState.identity}
423
+ defaultValue={formState.identity}
424
+ className="gap-0"
425
+ disabled={identities.data?.length === 0}
426
+ >
427
+ <Label
428
+ className="h-12 border-b items-center flex p-4 cursor-pointer hover:bg-accent"
429
+ htmlFor="none"
430
+ >
431
+ <RadioGroupItem value={NO_IDENTITY} id="none">
432
+ None
433
+ </RadioGroupItem>
434
+ <Label htmlFor="none" className="ml-2">
435
+ None
436
+ </Label>
437
+ </Label>
438
+ {identities.data?.map((identity) => (
439
+ <Label
440
+ key={identity.id}
441
+ className="h-12 border-b items-center flex p-4 cursor-pointer hover:bg-accent"
442
+ >
443
+ <RadioGroupItem
444
+ value={identity.id}
445
+ id={identity.id}
446
+ >
447
+ {identity.label}
448
+ </RadioGroupItem>
449
+ <Label htmlFor={identity.id} className="ml-2">
450
+ {identity.label}
451
+ </Label>
452
+ </Label>
453
+ ))}
454
+ </RadioGroup>
455
+ </Card>
378
456
  </div>
379
457
  </div>
380
- <Tabs defaultValue="response">
381
- <TabsList>
382
- <TabsTrigger value="response">Response</TabsTrigger>
383
- <TabsTrigger value="headers">
384
- {headerEntries.length
385
- ? `Headers (${headerEntries.length})`
386
- : "No headers"}
387
- </TabsTrigger>
388
- </TabsList>
389
-
390
- <TabsContent value="response">
391
- <ResponseTab
392
- headers={queryMutation.data.headers}
393
- body={queryMutation.data.body}
394
- />
395
- </TabsContent>
396
- <TabsContent value="headers">
397
- <Card
398
- // playground dialog has h-5/6 ≈ 83.333vh
399
- className="max-h-[calc(83.333vh-140px)] overflow-y-auto grid grid-cols-2 w-full gap-2.5 font-mono text-xs shadow-none p-4"
400
- >
401
- <div className="font-semibold">Key</div>
402
- <div className="font-semibold">Value</div>
403
- {headerEntries.map(([key, value]) => (
404
- <Fragment key={key}>
405
- <div>{key}</div>
406
- <div className="break-words">{value}</div>
407
- </Fragment>
408
- ))}
409
- </Card>
410
- </TabsContent>
411
- </Tabs>
412
- </div>
413
- ) : (
414
- <div className="grid place-items-center h-full">
415
- <span className="text-[16px] font-semibold text-muted-foreground">
416
- {queryMutation.isPending ? (
417
- <Spinner />
418
- ) : (
419
- "Send a request first to see the response here"
420
- )}
421
- </span>
422
- </div>
423
- )}
458
+ </TabsContent>
459
+ </Tabs>
424
460
  </div>
461
+ <ResultPanel
462
+ queryMutation={queryMutation}
463
+ showPathParamsWarning={formState.pathParams.some(
464
+ (p) => p.value === "",
465
+ )}
466
+ />
425
467
  </div>
426
468
  </form>
427
469
  </FormProvider>
@@ -47,7 +47,7 @@ const PlaygroundDialog = (props: PlaygroundDialogProps) => {
47
47
  </DialogTrigger>
48
48
 
49
49
  <DialogContent
50
- className="max-w-screen-xl w-full h-5/6 overflow-auto p-0"
50
+ className="max-w-screen-xl w-full h-5/6 overflow-hidden p-0"
51
51
  aria-describedby={undefined}
52
52
  >
53
53
  <VisuallyHidden>