zudoku 0.66.4 → 0.66.6

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 (216) hide show
  1. package/dist/app/main.d.ts +6 -6
  2. package/dist/config/validators/InputNavigationSchema.d.ts +2 -0
  3. package/dist/config/validators/InputNavigationSchema.js +1 -0
  4. package/dist/config/validators/InputNavigationSchema.js.map +1 -1
  5. package/dist/config/validators/NavigationSchema.js +6 -1
  6. package/dist/config/validators/NavigationSchema.js.map +1 -1
  7. package/dist/flat-config.d.ts +1 -0
  8. package/dist/lib/authentication/components/CallbackHandler.js +1 -1
  9. package/dist/lib/authentication/components/CallbackHandler.js.map +1 -1
  10. package/dist/lib/authentication/providers/auth0.js +11 -7
  11. package/dist/lib/authentication/providers/auth0.js.map +1 -1
  12. package/dist/lib/authentication/providers/clerk.js +0 -22
  13. package/dist/lib/authentication/providers/clerk.js.map +1 -1
  14. package/dist/lib/authentication/providers/supabase.js +6 -15
  15. package/dist/lib/authentication/providers/supabase.js.map +1 -1
  16. package/dist/lib/core/RouteGuard.js +12 -7
  17. package/dist/lib/core/RouteGuard.js.map +1 -1
  18. package/dist/lib/oas/graphql/circular.d.ts +1 -0
  19. package/dist/lib/oas/graphql/circular.js +20 -5
  20. package/dist/lib/oas/graphql/circular.js.map +1 -1
  21. package/dist/lib/plugins/api-keys/index.d.ts +9 -5
  22. package/dist/lib/plugins/api-keys/index.js +18 -8
  23. package/dist/lib/plugins/api-keys/index.js.map +1 -1
  24. package/dist/lib/plugins/api-keys/settings/ApiKeyList.js +3 -0
  25. package/dist/lib/plugins/api-keys/settings/ApiKeyList.js.map +1 -1
  26. package/dist/lib/plugins/openapi/OperationList.js +5 -1
  27. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  28. package/dist/lib/plugins/openapi/schema/utils.js +11 -3
  29. package/dist/lib/plugins/openapi/schema/utils.js.map +1 -1
  30. package/dist/lib/util/invariant.d.ts +1 -1
  31. package/dist/lib/util/invariant.js +2 -2
  32. package/dist/lib/util/invariant.js.map +1 -1
  33. package/dist/vite/api/SchemaManager.d.ts +1 -0
  34. package/dist/vite/api/SchemaManager.js +9 -3
  35. package/dist/vite/api/SchemaManager.js.map +1 -1
  36. package/dist/vite/mdx/remark-link-rewrite.js +1 -1
  37. package/dist/vite/plugin-api-keys.js +1 -0
  38. package/dist/vite/plugin-api-keys.js.map +1 -1
  39. package/dist/vite/prerender/utils.js +9 -3
  40. package/dist/vite/prerender/utils.js.map +1 -1
  41. package/lib/{ActionButton-BSM2oNHF.js → ActionButton-B0CXL1Lq.js} +3 -3
  42. package/lib/{ActionButton-BSM2oNHF.js.map → ActionButton-B0CXL1Lq.js.map} +1 -1
  43. package/lib/{Button-IOAeVaIH.js → Button-GUVe7pmt.js} +2 -2
  44. package/lib/{Button-IOAeVaIH.js.map → Button-GUVe7pmt.js.map} +1 -1
  45. package/lib/{Card-KFniaZn5.js → Card-DCdq37aA.js} +2 -2
  46. package/lib/{Card-KFniaZn5.js.map → Card-DCdq37aA.js.map} +1 -1
  47. package/lib/{ClaudeLogo-DgjivS8A.js → ClaudeLogo-BpqHBMS8.js} +4 -4
  48. package/lib/{ClaudeLogo-DgjivS8A.js.map → ClaudeLogo-BpqHBMS8.js.map} +1 -1
  49. package/lib/{Command-BpT1iBE6.js → Command-N6VujV30.js} +3 -3
  50. package/lib/{Command-BpT1iBE6.js.map → Command-N6VujV30.js.map} +1 -1
  51. package/lib/{Dialog-BQciPiHN.js → Dialog-hlvmmQ_c.js} +2 -2
  52. package/lib/{Dialog-BQciPiHN.js.map → Dialog-hlvmmQ_c.js.map} +1 -1
  53. package/lib/{Drawer-BRMcpfuF.js → Drawer-Ch7927PF.js} +2 -2
  54. package/lib/{Drawer-BRMcpfuF.js.map → Drawer-Ch7927PF.js.map} +1 -1
  55. package/lib/{DropdownMenu-C8SX_-S_.js → DropdownMenu-DN0jNrjj.js} +2 -2
  56. package/lib/{DropdownMenu-C8SX_-S_.js.map → DropdownMenu-DN0jNrjj.js.map} +1 -1
  57. package/lib/{Frame-DxlznfVd.js → Frame-DKlOmSkU.js} +2 -2
  58. package/lib/{Frame-DxlznfVd.js.map → Frame-DKlOmSkU.js.map} +1 -1
  59. package/lib/{IndexingDialog-DZWj_3cU.js → IndexingDialog-D0YdGfbn.js} +3 -3
  60. package/lib/{IndexingDialog-DZWj_3cU.js.map → IndexingDialog-D0YdGfbn.js.map} +1 -1
  61. package/lib/{Input-D-kqEQ5M.js → Input-B6YcAPv-.js} +39 -18
  62. package/lib/Input-B6YcAPv-.js.map +1 -0
  63. package/lib/{MdxPage-BL-HbZrv.js → MdxPage-CeFSxGb_.js} +11 -11
  64. package/lib/{MdxPage-BL-HbZrv.js.map → MdxPage-CeFSxGb_.js.map} +1 -1
  65. package/lib/{Mermaid-BjSczjLW.js → Mermaid-COVtAqcZ.js} +4 -4
  66. package/lib/{Mermaid-BjSczjLW.js.map → Mermaid-COVtAqcZ.js.map} +1 -1
  67. package/lib/{OAuthErrorPage-DQtg28Go.js → OAuthErrorPage-XTPBOMN8.js} +9 -9
  68. package/lib/OAuthErrorPage-XTPBOMN8.js.map +1 -0
  69. package/lib/{OasProvider--qcZwrKS.js → OasProvider-BS4rdzZC.js} +4 -4
  70. package/lib/{OasProvider--qcZwrKS.js.map → OasProvider-BS4rdzZC.js.map} +1 -1
  71. package/lib/{OperationList-CSJYzxQY.js → OperationList-Dg0Nm1tg.js} +136 -133
  72. package/lib/{OperationList-CSJYzxQY.js.map → OperationList-Dg0Nm1tg.js.map} +1 -1
  73. package/lib/RouteGuard-kCicqF3x.js +77 -0
  74. package/lib/RouteGuard-kCicqF3x.js.map +1 -0
  75. package/lib/{SchemaList-DtyuDrQA.js → SchemaList-DZKBH2WC.js} +9 -9
  76. package/lib/{SchemaList-DtyuDrQA.js.map → SchemaList-DZKBH2WC.js.map} +1 -1
  77. package/lib/{SchemaView-G-SVXxAG.js → SchemaView-DBaqV2yU.js} +95 -92
  78. package/lib/SchemaView-DBaqV2yU.js.map +1 -0
  79. package/lib/{Secret-BxGpIhDP.js → Secret-BDBqq4p3.js} +2 -2
  80. package/lib/{Secret-BxGpIhDP.js.map → Secret-BDBqq4p3.js.map} +1 -1
  81. package/lib/{Separator-CTPSeW1S.js → Separator-BXt1LYnm.js} +2 -2
  82. package/lib/{Separator-CTPSeW1S.js.map → Separator-BXt1LYnm.js.map} +1 -1
  83. package/lib/{SignUp-CDl7bQj3.js → SignUp-DNmOFbLD.js} +5 -5
  84. package/lib/{SignUp-CDl7bQj3.js.map → SignUp-DNmOFbLD.js.map} +1 -1
  85. package/lib/{SyntaxHighlight-Dgd0AaaX.js → SyntaxHighlight-C75W8uCn.js} +374 -365
  86. package/lib/SyntaxHighlight-C75W8uCn.js.map +1 -0
  87. package/lib/{Toc-D_Rj4jVx.js → Toc-ICilS65g.js} +3 -3
  88. package/lib/{Toc-D_Rj4jVx.js.map → Toc-ICilS65g.js.map} +1 -1
  89. package/lib/{ZudokuContext-DNHMZfcP.js → ZudokuContext-Ea7gxmGq.js} +542 -469
  90. package/lib/ZudokuContext-Ea7gxmGq.js.map +1 -0
  91. package/lib/{___vite-browser-external_commonjs-proxy-Cga3HsWk.js → ___vite-browser-external_commonjs-proxy-BttVsNON.js} +2 -2
  92. package/lib/___vite-browser-external_commonjs-proxy-BttVsNON.js.map +1 -0
  93. package/lib/chunk-EPOLDU6W-C6C8jAwd.js +8558 -0
  94. package/lib/chunk-EPOLDU6W-C6C8jAwd.js.map +1 -0
  95. package/lib/{circular-BxODTa7z.js → circular-DleWPaPP.js} +767 -747
  96. package/lib/{circular-BxODTa7z.js.map → circular-DleWPaPP.js.map} +1 -1
  97. package/lib/{cn-dYga0KKN.js → cn-5-Gd1Dss.js} +531 -498
  98. package/lib/cn-5-Gd1Dss.js.map +1 -0
  99. package/lib/{createServer-BpreIXp6.js → createServer-nqMW9kro.js} +6 -6
  100. package/lib/{createServer-BpreIXp6.js.map → createServer-nqMW9kro.js.map} +1 -1
  101. package/lib/{createVariantComponent-CQVt-H3r.js → createVariantComponent-Dc0vtOvr.js} +2 -2
  102. package/lib/{createVariantComponent-CQVt-H3r.js.map → createVariantComponent-Dc0vtOvr.js.map} +1 -1
  103. package/lib/{errors-DliW1dED.js → errors-D2FbERKl.js} +3 -3
  104. package/lib/{errors-DliW1dED.js.map → errors-D2FbERKl.js.map} +1 -1
  105. package/lib/{firebase-D4tbaCYB.js → firebase-Cn9CmB6h.js} +21 -21
  106. package/lib/{firebase-D4tbaCYB.js.map → firebase-Cn9CmB6h.js.map} +1 -1
  107. package/lib/{hook-CHw_R_xu.js → hook-B2nmfmYN.js} +3 -3
  108. package/lib/{hook-CHw_R_xu.js.map → hook-B2nmfmYN.js.map} +1 -1
  109. package/lib/{index-DXXZDuSJ.js → index-CC4L3gtM.js} +4 -4
  110. package/lib/{index-DXXZDuSJ.js.map → index-CC4L3gtM.js.map} +1 -1
  111. package/lib/{index-9MxNUgg4.js → index-CSDW7CHl.js} +21 -21
  112. package/lib/{index-9MxNUgg4.js.map → index-CSDW7CHl.js.map} +1 -1
  113. package/lib/{index-CboxZOVW.js → index-D5NeW2z6.js} +12 -12
  114. package/lib/{index-CboxZOVW.js.map → index-D5NeW2z6.js.map} +1 -1
  115. package/lib/{index-1TbL0HXQ.js → index-DSKBOdpT.js} +2 -2
  116. package/lib/{index-1TbL0HXQ.js.map → index-DSKBOdpT.js.map} +1 -1
  117. package/lib/{index.esm-ti5zvZS_.js → index.esm-B35e7P83.js} +2 -2
  118. package/lib/index.esm-B35e7P83.js.map +1 -0
  119. package/lib/{index.esm-DtzT_KoE.js → index.esm-B_0dvNjB.js} +2 -2
  120. package/lib/{index.esm-DtzT_KoE.js.map → index.esm-B_0dvNjB.js.map} +1 -1
  121. package/lib/{invariant-CGOLuIIz.js → invariant-BJAl77rw.js} +4 -4
  122. package/lib/invariant-BJAl77rw.js.map +1 -0
  123. package/lib/{mutation-DMHWqmFp.js → mutation-BOYnEDf6.js} +70 -44
  124. package/lib/mutation-BOYnEDf6.js.map +1 -0
  125. package/lib/ui/Accordion.js +1 -1
  126. package/lib/ui/ActionButton.js +2 -2
  127. package/lib/ui/Alert.js +1 -1
  128. package/lib/ui/AlertDialog.js +1 -1
  129. package/lib/ui/Badge.js +1 -1
  130. package/lib/ui/Breadcrumb.js +1 -1
  131. package/lib/ui/Button.js +1 -1
  132. package/lib/ui/ButtonGroup.js +1 -1
  133. package/lib/ui/Callout.js +1 -1
  134. package/lib/ui/Card.js +1 -1
  135. package/lib/ui/Carousel.js +1 -1
  136. package/lib/ui/Checkbox.js +1 -1
  137. package/lib/ui/CodeBlock.js +1 -1
  138. package/lib/ui/Command.js +2 -2
  139. package/lib/ui/Dialog.js +1 -1
  140. package/lib/ui/Drawer.js +2 -2
  141. package/lib/ui/DropdownMenu.js +1 -1
  142. package/lib/ui/EmbeddedCodeBlock.js +1 -1
  143. package/lib/ui/Form.js +1 -1
  144. package/lib/ui/Frame.js +1 -1
  145. package/lib/ui/HoverCard.js +1 -1
  146. package/lib/ui/Input.js +1 -1
  147. package/lib/ui/Item.js +1 -1
  148. package/lib/ui/Label.js +1 -1
  149. package/lib/ui/NativeSelect.js +1 -1
  150. package/lib/ui/Pagination.js +1 -1
  151. package/lib/ui/Popover.js +1 -1
  152. package/lib/ui/Progress.js +1 -1
  153. package/lib/ui/RadioGroup.js +1 -1
  154. package/lib/ui/ScrollArea.js +1 -1
  155. package/lib/ui/Secret.js +1 -1
  156. package/lib/ui/Separator.js +1 -1
  157. package/lib/ui/Skeleton.js +1 -1
  158. package/lib/ui/Slider.js +1 -1
  159. package/lib/ui/Switch.js +1 -1
  160. package/lib/ui/SyntaxHighlight.js +3 -3
  161. package/lib/ui/Tabs.js +1 -1
  162. package/lib/ui/Textarea.js +1 -1
  163. package/lib/ui/Toggle.js +1 -1
  164. package/lib/ui/ToggleGroup.js +1 -1
  165. package/lib/ui/Value.js +1 -1
  166. package/lib/ui/util.js +1 -1
  167. package/lib/zudoku.__internal.js +604 -602
  168. package/lib/zudoku.__internal.js.map +1 -1
  169. package/lib/zudoku.auth-auth0.js +16 -16
  170. package/lib/zudoku.auth-auth0.js.map +1 -1
  171. package/lib/zudoku.auth-azureb2c.js +4 -4
  172. package/lib/zudoku.auth-clerk.js +52 -75
  173. package/lib/zudoku.auth-clerk.js.map +1 -1
  174. package/lib/zudoku.auth-firebase.js +5 -5
  175. package/lib/zudoku.auth-openid.js +5 -5
  176. package/lib/zudoku.auth-supabase.js +31 -40
  177. package/lib/zudoku.auth-supabase.js.map +1 -1
  178. package/lib/zudoku.components.js +6 -6
  179. package/lib/zudoku.hooks.js +3 -3
  180. package/lib/zudoku.mermaid.js +3 -3
  181. package/lib/zudoku.plugin-api-catalog.js +5 -5
  182. package/lib/zudoku.plugin-api-keys.js +258 -240
  183. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  184. package/lib/zudoku.plugin-custom-pages.js +1 -1
  185. package/lib/zudoku.plugin-markdown.js +1 -1
  186. package/lib/zudoku.plugin-openapi.js +3 -3
  187. package/lib/zudoku.plugin-redirect.js +1 -1
  188. package/lib/zudoku.plugin-search-pagefind.js +7 -7
  189. package/lib/zudoku.router.js +1130 -1404
  190. package/lib/zudoku.router.js.map +1 -1
  191. package/package.json +12 -12
  192. package/src/lib/authentication/components/CallbackHandler.tsx +1 -1
  193. package/src/lib/authentication/providers/auth0.tsx +15 -9
  194. package/src/lib/authentication/providers/clerk.tsx +0 -26
  195. package/src/lib/authentication/providers/supabase.tsx +6 -15
  196. package/src/lib/core/RouteGuard.tsx +30 -24
  197. package/src/lib/oas/graphql/circular.ts +36 -3
  198. package/src/lib/plugins/api-keys/index.tsx +46 -16
  199. package/src/lib/plugins/api-keys/settings/ApiKeyList.tsx +3 -0
  200. package/src/lib/plugins/openapi/OperationList.tsx +6 -1
  201. package/src/lib/plugins/openapi/schema/utils.ts +15 -4
  202. package/src/lib/util/invariant.ts +2 -1
  203. package/lib/Input-D-kqEQ5M.js.map +0 -1
  204. package/lib/OAuthErrorPage-DQtg28Go.js.map +0 -1
  205. package/lib/RouteGuard-D0f743SM.js +0 -77
  206. package/lib/RouteGuard-D0f743SM.js.map +0 -1
  207. package/lib/SchemaView-G-SVXxAG.js.map +0 -1
  208. package/lib/SyntaxHighlight-Dgd0AaaX.js.map +0 -1
  209. package/lib/ZudokuContext-DNHMZfcP.js.map +0 -1
  210. package/lib/___vite-browser-external_commonjs-proxy-Cga3HsWk.js.map +0 -1
  211. package/lib/chunk-PVWAREVJ-ClM0m2aJ.js +0 -7965
  212. package/lib/chunk-PVWAREVJ-ClM0m2aJ.js.map +0 -1
  213. package/lib/cn-dYga0KKN.js.map +0 -1
  214. package/lib/index.esm-ti5zvZS_.js.map +0 -1
  215. package/lib/invariant-CGOLuIIz.js.map +0 -1
  216. 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.4",
3
+ "version": "0.66.6",
4
4
  "type": "module",
5
5
  "homepage": "https://zudoku.dev",
6
6
  "repository": {
@@ -180,17 +180,17 @@
180
180
  "@radix-ui/react-visually-hidden": "1.2.4",
181
181
  "@scalar/openapi-parser": "0.23.2",
182
182
  "@sentry/node": "10.27.0",
183
- "@shikijs/engine-javascript": "3.19.0",
184
- "@shikijs/langs": "3.19.0",
185
- "@shikijs/rehype": "3.19.0",
186
- "@shikijs/themes": "3.19.0",
187
- "@shikijs/transformers": "3.19.0",
183
+ "@shikijs/engine-javascript": "3.20.0",
184
+ "@shikijs/langs": "3.20.0",
185
+ "@shikijs/rehype": "3.20.0",
186
+ "@shikijs/themes": "3.20.0",
187
+ "@shikijs/transformers": "3.20.0",
188
188
  "@sindresorhus/slugify": "3.0.0",
189
189
  "@stefanprobst/rehype-extract-toc": "3.0.0",
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",
@@ -233,7 +233,7 @@
233
233
  "react-hook-form": "7.66.0",
234
234
  "react-is": "19.2.3",
235
235
  "react-markdown": "10.1.0",
236
- "react-router": "7.8.2",
236
+ "react-router": "7.12.0",
237
237
  "rehype-mdx-import-media": "1.2.0",
238
238
  "rehype-raw": "7.0.0",
239
239
  "rehype-slug": "6.0.0",
@@ -245,11 +245,11 @@
245
245
  "remark-mdx-frontmatter": "5.2.0",
246
246
  "rollup": "4.52.5",
247
247
  "semver": "7.7.2",
248
- "shiki": "3.19.0",
248
+ "shiki": "3.20.0",
249
249
  "sitemap": "9.0.0",
250
250
  "strip-ansi": "7.1.2",
251
- "tailwind-merge": "3.3.1",
252
- "tailwindcss": "4.1.17",
251
+ "tailwind-merge": "3.4.0",
252
+ "tailwindcss": "4.1.18",
253
253
  "tw-animate-css": "1.4.0",
254
254
  "unified": "^11.0.5",
255
255
  "unist-util-visit": "5.0.0",
@@ -280,7 +280,7 @@
280
280
  "@types/semver": "7.7.0",
281
281
  "@types/unist": "^3.0.3",
282
282
  "@types/yargs": "17.0.35",
283
- "@vitest/coverage-v8": "3.2.4",
283
+ "@vitest/coverage-v8": "4.0.16",
284
284
  "esbuild": "0.27.0",
285
285
  "happy-dom": "20.0.10",
286
286
  "mdast-util-mdx": "3.0.0",
@@ -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
 
@@ -1,4 +1,5 @@
1
1
  import type { Auth0AuthenticationConfig } from "../../../config/config.js";
2
+ import { joinUrl } from "../../util/joinUrl.js";
2
3
  import type {
3
4
  AuthActionContext,
4
5
  AuthenticationPlugin,
@@ -43,7 +44,10 @@ class Auth0AuthenticationProvider
43
44
 
44
45
  signOut = async (_: AuthActionContext): Promise<void> => {
45
46
  const as = await this.getAuthServer();
46
- const idToken = await this.getAccessToken();
47
+
48
+ // biome-ignore lint/suspicious/noExplicitAny: We don't have a good way for typing provider-data yet.
49
+ const providerData = useAuthState.getState().providerData as any;
50
+ const idToken = providerData?.idToken;
47
51
 
48
52
  useAuthState.setState({
49
53
  isAuthenticated: false,
@@ -53,15 +57,18 @@ class Auth0AuthenticationProvider
53
57
  });
54
58
 
55
59
  const redirectUrl = new URL(window.location.origin);
56
- redirectUrl.pathname = this.redirectToAfterSignOut;
60
+ redirectUrl.pathname = joinUrl(
61
+ import.meta.env.BASE_URL,
62
+ this.redirectToAfterSignOut,
63
+ );
57
64
 
58
65
  // SEE: https://auth0.com/docs/authenticate/login/logout/log-users-out-of-auth0
59
66
  // For Auth0 tenants created on or after 14 November 2023, RP-Initiated
60
67
  // Logout End Session Endpoint Discovery is enabled by default.
61
68
  // Otherwise we fallback to the old non-compliant logout
62
69
 
63
- // The endSessionEndpoint is set, the IdP supports some form of logout,
64
- // so we use the IdP logout. Otherwise, just redirect the user to home
70
+ // The end_session_endpoint is set, the IdP supports some form of logout,
71
+ // so we use auth0 logout. Otherwise, just redirect the user to home
65
72
  if (as.end_session_endpoint) {
66
73
  const logoutUrl = new URL(as.end_session_endpoint);
67
74
  if (idToken) {
@@ -72,12 +79,11 @@ class Auth0AuthenticationProvider
72
79
  redirectUrl.toString(),
73
80
  );
74
81
 
75
- // window.location.href = logoutUrl.toString();
82
+ window.location.href = logoutUrl.toString();
76
83
  } else {
77
- const _logoutUrl = new URL(
78
- `${this.issuer.replace(/\/$/, "")}/oidc/logout`,
79
- );
80
- // window.location.href = logoutUrl.toString();
84
+ // const logoutUrl = new URL(`${this.issuer.replace(/\/$/, "")}/v2/logout`);
85
+ // logoutUrl.searchParams.set("returnTo", redirectUrl.toString());
86
+ // don't support the deprecated logout today
81
87
  }
82
88
  };
83
89
  }
@@ -29,32 +29,6 @@ const clerkAuth: AuthenticationProviderInitializer<
29
29
 
30
30
  await clerkApi.load();
31
31
 
32
- if (clerkApi.user) {
33
- const verifiedEmail = clerkApi.user.emailAddresses.find(
34
- (email) => email.verification.status === "verified",
35
- );
36
- useAuthState.getState().setLoggedIn({
37
- profile: {
38
- sub: clerkApi.user.id,
39
- name: clerkApi.user.fullName ?? undefined,
40
- email:
41
- verifiedEmail?.emailAddress ??
42
- clerkApi.user.emailAddresses[0]?.emailAddress,
43
- emailVerified: verifiedEmail !== undefined,
44
- pictureUrl: clerkApi.user.imageUrl,
45
- },
46
- providerData: {
47
- user: {
48
- publicMetadata: clerkApi.user.publicMetadata,
49
- id: clerkApi.user.id,
50
- emailAddresses: clerkApi.user.emailAddresses,
51
- imageUrl: clerkApi.user.imageUrl,
52
- fullName: clerkApi.user.fullName,
53
- },
54
- },
55
- });
56
- }
57
-
58
32
  return clerkApi;
59
33
  })();
60
34
 
@@ -129,21 +129,12 @@ class SupabaseAuthenticationProvider
129
129
  };
130
130
 
131
131
  signOut = async () => {
132
- await new Promise<void>((resolve) => {
133
- const { data } = this.client.auth.onAuthStateChange(async (event) => {
134
- if (event !== "SIGNED_OUT") return;
135
- data.subscription.unsubscribe();
136
- resolve();
137
- });
138
- void this.client.auth.signOut();
139
- });
140
-
141
- useAuthState.setState({
142
- isAuthenticated: false,
143
- isPending: false,
144
- profile: undefined,
145
- providerData: undefined,
146
- });
132
+ const { error } = await this.client.auth.signOut({ scope: "local" });
133
+ if (error) {
134
+ // biome-ignore lint/suspicious: Logging is better than not doing anything
135
+ console.error("Error signing out", error);
136
+ }
137
+ useAuthState.getState().setLoggedOut();
147
138
  };
148
139
 
149
140
  onPageLoad = async () => {
@@ -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
  };
@@ -3,6 +3,7 @@ import { GraphQLJSON } from "graphql-type-json";
3
3
  import type { RecordAny } from "../../util/traverse.js";
4
4
 
5
5
  export const CIRCULAR_REF = "$[Circular Reference]";
6
+ export const SCHEMA_REF_PREFIX = "$ref:";
6
7
 
7
8
  const OPENAPI_PROPS = new Set([
8
9
  "properties",
@@ -19,13 +20,28 @@ const handleCircularRefs = (
19
20
  visited = new WeakSet(),
20
21
  refs = new WeakMap(),
21
22
  path: string[] = [],
23
+ seenRefPaths = new Set<string>(),
22
24
  // biome-ignore lint/suspicious/noExplicitAny: Allow any type
23
25
  ): any => {
24
26
  if (obj === null || typeof obj !== "object") return obj;
25
27
 
28
+ const refPath = obj.__$ref;
29
+
30
+ // Check if this object has a __$ref marker (set during schema code generation)
31
+ // If we've already fully processed this ref path, return a reference marker
32
+ // instead of the full data to avoid JSON.stringify serializing duplicates
33
+ if (typeof refPath === "string" && seenRefPaths.has(refPath)) {
34
+ return SCHEMA_REF_PREFIX + refPath;
35
+ }
36
+
26
37
  if (visited.has(obj)) {
27
38
  const cached = refs.get(obj);
28
- if (cached) return cached;
39
+ if (cached) {
40
+ return typeof refPath === "string"
41
+ ? // If already processed, return ref marker to avoid duplicate serialization
42
+ SCHEMA_REF_PREFIX + refPath
43
+ : cached;
44
+ }
29
45
  const circularProp = path.find((p) => !OPENAPI_PROPS.has(p)) || path[0];
30
46
 
31
47
  return [CIRCULAR_REF, circularProp].filter(Boolean).join(":");
@@ -35,7 +51,13 @@ const handleCircularRefs = (
35
51
 
36
52
  if (Array.isArray(obj)) {
37
53
  const result = obj.map((item, index) =>
38
- handleCircularRefs(item, visited, refs, [...path, index.toString()]),
54
+ handleCircularRefs(
55
+ item,
56
+ visited,
57
+ refs,
58
+ [...path, index.toString()],
59
+ seenRefPaths,
60
+ ),
39
61
  );
40
62
  refs.set(obj, result);
41
63
  return result;
@@ -43,9 +65,20 @@ const handleCircularRefs = (
43
65
 
44
66
  const result: RecordAny = {};
45
67
  for (const [key, value] of Object.entries(obj)) {
46
- result[key] = handleCircularRefs(value, visited, refs, [...path, key]);
68
+ result[key] = handleCircularRefs(
69
+ value,
70
+ visited,
71
+ refs,
72
+ [...path, key],
73
+ seenRefPaths,
74
+ );
47
75
  }
48
76
  refs.set(obj, result);
77
+
78
+ if (typeof refPath === "string") {
79
+ seenRefPaths.add(refPath);
80
+ }
81
+
49
82
  return result;
50
83
  };
51
84
 
@@ -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}`,
@@ -97,11 +106,15 @@ const createDefaultHandler = (
97
106
  invariant(response.ok, "Failed to delete API key");
98
107
  },
99
108
  updateConsumer: async (consumer, context) => {
109
+ invariant(
110
+ deploymentName,
111
+ "Cannot update API key description.",
112
+ developerHintOptions,
113
+ );
100
114
  const response = await fetch(
101
115
  await context.signRequest(
102
116
  new Request(
103
- DEFAULT_API_KEY_ENDPOINT +
104
- `/${deploymentName}/consumers/${consumer.id}`,
117
+ `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers/${consumer.id}`,
105
118
  {
106
119
  method: "PATCH",
107
120
  headers: {
@@ -118,11 +131,11 @@ const createDefaultHandler = (
118
131
  invariant(response.ok, "Failed to update API key description");
119
132
  },
120
133
  rollKey: async (consumerId, context) => {
134
+ invariant(deploymentName, "Cannot roll API key.", developerHintOptions);
121
135
  const response = await fetch(
122
136
  await context.signRequest(
123
137
  new Request(
124
- DEFAULT_API_KEY_ENDPOINT +
125
- `/${deploymentName}/consumers/${consumerId}/roll-key`,
138
+ `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers/${consumerId}/roll-key`,
126
139
  {
127
140
  method: "POST",
128
141
  headers: {
@@ -137,6 +150,7 @@ const createDefaultHandler = (
137
150
  invariant(response.ok, "Failed to roll API key");
138
151
  },
139
152
  getConsumers: async (context) => {
153
+ invariant(deploymentName, "Cannot get API keys.", developerHintOptions);
140
154
  const request = new Request(
141
155
  `${DEFAULT_API_KEY_ENDPOINT}/${deploymentName}/consumers`,
142
156
  );
@@ -179,14 +193,30 @@ const createDefaultHandler = (
179
193
  export const createApiKeyService = <T extends ApiKeyService>(service: T): T =>
180
194
  service;
181
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
+
182
203
  export const apiKeyPlugin = ({
183
204
  deploymentName,
205
+ isZuplo,
184
206
  ...options
185
- }: Omit<ApiKeysOptions, "enabled"> & {
186
- deploymentName?: string;
187
- }): ZudokuPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {
188
- const service = deploymentName
189
- ? 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 })
190
220
  : options;
191
221
 
192
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",
@@ -151,6 +151,11 @@ const OperationsForTagQuery = graphql(/* GraphQL */ `
151
151
 
152
152
  const LAZY_OPERATION_LIST_THRESHOLD = 30;
153
153
 
154
+ const getFileExtension = (filename: string): string => {
155
+ const lastDotIndex = filename.lastIndexOf(".");
156
+ return lastDotIndex !== -1 ? filename.slice(lastDotIndex) : "";
157
+ };
158
+
154
159
  export const OperationList = ({
155
160
  tag,
156
161
  untagged,
@@ -251,7 +256,7 @@ export const OperationList = ({
251
256
  typeof input === "string"
252
257
  ? type === "url"
253
258
  ? input
254
- : joinUrl(path, version, input.split("/").pop())
259
+ : joinUrl(path, version, `schema${getFileExtension(input)}`)
255
260
  : undefined;
256
261
 
257
262
  return (
@@ -1,4 +1,7 @@
1
- import { CIRCULAR_REF } from "../../../oas/graphql/circular.js";
1
+ import {
2
+ CIRCULAR_REF,
3
+ SCHEMA_REF_PREFIX,
4
+ } from "../../../oas/graphql/circular.js";
2
5
  import type {
3
6
  ArraySchemaObject,
4
7
  SchemaObject,
@@ -25,7 +28,8 @@ export const isComplexType = (value?: SchemaObject) =>
25
28
  (!value.items.type || value.items.type === "object")));
26
29
 
27
30
  export const isCircularRef = (schema: unknown): schema is string =>
28
- typeof schema === "string" && schema.startsWith(CIRCULAR_REF);
31
+ typeof schema === "string" &&
32
+ (schema.startsWith(CIRCULAR_REF) || schema.startsWith(SCHEMA_REF_PREFIX));
29
33
 
30
34
  export const isArrayCircularRef = (
31
35
  schema: SchemaObject,
@@ -34,5 +38,12 @@ export const isArrayCircularRef = (
34
38
 
35
39
  export const extractCircularRefInfo = (
36
40
  ref?: string | SchemaObject,
37
- ): string | undefined =>
38
- typeof ref === "string" ? ref.split(":")[1] : undefined;
41
+ ): string | undefined => {
42
+ if (typeof ref !== "string") return undefined;
43
+
44
+ if (ref.startsWith(SCHEMA_REF_PREFIX)) {
45
+ return ref.slice(SCHEMA_REF_PREFIX.length).split("/").pop();
46
+ }
47
+
48
+ return ref.split(":")[1];
49
+ };
@@ -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.3/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-DQtg28Go.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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"}