zudoku 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/entry.server.js +4 -5
- package/dist/app/entry.server.js.map +1 -1
- package/dist/app/main.d.ts +1 -1
- package/dist/app/main.js +2 -2
- package/dist/app/main.js.map +1 -1
- package/dist/config/validators/validate.d.ts +44 -44
- package/dist/config/validators/validate.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/authentication/authentication.d.ts +2 -2
- package/dist/lib/authentication/state.d.ts +1 -1
- package/dist/lib/authentication/state.js +5 -3
- package/dist/lib/authentication/state.js.map +1 -1
- package/dist/lib/authentication/use-broadcast/shared.d.ts +48 -0
- package/dist/lib/authentication/use-broadcast/shared.js +243 -0
- package/dist/lib/authentication/use-broadcast/shared.js.map +1 -0
- package/dist/lib/authentication/use-broadcast/useBroadcast.d.ts +24 -0
- package/dist/lib/authentication/use-broadcast/useBroadcast.js +106 -0
- package/dist/lib/authentication/use-broadcast/useBroadcast.js.map +1 -0
- package/dist/lib/components/ClientOnly.d.ts +4 -2
- package/dist/lib/components/ClientOnly.js +1 -1
- package/dist/lib/components/ClientOnly.js.map +1 -1
- package/dist/lib/components/Header.js +4 -2
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/{DevPortal.d.ts → Zudoku.d.ts} +3 -3
- package/dist/lib/components/{DevPortal.js → Zudoku.js} +11 -11
- package/dist/lib/components/Zudoku.js.map +1 -0
- package/dist/lib/components/context/ZudokuContext.d.ts +4 -4
- package/dist/lib/components/context/ZudokuContext.js +1 -1
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/context/ZudokuProvider.d.ts +2 -2
- package/dist/lib/components/context/ZudokuProvider.js.map +1 -1
- package/dist/lib/components/index.d.ts +4 -7
- package/dist/lib/components/index.js +2 -3
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/core/{DevPortalContext.d.ts → ZudokuContext.d.ts} +5 -5
- package/dist/lib/core/{DevPortalContext.js → ZudokuContext.js} +2 -2
- package/dist/lib/core/ZudokuContext.js.map +1 -0
- package/dist/lib/core/plugins.d.ts +12 -12
- package/dist/lib/core/plugins.js.map +1 -1
- package/dist/lib/plugins/api-keys/index.d.ts +9 -9
- package/dist/lib/plugins/api-keys/index.js.map +1 -1
- package/dist/lib/plugins/custom-pages/index.d.ts +2 -2
- package/dist/lib/plugins/custom-pages/index.js.map +1 -1
- package/dist/lib/plugins/markdown/index.d.ts +2 -2
- package/dist/lib/plugins/markdown/index.js.map +1 -1
- package/dist/lib/plugins/openapi/CollapsibleCode.js +4 -2
- package/dist/lib/plugins/openapi/CollapsibleCode.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +1 -1
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js +6 -1
- package/dist/lib/plugins/openapi/ParameterListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +28 -24
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/client/createMemoryClient.d.ts +1 -4
- package/dist/lib/plugins/openapi/client/createMemoryClient.js +9 -1
- package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +1 -1
- package/dist/lib/plugins/openapi/client/createWorkerClient.js +2 -1
- package/dist/lib/plugins/openapi/client/createWorkerClient.js.map +1 -1
- package/dist/lib/plugins/openapi/index.d.ts +2 -2
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/redirect/index.d.ts +2 -2
- package/dist/lib/plugins/redirect/index.js.map +1 -1
- package/dist/lib/plugins/search-inkeep/index.d.ts +2 -2
- package/dist/lib/plugins/search-inkeep/index.js.map +1 -1
- package/dist/lib/ui/ActionButton.d.ts +4 -0
- package/dist/lib/ui/ActionButton.js +10 -0
- package/dist/lib/ui/ActionButton.js.map +1 -0
- package/dist/lib/util/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/lib/util/useIsomorphicLayoutEffect.js +4 -0
- package/dist/lib/util/useIsomorphicLayoutEffect.js.map +1 -0
- package/dist/lib/util/useOnScreen.d.ts +4 -0
- package/dist/lib/util/useOnScreen.js +19 -0
- package/dist/lib/util/useOnScreen.js.map +1 -0
- package/dist/vite/plugin-mdx.d.ts +0 -6
- package/dist/vite/plugin-mdx.js.map +1 -1
- package/lib/{AnchorLink-BbB2q-jx.js → AnchorLink-DYbUOP9U.js} +2 -2
- package/lib/{AnchorLink-BbB2q-jx.js.map → AnchorLink-DYbUOP9U.js.map} +1 -1
- package/lib/{AuthenticationPlugin-C9BHGXlE.js → AuthenticationPlugin-bqGAKfot.js} +3 -3
- package/lib/{AuthenticationPlugin-C9BHGXlE.js.map → AuthenticationPlugin-bqGAKfot.js.map} +1 -1
- package/lib/{ClientOnly-CVN6leDu.js → ClientOnly-E7hGysn1.js} +4 -4
- package/lib/ClientOnly-E7hGysn1.js.map +1 -0
- package/lib/{Markdown-BDcCAWwm.js → Markdown-D6UxMbZm.js} +2 -2
- package/lib/{Markdown-BDcCAWwm.js.map → Markdown-D6UxMbZm.js.map} +1 -1
- package/lib/{MdxPage-DKMH_t0f.js → MdxPage-DRKqyn2b.js} +5 -5
- package/lib/{MdxPage-DKMH_t0f.js.map → MdxPage-DRKqyn2b.js.map} +1 -1
- package/lib/{OperationList-35iw_Gil.js → OperationList-BHUBGM0c.js} +116 -113
- package/lib/OperationList-BHUBGM0c.js.map +1 -0
- package/lib/{Route-BsEZmkNl.js → Route-B0XuN1oC.js} +3 -3
- package/lib/{Route-BsEZmkNl.js.map → Route-B0XuN1oC.js.map} +1 -1
- package/lib/{Select-Bagt3Bme.js → Select-DYKDahHt.js} +3 -3
- package/lib/{Select-Bagt3Bme.js.map → Select-DYKDahHt.js.map} +1 -1
- package/lib/{Spinner-C6zroowC.js → SidebarBadge-Bbt92M5K.js} +16 -18
- package/lib/SidebarBadge-Bbt92M5K.js.map +1 -0
- package/lib/{SlotletProvider-Da7eFgd2.js → SlotletProvider-mhjLPG44.js} +4 -4
- package/lib/{SlotletProvider-Da7eFgd2.js.map → SlotletProvider-mhjLPG44.js.map} +1 -1
- package/lib/Spinner-ChOGyPls.js +51 -0
- package/lib/Spinner-ChOGyPls.js.map +1 -0
- package/lib/{hook-sn0zMTkE.js → hook-CjQERPa7.js} +3 -3
- package/lib/{hook-sn0zMTkE.js.map → hook-CjQERPa7.js.map} +1 -1
- package/lib/{index-BdD8UbS-.js → index-BRg5pi5D.js} +1351 -1364
- package/lib/index-BRg5pi5D.js.map +1 -0
- package/lib/{index-CRo94sKK.js → index-DM9hrcCG.js} +4 -4
- package/lib/{index-CRo94sKK.js.map → index-DM9hrcCG.js.map} +1 -1
- package/lib/state-BsPrOUAh.js +252 -0
- package/lib/state-BsPrOUAh.js.map +1 -0
- package/lib/ui/ActionButton.js +24 -0
- package/lib/ui/ActionButton.js.map +1 -0
- package/lib/urql-core-35Qt_U4i.js +1511 -0
- package/lib/{urql-core-KJnLL26g.js.map → urql-core-35Qt_U4i.js.map} +1 -1
- package/lib/{useExposedProps-ChOIUaS4.js → useExposedProps-BxyHjPNN.js} +2 -2
- package/lib/{useExposedProps-ChOIUaS4.js.map → useExposedProps-BxyHjPNN.js.map} +1 -1
- package/lib/{ZudokuContext-BKXGJTmu.js → utils-DNAltzXc.js} +153 -152
- package/lib/utils-DNAltzXc.js.map +1 -0
- package/lib/zudoku.auth-auth0.js +1 -1
- package/lib/zudoku.auth-clerk.js +2 -2
- package/lib/zudoku.auth-openid.js +4 -4
- package/lib/zudoku.components.js +690 -667
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.openapi-worker.js +737 -729
- package/lib/zudoku.openapi-worker.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +5 -5
- package/lib/zudoku.plugin-api-keys.js.map +1 -1
- package/lib/zudoku.plugin-custom-pages.js +2 -2
- package/lib/zudoku.plugin-custom-pages.js.map +1 -1
- package/lib/zudoku.plugin-markdown.js +1 -1
- package/lib/zudoku.plugin-markdown.js.map +1 -1
- package/lib/zudoku.plugin-openapi.js +6 -6
- package/lib/zudoku.plugin-redirect.js.map +1 -1
- package/lib/zudoku.plugin-search-inkeep.js +1 -1
- package/lib/zudoku.plugin-search-inkeep.js.map +1 -1
- package/package.json +2 -2
- package/src/app/entry.server.tsx +9 -5
- package/src/app/main.tsx +4 -4
- package/src/lib/authentication/authentication.ts +2 -2
- package/src/lib/authentication/state.ts +12 -5
- package/{LICENSE.md → src/lib/authentication/use-broadcast/LICENSE.md} +2 -2
- package/src/lib/authentication/use-broadcast/shared.ts +372 -0
- package/src/lib/authentication/use-broadcast/useBroadcast.ts +146 -0
- package/src/lib/components/ClientOnly.tsx +6 -3
- package/src/lib/components/Header.tsx +31 -25
- package/src/lib/components/Zudoku.tsx +113 -0
- package/src/lib/components/context/ZudokuContext.ts +3 -3
- package/src/lib/components/context/ZudokuProvider.tsx +2 -2
- package/src/lib/components/index.ts +2 -3
- package/src/lib/core/{DevPortalContext.ts → ZudokuContext.ts} +5 -5
- package/src/lib/core/plugins.ts +12 -16
- package/src/lib/plugins/api-keys/index.tsx +9 -9
- package/src/lib/plugins/custom-pages/index.tsx +2 -2
- package/src/lib/plugins/markdown/index.tsx +2 -2
- package/src/lib/plugins/openapi/CollapsibleCode.tsx +5 -8
- package/src/lib/plugins/openapi/OperationList.tsx +2 -1
- package/src/lib/plugins/openapi/ParameterListItem.tsx +37 -31
- package/src/lib/plugins/openapi/Sidecar.tsx +65 -51
- package/src/lib/plugins/openapi/client/createMemoryClient.ts +17 -3
- package/src/lib/plugins/openapi/client/createWorkerClient.ts +5 -1
- package/src/lib/plugins/openapi/index.tsx +2 -4
- package/src/lib/plugins/redirect/index.tsx +2 -2
- package/src/lib/plugins/search-inkeep/index.tsx +2 -2
- package/src/lib/ui/ActionButton.tsx +28 -0
- package/src/lib/util/useIsomorphicLayoutEffect.ts +5 -0
- package/src/lib/util/useOnScreen.ts +32 -0
- package/dist/lib/components/DevPortal.js.map +0 -1
- package/dist/lib/core/DevPortalContext.js.map +0 -1
- package/lib/ClientOnly-CVN6leDu.js.map +0 -1
- package/lib/OperationList-35iw_Gil.js.map +0 -1
- package/lib/Spinner-C6zroowC.js.map +0 -1
- package/lib/ZudokuContext-BKXGJTmu.js.map +0 -1
- package/lib/index-BdD8UbS-.js.map +0 -1
- package/lib/state-CsuHT8ZO.js +0 -183
- package/lib/state-CsuHT8ZO.js.map +0 -1
- package/lib/urql-core-KJnLL26g.js +0 -1455
- package/src/lib/components/DevPortal.tsx +0 -111
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { MDXProvider } from "@mdx-js/react";
|
|
2
|
+
import { QueryClientProvider } from "@tanstack/react-query";
|
|
3
|
+
import { Helmet } from "@zudoku/react-helmet-async";
|
|
4
|
+
import {
|
|
5
|
+
Fragment,
|
|
6
|
+
memo,
|
|
7
|
+
type PropsWithChildren,
|
|
8
|
+
useContext,
|
|
9
|
+
useEffect,
|
|
10
|
+
useMemo,
|
|
11
|
+
useState,
|
|
12
|
+
} from "react";
|
|
13
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
14
|
+
import { Outlet, useNavigation } from "react-router-dom";
|
|
15
|
+
import { hasHead, isMdxProviderPlugin } from "../core/plugins.js";
|
|
16
|
+
import {
|
|
17
|
+
queryClient,
|
|
18
|
+
ZudokuContext,
|
|
19
|
+
ZudokuContextOptions,
|
|
20
|
+
} from "../core/ZudokuContext.js";
|
|
21
|
+
import { TopLevelError } from "../errors/TopLevelError.js";
|
|
22
|
+
import { StaggeredRenderContext } from "../plugins/openapi/StaggeredRender.js";
|
|
23
|
+
import { MdxComponents } from "../util/MdxComponents.js";
|
|
24
|
+
import "../util/requestIdleCallbackPolyfill.js";
|
|
25
|
+
import {
|
|
26
|
+
ComponentsProvider,
|
|
27
|
+
DEFAULT_COMPONENTS,
|
|
28
|
+
} from "./context/ComponentsContext.js";
|
|
29
|
+
import { ThemeProvider } from "./context/ThemeProvider.js";
|
|
30
|
+
import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
|
|
31
|
+
import { ZudokuProvider } from "./context/ZudokuProvider.js";
|
|
32
|
+
import { SlotletProvider } from "./SlotletProvider.js";
|
|
33
|
+
|
|
34
|
+
const ZudokoInner = memo(
|
|
35
|
+
({ children, ...props }: PropsWithChildren<ZudokuContextOptions>) => {
|
|
36
|
+
const components = useMemo(
|
|
37
|
+
() => ({ ...DEFAULT_COMPONENTS, ...props.overrides }),
|
|
38
|
+
[props.overrides],
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const mdxComponents = useMemo(() => {
|
|
42
|
+
const componentsFromPlugins = (props.plugins ?? [])
|
|
43
|
+
.filter(isMdxProviderPlugin)
|
|
44
|
+
.flatMap((plugin) =>
|
|
45
|
+
plugin.getMdxComponents ? [plugin.getMdxComponents()] : [],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...componentsFromPlugins.reduce(
|
|
50
|
+
(acc, curr) => ({ ...acc, ...curr }),
|
|
51
|
+
{},
|
|
52
|
+
),
|
|
53
|
+
...MdxComponents,
|
|
54
|
+
...props.mdx?.components,
|
|
55
|
+
};
|
|
56
|
+
}, [props.mdx?.components, props.plugins]);
|
|
57
|
+
const { stagger } = useContext(StaggeredRenderContext);
|
|
58
|
+
const [didNavigate, setDidNavigate] = useState(false);
|
|
59
|
+
const staggeredValue = useMemo(
|
|
60
|
+
() => (didNavigate ? { stagger: true } : { stagger }),
|
|
61
|
+
[stagger, didNavigate],
|
|
62
|
+
);
|
|
63
|
+
const navigation = useNavigation();
|
|
64
|
+
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (didNavigate) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setDidNavigate(true);
|
|
70
|
+
}, [didNavigate, navigation.location]);
|
|
71
|
+
|
|
72
|
+
const [zudokuContext] = useState(() => new ZudokuContext(props));
|
|
73
|
+
|
|
74
|
+
const heads = props.plugins
|
|
75
|
+
?.filter(hasHead)
|
|
76
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
77
|
+
.map((plugin, i) => <Fragment key={i}>{plugin.getHead?.()}</Fragment>);
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<QueryClientProvider client={queryClient}>
|
|
81
|
+
<Helmet>{heads}</Helmet>
|
|
82
|
+
<StaggeredRenderContext.Provider value={staggeredValue}>
|
|
83
|
+
<ZudokuProvider context={zudokuContext}>
|
|
84
|
+
<MDXProvider components={mdxComponents}>
|
|
85
|
+
<ThemeProvider>
|
|
86
|
+
<ComponentsProvider value={components}>
|
|
87
|
+
<SlotletProvider slotlets={props.slotlets}>
|
|
88
|
+
<ViewportAnchorProvider>
|
|
89
|
+
{children ?? <Outlet />}
|
|
90
|
+
</ViewportAnchorProvider>
|
|
91
|
+
</SlotletProvider>
|
|
92
|
+
</ComponentsProvider>
|
|
93
|
+
</ThemeProvider>
|
|
94
|
+
</MDXProvider>
|
|
95
|
+
</ZudokuProvider>
|
|
96
|
+
</StaggeredRenderContext.Provider>
|
|
97
|
+
</QueryClientProvider>
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
ZudokoInner.displayName = "ZudokoInner";
|
|
103
|
+
|
|
104
|
+
const Zudoku = (props: ZudokuContextOptions) => {
|
|
105
|
+
return (
|
|
106
|
+
<ErrorBoundary FallbackComponent={TopLevelError}>
|
|
107
|
+
<ZudokoInner {...props} />
|
|
108
|
+
</ErrorBoundary>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
111
|
+
Zudoku.displayName = "Zudoku";
|
|
112
|
+
|
|
113
|
+
export { Zudoku };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
3
|
import { matchPath, useLocation } from "react-router-dom";
|
|
4
|
-
import {
|
|
4
|
+
import { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
5
5
|
import { joinPath } from "../../util/joinPath.js";
|
|
6
6
|
import { traverseSidebar } from "../navigation/utils.js";
|
|
7
7
|
|
|
8
|
-
export const ZudokuReactContext = createContext<
|
|
8
|
+
export const ZudokuReactContext = createContext<ZudokuContext | undefined>(
|
|
9
9
|
undefined,
|
|
10
10
|
);
|
|
11
11
|
|
|
@@ -13,7 +13,7 @@ export const useZudoku = () => {
|
|
|
13
13
|
const context = useContext(ZudokuReactContext);
|
|
14
14
|
|
|
15
15
|
if (!context) {
|
|
16
|
-
throw new Error("
|
|
16
|
+
throw new Error("useZudoku must be used within a ZudokuProvider.");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
return context;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import type { PropsWithChildren } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
4
4
|
import { ZudokuReactContext } from "./ZudokuContext.js";
|
|
5
5
|
|
|
6
6
|
export const ZudokuProvider = ({
|
|
7
7
|
children,
|
|
8
8
|
context,
|
|
9
|
-
}: PropsWithChildren<{ context:
|
|
9
|
+
}: PropsWithChildren<{ context: ZudokuContext }>) => {
|
|
10
10
|
useSuspenseQuery({
|
|
11
11
|
queryFn: async () => {
|
|
12
12
|
await context.initialize();
|
|
@@ -11,11 +11,10 @@ import {
|
|
|
11
11
|
BootstrapStatic as BootstrapStaticImport,
|
|
12
12
|
} from "./Bootstrap.js";
|
|
13
13
|
import { ClientOnly as ClientOnlyImport } from "./ClientOnly.js";
|
|
14
|
-
import { DevPortal as DevPortalImport } from "./DevPortal.js";
|
|
15
14
|
import { Layout as LayoutImport } from "./Layout.js";
|
|
15
|
+
import { Zudoku as ZudokuImport } from "./Zudoku.js";
|
|
16
16
|
import { useZudoku as useZudokuImport } from "./context/ZudokuContext.js";
|
|
17
17
|
export const useMDXComponents = /*@__PURE__*/ useMDXComponentsImport;
|
|
18
|
-
export const DevPortal = /*@__PURE__*/ DevPortalImport;
|
|
19
18
|
export const Layout = /*@__PURE__*/ LayoutImport;
|
|
20
19
|
export const RouterError = /*@__PURE__*/ RouterErrorImport;
|
|
21
20
|
export const ServerError = /*@__PURE__*/ ServerErrorImport;
|
|
@@ -26,7 +25,7 @@ export const Head = /*@__PURE__*/ Helmet;
|
|
|
26
25
|
|
|
27
26
|
export const useZudoku = /*@__PURE__*/ useZudokuImport;
|
|
28
27
|
export const useAuth = /*@__PURE__*/ useAuthState;
|
|
29
|
-
export const Zudoku = /*@__PURE__*/
|
|
28
|
+
export const Zudoku = /*@__PURE__*/ ZudokuImport;
|
|
30
29
|
|
|
31
30
|
export const Callout = /*@__PURE__*/ CalloutImport;
|
|
32
31
|
export const ClientOnly = /*@__PURE__*/ ClientOnlyImport;
|
|
@@ -8,11 +8,11 @@ import { Slotlets } from "../components/SlotletProvider.js";
|
|
|
8
8
|
import { joinPath } from "../util/joinPath.js";
|
|
9
9
|
import type { MdxComponentsType } from "../util/MdxComponents.js";
|
|
10
10
|
import {
|
|
11
|
-
type DevPortalPlugin,
|
|
12
11
|
isApiIdentityPlugin,
|
|
13
12
|
isNavigationPlugin,
|
|
14
13
|
type NavigationPlugin,
|
|
15
14
|
needsInitialization,
|
|
15
|
+
type ZudokuPlugin,
|
|
16
16
|
} from "./plugins.js";
|
|
17
17
|
|
|
18
18
|
export interface ApiIdentity {
|
|
@@ -24,7 +24,7 @@ export interface ApiIdentity {
|
|
|
24
24
|
export const queryClient = new QueryClient();
|
|
25
25
|
|
|
26
26
|
export type ApiKeyCache = "api-keys";
|
|
27
|
-
export type
|
|
27
|
+
export type ZudokuCacheKey = ApiKeyCache | string;
|
|
28
28
|
|
|
29
29
|
type Metadata = Partial<{
|
|
30
30
|
title: string;
|
|
@@ -63,7 +63,7 @@ export type ZudokuContextOptions = {
|
|
|
63
63
|
authentication?: AuthenticationProvider;
|
|
64
64
|
topNavigation?: TopNavigationItem[];
|
|
65
65
|
sidebars?: SidebarConfig;
|
|
66
|
-
plugins?:
|
|
66
|
+
plugins?: ZudokuPlugin[];
|
|
67
67
|
slotlets?: Slotlets;
|
|
68
68
|
mdx?: {
|
|
69
69
|
components?: MdxComponentsType;
|
|
@@ -71,7 +71,7 @@ export type ZudokuContextOptions = {
|
|
|
71
71
|
overrides?: ComponentsContextType;
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
export class
|
|
74
|
+
export class ZudokuContext {
|
|
75
75
|
public plugins: NonNullable<ZudokuContextOptions["plugins"]>;
|
|
76
76
|
public sidebars: SidebarConfig;
|
|
77
77
|
public topNavigation: NonNullable<ZudokuContextOptions["topNavigation"]>;
|
|
@@ -98,7 +98,7 @@ export class DevPortalContext {
|
|
|
98
98
|
);
|
|
99
99
|
};
|
|
100
100
|
|
|
101
|
-
invalidateCache = async (key:
|
|
101
|
+
invalidateCache = async (key: ZudokuCacheKey[]) => {
|
|
102
102
|
await queryClient.invalidateQueries({ queryKey: key });
|
|
103
103
|
};
|
|
104
104
|
|
package/src/lib/core/plugins.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { type ReactElement } from "react";
|
|
|
2
2
|
import { type RouteObject } from "react-router-dom";
|
|
3
3
|
import type { Sidebar } from "../../config/validators/SidebarSchema.js";
|
|
4
4
|
import { MdxComponentsType } from "../util/MdxComponents.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ZudokuContext, type ApiIdentity } from "./ZudokuContext.js";
|
|
6
6
|
|
|
7
|
-
export type
|
|
7
|
+
export type ZudokuPlugin =
|
|
8
8
|
| CommonPlugin
|
|
9
9
|
| ProfileMenuPlugin
|
|
10
10
|
| NavigationPlugin
|
|
@@ -19,7 +19,7 @@ export interface NavigationPlugin {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export interface ApiIdentityPlugin {
|
|
22
|
-
getIdentities: (context:
|
|
22
|
+
getIdentities: (context: ZudokuContext) => Promise<ApiIdentity[]>;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export interface SearchProviderPlugin {
|
|
@@ -30,7 +30,7 @@ export interface SearchProviderPlugin {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export interface ProfileMenuPlugin {
|
|
33
|
-
getProfileMenuItems: (context:
|
|
33
|
+
getProfileMenuItems: (context: ZudokuContext) => ProfileNavigationItem[];
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export type ProfileNavigationItem = {
|
|
@@ -41,41 +41,37 @@ export type ProfileNavigationItem = {
|
|
|
41
41
|
|
|
42
42
|
export interface CommonPlugin {
|
|
43
43
|
initialize?: (
|
|
44
|
-
context:
|
|
44
|
+
context: ZudokuContext,
|
|
45
45
|
) => Promise<void | boolean> | void | boolean;
|
|
46
46
|
getHead?: () => ReactElement | undefined;
|
|
47
47
|
getMdxComponents?: () => MdxComponentsType;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
export const isProfileMenuPlugin = (
|
|
51
|
-
obj:
|
|
51
|
+
obj: ZudokuPlugin,
|
|
52
52
|
): obj is ProfileMenuPlugin =>
|
|
53
53
|
"getProfileMenuItems" in obj && typeof obj.getProfileMenuItems === "function";
|
|
54
54
|
|
|
55
55
|
export const isNavigationPlugin = (
|
|
56
|
-
obj:
|
|
56
|
+
obj: ZudokuPlugin,
|
|
57
57
|
): obj is NavigationPlugin =>
|
|
58
58
|
"getRoutes" in obj && typeof obj.getRoutes === "function";
|
|
59
59
|
|
|
60
60
|
export const isSearchPlugin = (
|
|
61
|
-
obj:
|
|
61
|
+
obj: ZudokuPlugin,
|
|
62
62
|
): obj is SearchProviderPlugin =>
|
|
63
63
|
"renderSearch" in obj && typeof obj.renderSearch === "function";
|
|
64
64
|
|
|
65
|
-
export const needsInitialization = (
|
|
66
|
-
obj: DevPortalPlugin,
|
|
67
|
-
): obj is CommonPlugin =>
|
|
65
|
+
export const needsInitialization = (obj: ZudokuPlugin): obj is CommonPlugin =>
|
|
68
66
|
"initialize" in obj && typeof obj.initialize === "function";
|
|
69
67
|
|
|
70
|
-
export const hasHead = (obj:
|
|
68
|
+
export const hasHead = (obj: ZudokuPlugin): obj is CommonPlugin =>
|
|
71
69
|
"getHead" in obj && typeof obj.getHead === "function";
|
|
72
70
|
|
|
73
|
-
export const isMdxProviderPlugin = (
|
|
74
|
-
obj: DevPortalPlugin,
|
|
75
|
-
): obj is CommonPlugin =>
|
|
71
|
+
export const isMdxProviderPlugin = (obj: ZudokuPlugin): obj is CommonPlugin =>
|
|
76
72
|
"getMdxComponents" in obj && typeof obj.getMdxComponents === "function";
|
|
77
73
|
|
|
78
74
|
export const isApiIdentityPlugin = (
|
|
79
|
-
obj:
|
|
75
|
+
obj: ZudokuPlugin,
|
|
80
76
|
): obj is ApiIdentityPlugin =>
|
|
81
77
|
"getIdentities" in obj && typeof obj.getIdentities === "function";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type RouteObject } from "react-router-dom";
|
|
2
|
-
import {
|
|
2
|
+
import { ZudokuContext } from "../../core/ZudokuContext.js";
|
|
3
3
|
import {
|
|
4
4
|
type ApiIdentityPlugin,
|
|
5
|
-
type
|
|
5
|
+
type ZudokuPlugin,
|
|
6
6
|
ProfileMenuPlugin,
|
|
7
7
|
} from "../../core/plugins.js";
|
|
8
8
|
import { RouterError } from "../../errors/RouterError.js";
|
|
@@ -15,17 +15,17 @@ const DEFAULT_API_KEY_ENDPOINT =
|
|
|
15
15
|
"https://zudoku-rewiringamerica-main-ef9c9c0.d2.zuplo.dev";
|
|
16
16
|
|
|
17
17
|
export type ApiKeyService = {
|
|
18
|
-
getKeys: (context:
|
|
19
|
-
rollKey?: (id: string, context:
|
|
20
|
-
deleteKey?: (id: string, context:
|
|
18
|
+
getKeys: (context: ZudokuContext) => Promise<ApiKey[]>;
|
|
19
|
+
rollKey?: (id: string, context: ZudokuContext) => Promise<void>;
|
|
20
|
+
deleteKey?: (id: string, context: ZudokuContext) => Promise<void>;
|
|
21
21
|
updateKeyDescription?: (
|
|
22
22
|
apiKey: { id: string; description: string },
|
|
23
|
-
context:
|
|
23
|
+
context: ZudokuContext,
|
|
24
24
|
) => Promise<void>;
|
|
25
|
-
getUsage?: (apiKeys: string[], context:
|
|
25
|
+
getUsage?: (apiKeys: string[], context: ZudokuContext) => Promise<void>;
|
|
26
26
|
createKey?: (
|
|
27
27
|
apiKey: { description: string; expiresOn?: string },
|
|
28
|
-
context:
|
|
28
|
+
context: ZudokuContext,
|
|
29
29
|
) => Promise<void>;
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -93,7 +93,7 @@ const createDefaultHandler = (endpoint: string): ApiKeyService => {
|
|
|
93
93
|
|
|
94
94
|
export const apiKeyPlugin = (
|
|
95
95
|
options: ApiKeyPluginOptions,
|
|
96
|
-
):
|
|
96
|
+
): ZudokuPlugin & ApiIdentityPlugin & ProfileMenuPlugin => {
|
|
97
97
|
const endpoint =
|
|
98
98
|
"endpoint" in options ? options.endpoint : DEFAULT_API_KEY_ENDPOINT;
|
|
99
99
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComponentType, type ReactNode } from "react";
|
|
2
2
|
import type { RouteObject } from "react-router-dom";
|
|
3
3
|
import { type ExposedComponentProps } from "../../components/SlotletProvider.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { NavigationPlugin, ZudokuPlugin } from "../../core/plugins.js";
|
|
5
5
|
import { CustomPage } from "./CustomPage.js";
|
|
6
6
|
|
|
7
7
|
export type CustomPageConfig = {
|
|
@@ -13,7 +13,7 @@ export type CustomPageConfig = {
|
|
|
13
13
|
|
|
14
14
|
export const customPagesPlugin = (
|
|
15
15
|
config: CustomPageConfig[],
|
|
16
|
-
):
|
|
16
|
+
): ZudokuPlugin & NavigationPlugin => {
|
|
17
17
|
return {
|
|
18
18
|
getRoutes: (): RouteObject[] =>
|
|
19
19
|
config.map(({ path, ...props }) => ({
|
|
@@ -2,7 +2,7 @@ import type { Toc } from "@stefanprobst/rehype-extract-toc";
|
|
|
2
2
|
import type { MDXProps } from "mdx/types.js";
|
|
3
3
|
import { RouteObject } from "react-router-dom";
|
|
4
4
|
import { ZudokuDocsConfig } from "../../../config/validators/validate.js";
|
|
5
|
-
import type {
|
|
5
|
+
import type { ZudokuPlugin } from "../../core/plugins.js";
|
|
6
6
|
import { DocResolver } from "./resolver.js";
|
|
7
7
|
|
|
8
8
|
export interface MarkdownPluginOptions extends ZudokuDocsConfig {
|
|
@@ -29,7 +29,7 @@ export type MDXImport = {
|
|
|
29
29
|
|
|
30
30
|
export const markdownPlugin = (
|
|
31
31
|
options: MarkdownPluginOptions[],
|
|
32
|
-
):
|
|
32
|
+
): ZudokuPlugin => ({
|
|
33
33
|
getRoutes: () => {
|
|
34
34
|
const routeMap = new Map<string, RouteObject>();
|
|
35
35
|
options.forEach(({ fileImports, files, defaultOptions }) =>
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type CSSProperties,
|
|
3
|
-
type ReactNode,
|
|
4
|
-
useEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react";
|
|
1
|
+
import { type CSSProperties, type ReactNode, useRef, useState } from "react";
|
|
8
2
|
import { Button } from "zudoku/ui/Button.js";
|
|
9
3
|
import {
|
|
10
4
|
Collapsible,
|
|
@@ -12,6 +6,7 @@ import {
|
|
|
12
6
|
CollapsibleTrigger,
|
|
13
7
|
} from "zudoku/ui/Collapsible.js";
|
|
14
8
|
import { cn } from "../../util/cn.js";
|
|
9
|
+
import useIsomorphicLayoutEffect from "../../util/useIsomorphicLayoutEffect.js";
|
|
15
10
|
|
|
16
11
|
export const CollapsibleCode = ({
|
|
17
12
|
children,
|
|
@@ -24,10 +19,12 @@ export const CollapsibleCode = ({
|
|
|
24
19
|
const [isOverflowing, setIsOverflowing] = useState(false);
|
|
25
20
|
const [open, setOpen] = useState(false);
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
useIsomorphicLayoutEffect(() => {
|
|
28
23
|
const el = contentRef.current;
|
|
29
24
|
if (!el) return;
|
|
30
25
|
|
|
26
|
+
setIsOverflowing(el.scrollHeight > maxHeight);
|
|
27
|
+
|
|
31
28
|
const observer = new ResizeObserver(() => {
|
|
32
29
|
setIsOverflowing(el.scrollHeight > maxHeight);
|
|
33
30
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ResultOf } from "@graphql-typed-document-node/core";
|
|
2
|
+
import type { CSSProperties } from "react";
|
|
2
3
|
import { useQuery } from "urql";
|
|
3
4
|
import { CategoryHeading } from "../../components/CategoryHeading.js";
|
|
4
5
|
import { DeveloperHint } from "../../components/DeveloperHint.js";
|
|
@@ -154,7 +155,7 @@ export const OperationList = () => {
|
|
|
154
155
|
{result.data.schema.tags
|
|
155
156
|
.filter((tag) => tag.operations.length > 0)
|
|
156
157
|
.map((tag) => (
|
|
157
|
-
<div key={tag.name}>
|
|
158
|
+
<div key={tag.name} className="[content-visibility:auto]">
|
|
158
159
|
{tag.name && <CategoryHeading>{tag.name}</CategoryHeading>}
|
|
159
160
|
{tag.description && (
|
|
160
161
|
<Markdown
|
|
@@ -27,36 +27,42 @@ export const ParameterListItem = ({
|
|
|
27
27
|
parameter: ParameterListItemResult;
|
|
28
28
|
group: ParameterGroup;
|
|
29
29
|
id: string;
|
|
30
|
-
}) =>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
}) => {
|
|
31
|
+
const paramSchema = getParameterSchema(parameter);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<li className="p-4 bg-border/20 text-sm flex flex-col gap-1">
|
|
35
|
+
<div className="flex items-center gap-2">
|
|
36
|
+
<code>
|
|
37
|
+
{group === "path" ? (
|
|
38
|
+
<ColorizedParam
|
|
39
|
+
name={parameter.name}
|
|
40
|
+
backgroundOpacity="15%"
|
|
41
|
+
slug={id + "-" + parameter.name.toLocaleLowerCase()}
|
|
42
|
+
/>
|
|
43
|
+
) : (
|
|
44
|
+
parameter.name
|
|
45
|
+
)}
|
|
46
|
+
</code>
|
|
47
|
+
{parameter.required && (
|
|
48
|
+
<span className="py-px px-1.5 font-medium bg-primary/75 text-muted rounded-lg">
|
|
49
|
+
required
|
|
50
|
+
</span>
|
|
42
51
|
)}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
{paramSchema.type && (
|
|
53
|
+
<span className="text-muted-foreground">
|
|
54
|
+
{paramSchema.type === "array"
|
|
55
|
+
? `${paramSchema.items.type}[]`
|
|
56
|
+
: paramSchema.type}
|
|
57
|
+
</span>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
{parameter.description && (
|
|
61
|
+
<Markdown
|
|
62
|
+
content={parameter.description}
|
|
63
|
+
className="text-sm prose-p:my-1 prose-code:whitespace-pre-line"
|
|
64
|
+
/>
|
|
53
65
|
)}
|
|
54
|
-
</
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
content={parameter.description}
|
|
58
|
-
className="text-sm prose-p:my-1 prose-code:whitespace-pre-line"
|
|
59
|
-
/>
|
|
60
|
-
)}
|
|
61
|
-
</li>
|
|
62
|
-
);
|
|
66
|
+
</li>
|
|
67
|
+
);
|
|
68
|
+
};
|
|
@@ -7,6 +7,7 @@ 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
|
+
import { useOnScreen } from "../../util/useOnScreen.js";
|
|
10
11
|
import { CollapsibleCode } from "./CollapsibleCode.js";
|
|
11
12
|
import { ColorizedParam } from "./ColorizedParam.js";
|
|
12
13
|
import { useOasConfig } from "./context.js";
|
|
@@ -87,6 +88,20 @@ const methodToColor = {
|
|
|
87
88
|
trace: TextColorMap.gray,
|
|
88
89
|
};
|
|
89
90
|
|
|
91
|
+
const EXAMPLE_LANGUAGES = [
|
|
92
|
+
{ value: "shell", label: "cURL" },
|
|
93
|
+
{ value: "js", label: "JavaScript" },
|
|
94
|
+
{ value: "python", label: "Python" },
|
|
95
|
+
{ value: "java", label: "Java" },
|
|
96
|
+
{ value: "go", label: "Go" },
|
|
97
|
+
{ value: "csharp", label: "C#" },
|
|
98
|
+
{ value: "kotlin", label: "Kotlin" },
|
|
99
|
+
{ value: "objc", label: "Objective-C" },
|
|
100
|
+
{ value: "php", label: "PHP" },
|
|
101
|
+
{ value: "ruby", label: "Ruby" },
|
|
102
|
+
{ value: "swift", label: "Swift" },
|
|
103
|
+
];
|
|
104
|
+
|
|
90
105
|
export const Sidecar = ({
|
|
91
106
|
operation,
|
|
92
107
|
selectedResponse,
|
|
@@ -168,15 +183,20 @@ export const Sidecar = ({
|
|
|
168
183
|
|
|
169
184
|
return getConverted(snippet, selectedLang);
|
|
170
185
|
}, [
|
|
171
|
-
|
|
172
|
-
selectedLang,
|
|
186
|
+
requestBodyContent,
|
|
173
187
|
operation.method,
|
|
174
188
|
operation.path,
|
|
175
|
-
|
|
189
|
+
selectedServer,
|
|
190
|
+
result.data?.schema.url,
|
|
191
|
+
selectedLang,
|
|
176
192
|
]);
|
|
193
|
+
const [ref, isOnScreen] = useOnScreen({ rootMargin: "200px 0px 200px 0px" });
|
|
177
194
|
|
|
178
195
|
return (
|
|
179
|
-
<aside
|
|
196
|
+
<aside
|
|
197
|
+
ref={ref}
|
|
198
|
+
className="flex flex-col overflow-hidden sticky top-[--scroll-padding] gap-4"
|
|
199
|
+
>
|
|
180
200
|
<SidecarBox.Root>
|
|
181
201
|
<SidecarBox.Head className="flex justify-between items-center flex-nowrap py-3 gap-2 text-xs">
|
|
182
202
|
<span className="font-mono break-words">
|
|
@@ -186,57 +206,51 @@ export const Sidecar = ({
|
|
|
186
206
|
|
|
187
207
|
{path}
|
|
188
208
|
</span>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
</SidecarBox.Head>
|
|
197
|
-
<SidecarBox.Body className="p-0">
|
|
198
|
-
<CollapsibleCode>
|
|
199
|
-
<SyntaxHighlight
|
|
200
|
-
language={selectedLang}
|
|
201
|
-
noBackground
|
|
202
|
-
className="[--scrollbar-color:gray] text-xs max-h-[500px] p-2"
|
|
203
|
-
code={code!}
|
|
209
|
+
{isOnScreen && (
|
|
210
|
+
<PlaygroundDialogWrapper
|
|
211
|
+
server={result.data?.schema.url ?? ""}
|
|
212
|
+
servers={
|
|
213
|
+
result.data?.schema.servers.map((server) => server.url) ?? []
|
|
214
|
+
}
|
|
215
|
+
operation={operation}
|
|
204
216
|
/>
|
|
205
|
-
|
|
206
|
-
</SidecarBox.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
217
|
+
)}
|
|
218
|
+
</SidecarBox.Head>
|
|
219
|
+
{isOnScreen && (
|
|
220
|
+
<>
|
|
221
|
+
<SidecarBox.Body className="p-0">
|
|
222
|
+
<CollapsibleCode>
|
|
223
|
+
<SyntaxHighlight
|
|
224
|
+
language={selectedLang}
|
|
225
|
+
noBackground
|
|
226
|
+
className="[--scrollbar-color:gray] text-xs max-h-[500px] p-2"
|
|
227
|
+
code={code!}
|
|
228
|
+
/>
|
|
229
|
+
</CollapsibleCode>
|
|
230
|
+
</SidecarBox.Body>
|
|
231
|
+
<SidecarBox.Footer className="flex items-center text-xs gap-2 justify-end py-1">
|
|
232
|
+
<span>Show example in</span>
|
|
233
|
+
<SimpleSelect
|
|
234
|
+
className="self-start max-w-[150px]"
|
|
235
|
+
value={selectedLang}
|
|
236
|
+
onChange={(e) => {
|
|
237
|
+
startTransition(() => {
|
|
238
|
+
setSearchParams((prev) => {
|
|
239
|
+
prev.set("lang", e.target.value);
|
|
240
|
+
return prev;
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
}}
|
|
244
|
+
options={EXAMPLE_LANGUAGES}
|
|
245
|
+
/>
|
|
246
|
+
</SidecarBox.Footer>
|
|
247
|
+
</>
|
|
248
|
+
)}
|
|
235
249
|
</SidecarBox.Root>
|
|
236
|
-
{requestBodyContent && (
|
|
250
|
+
{isOnScreen && requestBodyContent && (
|
|
237
251
|
<RequestBodySidecarBox content={requestBodyContent} />
|
|
238
252
|
)}
|
|
239
|
-
{operation.responses.length > 0 && (
|
|
253
|
+
{isOnScreen && operation.responses.length > 0 && (
|
|
240
254
|
<ResponsesSidecarBox
|
|
241
255
|
selectedResponse={selectedResponse}
|
|
242
256
|
onSelectResponse={onSelectResponse}
|