zudoku 0.66.3 → 0.66.5

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 (211) hide show
  1. package/dist/lib/authentication/components/CallbackHandler.js +1 -1
  2. package/dist/lib/authentication/components/CallbackHandler.js.map +1 -1
  3. package/dist/lib/authentication/components/SignIn.js +4 -2
  4. package/dist/lib/authentication/components/SignIn.js.map +1 -1
  5. package/dist/lib/authentication/components/SignUp.js +4 -2
  6. package/dist/lib/authentication/components/SignUp.js.map +1 -1
  7. package/dist/lib/core/RouteGuard.js +12 -7
  8. package/dist/lib/core/RouteGuard.js.map +1 -1
  9. package/dist/lib/oas/graphql/index.js +7 -3
  10. package/dist/lib/oas/graphql/index.js.map +1 -1
  11. package/dist/lib/plugins/api-keys/index.d.ts +9 -5
  12. package/dist/lib/plugins/api-keys/index.js +20 -11
  13. package/dist/lib/plugins/api-keys/index.js.map +1 -1
  14. package/dist/lib/plugins/api-keys/settings/ApiKeyList.js +3 -0
  15. package/dist/lib/plugins/api-keys/settings/ApiKeyList.js.map +1 -1
  16. package/dist/lib/plugins/openapi/ParamInfos.js +1 -0
  17. package/dist/lib/plugins/openapi/ParamInfos.js.map +1 -1
  18. package/dist/lib/plugins/openapi/Sidecar.js +3 -2
  19. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  20. package/dist/lib/plugins/openapi/schema/SchemaView.js +1 -1
  21. package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
  22. package/dist/lib/plugins/openapi/util/createHttpSnippet.js +24 -1
  23. package/dist/lib/plugins/openapi/util/createHttpSnippet.js.map +1 -1
  24. package/dist/lib/ui/Button.js +1 -1
  25. package/dist/lib/ui/Button.js.map +1 -1
  26. package/dist/lib/util/invariant.d.ts +1 -1
  27. package/dist/lib/util/invariant.js +2 -2
  28. package/dist/lib/util/invariant.js.map +1 -1
  29. package/dist/vite/mdx/remark-link-rewrite.js +1 -1
  30. package/dist/vite/plugin-api-keys.js +1 -0
  31. package/dist/vite/plugin-api-keys.js.map +1 -1
  32. package/dist/vite/plugin-markdown-export.js +1 -1
  33. package/dist/vite/plugin-markdown-export.js.map +1 -1
  34. package/dist/vite/prerender/worker.js +3 -0
  35. package/dist/vite/prerender/worker.js.map +1 -1
  36. package/lib/{ActionButton-DUgvSylL.js → ActionButton-B0CXL1Lq.js} +3 -3
  37. package/lib/{ActionButton-DUgvSylL.js.map → ActionButton-B0CXL1Lq.js.map} +1 -1
  38. package/lib/{Button-CynVW1JV.js → Button-GUVe7pmt.js} +8 -7
  39. package/lib/{Button-CynVW1JV.js.map → Button-GUVe7pmt.js.map} +1 -1
  40. package/lib/{Card-KFniaZn5.js → Card-DCdq37aA.js} +2 -2
  41. package/lib/{Card-KFniaZn5.js.map → Card-DCdq37aA.js.map} +1 -1
  42. package/lib/{ClaudeLogo-BZslN9XF.js → ClaudeLogo-ByzA8TYR.js} +3 -3
  43. package/lib/{ClaudeLogo-BZslN9XF.js.map → ClaudeLogo-ByzA8TYR.js.map} +1 -1
  44. package/lib/{Command-BpT1iBE6.js → Command-N6VujV30.js} +3 -3
  45. package/lib/{Command-BpT1iBE6.js.map → Command-N6VujV30.js.map} +1 -1
  46. package/lib/{Dialog-BQciPiHN.js → Dialog-hlvmmQ_c.js} +2 -2
  47. package/lib/{Dialog-BQciPiHN.js.map → Dialog-hlvmmQ_c.js.map} +1 -1
  48. package/lib/{Drawer-BRMcpfuF.js → Drawer-Ch7927PF.js} +2 -2
  49. package/lib/{Drawer-BRMcpfuF.js.map → Drawer-Ch7927PF.js.map} +1 -1
  50. package/lib/{DropdownMenu-C8SX_-S_.js → DropdownMenu-DN0jNrjj.js} +2 -2
  51. package/lib/{DropdownMenu-C8SX_-S_.js.map → DropdownMenu-DN0jNrjj.js.map} +1 -1
  52. package/lib/{Frame-DxlznfVd.js → Frame-DKlOmSkU.js} +2 -2
  53. package/lib/{Frame-DxlznfVd.js.map → Frame-DKlOmSkU.js.map} +1 -1
  54. package/lib/{IndexingDialog-B5zCiUKr.js → IndexingDialog-D0YdGfbn.js} +3 -3
  55. package/lib/{IndexingDialog-B5zCiUKr.js.map → IndexingDialog-D0YdGfbn.js.map} +1 -1
  56. package/lib/{Input-D-kqEQ5M.js → Input-nskrp_mj.js} +39 -18
  57. package/lib/Input-nskrp_mj.js.map +1 -0
  58. package/lib/{MdxPage-B4zZq5aR.js → MdxPage-Bh5YNRV9.js} +10 -10
  59. package/lib/{MdxPage-B4zZq5aR.js.map → MdxPage-Bh5YNRV9.js.map} +1 -1
  60. package/lib/{Mermaid-BjSczjLW.js → Mermaid-CGRoylZf.js} +4 -4
  61. package/lib/{Mermaid-BjSczjLW.js.map → Mermaid-CGRoylZf.js.map} +1 -1
  62. package/lib/{OAuthErrorPage-DRY2hlga.js → OAuthErrorPage-CsTKz5hX.js} +8 -8
  63. package/lib/OAuthErrorPage-CsTKz5hX.js.map +1 -0
  64. package/lib/{OasProvider-lMwTD76Y.js → OasProvider-BBAbJiYa.js} +3 -3
  65. package/lib/{OasProvider-lMwTD76Y.js.map → OasProvider-BBAbJiYa.js.map} +1 -1
  66. package/lib/{OperationList-Bm76b4vl.js → OperationList-DUxrNisd.js} +1104 -1089
  67. package/lib/{OperationList-Bm76b4vl.js.map → OperationList-DUxrNisd.js.map} +1 -1
  68. package/lib/RouteGuard-CIN9Ou-r.js +77 -0
  69. package/lib/RouteGuard-CIN9Ou-r.js.map +1 -0
  70. package/lib/{SchemaList-DX4FPogg.js → SchemaList-BbnkfjIe.js} +9 -9
  71. package/lib/{SchemaList-DX4FPogg.js.map → SchemaList-BbnkfjIe.js.map} +1 -1
  72. package/lib/{SchemaView-CjXvSRxy.js → SchemaView-BrUf6_nP.js} +112 -111
  73. package/lib/SchemaView-BrUf6_nP.js.map +1 -0
  74. package/lib/{Secret-BxGpIhDP.js → Secret-BDBqq4p3.js} +2 -2
  75. package/lib/{Secret-BxGpIhDP.js.map → Secret-BDBqq4p3.js.map} +1 -1
  76. package/lib/{Separator-CTPSeW1S.js → Separator-BXt1LYnm.js} +2 -2
  77. package/lib/{Separator-CTPSeW1S.js.map → Separator-BXt1LYnm.js.map} +1 -1
  78. package/lib/SignUp-AlaaduyY.js +50 -0
  79. package/lib/SignUp-AlaaduyY.js.map +1 -0
  80. package/lib/{SyntaxHighlight-Dgd0AaaX.js → SyntaxHighlight-DveJcTOQ.js} +4 -4
  81. package/lib/{SyntaxHighlight-Dgd0AaaX.js.map → SyntaxHighlight-DveJcTOQ.js.map} +1 -1
  82. package/lib/{Toc-L1vGGHA1.js → Toc-B4ShtN-I.js} +3 -3
  83. package/lib/{Toc-L1vGGHA1.js.map → Toc-B4ShtN-I.js.map} +1 -1
  84. package/lib/{ZudokuContext-DNHMZfcP.js → ZudokuContext-CDJYKqMY.js} +542 -469
  85. package/lib/ZudokuContext-CDJYKqMY.js.map +1 -0
  86. package/lib/{___vite-browser-external_commonjs-proxy-Cga3HsWk.js → ___vite-browser-external_commonjs-proxy-BttVsNON.js} +2 -2
  87. package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js.map +1 -0
  88. package/lib/chunk-PVWAREVJ-ClM0m2aJ.js.map +1 -1
  89. package/lib/{circular-BIN_WQ0c.js → circular-CuSWVYOZ.js} +2 -2
  90. package/lib/{circular-BIN_WQ0c.js.map → circular-CuSWVYOZ.js.map} +1 -1
  91. package/lib/{cn-dYga0KKN.js → cn-5-Gd1Dss.js} +531 -498
  92. package/lib/cn-5-Gd1Dss.js.map +1 -0
  93. package/lib/{createServer-BEl12QFw.js → createServer-B1_RUTJP.js} +12 -12
  94. package/lib/{createServer-BEl12QFw.js.map → createServer-B1_RUTJP.js.map} +1 -1
  95. package/lib/{createVariantComponent-CQVt-H3r.js → createVariantComponent-Dc0vtOvr.js} +2 -2
  96. package/lib/{createVariantComponent-CQVt-H3r.js.map → createVariantComponent-Dc0vtOvr.js.map} +1 -1
  97. package/lib/{errors-CtBbD47A.js → errors-iDfQAr_v.js} +3 -3
  98. package/lib/{errors-CtBbD47A.js.map → errors-iDfQAr_v.js.map} +1 -1
  99. package/lib/{firebase-CT38ugg4.js → firebase-I54w2ZsH.js} +20 -20
  100. package/lib/{firebase-CT38ugg4.js.map → firebase-I54w2ZsH.js.map} +1 -1
  101. package/lib/{hook-CHw_R_xu.js → hook-BxWvqzB0.js} +2 -2
  102. package/lib/{hook-CHw_R_xu.js.map → hook-BxWvqzB0.js.map} +1 -1
  103. package/lib/{index-CG2v-T7-.js → index-A5Cre871.js} +11 -11
  104. package/lib/{index-CG2v-T7-.js.map → index-A5Cre871.js.map} +1 -1
  105. package/lib/{index-jI2Fjpy-.js → index-B4puReRo.js} +20 -20
  106. package/lib/{index-jI2Fjpy-.js.map → index-B4puReRo.js.map} +1 -1
  107. package/lib/{index-DXXZDuSJ.js → index-CjTisMeX.js} +3 -3
  108. package/lib/{index-DXXZDuSJ.js.map → index-CjTisMeX.js.map} +1 -1
  109. package/lib/index-CrcNWbel.js.map +1 -1
  110. package/lib/{index-CISwSpdT.js → index-Dbrv6d94.js} +2 -2
  111. package/lib/{index-CISwSpdT.js.map → index-Dbrv6d94.js.map} +1 -1
  112. package/lib/index.esm-BYObtETB.js.map +1 -1
  113. package/lib/{index.esm-DtzT_KoE.js → index.esm-B_0dvNjB.js} +2 -2
  114. package/lib/{index.esm-DtzT_KoE.js.map → index.esm-B_0dvNjB.js.map} +1 -1
  115. package/lib/{index.esm-Bu35TNgg.js → index.esm-BxIXRKtj.js} +2 -2
  116. package/lib/index.esm-BxIXRKtj.js.map +1 -0
  117. package/lib/{invariant-CGOLuIIz.js → invariant-BJAl77rw.js} +4 -4
  118. package/lib/invariant-BJAl77rw.js.map +1 -0
  119. package/lib/jsx-runtime-BzflLqGi.js.map +1 -1
  120. package/lib/{mutation-DMHWqmFp.js → mutation-Cq0wKBqW.js} +70 -44
  121. package/lib/mutation-Cq0wKBqW.js.map +1 -0
  122. package/lib/ui/Accordion.js +1 -1
  123. package/lib/ui/ActionButton.js +2 -2
  124. package/lib/ui/Alert.js +1 -1
  125. package/lib/ui/AlertDialog.js +1 -1
  126. package/lib/ui/Badge.js +1 -1
  127. package/lib/ui/Breadcrumb.js +1 -1
  128. package/lib/ui/Button.js +7 -6
  129. package/lib/ui/Button.js.map +1 -1
  130. package/lib/ui/ButtonGroup.js +1 -1
  131. package/lib/ui/Callout.js +1 -1
  132. package/lib/ui/Card.js +1 -1
  133. package/lib/ui/Carousel.js +1 -1
  134. package/lib/ui/Carousel.js.map +1 -1
  135. package/lib/ui/Checkbox.js +1 -1
  136. package/lib/ui/CodeBlock.js +1 -1
  137. package/lib/ui/Command.js +2 -2
  138. package/lib/ui/Dialog.js +1 -1
  139. package/lib/ui/Drawer.js +2 -2
  140. package/lib/ui/DropdownMenu.js +1 -1
  141. package/lib/ui/EmbeddedCodeBlock.js +1 -1
  142. package/lib/ui/Form.js +1 -1
  143. package/lib/ui/Frame.js +1 -1
  144. package/lib/ui/HoverCard.js +1 -1
  145. package/lib/ui/Input.js +1 -1
  146. package/lib/ui/Item.js +1 -1
  147. package/lib/ui/Label.js +1 -1
  148. package/lib/ui/NativeSelect.js +1 -1
  149. package/lib/ui/Pagination.js +1 -1
  150. package/lib/ui/Popover.js +1 -1
  151. package/lib/ui/Progress.js +1 -1
  152. package/lib/ui/RadioGroup.js +1 -1
  153. package/lib/ui/ScrollArea.js +1 -1
  154. package/lib/ui/Secret.js +1 -1
  155. package/lib/ui/Separator.js +1 -1
  156. package/lib/ui/Skeleton.js +1 -1
  157. package/lib/ui/Slider.js +1 -1
  158. package/lib/ui/Switch.js +1 -1
  159. package/lib/ui/SyntaxHighlight.js +3 -3
  160. package/lib/ui/Tabs.js +1 -1
  161. package/lib/ui/Textarea.js +1 -1
  162. package/lib/ui/Toggle.js +1 -1
  163. package/lib/ui/ToggleGroup.js +1 -1
  164. package/lib/ui/Value.js +1 -1
  165. package/lib/ui/util.js +1 -1
  166. package/lib/zudoku.__internal.js +576 -574
  167. package/lib/zudoku.__internal.js.map +1 -1
  168. package/lib/zudoku.auth-auth0.js +1 -1
  169. package/lib/zudoku.auth-azureb2c.js +4 -4
  170. package/lib/zudoku.auth-clerk.js +2 -2
  171. package/lib/zudoku.auth-firebase.js +5 -5
  172. package/lib/zudoku.auth-openid.js +5 -5
  173. package/lib/zudoku.auth-supabase.js +4 -4
  174. package/lib/zudoku.components.js +5 -5
  175. package/lib/zudoku.hooks.js +3 -3
  176. package/lib/zudoku.mermaid.js +3 -3
  177. package/lib/zudoku.plugin-api-catalog.js +4 -4
  178. package/lib/zudoku.plugin-api-keys.js +258 -242
  179. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  180. package/lib/zudoku.plugin-custom-pages.js +1 -1
  181. package/lib/zudoku.plugin-markdown.js +1 -1
  182. package/lib/zudoku.plugin-openapi.js +2 -2
  183. package/lib/zudoku.plugin-search-pagefind.js +6 -6
  184. package/lib/zudoku.router.js.map +1 -1
  185. package/package.json +6 -6
  186. package/src/lib/authentication/components/CallbackHandler.tsx +1 -1
  187. package/src/lib/authentication/components/SignIn.tsx +5 -2
  188. package/src/lib/authentication/components/SignUp.tsx +5 -2
  189. package/src/lib/core/RouteGuard.tsx +30 -24
  190. package/src/lib/oas/graphql/index.ts +7 -3
  191. package/src/lib/plugins/api-keys/index.tsx +48 -19
  192. package/src/lib/plugins/api-keys/settings/ApiKeyList.tsx +3 -0
  193. package/src/lib/plugins/openapi/ParamInfos.tsx +1 -0
  194. package/src/lib/plugins/openapi/Sidecar.tsx +3 -2
  195. package/src/lib/plugins/openapi/schema/SchemaView.tsx +6 -4
  196. package/src/lib/plugins/openapi/util/createHttpSnippet.ts +29 -1
  197. package/src/lib/ui/Button.tsx +1 -0
  198. package/src/lib/util/invariant.ts +2 -1
  199. package/lib/Input-D-kqEQ5M.js.map +0 -1
  200. package/lib/OAuthErrorPage-DRY2hlga.js.map +0 -1
  201. package/lib/RouteGuard-DGc32XJV.js +0 -77
  202. package/lib/RouteGuard-DGc32XJV.js.map +0 -1
  203. package/lib/SchemaView-CjXvSRxy.js.map +0 -1
  204. package/lib/SignUp-CntxjFGS.js +0 -50
  205. package/lib/SignUp-CntxjFGS.js.map +0 -1
  206. package/lib/ZudokuContext-DNHMZfcP.js.map +0 -1
  207. package/lib/___vite-browser-external_commonjs-proxy-Cga3HsWk.js.map +0 -1
  208. package/lib/cn-dYga0KKN.js.map +0 -1
  209. package/lib/index.esm-Bu35TNgg.js.map +0 -1
  210. package/lib/invariant-CGOLuIIz.js.map +0 -1
  211. package/lib/mutation-DMHWqmFp.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.66.3",
3
+ "version": "0.66.5",
4
4
  "type": "module",
5
5
  "homepage": "https://zudoku.dev",
6
6
  "repository": {
@@ -190,7 +190,7 @@
190
190
  "@tailwindcss/typography": "0.5.19",
191
191
  "@tailwindcss/vite": "4.1.16",
192
192
  "@tanem/react-nprogress": "5.0.56",
193
- "@tanstack/react-query": "5.85.5",
193
+ "@tanstack/react-query": "5.90.12",
194
194
  "@types/react": "19.2.7",
195
195
  "@types/react-dom": "19.2.3",
196
196
  "@vitejs/plugin-react": "5.1.0",
@@ -231,7 +231,7 @@
231
231
  "posthog-node": "5.14.1",
232
232
  "react-error-boundary": "6.0.0",
233
233
  "react-hook-form": "7.66.0",
234
- "react-is": "19.2.1",
234
+ "react-is": "19.2.3",
235
235
  "react-markdown": "10.1.0",
236
236
  "react-router": "7.8.2",
237
237
  "rehype-mdx-import-media": "1.2.0",
@@ -248,7 +248,7 @@
248
248
  "shiki": "3.19.0",
249
249
  "sitemap": "9.0.0",
250
250
  "strip-ansi": "7.1.2",
251
- "tailwind-merge": "3.3.1",
251
+ "tailwind-merge": "3.4.0",
252
252
  "tailwindcss": "4.1.17",
253
253
  "tw-animate-css": "1.4.0",
254
254
  "unified": "^11.0.5",
@@ -284,8 +284,8 @@
284
284
  "esbuild": "0.27.0",
285
285
  "happy-dom": "20.0.10",
286
286
  "mdast-util-mdx": "3.0.0",
287
- "react": "19.2.1",
288
- "react-dom": "19.2.1",
287
+ "react": "19.2.3",
288
+ "react-dom": "19.2.3",
289
289
  "rollup-plugin-visualizer": "6.0.5",
290
290
  "tsx": "4.20.6",
291
291
  "typescript": "5.9.3",
@@ -13,7 +13,7 @@ export function CallbackHandler({
13
13
  const { options } = useZudoku();
14
14
  const executeCallback = useSuspenseQuery({
15
15
  retry: false,
16
- queryKey: ["oauth-callback"],
16
+ queryKey: ["oauth-callback", window.location.search],
17
17
  queryFn: async () => {
18
18
  const url = new URL(window.location.href);
19
19
 
@@ -8,6 +8,7 @@ import {
8
8
  CardHeader,
9
9
  CardTitle,
10
10
  } from "zudoku/ui/Card.js";
11
+ import { useLatest } from "../../util/useLatest.js";
11
12
  import { useAuth } from "../hook.js";
12
13
 
13
14
  export const SignIn = () => {
@@ -15,12 +16,14 @@ export const SignIn = () => {
15
16
  const [search] = useSearchParams();
16
17
  const redirectTo = search.get("redirect") ?? undefined;
17
18
 
19
+ const login = useLatest(auth.login);
20
+
18
21
  useEffect(() => {
19
- void auth.login({
22
+ void login.current({
20
23
  redirectTo,
21
24
  replace: true,
22
25
  });
23
- }, [auth, redirectTo]);
26
+ }, [login, redirectTo]);
24
27
 
25
28
  return (
26
29
  <div className="flex items-center justify-center mt-8">
@@ -7,14 +7,17 @@ import {
7
7
  CardHeader,
8
8
  CardTitle,
9
9
  } from "zudoku/ui/Card.js";
10
+ import { useLatest } from "../../util/useLatest.js";
10
11
  import { useAuth } from "../hook.js";
11
12
 
12
13
  export const SignUp = () => {
13
14
  const auth = useAuth();
14
15
 
16
+ const signup = useLatest(auth.signup);
17
+
15
18
  useEffect(() => {
16
- void auth.signup();
17
- }, [auth]);
19
+ void signup.current();
20
+ }, [signup]);
18
21
 
19
22
  return (
20
23
  <div className="flex items-center justify-center mt-8">
@@ -27,16 +27,31 @@ export const RouteGuard = () => {
27
27
  const shouldBypass = use(BypassProtectedRoutesContext);
28
28
  const { protectedRoutes } = zudoku.options;
29
29
 
30
- const authCheckFn =
31
- !shouldBypass && protectedRoutes
32
- ? Object.entries(protectedRoutes).find(([path]) =>
33
- matchPath({ path, end: true }, location.pathname),
34
- )?.[1]
35
- : undefined;
30
+ const protectedRouteEntry = protectedRoutes
31
+ ? Object.entries(protectedRoutes).find(([path]) =>
32
+ matchPath({ path, end: true }, location.pathname),
33
+ )
34
+ : undefined;
36
35
 
37
- const isProtectedRoute = authCheckFn !== undefined;
38
- const needsToSignIn =
39
- isProtectedRoute && !authCheckFn({ auth, context: zudoku });
36
+ const isProtectedRoute = protectedRouteEntry !== undefined;
37
+
38
+ // SSR/prerendering mode: render content with search meta tag, skip all auth
39
+ if (shouldBypass) {
40
+ return (
41
+ <>
42
+ {isProtectedRoute && (
43
+ <Helmet>
44
+ <meta
45
+ name="pagefind"
46
+ data-pagefind-filter={`section:${SEARCH_PROTECTED_SECTION}`}
47
+ content="true"
48
+ />
49
+ </Helmet>
50
+ )}
51
+ <Outlet />
52
+ </>
53
+ );
54
+ }
40
55
 
41
56
  if (isProtectedRoute && !auth.isAuthEnabled) {
42
57
  throw new ZudokuError("Authentication is not enabled", {
@@ -46,6 +61,10 @@ export const RouteGuard = () => {
46
61
  });
47
62
  }
48
63
 
64
+ const authCheckFn = protectedRouteEntry?.[1];
65
+ const needsToSignIn =
66
+ isProtectedRoute && !authCheckFn?.({ auth, context: zudoku });
67
+
49
68
  if (needsToSignIn && auth.isPending && typeof window !== "undefined") {
50
69
  return null;
51
70
  }
@@ -91,7 +110,7 @@ export const RouteGuard = () => {
91
110
  )
92
111
  }
93
112
  >
94
- Login{" "}
113
+ Login
95
114
  </Button>
96
115
  </DialogFooter>
97
116
  </DialogContent>
@@ -99,18 +118,5 @@ export const RouteGuard = () => {
99
118
  );
100
119
  }
101
120
 
102
- return (
103
- <>
104
- {shouldBypass && isProtectedRoute && (
105
- <Helmet>
106
- <meta
107
- name="pagefind"
108
- data-pagefind-filter={`section:${SEARCH_PROTECTED_SECTION}`}
109
- content="true"
110
- />
111
- </Helmet>
112
- )}
113
- <Outlet />
114
- </>
115
- );
121
+ return <Outlet />;
116
122
  };
@@ -473,7 +473,9 @@ const OperationItem = builder
473
473
  name,
474
474
  ...(typeof value === "string" ? { value } : value),
475
475
  }))
476
- : [],
476
+ : content.example !== undefined
477
+ ? [{ name: "", value: content.example }]
478
+ : [],
477
479
  encoding: Object.entries(content.encoding ?? {}).map(
478
480
  ([name, value]) => ({ name, ...value }),
479
481
  ),
@@ -490,7 +492,7 @@ const OperationItem = builder
490
492
  statusCode,
491
493
  description: response.description,
492
494
  content: Object.entries(response.content ?? {}).map(
493
- ([mediaType, { schema, examples }]) => ({
495
+ ([mediaType, { schema, examples, example }]) => ({
494
496
  mediaType,
495
497
  schema,
496
498
  examples: examples
@@ -498,7 +500,9 @@ const OperationItem = builder
498
500
  name,
499
501
  ...(typeof value === "string" ? { value } : value),
500
502
  }))
501
- : [],
503
+ : example !== undefined
504
+ ? [{ name: "", value: example }]
505
+ : [],
502
506
  }),
503
507
  ),
504
508
  headers: response.headers,
@@ -37,9 +37,11 @@ export type ApiKeyService = {
37
37
  }) => Promise<void>;
38
38
  };
39
39
 
40
- export type ApiKeyPluginOptions =
41
- | ApiKeyService
42
- | ({ deploymentName: string } & Partial<ApiKeyService>);
40
+ export type ApiKeyPluginOptions = ApiKeyService | DefaultApiKeyServiceOptions;
41
+
42
+ type DefaultApiKeyServiceOptions = {
43
+ deploymentName?: string;
44
+ } & Partial<ApiKeyService>;
43
45
 
44
46
  export interface ApiKey {
45
47
  id: string;
@@ -79,12 +81,19 @@ const throwIfProblemJson = async (response: Response) => {
79
81
  }
80
82
  };
81
83
 
82
- const createDefaultHandler = (
83
- deploymentName: string,
84
- options: ApiKeyPluginOptions,
85
- ): ApiKeyService => {
84
+ const developerHintOptions = {
85
+ developerHint:
86
+ "This project is not linked to a Zuplo deployment. Run `zuplo link` to get started with API Keys.",
87
+ title: "Not linked to a Zuplo deployment",
88
+ };
89
+
90
+ const createZuploService = ({
91
+ deploymentName,
92
+ ...options
93
+ }: DefaultApiKeyServiceOptions): ApiKeyService => {
86
94
  return {
87
95
  deleteKey: async (consumerId, keyId, context) => {
96
+ invariant(deploymentName, "Cannot delete API key.", developerHintOptions);
88
97
  const request = new Request(
89
98
  DEFAULT_API_KEY_ENDPOINT +
90
99
  `/${deploymentName}/consumers/${consumerId}/keys/${keyId}`,
@@ -92,17 +101,20 @@ const createDefaultHandler = (
92
101
  method: "DELETE",
93
102
  },
94
103
  );
95
- await context.signRequest(request);
96
- const response = await fetch(request);
104
+ const response = await fetch(await context.signRequest(request));
97
105
  await throwIfProblemJson(response);
98
106
  invariant(response.ok, "Failed to delete API key");
99
107
  },
100
108
  updateConsumer: async (consumer, context) => {
109
+ invariant(
110
+ deploymentName,
111
+ "Cannot update API key description.",
112
+ developerHintOptions,
113
+ );
101
114
  const response = await fetch(
102
115
  await context.signRequest(
103
116
  new Request(
104
- DEFAULT_API_KEY_ENDPOINT +
105
- `/${deploymentName}/consumers/${consumer.id}`,
117
+ `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers/${consumer.id}`,
106
118
  {
107
119
  method: "PATCH",
108
120
  headers: {
@@ -119,11 +131,11 @@ const createDefaultHandler = (
119
131
  invariant(response.ok, "Failed to update API key description");
120
132
  },
121
133
  rollKey: async (consumerId, context) => {
134
+ invariant(deploymentName, "Cannot roll API key.", developerHintOptions);
122
135
  const response = await fetch(
123
136
  await context.signRequest(
124
137
  new Request(
125
- DEFAULT_API_KEY_ENDPOINT +
126
- `/${deploymentName}/consumers/${consumerId}/roll-key`,
138
+ `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers/${consumerId}/roll-key`,
127
139
  {
128
140
  method: "POST",
129
141
  headers: {
@@ -135,9 +147,10 @@ const createDefaultHandler = (
135
147
  ),
136
148
  );
137
149
  await throwIfProblemJson(response);
138
- invariant(response.ok, "Failed to delete API key");
150
+ invariant(response.ok, "Failed to roll API key");
139
151
  },
140
152
  getConsumers: async (context) => {
153
+ invariant(deploymentName, "Cannot get API keys.", developerHintOptions);
141
154
  const request = new Request(
142
155
  `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers`,
143
156
  );
@@ -180,14 +193,30 @@ const createDefaultHandler = (
180
193
  export const createApiKeyService = <T extends ApiKeyService>(service: T): T =>
181
194
  service;
182
195
 
196
+ type InternalApiKeyPluginOptions = {
197
+ // The name of the Zuplo deployment
198
+ deploymentName?: string;
199
+ // Indicates that the plugin is running in Zuplo "mode"
200
+ isZuplo?: boolean;
201
+ };
202
+
183
203
  export const apiKeyPlugin = ({
184
204
  deploymentName,
205
+ isZuplo,
185
206
  ...options
186
- }: Omit<ApiKeysOptions, "enabled"> & {
187
- deploymentName?: string;
188
- }): ZudokuPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {
189
- const service = deploymentName
190
- ? createDefaultHandler(deploymentName, { deploymentName, ...options })
207
+ }: Omit<ApiKeysOptions, "enabled"> &
208
+ InternalApiKeyPluginOptions): ZudokuPlugin &
209
+ ApiIdentityPlugin &
210
+ ProfileMenuPlugin => {
211
+ if (isZuplo && !deploymentName) {
212
+ // biome-ignore lint/suspicious/noConsole: Important warning
213
+ console.warn(
214
+ "This project is not linked to a Zuplo deployment. Run `zuplo link` to get started.",
215
+ );
216
+ }
217
+
218
+ const service = isZuplo
219
+ ? createZuploService({ deploymentName, ...options })
191
220
  : options;
192
221
 
193
222
  if (!service.getConsumers) {
@@ -15,6 +15,9 @@ export const ApiKeyList = ({ service }: { service: ApiKeyService }) => {
15
15
  try {
16
16
  return await service.getConsumers(context);
17
17
  } catch (error) {
18
+ if (error instanceof ZudokuError) {
19
+ throw error;
20
+ }
18
21
  throw new ZudokuError("Cannot get API keys", {
19
22
  cause: error,
20
23
  title: "Error getting API keys",
@@ -40,6 +40,7 @@ const getSchemaInfos = (schema?: SchemaObject) => {
40
40
  schema.enum && "enum",
41
41
  schema.const && "const",
42
42
  schema.format,
43
+ schema.type === "array" && schema.items?.contentMediaType,
43
44
  schema.minimum !== undefined && `min: ${schema.minimum}`,
44
45
  schema.maximum !== undefined && `max: ${schema.maximum}`,
45
46
  schema.minLength !== undefined && `minLength: ${schema.minLength}`,
@@ -149,10 +149,10 @@ export const Sidecar = ({
149
149
  selectedServer,
150
150
  exampleBody: currentExampleCode
151
151
  ? {
152
- mimeType: "application/json",
152
+ mimeType: selectedContent?.mediaType ?? "application/json",
153
153
  text: JSON.stringify(currentExampleCode, null, 2),
154
154
  }
155
- : { mimeType: "application/json" },
155
+ : { mimeType: selectedContent?.mediaType ?? "application/json" },
156
156
  });
157
157
 
158
158
  return getConverted(snippet, selectedLang);
@@ -161,6 +161,7 @@ export const Sidecar = ({
161
161
  operation,
162
162
  selectedServer,
163
163
  selectedLang,
164
+ selectedContent,
164
165
  options,
165
166
  auth,
166
167
  context,
@@ -154,10 +154,12 @@ export const SchemaView = ({
154
154
  <FrameDescription>{schema.description}</FrameDescription>
155
155
  </FrameHeader>
156
156
  )}
157
- <FramePanel className="p-0!">
158
- {itemsList}
159
- {additionalObjectProperties}
160
- </FramePanel>
157
+ {(itemsList.length > 0 || additionalObjectProperties) && (
158
+ <FramePanel className="p-0!">
159
+ {itemsList}
160
+ {additionalObjectProperties}
161
+ </FramePanel>
162
+ )}
161
163
  {schema.additionalProperties === true && (
162
164
  <FrameFooter>
163
165
  <a
@@ -1,6 +1,23 @@
1
1
  import { HTTPSnippet } from "@zudoku/httpsnippet";
2
2
  import type { OperationsFragmentFragment } from "../graphql/graphql.js";
3
3
 
4
+ const toFormDataParams = (text?: string) => {
5
+ const stringify = (v: unknown) =>
6
+ typeof v === "string" ? v : JSON.stringify(v);
7
+
8
+ try {
9
+ const obj = text && JSON.parse(text);
10
+ if (typeof obj !== "object" || !obj) return [];
11
+
12
+ return Object.entries(obj).flatMap(([name, value]) => {
13
+ const values = Array.isArray(value) ? value : [value];
14
+ return values.map((v) => ({ name, value: stringify(v) }));
15
+ });
16
+ } catch {
17
+ return [];
18
+ }
19
+ };
20
+
4
21
  export const createHttpSnippet = ({
5
22
  operation,
6
23
  selectedServer,
@@ -13,11 +30,22 @@ export const createHttpSnippet = ({
13
30
  text?: string;
14
31
  };
15
32
  }) => {
33
+ const isMultipart =
34
+ exampleBody.mimeType === "multipart/form-data" ||
35
+ exampleBody.mimeType === "application/x-www-form-urlencoded";
36
+
37
+ const postData = isMultipart
38
+ ? {
39
+ mimeType: exampleBody.mimeType,
40
+ params: toFormDataParams(exampleBody.text),
41
+ }
42
+ : exampleBody;
43
+
16
44
  return new HTTPSnippet({
17
45
  method: operation.method.toUpperCase(),
18
46
  url:
19
47
  selectedServer + operation.path.replaceAll("{", ":").replaceAll("}", ""),
20
- postData: exampleBody,
48
+ postData,
21
49
  headers: [
22
50
  ...(exampleBody.text
23
51
  ? [{ name: "Content-Type", value: exampleBody.mimeType }]
@@ -51,6 +51,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
51
51
  const Comp = asChild ? Slot : "button";
52
52
  return (
53
53
  <Comp
54
+ type={asChild ? undefined : "button"}
54
55
  className={cn(buttonVariants({ variant, size, className }))}
55
56
  ref={ref}
56
57
  {...props}
@@ -7,6 +7,7 @@ export default function invariant(
7
7
  * the message takes a fair amount of effort to compute
8
8
  */
9
9
  message?: string | (() => string),
10
+ options?: ZudokuErrorOptions,
10
11
  ): asserts condition {
11
12
  if (condition) {
12
13
  return;
@@ -16,7 +17,7 @@ export default function invariant(
16
17
  const provided: string | undefined =
17
18
  typeof message === "function" ? message() : message;
18
19
 
19
- throw new ZudokuError(provided ?? "Invariant failed");
20
+ throw new ZudokuError(provided ?? "Invariant failed", options);
20
21
  }
21
22
 
22
23
  export type ZudokuErrorOptions = {
@@ -1 +0,0 @@
1
- {"version":3,"file":"Input-D-kqEQ5M.js","sources":["../../../node_modules/.pnpm/@tanstack+query-core@5.85.5/node_modules/@tanstack/query-core/build/modern/mutationObserver.js","../../../node_modules/.pnpm/@tanstack+react-query@5.85.5_react@19.2.1/node_modules/@tanstack/react-query/build/modern/useMutation.js","../src/lib/ui/Input.tsx"],"sourcesContent":["// src/mutationObserver.ts\nimport { getDefaultState } from \"./mutation.js\";\nimport { notifyManager } from \"./notifyManager.js\";\nimport { Subscribable } from \"./subscribable.js\";\nimport { hashKey, shallowEqualObjects } from \"./utils.js\";\nvar MutationObserver = class extends Subscribable {\n #client;\n #currentResult = void 0;\n #currentMutation;\n #mutateOptions;\n constructor(client, options) {\n super();\n this.#client = client;\n this.setOptions(options);\n this.bindMethods();\n this.#updateResult();\n }\n bindMethods() {\n this.mutate = this.mutate.bind(this);\n this.reset = this.reset.bind(this);\n }\n setOptions(options) {\n const prevOptions = this.options;\n this.options = this.#client.defaultMutationOptions(options);\n if (!shallowEqualObjects(this.options, prevOptions)) {\n this.#client.getMutationCache().notify({\n type: \"observerOptionsUpdated\",\n mutation: this.#currentMutation,\n observer: this\n });\n }\n if (prevOptions?.mutationKey && this.options.mutationKey && hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)) {\n this.reset();\n } else if (this.#currentMutation?.state.status === \"pending\") {\n this.#currentMutation.setOptions(this.options);\n }\n }\n onUnsubscribe() {\n if (!this.hasListeners()) {\n this.#currentMutation?.removeObserver(this);\n }\n }\n onMutationUpdate(action) {\n this.#updateResult();\n this.#notify(action);\n }\n getCurrentResult() {\n return this.#currentResult;\n }\n reset() {\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = void 0;\n this.#updateResult();\n this.#notify();\n }\n mutate(variables, options) {\n this.#mutateOptions = options;\n this.#currentMutation?.removeObserver(this);\n this.#currentMutation = this.#client.getMutationCache().build(this.#client, this.options);\n this.#currentMutation.addObserver(this);\n return this.#currentMutation.execute(variables);\n }\n #updateResult() {\n const state = this.#currentMutation?.state ?? getDefaultState();\n this.#currentResult = {\n ...state,\n isPending: state.status === \"pending\",\n isSuccess: state.status === \"success\",\n isError: state.status === \"error\",\n isIdle: state.status === \"idle\",\n mutate: this.mutate,\n reset: this.reset\n };\n }\n #notify(action) {\n notifyManager.batch(() => {\n if (this.#mutateOptions && this.hasListeners()) {\n const variables = this.#currentResult.variables;\n const context = this.#currentResult.context;\n if (action?.type === \"success\") {\n this.#mutateOptions.onSuccess?.(action.data, variables, context);\n this.#mutateOptions.onSettled?.(action.data, null, variables, context);\n } else if (action?.type === \"error\") {\n this.#mutateOptions.onError?.(action.error, variables, context);\n this.#mutateOptions.onSettled?.(\n void 0,\n action.error,\n variables,\n context\n );\n }\n }\n this.listeners.forEach((listener) => {\n listener(this.#currentResult);\n });\n });\n }\n};\nexport {\n MutationObserver\n};\n//# sourceMappingURL=mutationObserver.js.map","\"use client\";\n\n// src/useMutation.ts\nimport * as React from \"react\";\nimport {\n MutationObserver,\n noop,\n notifyManager,\n shouldThrowError\n} from \"@tanstack/query-core\";\nimport { useQueryClient } from \"./QueryClientProvider.js\";\nfunction useMutation(options, queryClient) {\n const client = useQueryClient(queryClient);\n const [observer] = React.useState(\n () => new MutationObserver(\n client,\n options\n )\n );\n React.useEffect(() => {\n observer.setOptions(options);\n }, [observer, options]);\n const result = React.useSyncExternalStore(\n React.useCallback(\n (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)),\n [observer]\n ),\n () => observer.getCurrentResult(),\n () => observer.getCurrentResult()\n );\n const mutate = React.useCallback(\n (variables, mutateOptions) => {\n observer.mutate(variables, mutateOptions).catch(noop);\n },\n [observer]\n );\n if (result.error && shouldThrowError(observer.options.throwOnError, [result.error])) {\n throw result.error;\n }\n return { ...result, mutate, mutateAsync: result.mutate };\n}\nexport {\n useMutation\n};\n//# sourceMappingURL=useMutation.js.map","import * as React from \"react\";\nimport { cn } from \"../util/cn.js\";\n\ntype InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n return (\n <input\n type={type}\n className={cn(\n \"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n ref={ref}\n {...props}\n />\n );\n },\n);\nInput.displayName = \"Input\";\n\nexport { Input };\n"],"names":["MutationObserver","Subscribable","#client","#currentResult","#currentMutation","#mutateOptions","client","options","#updateResult","prevOptions","shallowEqualObjects","hashKey","action","#notify","variables","state","getDefaultState","notifyManager","context","listener","useMutation","queryClient","useQueryClient","observer","React","result","onStoreChange","mutate","mutateOptions","noop","shouldThrowError","Input","className","type","props","ref","jsx","cn"],"mappings":"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","x_google_ignoreList":[0,1]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"OAuthErrorPage-DRY2hlga.js","sources":["../src/lib/util/url.ts","../src/lib/authentication/components/CallbackHandler.tsx","../src/lib/authentication/components/OAuthErrorPage.tsx"],"sourcesContent":["/**\n * Normalizes a redirect URL by removing the origin and optionally the root path\n */\nexport function normalizeRedirectUrl(\n redirectTo: string,\n origin: string,\n basePath: string = \"/\",\n): string {\n if (!redirectTo.startsWith(origin)) {\n return redirectTo;\n }\n\n if (basePath !== \"/\" && redirectTo.startsWith(origin + basePath)) {\n return redirectTo.slice(origin.length + basePath.length);\n }\n\n return redirectTo.slice(origin.length);\n}\n","import { useSuspenseQuery } from \"@tanstack/react-query\";\nimport { Navigate } from \"react-router\";\nimport { useZudoku } from \"zudoku/components\";\nimport { joinUrl } from \"../../util/joinUrl.js\";\nimport { normalizeRedirectUrl } from \"../../util/url.js\";\nimport { OAuthAuthorizationError, type OAuthErrorType } from \"../errors.js\";\n\nexport function CallbackHandler({\n handleCallback,\n}: {\n handleCallback: () => Promise<string>;\n}) {\n const { options } = useZudoku();\n const executeCallback = useSuspenseQuery({\n retry: false,\n queryKey: [\"oauth-callback\"],\n queryFn: async () => {\n const url = new URL(window.location.href);\n\n const errorParam = url.searchParams.get(\"error\");\n const errorDescription =\n url.searchParams.get(\"error_description\") ?? undefined;\n const errorUri = url.searchParams.get(\"error_uri\") ?? undefined;\n if (errorParam) {\n throw new OAuthAuthorizationError(\n `OAuth error '${errorParam}': ${errorDescription}`,\n {\n error: errorParam as OAuthErrorType,\n error_description: errorDescription,\n error_uri: errorUri,\n },\n );\n }\n return joinUrl(\n normalizeRedirectUrl(\n await handleCallback(),\n window.location.origin,\n options.basePath,\n ),\n );\n },\n });\n\n return <Navigate to={executeCallback.data} replace />;\n}\n","import { HomeIcon } from \"lucide-react\";\nimport { Link } from \"react-router\";\nimport { Heading } from \"../../components/Heading.js\";\nimport { Typography } from \"../../components/Typography.js\";\nimport { Button } from \"../../ui/Button.js\";\nimport { OAuthAuthorizationError } from \"../errors.js\";\nimport { useAuth } from \"../hook.js\";\n\nconst errorDetailsMap: Record<string, { message: string }> = {\n invalid_request: {\n message:\n \"The authentication request was invalid. Please try signing in again.\",\n },\n unauthorized_client: {\n message:\n \"This application is not authorized to access your account. Please contact support.\",\n },\n access_denied: {\n message:\n \"You denied access to this application. To continue, please sign in and grant access.\",\n },\n unsupported_response_type: {\n message:\n \"The authentication method is not supported. Please contact support.\",\n },\n invalid_scope: {\n message: \"The requested permissions are invalid. Please contact support.\",\n },\n server_error: {\n message:\n \"The authentication server encountered an error. Please try again in a few moments.\",\n },\n temporarily_unavailable: {\n message:\n \"The authentication service is temporarily unavailable. Please try again in a few moments.\",\n },\n // Token errors\n invalid_client: {\n message: \"Invalid application credentials. Please contact support.\",\n },\n invalid_grant: {\n message:\n \"The authentication code has expired or is invalid. Please sign in again.\",\n },\n unsupported_grant_type: {\n message:\n \"The authentication method is not supported. Please contact support.\",\n },\n // Custom errors\n invalid_state: {\n message:\n \"Security validation failed. This may be due to a potential security attack. Please try signing in again.\",\n },\n missing_code_verifier: {\n message:\n \"Authentication security information is missing. Please clear your browser cache and try again.\",\n },\n network_error: {\n message:\n \"A network error occurred during authentication. Please check your connection and try again.\",\n },\n token_expired: {\n message: \"Your authentication session has expired. Please sign in again.\",\n },\n configuration_error: {\n message:\n \"There is an issue with the authentication configuration. Please contact support.\",\n },\n unknown_error: {\n message:\n \"An unexpected error occurred during authentication. Please try again or contact support.\",\n },\n};\n\nexport function OAuthErrorPage({ error }: { error: unknown }) {\n const { login } = useAuth();\n\n if (!(error instanceof OAuthAuthorizationError)) {\n throw error;\n }\n\n const oauthError = error.error;\n const type = oauthError.error;\n\n const details = errorDetailsMap[type] ?? errorDetailsMap.unknown_error;\n\n return (\n <div className=\"min-h-[400px] flex items-center justify-center p-4\">\n <div className=\"max-w-md w-full text-center space-y-6\">\n <div className=\"space-y-4 items-center\">\n <Heading level={2} className=\"text-2xl inline-block font-bold\">\n {titles[type] || \"Authentication Error\"}\n </Heading>\n\n <Typography className=\"text-gray-600 dark:text-gray-300 leading-relaxed\">\n {details?.message}\n </Typography>\n\n {/* Technical details for developers (only in development) */}\n </div>\n\n {/* Action Buttons */}\n <div className=\"space-y-3 pt-4\">\n <div className=\"space-y-2\">\n {(type === \"access_denied\" ||\n type === \"invalid_grant\" ||\n type === \"token_expired\") && (\n <Button\n onClick={() => login()}\n className=\"w-full capitalize\"\n variant={\"default\"}\n >\n Sign in again\n </Button>\n )}\n </div>\n\n <div className=\"flex gap-2\">\n <Button asChild className=\"flex-1\" variant=\"outline\">\n <Link to=\"/\">\n <HomeIcon className=\"w-4 h-4 mr-2\" />\n Go Home\n </Link>\n </Button>\n </div>\n </div>\n\n {/* Additional Help */}\n {helpMessages[type] && (\n <Typography className=\"text-sm text-gray-500 dark:text-gray-400\">\n {helpMessages[type]}\n </Typography>\n )}\n </div>\n </div>\n );\n}\n\nconst titles: Record<string, string> = {\n access_denied: \"Access Denied\",\n invalid_request: \"Invalid Request\",\n unauthorized_client: \"Unauthorized Application\",\n unsupported_response_type: \"Unsupported Method\",\n invalid_scope: \"Invalid Permissions\",\n server_error: \"Server Error\",\n temporarily_unavailable: \"Service Unavailable\",\n invalid_client: \"Invalid Credentials\",\n invalid_grant: \"Authentication Expired\",\n unsupported_grant_type: \"Unsupported Authentication\",\n invalid_state: \"Security Check Failed\",\n missing_code_verifier: \"Security Information Missing\",\n network_error: \"Network Error\",\n token_expired: \"Session Expired\",\n configuration_error: \"Configuration Error\",\n unknown_error: \"Authentication Failed\",\n};\n\nconst helpMessages: Record<string, string> = {\n access_denied:\n \"If you changed your mind, you can try signing in again to grant access.\",\n invalid_state:\n \"This error can occur if you have multiple tabs open or if your session was compromised.\",\n missing_code_verifier:\n \"Try clearing your browser's cache and cookies for this site.\",\n network_error:\n \"Check your internet connection and ensure you can access other websites.\",\n server_error:\n \"The issue is on our end. Our team has been notified and is working to fix it.\",\n temporarily_unavailable:\n \"This is usually temporary. Try again in a few minutes.\",\n};\n"],"names":["normalizeRedirectUrl","redirectTo","origin","basePath","CallbackHandler","handleCallback","options","useZudoku","executeCallback","useSuspenseQuery","url","errorParam","errorDescription","errorUri","OAuthAuthorizationError","joinUrl","Navigate","errorDetailsMap","OAuthErrorPage","error","login","useAuth","type","details","jsxs","jsx","Heading","titles","Typography","Button","Link","HomeIcon","helpMessages"],"mappings":"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"}
@@ -1,77 +0,0 @@
1
- import { j as t } from "./jsx-runtime-BzflLqGi.js";
2
- import { H as m } from "./index.esm-DtzT_KoE.js";
3
- import { createContext as p, use as f } from "react";
4
- import { u as g, a as x, m as j, O as v } from "./chunk-PVWAREVJ-ClM0m2aJ.js";
5
- import { B as a } from "./Button-CynVW1JV.js";
6
- import { D as C, a as R, b as D, c as w, d as T, e as b } from "./Dialog-BQciPiHN.js";
7
- import { u as k } from "./hook-CHw_R_xu.js";
8
- import { a as E } from "./ZudokuContext-DNHMZfcP.js";
9
- import { Z as P } from "./invariant-CGOLuIIz.js";
10
- import { u as y } from "./useLatest-hmRS46UF.js";
11
- const O = p(!1), A = "protected", G = () => {
12
- const n = k(), e = E(), o = g(), r = x(), c = y(r.pathname), u = f(O), { protectedRoutes: d } = e.options, l = !u && d ? Object.entries(d).find(
13
- ([s]) => j({ path: s, end: !0 }, r.pathname)
14
- )?.[1] : void 0, i = l !== void 0, h = i && !l({ auth: n, context: e });
15
- if (i && !n.isAuthEnabled)
16
- throw new P("Authentication is not enabled", {
17
- title: "Authentication is not enabled",
18
- developerHint: "To use protectedRoutes you need authentication to be enabled"
19
- });
20
- return h && n.isPending && typeof window < "u" ? null : h ? /* @__PURE__ */ t.jsx(
21
- C,
22
- {
23
- open: !0,
24
- onOpenChange: (s) => {
25
- s || o(-1);
26
- },
27
- children: /* @__PURE__ */ t.jsxs(R, { children: [
28
- /* @__PURE__ */ t.jsx(D, { children: /* @__PURE__ */ t.jsx(w, { children: "Login to continue" }) }),
29
- /* @__PURE__ */ t.jsx(T, { children: "Please wait while we log you in." }),
30
- /* @__PURE__ */ t.jsxs(b, { children: [
31
- /* @__PURE__ */ t.jsx(a, { variant: "outline", onClick: () => void o(-1), children: "Cancel" }),
32
- /* @__PURE__ */ t.jsx("div", { className: "w-full" }),
33
- /* @__PURE__ */ t.jsx(
34
- a,
35
- {
36
- variant: "secondary",
37
- onClick: () => void e.authentication?.signUp(
38
- { navigate: o },
39
- { redirectTo: c.current }
40
- ),
41
- children: "Register"
42
- }
43
- ),
44
- /* @__PURE__ */ t.jsxs(
45
- a,
46
- {
47
- onClick: () => void e.authentication?.signIn(
48
- { navigate: o },
49
- { redirectTo: c.current }
50
- ),
51
- children: [
52
- "Login",
53
- " "
54
- ]
55
- }
56
- )
57
- ] })
58
- ] })
59
- }
60
- ) : /* @__PURE__ */ t.jsxs(t.Fragment, { children: [
61
- u && i && /* @__PURE__ */ t.jsx(m, { children: /* @__PURE__ */ t.jsx(
62
- "meta",
63
- {
64
- name: "pagefind",
65
- "data-pagefind-filter": `section:${A}`,
66
- content: "true"
67
- }
68
- ) }),
69
- /* @__PURE__ */ t.jsx(v, {})
70
- ] });
71
- };
72
- export {
73
- O as B,
74
- G as R,
75
- A as S
76
- };
77
- //# sourceMappingURL=RouteGuard-DGc32XJV.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RouteGuard-DGc32XJV.js","sources":["../src/lib/components/context/BypassProtectedRoutesContext.ts","../src/lib/core/RouteGuard.tsx"],"sourcesContent":["import { createContext } from \"react\";\n\nexport const BypassProtectedRoutesContext = createContext(false);\n","import { Helmet } from \"@zudoku/react-helmet-async\";\nimport { use } from \"react\";\nimport { matchPath, Outlet, useLocation, useNavigate } from \"react-router\";\nimport { Button } from \"zudoku/ui/Button.js\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"zudoku/ui/Dialog.js\";\nimport { useAuth } from \"../authentication/hook.js\";\nimport { BypassProtectedRoutesContext } from \"../components/context/BypassProtectedRoutesContext.js\";\nimport { useZudoku } from \"../components/context/ZudokuContext.js\";\nimport { ZudokuError } from \"../util/invariant.js\";\nimport { useLatest } from \"../util/useLatest.js\";\n\nexport const SEARCH_PROTECTED_SECTION = \"protected\";\n\nexport const RouteGuard = () => {\n const auth = useAuth();\n const zudoku = useZudoku();\n const navigate = useNavigate();\n const location = useLocation();\n const latestPath = useLatest(location.pathname);\n const shouldBypass = use(BypassProtectedRoutesContext);\n const { protectedRoutes } = zudoku.options;\n\n const authCheckFn =\n !shouldBypass && protectedRoutes\n ? Object.entries(protectedRoutes).find(([path]) =>\n matchPath({ path, end: true }, location.pathname),\n )?.[1]\n : undefined;\n\n const isProtectedRoute = authCheckFn !== undefined;\n const needsToSignIn =\n isProtectedRoute && !authCheckFn({ auth, context: zudoku });\n\n if (isProtectedRoute && !auth.isAuthEnabled) {\n throw new ZudokuError(\"Authentication is not enabled\", {\n title: \"Authentication is not enabled\",\n developerHint:\n \"To use protectedRoutes you need authentication to be enabled\",\n });\n }\n\n if (needsToSignIn && auth.isPending && typeof window !== \"undefined\") {\n return null;\n }\n\n if (needsToSignIn) {\n return (\n <Dialog\n open={true}\n onOpenChange={(open) => {\n if (!open) {\n void navigate(-1);\n }\n }}\n >\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Login to continue</DialogTitle>\n </DialogHeader>\n <DialogDescription>\n Please wait while we log you in.\n </DialogDescription>\n <DialogFooter>\n <Button variant=\"outline\" onClick={() => void navigate(-1)}>\n Cancel\n </Button>\n <div className=\"w-full\"></div>\n <Button\n variant=\"secondary\"\n onClick={() =>\n void zudoku.authentication?.signUp(\n { navigate },\n { redirectTo: latestPath.current },\n )\n }\n >\n Register\n </Button>\n <Button\n onClick={() =>\n void zudoku.authentication?.signIn(\n { navigate },\n { redirectTo: latestPath.current },\n )\n }\n >\n Login{\" \"}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n }\n\n return (\n <>\n {shouldBypass && isProtectedRoute && (\n <Helmet>\n <meta\n name=\"pagefind\"\n data-pagefind-filter={`section:${SEARCH_PROTECTED_SECTION}`}\n content=\"true\"\n />\n </Helmet>\n )}\n <Outlet />\n </>\n );\n};\n"],"names":["BypassProtectedRoutesContext","createContext","SEARCH_PROTECTED_SECTION","RouteGuard","auth","useAuth","zudoku","useZudoku","navigate","useNavigate","location","useLocation","latestPath","useLatest","shouldBypass","use","protectedRoutes","authCheckFn","path","matchPath","isProtectedRoute","needsToSignIn","ZudokuError","jsx","Dialog","open","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","Button","jsxs","Fragment","Helmet","Outlet"],"mappings":";;;;;;;;;;AAEO,MAAMA,IAA+BC,EAAc,EAAK,GCgBlDC,IAA2B,aAE3BC,IAAa,MAAM;AAC9B,QAAMC,IAAOC,EAAA,GACPC,IAASC,EAAA,GACTC,IAAWC,EAAA,GACXC,IAAWC,EAAA,GACXC,IAAaC,EAAUH,EAAS,QAAQ,GACxCI,IAAeC,EAAIf,CAA4B,GAC/C,EAAE,iBAAAgB,MAAoBV,EAAO,SAE7BW,IACJ,CAACH,KAAgBE,IACb,OAAO,QAAQA,CAAe,EAAE;AAAA,IAAK,CAAC,CAACE,CAAI,MACzCC,EAAU,EAAE,MAAAD,GAAM,KAAK,MAAQR,EAAS,QAAQ;AAAA,EAAA,IAC9C,CAAC,IACL,QAEAU,IAAmBH,MAAgB,QACnCI,IACJD,KAAoB,CAACH,EAAY,EAAE,MAAAb,GAAM,SAASE,GAAQ;AAE5D,MAAIc,KAAoB,CAAChB,EAAK;AAC5B,UAAM,IAAIkB,EAAY,iCAAiC;AAAA,MACrD,OAAO;AAAA,MACP,eACE;AAAA,IAAA,CACH;AAGH,SAAID,KAAiBjB,EAAK,aAAa,OAAO,SAAW,MAChD,OAGLiB,IAEAE,gBAAAA,EAAAA;AAAAA,IAACC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,MACN,cAAc,CAACC,MAAS;AACtB,QAAKA,KACEjB,EAAS,EAAE;AAAA,MAEpB;AAAA,MAEA,iCAACkB,GAAA,EACC,UAAA;AAAA,QAAAH,gBAAAA,MAACI,GAAA,EACC,UAAAJ,gBAAAA,EAAAA,IAACK,GAAA,EAAY,UAAA,oBAAA,CAAiB,GAChC;AAAA,QACAL,gBAAAA,EAAAA,IAACM,KAAkB,UAAA,mCAAA,CAEnB;AAAA,+BACCC,GAAA,EACC,UAAA;AAAA,UAAAP,gBAAAA,EAAAA,IAACQ,GAAA,EAAO,SAAQ,WAAU,SAAS,MAAM,KAAKvB,EAAS,EAAE,GAAG,UAAA,SAAA,CAE5D;AAAA,UACAe,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,UACxBA,gBAAAA,EAAAA;AAAAA,YAACQ;AAAA,YAAA;AAAA,cACC,SAAQ;AAAA,cACR,SAAS,MACP,KAAKzB,EAAO,gBAAgB;AAAA,gBAC1B,EAAE,UAAAE,EAAA;AAAA,gBACF,EAAE,YAAYI,EAAW,QAAA;AAAA,cAAQ;AAAA,cAGtC,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGDoB,gBAAAA,EAAAA;AAAAA,YAACD;AAAA,YAAA;AAAA,cACC,SAAS,MACP,KAAKzB,EAAO,gBAAgB;AAAA,gBAC1B,EAAE,UAAAE,EAAA;AAAA,gBACF,EAAE,YAAYI,EAAW,QAAA;AAAA,cAAQ;AAAA,cAGtC,UAAA;AAAA,gBAAA;AAAA,gBACO;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,QACR,EAAA,CACF;AAAA,MAAA,EAAA,CACF;AAAA,IAAA;AAAA,EAAA,IAMJoB,gBAAAA,EAAAA,KAAAC,YAAA,EACG,UAAA;AAAA,IAAAnB,KAAgBM,2BACdc,GAAA,EACC,UAAAX,gBAAAA,EAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,wBAAsB,WAAWrB,CAAwB;AAAA,QACzD,SAAQ;AAAA,MAAA;AAAA,IAAA,GAEZ;AAAA,0BAEDiC,GAAA,CAAA,CAAO;AAAA,EAAA,GACV;AAEJ;"}