zudoku 0.17.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/demo.js +0 -2
- package/dist/app/demo.js.map +1 -1
- package/dist/app/entry.client.js +14 -0
- package/dist/app/entry.client.js.map +1 -1
- package/dist/app/entry.server.js +5 -4
- package/dist/app/entry.server.js.map +1 -1
- package/dist/app/standalone.js +0 -2
- package/dist/app/standalone.js.map +1 -1
- package/dist/codegen.d.ts +3 -0
- package/dist/codegen.js +45 -0
- package/dist/codegen.js.map +1 -0
- package/dist/config/validators/InputSidebarSchema.d.ts +10 -10
- package/dist/config/validators/validate.d.ts +74 -74
- package/dist/lib/authentication/hook.d.ts +5 -4
- package/dist/lib/authentication/hook.js +1 -3
- package/dist/lib/authentication/hook.js.map +1 -1
- package/dist/lib/authentication/providers/auth0.js +11 -11
- package/dist/lib/authentication/providers/auth0.js.map +1 -1
- package/dist/lib/authentication/providers/openid.d.ts +0 -1
- package/dist/lib/authentication/providers/openid.js +11 -26
- package/dist/lib/authentication/providers/openid.js.map +1 -1
- package/dist/lib/authentication/state.d.ts +25 -4
- package/dist/lib/authentication/state.js +28 -5
- package/dist/lib/authentication/state.js.map +1 -1
- package/dist/lib/components/Bootstrap.d.ts +3 -1
- package/dist/lib/components/Bootstrap.js +10 -4
- package/dist/lib/components/Bootstrap.js.map +1 -1
- package/dist/lib/components/DeveloperHint.js +2 -1
- package/dist/lib/components/DeveloperHint.js.map +1 -1
- package/dist/lib/components/Header.js +3 -7
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/Heading.d.ts +1 -1
- package/dist/lib/components/Layout.js +11 -3
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/MobileTopNavigation.js +6 -7
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/SyntaxHighlight.js +16 -12
- package/dist/lib/components/SyntaxHighlight.js.map +1 -1
- package/dist/lib/components/ThemeSwitch.d.ts +1 -0
- package/dist/lib/components/ThemeSwitch.js +13 -0
- package/dist/lib/components/ThemeSwitch.js.map +1 -0
- package/dist/lib/components/TopNavigation.d.ts +2 -0
- package/dist/lib/components/TopNavigation.js +13 -7
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/Zudoku.js +4 -5
- package/dist/lib/components/Zudoku.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +3 -3
- package/dist/lib/components/context/ZudokuContext.js +7 -12
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +14 -3
- package/dist/lib/components/navigation/Sidebar.js +1 -1
- package/dist/lib/components/navigation/Sidebar.js.map +1 -1
- package/dist/lib/components/navigation/utils.js +2 -2
- package/dist/lib/components/navigation/utils.js.map +1 -1
- package/dist/lib/core/ZudokuContext.d.ts +0 -4
- package/dist/lib/core/ZudokuContext.js +0 -5
- package/dist/lib/core/ZudokuContext.js.map +1 -1
- package/dist/lib/errors/ErrorAlert.js +1 -1
- package/dist/lib/errors/ErrorAlert.js.map +1 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js +13 -9
- package/dist/lib/plugins/openapi/ColorizedParam.js.map +1 -1
- package/dist/lib/plugins/openapi/Endpoint.d.ts +1 -1
- package/dist/lib/plugins/openapi/Endpoint.js +5 -9
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.d.ts +2 -2
- package/dist/lib/plugins/openapi/OperationList.js +6 -21
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/Route.d.ts +4 -4
- package/dist/lib/plugins/openapi/Route.js +2 -4
- package/dist/lib/plugins/openapi/Route.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.d.ts +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +8 -11
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/client/GraphQLClient.d.ts +8 -0
- package/dist/lib/plugins/openapi/client/GraphQLClient.js +102 -0
- package/dist/lib/plugins/openapi/client/GraphQLClient.js.map +1 -0
- package/dist/lib/plugins/openapi/client/GraphQLContext.d.ts +7 -0
- package/dist/lib/plugins/openapi/client/GraphQLContext.js +5 -0
- package/dist/lib/plugins/openapi/client/GraphQLContext.js.map +1 -0
- package/dist/lib/plugins/openapi/client/createServer.d.ts +1 -0
- package/dist/lib/plugins/openapi/client/useCreateQuery.d.ts +5 -0
- package/dist/lib/plugins/openapi/client/useCreateQuery.js +13 -0
- package/dist/lib/plugins/openapi/client/useCreateQuery.js.map +1 -0
- package/dist/lib/plugins/openapi/client/worker.d.ts +4 -1
- package/dist/lib/plugins/openapi/client/worker.js +23 -14
- package/dist/lib/plugins/openapi/client/worker.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/fragment-masking.d.ts +3 -3
- package/dist/lib/plugins/openapi/graphql/fragment-masking.js +3 -4
- package/dist/lib/plugins/openapi/graphql/fragment-masking.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +5 -52
- package/dist/lib/plugins/openapi/graphql/gql.js +2 -1
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +134 -9
- package/dist/lib/plugins/openapi/graphql/graphql.js +194 -778
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +40 -53
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/schema/SchemaView.js.map +1 -1
- package/dist/lib/plugins/openapi-worker.d.ts +1 -1
- package/dist/lib/plugins/openapi-worker.js +7 -1
- package/dist/lib/plugins/openapi-worker.js.map +1 -1
- package/dist/lib/util/MdxComponents.d.ts +1 -1
- package/dist/vite/config.js +0 -1
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/html.js +0 -2
- package/dist/vite/html.js.map +1 -1
- package/dist/vite/plugin-component.js +1 -1
- package/dist/vite/plugin-component.js.map +1 -1
- package/dist/vite/plugin-mdx.js +3 -2
- package/dist/vite/plugin-mdx.js.map +1 -1
- package/dist/vite/plugin.js +0 -2
- package/dist/vite/plugin.js.map +1 -1
- package/dist/vite/remarkStaticGeneration.d.ts +3 -0
- package/dist/vite/remarkStaticGeneration.js +125 -0
- package/dist/vite/remarkStaticGeneration.js.map +1 -0
- package/lib/{AnchorLink-DYbUOP9U.js → AnchorLink-CDlhr8gL.js} +11 -10
- package/lib/{AnchorLink-DYbUOP9U.js.map → AnchorLink-CDlhr8gL.js.map} +1 -1
- package/lib/{AuthenticationPlugin-bqGAKfot.js → AuthenticationPlugin-DeGDVa1r.js} +6 -5
- package/lib/{AuthenticationPlugin-bqGAKfot.js.map → AuthenticationPlugin-DeGDVa1r.js.map} +1 -1
- package/lib/{Spinner-ChOGyPls.js → Button-jK0EsymC.js} +12 -15
- package/lib/Button-jK0EsymC.js.map +1 -0
- package/lib/Markdown-ievDDhFT.js +15192 -0
- package/lib/Markdown-ievDDhFT.js.map +1 -0
- package/lib/{MdxPage-DRKqyn2b.js → MdxPage-Bwn-VSsH.js} +5 -5
- package/lib/{MdxPage-DRKqyn2b.js.map → MdxPage-Bwn-VSsH.js.map} +1 -1
- package/lib/OperationList-BwBl1xrD.js +4691 -0
- package/lib/OperationList-BwBl1xrD.js.map +1 -0
- package/lib/Route-DlG_HTMu.js +11 -0
- package/lib/Route-DlG_HTMu.js.map +1 -0
- package/lib/{Select-DYKDahHt.js → Select-O9ZM3ZgX.js} +7 -7
- package/lib/Select-O9ZM3ZgX.js.map +1 -0
- package/lib/SidebarBadge-DxFJcJ6V.js +51 -0
- package/lib/SidebarBadge-DxFJcJ6V.js.map +1 -0
- package/lib/SlotletProvider-DyomlzGx.js +252 -0
- package/lib/SlotletProvider-DyomlzGx.js.map +1 -0
- package/lib/Spinner-3cQDBVGr.js +7 -0
- package/lib/Spinner-3cQDBVGr.js.map +1 -0
- package/lib/SyntaxHighlight-DkLOsjHS.js +2983 -0
- package/lib/SyntaxHighlight-DkLOsjHS.js.map +1 -0
- package/lib/assets/{worker-YA-aCP3P.js → worker-CPsGZsve.js} +24 -22
- package/lib/assets/{worker-YA-aCP3P.js.map → worker-CPsGZsve.js.map} +1 -1
- package/lib/context-D1nXWxm7.js +22 -0
- package/lib/context-D1nXWxm7.js.map +1 -0
- package/lib/createServer-DK-g7kbB.js +16089 -0
- package/lib/createServer-DK-g7kbB.js.map +1 -0
- package/lib/{hook-CjQERPa7.js → hook-hEqe7fPB.js} +12 -14
- package/lib/hook-hEqe7fPB.js.map +1 -0
- package/lib/index-Czzd9rjU.js +899 -0
- package/lib/index-Czzd9rjU.js.map +1 -0
- package/lib/index-DNxQ_rCt.js +1273 -0
- package/lib/index-DNxQ_rCt.js.map +1 -0
- package/lib/index-Yn8c3UWE.js +921 -0
- package/lib/index-Yn8c3UWE.js.map +1 -0
- package/lib/{router-BsfSoK2j.js → router-lfyopgBI.js} +23 -23
- package/lib/{router-BsfSoK2j.js.map → router-lfyopgBI.js.map} +1 -1
- package/lib/state-tsXBLONe.js +203 -0
- package/lib/state-tsXBLONe.js.map +1 -0
- package/lib/ui/ActionButton.js +11 -10
- package/lib/ui/ActionButton.js.map +1 -1
- package/lib/useExposedProps-CTPtylCV.js +10 -0
- package/lib/{useExposedProps-BxyHjPNN.js.map → useExposedProps-CTPtylCV.js.map} +1 -1
- package/lib/{utils-DNAltzXc.js → utils-DcpDOncX.js} +197 -202
- package/lib/utils-DcpDOncX.js.map +1 -0
- package/lib/zudoku.auth-auth0.js +24 -18
- package/lib/zudoku.auth-auth0.js.map +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-openid.js +124 -138
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +1128 -992
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.openapi-worker.js +10 -16346
- package/lib/zudoku.openapi-worker.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +18 -18
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-openapi.js +5 -9
- package/lib/zudoku.plugin-openapi.js.map +1 -1
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/package.json +14 -4
- package/src/app/demo.tsx +0 -3
- package/src/app/entry.client.tsx +14 -0
- package/src/app/entry.server.tsx +59 -57
- package/src/app/standalone.tsx +0 -3
- package/src/lib/authentication/hook.ts +1 -3
- package/src/lib/authentication/providers/auth0.tsx +16 -11
- package/src/lib/authentication/providers/openid.tsx +12 -30
- package/src/lib/authentication/state.ts +44 -10
- package/src/lib/components/Bootstrap.tsx +36 -14
- package/src/lib/components/DeveloperHint.tsx +6 -1
- package/src/lib/components/Header.tsx +31 -42
- package/src/lib/components/Layout.tsx +48 -36
- package/src/lib/components/MobileTopNavigation.tsx +15 -18
- package/src/lib/components/SyntaxHighlight.tsx +81 -46
- package/src/lib/components/ThemeSwitch.tsx +26 -0
- package/src/lib/components/TopNavigation.tsx +27 -19
- package/src/lib/components/Zudoku.tsx +5 -10
- package/src/lib/components/context/ZudokuContext.ts +8 -13
- package/src/lib/components/navigation/Sidebar.tsx +3 -3
- package/src/lib/components/navigation/utils.ts +2 -2
- package/src/lib/core/ZudokuContext.ts +0 -8
- package/src/lib/errors/ErrorAlert.tsx +2 -1
- package/src/lib/plugins/openapi/ColorizedParam.tsx +23 -14
- package/src/lib/plugins/openapi/Endpoint.tsx +5 -10
- package/src/lib/plugins/openapi/OperationList.tsx +5 -40
- package/src/lib/plugins/openapi/Route.tsx +11 -12
- package/src/lib/plugins/openapi/Sidecar.tsx +10 -13
- package/src/lib/plugins/openapi/client/GraphQLClient.tsx +140 -0
- package/src/lib/plugins/openapi/client/GraphQLContext.tsx +16 -0
- package/src/lib/plugins/openapi/client/createServer.ts +2 -0
- package/src/lib/plugins/openapi/client/useCreateQuery.ts +18 -0
- package/src/lib/plugins/openapi/client/worker.ts +38 -24
- package/src/lib/plugins/openapi/graphql/fragment-masking.ts +11 -18
- package/src/lib/plugins/openapi/graphql/gql.ts +7 -25
- package/src/lib/plugins/openapi/graphql/graphql.ts +351 -782
- package/src/lib/plugins/openapi/index.tsx +40 -63
- package/src/lib/plugins/openapi/schema/SchemaView.tsx +1 -1
- package/src/lib/plugins/openapi-worker.ts +11 -1
- package/dist/lib/components/context/ThemeContext.d.ts +0 -2
- package/dist/lib/components/context/ThemeContext.js +0 -7
- package/dist/lib/components/context/ThemeContext.js.map +0 -1
- package/dist/lib/components/context/ThemeProvider.d.ts +0 -4
- package/dist/lib/components/context/ThemeProvider.js +0 -23
- package/dist/lib/components/context/ThemeProvider.js.map +0 -1
- package/dist/lib/plugins/openapi/client/createMemoryClient.d.ts +0 -9
- package/dist/lib/plugins/openapi/client/createMemoryClient.js +0 -54
- package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +0 -1
- package/dist/lib/plugins/openapi/client/createWorkerClient.d.ts +0 -10
- package/dist/lib/plugins/openapi/client/createWorkerClient.js +0 -62
- package/dist/lib/plugins/openapi/client/createWorkerClient.js.map +0 -1
- package/dist/lib/plugins/openapi/client/interfaces.d.ts +0 -4
- package/dist/lib/plugins/openapi/client/interfaces.js +0 -2
- package/dist/lib/plugins/openapi/client/interfaces.js.map +0 -1
- package/dist/lib/themeToggle.d.ts +0 -1
- package/dist/lib/themeToggle.js +0 -7
- package/dist/lib/themeToggle.js.map +0 -1
- package/dist/lib/util/createWaitForNotify.d.ts +0 -1
- package/dist/lib/util/createWaitForNotify.js +0 -15
- package/dist/lib/util/createWaitForNotify.js.map +0 -1
- package/dist/vite/plugin-html-transform.d.ts +0 -2
- package/dist/vite/plugin-html-transform.js +0 -15
- package/dist/vite/plugin-html-transform.js.map +0 -1
- package/lib/DeveloperHint-DHdLXGHA.js +0 -16
- package/lib/DeveloperHint-DHdLXGHA.js.map +0 -1
- package/lib/Markdown-D6UxMbZm.js +0 -18059
- package/lib/Markdown-D6UxMbZm.js.map +0 -1
- package/lib/OperationList-BHUBGM0c.js +0 -621
- package/lib/OperationList-BHUBGM0c.js.map +0 -1
- package/lib/Route-B0XuN1oC.js +0 -13
- package/lib/Route-B0XuN1oC.js.map +0 -1
- package/lib/Select-DYKDahHt.js.map +0 -1
- package/lib/SidebarBadge-Bbt92M5K.js +0 -38
- package/lib/SidebarBadge-Bbt92M5K.js.map +0 -1
- package/lib/SlotletProvider-mhjLPG44.js +0 -241
- package/lib/SlotletProvider-mhjLPG44.js.map +0 -1
- package/lib/Spinner-ChOGyPls.js.map +0 -1
- package/lib/StaggeredRender-DDHSzQKE.js +0 -17
- package/lib/StaggeredRender-DDHSzQKE.js.map +0 -1
- package/lib/hook-CjQERPa7.js.map +0 -1
- package/lib/index-BRg5pi5D.js +0 -5902
- package/lib/index-BRg5pi5D.js.map +0 -1
- package/lib/index-DM9hrcCG.js +0 -1783
- package/lib/index-DM9hrcCG.js.map +0 -1
- package/lib/state-BsPrOUAh.js +0 -252
- package/lib/state-BsPrOUAh.js.map +0 -1
- package/lib/urql-core-35Qt_U4i.js +0 -1511
- package/lib/urql-core-35Qt_U4i.js.map +0 -1
- package/lib/useExposedProps-BxyHjPNN.js +0 -9
- package/lib/utils-DNAltzXc.js.map +0 -1
- package/src/lib/components/context/ThemeContext.tsx +0 -8
- package/src/lib/components/context/ThemeProvider.tsx +0 -27
- package/src/lib/plugins/openapi/client/createMemoryClient.ts +0 -65
- package/src/lib/plugins/openapi/client/createWorkerClient.ts +0 -79
- package/src/lib/plugins/openapi/client/interfaces.ts +0 -5
- package/src/lib/themeToggle.ts +0 -7
- package/src/lib/util/createWaitForNotify.ts +0 -18
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { cx } from "class-variance-authority";
|
|
2
2
|
import { Suspense } from "react";
|
|
3
|
-
import {
|
|
4
|
-
import { useAuth } from "../authentication/hook.js";
|
|
3
|
+
import { NavLink, useNavigation } from "react-router-dom";
|
|
5
4
|
import { TopNavigationItem } from "../../config/validators/validate.js";
|
|
5
|
+
import { useAuth } from "../authentication/hook.js";
|
|
6
|
+
import { ZudokuError } from "../util/invariant.js";
|
|
6
7
|
import { joinPath } from "../util/joinPath.js";
|
|
7
8
|
import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
|
|
8
9
|
import { traverseSidebar } from "./navigation/utils.js";
|
|
@@ -32,7 +33,7 @@ export const TopNavigation = () => {
|
|
|
32
33
|
<nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
|
|
33
34
|
<ul className="flex flex-row items-center gap-8">
|
|
34
35
|
{topNavigation.filter(isHiddenItem(isAuthenticated)).map((item) => (
|
|
35
|
-
|
|
36
|
+
<li key={item.id}>
|
|
36
37
|
<TopNavItem {...item} />
|
|
37
38
|
</li>
|
|
38
39
|
))}
|
|
@@ -42,10 +43,16 @@ export const TopNavigation = () => {
|
|
|
42
43
|
);
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
const TopNavItem = ({
|
|
46
|
+
export const TopNavItem = ({
|
|
47
|
+
id,
|
|
48
|
+
label,
|
|
49
|
+
default: defaultLink,
|
|
50
|
+
}: TopNavigationItem) => {
|
|
46
51
|
const { sidebars } = useZudoku();
|
|
47
|
-
const nav = useCurrentNavigation();
|
|
48
52
|
const currentSidebar = sidebars[id];
|
|
53
|
+
const currentNav = useCurrentNavigation();
|
|
54
|
+
const isNavigating = Boolean(useNavigation().location);
|
|
55
|
+
const isActive = currentNav.topNavItem?.id === id && !isNavigating;
|
|
49
56
|
|
|
50
57
|
// TODO: This is a bit of a hack to get the first link in the sidebar
|
|
51
58
|
// We should really process this when we load the config so we can validate
|
|
@@ -60,25 +67,26 @@ const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
|
|
|
60
67
|
: joinPath(id));
|
|
61
68
|
|
|
62
69
|
if (!first) {
|
|
63
|
-
throw new
|
|
64
|
-
`No links found in top navigation for
|
|
65
|
-
);
|
|
70
|
+
throw new ZudokuError("Page not found.", {
|
|
71
|
+
developerHint: `No links found in top navigation for '${id}'. Check that the sidebar isn't empty or that a default link is set.`,
|
|
72
|
+
});
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
// Manually set the active sidebar based on our logic of what is active
|
|
69
|
-
const isActive = nav.data.topNavItem?.id === id;
|
|
70
|
-
|
|
71
75
|
return (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
:
|
|
78
|
-
|
|
76
|
+
// We don't use isActive here because it has to be inside the sidebar,
|
|
77
|
+
// the top nav id doesn't necessarily start with the sidebar id
|
|
78
|
+
<NavLink
|
|
79
|
+
className={({ isPending }) =>
|
|
80
|
+
cx(
|
|
81
|
+
"block lg:py-3.5 font-medium -mb-px border-b-2",
|
|
82
|
+
isActive || isPending
|
|
83
|
+
? "border-primary text-foreground"
|
|
84
|
+
: "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
|
|
85
|
+
)
|
|
86
|
+
}
|
|
79
87
|
to={first}
|
|
80
88
|
>
|
|
81
89
|
{label}
|
|
82
|
-
</
|
|
90
|
+
</NavLink>
|
|
83
91
|
);
|
|
84
92
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MDXProvider } from "@mdx-js/react";
|
|
2
|
-
import { QueryClientProvider } from "@tanstack/react-query";
|
|
3
2
|
import { Helmet } from "@zudoku/react-helmet-async";
|
|
3
|
+
import { ThemeProvider } from "next-themes";
|
|
4
4
|
import {
|
|
5
5
|
Fragment,
|
|
6
6
|
memo,
|
|
@@ -13,11 +13,7 @@ import {
|
|
|
13
13
|
import { ErrorBoundary } from "react-error-boundary";
|
|
14
14
|
import { Outlet, useNavigation } from "react-router-dom";
|
|
15
15
|
import { hasHead, isMdxProviderPlugin } from "../core/plugins.js";
|
|
16
|
-
import {
|
|
17
|
-
queryClient,
|
|
18
|
-
ZudokuContext,
|
|
19
|
-
ZudokuContextOptions,
|
|
20
|
-
} from "../core/ZudokuContext.js";
|
|
16
|
+
import { ZudokuContext, ZudokuContextOptions } from "../core/ZudokuContext.js";
|
|
21
17
|
import { TopLevelError } from "../errors/TopLevelError.js";
|
|
22
18
|
import { StaggeredRenderContext } from "../plugins/openapi/StaggeredRender.js";
|
|
23
19
|
import { MdxComponents } from "../util/MdxComponents.js";
|
|
@@ -26,7 +22,6 @@ import {
|
|
|
26
22
|
ComponentsProvider,
|
|
27
23
|
DEFAULT_COMPONENTS,
|
|
28
24
|
} from "./context/ComponentsContext.js";
|
|
29
|
-
import { ThemeProvider } from "./context/ThemeProvider.js";
|
|
30
25
|
import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
|
|
31
26
|
import { ZudokuProvider } from "./context/ZudokuProvider.js";
|
|
32
27
|
import { SlotletProvider } from "./SlotletProvider.js";
|
|
@@ -77,12 +72,12 @@ const ZudokoInner = memo(
|
|
|
77
72
|
.map((plugin, i) => <Fragment key={i}>{plugin.getHead?.()}</Fragment>);
|
|
78
73
|
|
|
79
74
|
return (
|
|
80
|
-
|
|
75
|
+
<>
|
|
81
76
|
<Helmet>{heads}</Helmet>
|
|
82
77
|
<StaggeredRenderContext.Provider value={staggeredValue}>
|
|
83
78
|
<ZudokuProvider context={zudokuContext}>
|
|
84
79
|
<MDXProvider components={mdxComponents}>
|
|
85
|
-
<ThemeProvider>
|
|
80
|
+
<ThemeProvider attribute="class" disableTransitionOnChange>
|
|
86
81
|
<ComponentsProvider value={components}>
|
|
87
82
|
<SlotletProvider slotlets={props.slotlets}>
|
|
88
83
|
<ViewportAnchorProvider>
|
|
@@ -94,7 +89,7 @@ const ZudokoInner = memo(
|
|
|
94
89
|
</MDXProvider>
|
|
95
90
|
</ZudokuProvider>
|
|
96
91
|
</StaggeredRenderContext.Provider>
|
|
97
|
-
|
|
92
|
+
</>
|
|
98
93
|
);
|
|
99
94
|
},
|
|
100
95
|
);
|
|
@@ -49,18 +49,13 @@ export const useCurrentNavigation = () => {
|
|
|
49
49
|
topNavigation.find((t) => t.id === currentSidebarItem?.[0]) ??
|
|
50
50
|
topNavigation.find((item) => matchPath(item.id, location.pathname));
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
queryFn:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
sidebar: [
|
|
58
|
-
...(currentSidebarItem ? currentSidebarItem[1] : []),
|
|
59
|
-
...pluginSidebar,
|
|
60
|
-
],
|
|
61
|
-
topNavItem: currentTopNavItem,
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
queryKey: ["navigation", location.pathname],
|
|
52
|
+
const { data } = useSuspenseQuery({
|
|
53
|
+
queryFn: () => getPluginSidebar(location.pathname),
|
|
54
|
+
queryKey: ["plugin-sidebar", location.pathname],
|
|
65
55
|
});
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
sidebar: [...(currentSidebarItem ? currentSidebarItem[1] : []), ...data],
|
|
59
|
+
topNavItem: currentTopNavItem,
|
|
60
|
+
};
|
|
66
61
|
};
|
|
@@ -15,10 +15,10 @@ export const Sidebar = () => {
|
|
|
15
15
|
<>
|
|
16
16
|
<SidebarWrapper
|
|
17
17
|
ref={navRef}
|
|
18
|
-
pushMainContent={navigation.
|
|
18
|
+
pushMainContent={navigation.sidebar.length > 0}
|
|
19
19
|
>
|
|
20
20
|
<Slotlet name="zudoku-before-navigation" />
|
|
21
|
-
{navigation.
|
|
21
|
+
{navigation.sidebar.map((item) => (
|
|
22
22
|
<SidebarItem key={item.label} item={item} />
|
|
23
23
|
))}
|
|
24
24
|
<Slotlet name="zudoku-after-navigation" />
|
|
@@ -30,7 +30,7 @@ export const Sidebar = () => {
|
|
|
30
30
|
<VisuallyHidden>
|
|
31
31
|
<DrawerTitle>Sidebar</DrawerTitle>
|
|
32
32
|
</VisuallyHidden>
|
|
33
|
-
{navigation.
|
|
33
|
+
{navigation.sidebar.map((item) => (
|
|
34
34
|
<SidebarItem key={item.label} item={item} />
|
|
35
35
|
))}
|
|
36
36
|
</DrawerContent>
|
|
@@ -44,7 +44,7 @@ export const useCurrentItem = () => {
|
|
|
44
44
|
const location = useLocation();
|
|
45
45
|
const nav = useCurrentNavigation();
|
|
46
46
|
|
|
47
|
-
const currentSidebar = nav.
|
|
47
|
+
const currentSidebar = nav.sidebar;
|
|
48
48
|
|
|
49
49
|
return traverseSidebar(currentSidebar, (item) => {
|
|
50
50
|
if (item.type === "doc" && joinPath(item.id) === location.pathname) {
|
|
@@ -79,7 +79,7 @@ export const usePrevNext = (): {
|
|
|
79
79
|
} => {
|
|
80
80
|
const currentId = useLocation().pathname;
|
|
81
81
|
const nav = useCurrentNavigation();
|
|
82
|
-
const currentSidebar = nav.
|
|
82
|
+
const currentSidebar = nav.sidebar;
|
|
83
83
|
|
|
84
84
|
let prev;
|
|
85
85
|
let next;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { QueryClient } from "@tanstack/react-query";
|
|
2
1
|
import { ReactNode } from "react";
|
|
3
2
|
import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
|
|
4
3
|
import { TopNavigationItem } from "../../config/validators/validate.js";
|
|
@@ -21,10 +20,7 @@ export interface ApiIdentity {
|
|
|
21
20
|
id: string;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
export const queryClient = new QueryClient();
|
|
25
|
-
|
|
26
23
|
export type ApiKeyCache = "api-keys";
|
|
27
|
-
export type ZudokuCacheKey = ApiKeyCache | string;
|
|
28
24
|
|
|
29
25
|
type Metadata = Partial<{
|
|
30
26
|
title: string;
|
|
@@ -98,10 +94,6 @@ export class ZudokuContext {
|
|
|
98
94
|
);
|
|
99
95
|
};
|
|
100
96
|
|
|
101
|
-
invalidateCache = async (key: ZudokuCacheKey[]) => {
|
|
102
|
-
await queryClient.invalidateQueries({ queryKey: key });
|
|
103
|
-
};
|
|
104
|
-
|
|
105
97
|
getApiIdentities = async () => {
|
|
106
98
|
const keys = await Promise.all(
|
|
107
99
|
this.plugins
|
|
@@ -5,6 +5,7 @@ import { ZudokuError } from "../util/invariant.js";
|
|
|
5
5
|
export function ErrorAlert({ error }: { error: unknown }) {
|
|
6
6
|
const message =
|
|
7
7
|
error instanceof Error ? error.message : "Something went wrong";
|
|
8
|
+
|
|
8
9
|
const hint = error instanceof ZudokuError ? error.developerHint : undefined;
|
|
9
10
|
const title =
|
|
10
11
|
error instanceof ZudokuError ? error.title : "Something went wrong";
|
|
@@ -12,7 +13,7 @@ export function ErrorAlert({ error }: { error: unknown }) {
|
|
|
12
13
|
const cause = error instanceof Error ? error.cause : undefined;
|
|
13
14
|
|
|
14
15
|
return (
|
|
15
|
-
<div className="flex h-screen max-h-
|
|
16
|
+
<div className="flex h-screen max-h-[calc(100vh-var(--header-height))] min-h-full items-center justify-center bg-primary-background px-4 py-16 lg:px-8">
|
|
16
17
|
<div className="mx-auto max-w-[85%] sm:max-w-[50%]">
|
|
17
18
|
<h1 className="text-4xl font-bold tracking-tight text-h1-text sm:text-5xl">
|
|
18
19
|
{title}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useTheme } from "next-themes";
|
|
2
|
+
import { useEffect, useRef, type CSSProperties, type ReactNode } from "react";
|
|
3
3
|
import { cn } from "../../util/cn.js";
|
|
4
4
|
import { pastellize } from "../../util/pastellize.js";
|
|
5
5
|
|
|
6
6
|
export const DATA_ATTR = "data-linked-param";
|
|
7
7
|
|
|
8
8
|
export const usePastellizedColor = (name: string) => {
|
|
9
|
-
const
|
|
9
|
+
const { resolvedTheme } = useTheme();
|
|
10
10
|
return pastellize(
|
|
11
11
|
name,
|
|
12
|
-
|
|
12
|
+
resolvedTheme === "light" ? { saturation: 85, lightness: 50 } : undefined,
|
|
13
13
|
);
|
|
14
14
|
};
|
|
15
15
|
|
|
@@ -61,27 +61,36 @@ export const ColorizedParam = ({
|
|
|
61
61
|
});
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
ref.current
|
|
65
|
-
|
|
64
|
+
const el = ref.current;
|
|
65
|
+
|
|
66
|
+
el.addEventListener("mouseenter", onMouseEnter);
|
|
67
|
+
el.addEventListener("mouseleave", onMouseLeave);
|
|
66
68
|
|
|
67
69
|
return () => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
el.removeEventListener("mouseenter", onMouseEnter);
|
|
71
|
+
el.removeEventListener("mouseleave", onMouseLeave);
|
|
70
72
|
};
|
|
71
73
|
}, [normalizedSlug]);
|
|
72
74
|
|
|
73
75
|
return (
|
|
74
76
|
<span
|
|
75
|
-
className={cn("inline-flex relative rounded group", className)}
|
|
76
77
|
{...{ [DATA_ATTR]: normalizedSlug }}
|
|
78
|
+
className={cn(
|
|
79
|
+
"relative after:rounded after:absolute after:inset-0 after:-bottom-0.5 after:border-b-2 after:transition-opacity after:duration-200",
|
|
80
|
+
"after:pointer-events-none after:border-[--border-color] after:opacity-30 after:data-[active=true]:opacity-100",
|
|
81
|
+
className,
|
|
82
|
+
)}
|
|
83
|
+
suppressHydrationWarning
|
|
77
84
|
ref={ref}
|
|
78
85
|
onClick={onClick}
|
|
86
|
+
style={
|
|
87
|
+
{
|
|
88
|
+
"--border-color": borderColor,
|
|
89
|
+
"--background-color": backgroundColor,
|
|
90
|
+
} as CSSProperties
|
|
91
|
+
}
|
|
79
92
|
>
|
|
80
|
-
|
|
81
|
-
className="absolute inset-0 border-b-2 transition-opacity duration-200 opacity-30 group-data-[active=true]:opacity-100"
|
|
82
|
-
style={{ borderColor, backgroundColor }}
|
|
83
|
-
/>
|
|
84
|
-
<span className="relative">{children ?? name}</span>
|
|
93
|
+
{children ?? name}
|
|
85
94
|
</span>
|
|
86
95
|
);
|
|
87
96
|
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
1
2
|
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
2
3
|
import { useState, useTransition } from "react";
|
|
3
|
-
import { useQuery } from "urql";
|
|
4
4
|
import { useSelectedServerStore } from "../../authentication/state.js";
|
|
5
5
|
import { InlineCode } from "../../components/InlineCode.js";
|
|
6
6
|
import { Button } from "../../ui/Button.js";
|
|
7
|
+
import { useCreateQuery } from "./client/useCreateQuery.js";
|
|
7
8
|
import { useOasConfig } from "./context.js";
|
|
8
9
|
import { graphql } from "./graphql/index.js";
|
|
9
10
|
import { SimpleSelect } from "./SimpleSelect.js";
|
|
@@ -42,19 +43,13 @@ const CopyButton = ({ url }: { url: string }) => {
|
|
|
42
43
|
);
|
|
43
44
|
};
|
|
44
45
|
|
|
45
|
-
const context = { suspense: true } as const;
|
|
46
|
-
|
|
47
46
|
export const Endpoint = () => {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
context,
|
|
52
|
-
});
|
|
47
|
+
const { input, type } = useOasConfig();
|
|
48
|
+
const query = useCreateQuery(ServersQuery, { input, type });
|
|
49
|
+
const result = useSuspenseQuery(query);
|
|
53
50
|
const [, startTransition] = useTransition();
|
|
54
51
|
const { selectedServer, setSelectedServer } = useSelectedServerStore();
|
|
55
52
|
|
|
56
|
-
if (!result.data) return null;
|
|
57
|
-
|
|
58
53
|
const { servers } = result.data.schema;
|
|
59
54
|
|
|
60
55
|
if (servers.length === 1) {
|
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
import { ResultOf } from "@graphql-typed-document-node/core";
|
|
2
|
-
import
|
|
3
|
-
import { useQuery } from "urql";
|
|
2
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
4
3
|
import { CategoryHeading } from "../../components/CategoryHeading.js";
|
|
5
|
-
import { DeveloperHint } from "../../components/DeveloperHint.js";
|
|
6
|
-
import { ErrorPage } from "../../components/ErrorPage.js";
|
|
7
4
|
import { Heading } from "../../components/Heading.js";
|
|
8
|
-
import { InlineCode } from "../../components/InlineCode.js";
|
|
9
5
|
import { Markdown, ProseClasses } from "../../components/Markdown.js";
|
|
10
|
-
import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
11
6
|
import { cn } from "../../util/cn.js";
|
|
12
7
|
import { Endpoint } from "./Endpoint.js";
|
|
13
8
|
import { OperationListItem } from "./OperationListItem.js";
|
|
14
9
|
import StaggeredRender from "./StaggeredRender.js";
|
|
10
|
+
import { useCreateQuery } from "./client/useCreateQuery.js";
|
|
15
11
|
import { useOasConfig } from "./context.js";
|
|
16
12
|
import { graphql } from "./graphql/index.js";
|
|
17
13
|
|
|
@@ -100,41 +96,10 @@ const AllOperationsQuery = graphql(/* GraphQL */ `
|
|
|
100
96
|
}
|
|
101
97
|
`);
|
|
102
98
|
|
|
103
|
-
const suspenseContext = { suspense: true };
|
|
104
|
-
|
|
105
99
|
export const OperationList = () => {
|
|
106
|
-
const {
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
query: AllOperationsQuery,
|
|
110
|
-
variables: { type, input },
|
|
111
|
-
context: suspenseContext,
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
const error = result.error?.graphQLErrors.at(0);
|
|
115
|
-
|
|
116
|
-
// Looks like there is no Suspense level error handling (yet)?
|
|
117
|
-
// So we handle the error case in the component directly
|
|
118
|
-
if (error) {
|
|
119
|
-
return (
|
|
120
|
-
<ErrorPage
|
|
121
|
-
category="Error"
|
|
122
|
-
title="Schema cannot be displayed"
|
|
123
|
-
message={
|
|
124
|
-
<>
|
|
125
|
-
<DeveloperHint className="mb-4">
|
|
126
|
-
Check your configuration value <InlineCode>apis.type</InlineCode>{" "}
|
|
127
|
-
and <InlineCode>apis.input</InlineCode> in the Zudoku config.
|
|
128
|
-
</DeveloperHint>
|
|
129
|
-
An error occurred while trying to fetch the API reference:
|
|
130
|
-
<SyntaxHighlight code={error.toString()} language="plain" />
|
|
131
|
-
</>
|
|
132
|
-
}
|
|
133
|
-
/>
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!result.data) return null;
|
|
100
|
+
const { input, type } = useOasConfig();
|
|
101
|
+
const query = useCreateQuery(AllOperationsQuery, { input, type });
|
|
102
|
+
const result = useSuspenseQuery(query);
|
|
138
103
|
|
|
139
104
|
return (
|
|
140
105
|
<div className="pt-[--padding-content-top]">
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { Outlet } from "react-router-dom";
|
|
2
|
-
import {
|
|
2
|
+
import type { GraphQLClient } from "./client/GraphQLClient.js";
|
|
3
|
+
import { GraphQLProvider } from "./client/GraphQLContext.js";
|
|
3
4
|
import { OasConfigProvider } from "./context.js";
|
|
4
5
|
import { OasPluginConfig } from "./interfaces.js";
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
+
export const OpenApiRoute = ({
|
|
7
8
|
config,
|
|
8
9
|
client,
|
|
9
10
|
}: {
|
|
10
11
|
config: OasPluginConfig;
|
|
11
|
-
client:
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
);
|
|
20
|
-
}
|
|
12
|
+
client: GraphQLClient;
|
|
13
|
+
}) => (
|
|
14
|
+
<OasConfigProvider value={{ config }}>
|
|
15
|
+
<GraphQLProvider client={client}>
|
|
16
|
+
<Outlet />
|
|
17
|
+
</GraphQLProvider>
|
|
18
|
+
</OasConfigProvider>
|
|
19
|
+
);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
1
2
|
import { HTTPSnippet } from "@zudoku/httpsnippet";
|
|
2
3
|
import { Fragment, useMemo, useTransition } from "react";
|
|
3
4
|
import { useSearchParams } from "react-router-dom";
|
|
4
|
-
import { useQuery } from "urql";
|
|
5
5
|
import { useSelectedServerStore } from "../../authentication/state.js";
|
|
6
6
|
import { TextColorMap } from "../../components/navigation/SidebarBadge.js";
|
|
7
7
|
import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
8
8
|
import type { SchemaObject } from "../../oas/parser/index.js";
|
|
9
9
|
import { cn } from "../../util/cn.js";
|
|
10
10
|
import { useOnScreen } from "../../util/useOnScreen.js";
|
|
11
|
+
import { useCreateQuery } from "./client/useCreateQuery.js";
|
|
11
12
|
import { CollapsibleCode } from "./CollapsibleCode.js";
|
|
12
13
|
import { ColorizedParam } from "./ColorizedParam.js";
|
|
13
14
|
import { useOasConfig } from "./context.js";
|
|
@@ -75,8 +76,6 @@ export const GetServerQuery = graphql(/* GraphQL */ `
|
|
|
75
76
|
}
|
|
76
77
|
`);
|
|
77
78
|
|
|
78
|
-
const context = { suspense: true };
|
|
79
|
-
|
|
80
79
|
const methodToColor = {
|
|
81
80
|
get: TextColorMap.green,
|
|
82
81
|
post: TextColorMap.blue,
|
|
@@ -111,12 +110,10 @@ export const Sidecar = ({
|
|
|
111
110
|
selectedResponse?: string;
|
|
112
111
|
onSelectResponse: (response: string) => void;
|
|
113
112
|
}) => {
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
context,
|
|
119
|
-
});
|
|
113
|
+
const { input, type } = useOasConfig();
|
|
114
|
+
const query = useCreateQuery(GetServerQuery, { input, type });
|
|
115
|
+
const result = useSuspenseQuery(query);
|
|
116
|
+
|
|
120
117
|
const methodTextColor =
|
|
121
118
|
methodToColor[
|
|
122
119
|
operation.method.toLocaleLowerCase() as keyof typeof methodToColor
|
|
@@ -165,7 +162,7 @@ export const Sidecar = ({
|
|
|
165
162
|
const snippet = new HTTPSnippet({
|
|
166
163
|
method: operation.method.toLocaleUpperCase(),
|
|
167
164
|
url:
|
|
168
|
-
(selectedServer ?? result.data
|
|
165
|
+
(selectedServer ?? result.data.schema.url ?? "") +
|
|
169
166
|
operation.path.replaceAll("{", ":").replaceAll("}", ""),
|
|
170
167
|
postData: example
|
|
171
168
|
? {
|
|
@@ -187,7 +184,7 @@ export const Sidecar = ({
|
|
|
187
184
|
operation.method,
|
|
188
185
|
operation.path,
|
|
189
186
|
selectedServer,
|
|
190
|
-
result.data
|
|
187
|
+
result.data.schema.url,
|
|
191
188
|
selectedLang,
|
|
192
189
|
]);
|
|
193
190
|
const [ref, isOnScreen] = useOnScreen({ rootMargin: "200px 0px 200px 0px" });
|
|
@@ -208,9 +205,9 @@ export const Sidecar = ({
|
|
|
208
205
|
</span>
|
|
209
206
|
{isOnScreen && (
|
|
210
207
|
<PlaygroundDialogWrapper
|
|
211
|
-
server={result.data
|
|
208
|
+
server={result.data.schema.url ?? ""}
|
|
212
209
|
servers={
|
|
213
|
-
result.data
|
|
210
|
+
result.data.schema.servers.map((server) => server.url) ?? []
|
|
214
211
|
}
|
|
215
212
|
operation={operation}
|
|
216
213
|
/>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { GraphQLError } from "graphql/error/index.js";
|
|
2
|
+
import { ulid } from "ulidx";
|
|
3
|
+
import { initializeWorker } from "zudoku/openapi-worker";
|
|
4
|
+
import { ZudokuError } from "../../../util/invariant.js";
|
|
5
|
+
import type { TypedDocumentString } from "../graphql/graphql.js";
|
|
6
|
+
import type { OpenApiPluginOptions } from "../index.js";
|
|
7
|
+
import type { LocalServer } from "./createServer.js";
|
|
8
|
+
import type { WorkerGraphQLMessage } from "./worker.js";
|
|
9
|
+
|
|
10
|
+
let localServerPromise: Promise<LocalServer> | undefined;
|
|
11
|
+
let worker: SharedWorker | undefined;
|
|
12
|
+
|
|
13
|
+
type GraphQLResponse<TResult> = {
|
|
14
|
+
errors?: GraphQLError[];
|
|
15
|
+
data: TResult;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const throwIfError = (response: GraphQLResponse<unknown>) => {
|
|
19
|
+
if (!response.errors?.[0]) return;
|
|
20
|
+
|
|
21
|
+
throw new ZudokuError(response.errors[0].message, {
|
|
22
|
+
developerHint:
|
|
23
|
+
"Check your configuration value `apis.type` and `apis.input` in the Zudoku config.",
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class GraphQLClient {
|
|
28
|
+
readonly #mode: "remote" | "in-memory" | "worker";
|
|
29
|
+
#pendingRequests = new Map<string, (value: any) => void>();
|
|
30
|
+
#port: MessagePort | undefined;
|
|
31
|
+
|
|
32
|
+
constructor(private config: OpenApiPluginOptions) {
|
|
33
|
+
if (config.server) {
|
|
34
|
+
this.#mode = "remote";
|
|
35
|
+
} else if (config.inMemory || typeof SharedWorker === "undefined") {
|
|
36
|
+
this.#mode = "in-memory";
|
|
37
|
+
} else {
|
|
38
|
+
this.#mode = "worker";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#initializeLocalServer = () =>
|
|
43
|
+
import("./createServer.js").then((m) => m.createServer());
|
|
44
|
+
|
|
45
|
+
fetch = async <TResult, TVariables>(
|
|
46
|
+
query: TypedDocumentString<TResult, TVariables>,
|
|
47
|
+
...[variables]: TVariables extends Record<string, never> ? [] : [TVariables]
|
|
48
|
+
) => {
|
|
49
|
+
const operationName = query.match(/query (\w+)/)?.[1];
|
|
50
|
+
const body = JSON.stringify({ query, variables, operationName });
|
|
51
|
+
|
|
52
|
+
switch (this.#mode) {
|
|
53
|
+
case "remote": {
|
|
54
|
+
const response = await fetch(this.config.server!, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
body,
|
|
57
|
+
headers: { "Content-Type": "application/json" },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
throw new Error("Network response was not ok");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const result = (await response.json()) as GraphQLResponse<TResult>;
|
|
65
|
+
throwIfError(result);
|
|
66
|
+
|
|
67
|
+
return result.data;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
case "in-memory": {
|
|
71
|
+
if (!localServerPromise) {
|
|
72
|
+
localServerPromise = this.#initializeLocalServer();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const localServer = await localServerPromise;
|
|
76
|
+
if (!localServer) throw new Error("Local server not initialized");
|
|
77
|
+
|
|
78
|
+
const response = await localServer.fetch(
|
|
79
|
+
new Request("http://localhost/graphql", {
|
|
80
|
+
method: "POST",
|
|
81
|
+
body,
|
|
82
|
+
headers: { "Content-Type": "application/json" },
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
throw new Error("Network response was not ok");
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const result = (await response.json()) as GraphQLResponse<TResult>;
|
|
91
|
+
throwIfError(result);
|
|
92
|
+
|
|
93
|
+
return result.data;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
case "worker": {
|
|
97
|
+
if (!worker) {
|
|
98
|
+
worker = initializeWorker();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!this.#port) {
|
|
102
|
+
const channel = new MessageChannel();
|
|
103
|
+
|
|
104
|
+
worker.port.postMessage({ port: channel.port2 }, [channel.port2]);
|
|
105
|
+
|
|
106
|
+
this.#port = channel.port1;
|
|
107
|
+
|
|
108
|
+
this.#port.onmessage = (e: MessageEvent<WorkerGraphQLMessage>) => {
|
|
109
|
+
const { id, body } = e.data;
|
|
110
|
+
const resolve = this.#pendingRequests.get(id);
|
|
111
|
+
if (resolve) {
|
|
112
|
+
const result = JSON.parse(body);
|
|
113
|
+
resolve(result);
|
|
114
|
+
this.#pendingRequests.delete(id);
|
|
115
|
+
} else {
|
|
116
|
+
// eslint-disable-next-line no-console
|
|
117
|
+
console.error(`No pending request found for id: ${id}`);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
this.#port.start();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const id = ulid();
|
|
125
|
+
|
|
126
|
+
const resultPromise = new Promise<GraphQLResponse<TResult>>(
|
|
127
|
+
(resolve) => {
|
|
128
|
+
this.#pendingRequests.set(id, resolve);
|
|
129
|
+
this.#port!.postMessage({ id, body } as WorkerGraphQLMessage);
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const result = await resultPromise;
|
|
134
|
+
throwIfError(result);
|
|
135
|
+
|
|
136
|
+
return result.data;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createContext, type ReactNode } from "react";
|
|
2
|
+
import { GraphQLClient } from "./GraphQLClient.js";
|
|
3
|
+
|
|
4
|
+
export const GraphQLContext = createContext<GraphQLClient | undefined>(
|
|
5
|
+
undefined,
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
export const GraphQLProvider = ({
|
|
9
|
+
children,
|
|
10
|
+
client,
|
|
11
|
+
}: {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
client: GraphQLClient;
|
|
14
|
+
}) => (
|
|
15
|
+
<GraphQLContext.Provider value={client}>{children}</GraphQLContext.Provider>
|
|
16
|
+
);
|