zudoku 0.0.0-eff6f9b → 0.0.0-f3858d6
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/cli.js +2 -2
- package/dist/app/entry.client.js +2 -2
- package/dist/app/entry.client.js.map +1 -1
- package/dist/app/entry.server.js +3 -0
- package/dist/app/entry.server.js.map +1 -1
- package/dist/app/main.d.ts +1 -0
- package/dist/app/main.js +9 -24
- package/dist/app/main.js.map +1 -1
- package/dist/app/standalone.js.map +1 -1
- package/dist/cli/common/machine-id/lib.js.map +1 -1
- package/dist/cli/common/outdated.js.map +1 -1
- package/dist/cli/common/utils/box.js.map +1 -1
- package/dist/cli/dev/handler.js +2 -2
- package/dist/cli/dev/handler.js.map +1 -1
- package/dist/config/config.d.ts +2 -1
- package/dist/config/validators/InputSidebarSchema.d.ts +2 -1
- package/dist/config/validators/SidebarSchema.d.ts +1 -1
- package/dist/config/validators/SidebarSchema.js +5 -9
- package/dist/config/validators/SidebarSchema.js.map +1 -1
- package/dist/config/validators/validate.d.ts +97 -30
- package/dist/config/validators/validate.js +10 -7
- package/dist/config/validators/validate.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/authentication/state.d.ts +16 -0
- package/dist/lib/authentication/state.js +5 -0
- package/dist/lib/authentication/state.js.map +1 -1
- package/dist/lib/components/Banner.js +7 -1
- package/dist/lib/components/Banner.js.map +1 -1
- package/dist/lib/components/ErrorPage.js +1 -2
- package/dist/lib/components/ErrorPage.js.map +1 -1
- package/dist/lib/components/Header.js +5 -1
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/InlineCode.d.ts +2 -1
- package/dist/lib/components/InlineCode.js +9 -1
- package/dist/lib/components/InlineCode.js.map +1 -1
- package/dist/lib/components/Layout.js +1 -1
- package/dist/lib/components/Layout.js.map +1 -1
- package/dist/lib/components/MobileTopNavigation.js +2 -1
- package/dist/lib/components/MobileTopNavigation.js.map +1 -1
- package/dist/lib/components/SlotletProvider.d.ts +5 -2
- package/dist/lib/components/SlotletProvider.js +6 -2
- package/dist/lib/components/SlotletProvider.js.map +1 -1
- package/dist/lib/components/TopNavigation.js +30 -5
- package/dist/lib/components/TopNavigation.js.map +1 -1
- package/dist/lib/components/context/ZudokuContext.d.ts +4 -9
- package/dist/lib/components/context/ZudokuContext.js +26 -20
- package/dist/lib/components/context/ZudokuContext.js.map +1 -1
- package/dist/lib/components/index.d.ts +2 -1
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/Sidebar.js +3 -3
- package/dist/lib/components/navigation/Sidebar.js.map +1 -1
- package/dist/lib/components/navigation/SidebarCategory.js +1 -3
- package/dist/lib/components/navigation/SidebarCategory.js.map +1 -1
- package/dist/lib/components/navigation/SidebarItem.js +1 -3
- package/dist/lib/components/navigation/SidebarItem.js.map +1 -1
- package/dist/lib/components/navigation/utils.js +10 -14
- package/dist/lib/components/navigation/utils.js.map +1 -1
- package/dist/lib/core/DevPortalContext.d.ts +4 -7
- package/dist/lib/core/DevPortalContext.js.map +1 -1
- package/dist/lib/core/plugins.d.ts +1 -0
- package/dist/lib/core/plugins.js.map +1 -1
- package/dist/lib/oas/graphql/index.d.ts +2 -1
- package/dist/lib/oas/graphql/index.js +23 -15
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/oas/parser/index.d.ts +1 -0
- package/dist/lib/oas/parser/index.js.map +1 -1
- package/dist/lib/plugins/{custom-page → custom-pages}/index.d.ts +2 -2
- package/dist/lib/plugins/{custom-page → custom-pages}/index.js +1 -1
- package/dist/lib/plugins/custom-pages/index.js.map +1 -0
- package/dist/lib/plugins/markdown/MdxPage.js +2 -2
- package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
- package/dist/lib/plugins/markdown/index.d.ts +5 -6
- package/dist/lib/plugins/markdown/index.js +31 -3
- package/dist/lib/plugins/markdown/index.js.map +1 -1
- package/dist/lib/plugins/markdown/resolver.d.ts +38 -0
- package/dist/lib/plugins/markdown/resolver.js +75 -0
- package/dist/lib/plugins/markdown/resolver.js.map +1 -0
- package/dist/lib/plugins/openapi/Endpoint.d.ts +1 -3
- package/dist/lib/plugins/openapi/Endpoint.js +46 -8
- package/dist/lib/plugins/openapi/Endpoint.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +2 -2
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.d.ts +2 -1
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js +2 -2
- package/dist/lib/plugins/openapi/PlaygroundDialogWrapper.js.map +1 -1
- package/dist/lib/plugins/openapi/RequestBodySidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/Route.d.ts +1 -1
- package/dist/lib/plugins/openapi/Route.js +1 -1
- package/dist/lib/plugins/openapi/Route.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +15 -4
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/SimpleSelect.d.ts +2 -1
- package/dist/lib/plugins/openapi/SimpleSelect.js +1 -1
- package/dist/lib/plugins/openapi/SimpleSelect.js.map +1 -1
- package/dist/lib/plugins/openapi/client/createMemoryClient.js +1 -1
- package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +1 -1
- package/dist/lib/plugins/openapi/client/createWorkerClient.js +1 -1
- package/dist/lib/plugins/openapi/client/createWorkerClient.js.map +1 -1
- package/dist/lib/plugins/openapi/client/worker.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +10 -2
- 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 +26 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js +87 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/index.js +3 -2
- package/dist/lib/plugins/openapi/index.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +2 -1
- package/dist/lib/plugins/openapi/playground/Playground.js +13 -5
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/ResponseTab.js +1 -1
- package/dist/lib/plugins/openapi/playground/ResponseTab.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/createUrl.js +3 -1
- package/dist/lib/plugins/openapi/playground/createUrl.js.map +1 -1
- package/dist/lib/ui/Callout.d.ts +36 -35
- package/dist/lib/ui/Callout.js.map +1 -1
- package/dist/lib/ui/Drawer.d.ts +8 -10
- package/dist/lib/ui/Drawer.js.map +1 -1
- package/dist/lib/util/useScrollToAnchor.js.map +1 -1
- package/dist/vite/build.js +7 -2
- package/dist/vite/build.js.map +1 -1
- package/dist/vite/config.d.ts +1 -1
- package/dist/vite/config.js +22 -16
- package/dist/vite/config.js.map +1 -1
- package/dist/vite/debug.d.ts +1 -0
- package/dist/vite/debug.js +10 -0
- package/dist/vite/debug.js.map +1 -0
- package/dist/vite/dev-server.d.ts +6 -1
- package/dist/vite/dev-server.js +14 -4
- package/dist/vite/dev-server.js.map +1 -1
- package/dist/vite/plugin-api.js +4 -7
- package/dist/vite/plugin-api.js.map +1 -1
- package/dist/vite/plugin-component.js +0 -1
- package/dist/vite/plugin-component.js.map +1 -1
- package/dist/vite/plugin-config-reload.js +9 -4
- package/dist/vite/plugin-config-reload.js.map +1 -1
- package/dist/vite/plugin-custom-pages.d.ts +4 -0
- package/dist/vite/plugin-custom-pages.js +30 -0
- package/dist/vite/plugin-custom-pages.js.map +1 -0
- package/dist/vite/plugin-docs.js +26 -26
- package/dist/vite/plugin-docs.js.map +1 -1
- package/dist/vite/plugin-frontmatter.d.ts +2 -0
- package/dist/vite/plugin-frontmatter.js +30 -0
- package/dist/vite/plugin-frontmatter.js.map +1 -0
- package/dist/vite/plugin-sidebar.js +19 -3
- package/dist/vite/plugin-sidebar.js.map +1 -1
- package/dist/vite/plugin.js +4 -2
- package/dist/vite/plugin.js.map +1 -1
- package/dist/vite/prerender.d.ts +5 -1
- package/dist/vite/prerender.js +6 -5
- package/dist/vite/prerender.js.map +1 -1
- package/lib/{utils-DtEHoAvg.js → AnchorLink-DovtSBJk.js} +214 -261
- package/lib/AnchorLink-DovtSBJk.js.map +1 -0
- package/lib/{AuthenticationPlugin-gtf8JS3V.js → AuthenticationPlugin-Cnqy9csQ.js} +3 -3
- package/lib/{AuthenticationPlugin-gtf8JS3V.js.map → AuthenticationPlugin-Cnqy9csQ.js.map} +1 -1
- package/lib/{CategoryHeading-XnFqN2lJ.js → CategoryHeading-C7VfgpFZ.js} +2 -2
- package/lib/{CategoryHeading-XnFqN2lJ.js.map → CategoryHeading-C7VfgpFZ.js.map} +1 -1
- package/lib/{DeveloperHint-FBb2uXJe.js → DeveloperHint-CNyuFROc.js} +2 -2
- package/lib/{DeveloperHint-FBb2uXJe.js.map → DeveloperHint-CNyuFROc.js.map} +1 -1
- package/lib/ErrorPage-CUz-Zzmx.js +16 -0
- package/lib/ErrorPage-CUz-Zzmx.js.map +1 -0
- package/lib/Input-x-t53FyR.js +2229 -0
- package/lib/Input-x-t53FyR.js.map +1 -0
- package/lib/{Markdown-B4aR03g6.js → Markdown-C-0TaxoY.js} +1448 -1286
- package/lib/Markdown-C-0TaxoY.js.map +1 -0
- package/lib/{MdxPage-BcftTg5g.js → MdxPage-C5I9c7R1.js} +19 -18
- package/lib/MdxPage-C5I9c7R1.js.map +1 -0
- package/lib/{OperationList-Da36LrGl.js → OperationList-qsBOguHS.js} +149 -108
- package/lib/OperationList-qsBOguHS.js.map +1 -0
- package/lib/{Route-CWj1ECzh.js → Route-DlKvXPAO.js} +3 -4
- package/lib/Route-DlKvXPAO.js.map +1 -0
- package/lib/SidebarBadge-DaA0-bFW.js +503 -0
- package/lib/SidebarBadge-DaA0-bFW.js.map +1 -0
- package/lib/{SlotletProvider-DJMaOUDs.js → SlotletProvider-BGEs7yyu.js} +28 -26
- package/lib/{SlotletProvider-DJMaOUDs.js.map → SlotletProvider-BGEs7yyu.js.map} +1 -1
- package/lib/ZudokuContext-DSipF8sq.js +1222 -0
- package/lib/ZudokuContext-DSipF8sq.js.map +1 -0
- package/lib/__vite-browser-external-BYRIRx8p.js +9 -0
- package/lib/__vite-browser-external-BYRIRx8p.js.map +1 -0
- package/lib/assets/{index-B9EWVYfo.js → index-B_Jk_Yzp.js} +968 -938
- package/lib/assets/index-B_Jk_Yzp.js.map +1 -0
- package/lib/assets/{worker-TYRbYl6N.js → worker-DaFlmuyf.js} +6549 -4277
- package/lib/assets/worker-DaFlmuyf.js.map +1 -0
- package/lib/{index-DIkaYL-l.js → index-BIl-R3aH.js} +1943 -1675
- package/lib/index-BIl-R3aH.js.map +1 -0
- package/lib/{index-B_9xr661.js → index-CKmSo0py.js} +3 -3
- package/lib/{index-B_9xr661.js.map → index-CKmSo0py.js.map} +1 -1
- package/lib/{index-CLd8ycZz.js → index-CkwDvuPt.js} +947 -917
- package/lib/index-CkwDvuPt.js.map +1 -0
- package/lib/index-D06ATMgg.js +2094 -0
- package/lib/index-D06ATMgg.js.map +1 -0
- package/lib/index-DJqnphbT.js +35 -0
- package/lib/index-DJqnphbT.js.map +1 -0
- package/lib/{index-BoXX7LeD.js → index-Dssw7Gff.js} +597 -544
- package/lib/index-Dssw7Gff.js.map +1 -0
- package/lib/{index-BG0g4WW0.js → index-SrtqdZ3j.js} +746 -736
- package/lib/index-SrtqdZ3j.js.map +1 -0
- package/lib/router-Oe6YmY6B.js +3024 -0
- package/lib/router-Oe6YmY6B.js.map +1 -0
- package/lib/state-CsuHT8ZO.js +183 -0
- package/lib/state-CsuHT8ZO.js.map +1 -0
- package/lib/urql-core-KJnLL26g.js +1455 -0
- package/lib/urql-core-KJnLL26g.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 +363 -350
- package/lib/zudoku.auth-openid.js.map +1 -1
- package/lib/zudoku.components.js +1717 -1633
- package/lib/zudoku.components.js.map +1 -1
- package/lib/zudoku.openapi-worker.js +4485 -4283
- package/lib/zudoku.openapi-worker.js.map +1 -1
- package/lib/zudoku.plugin-api-keys.js +7 -7
- package/lib/{zudoku.plugin-custom-page.js → zudoku.plugin-custom-pages.js} +3 -3
- package/lib/zudoku.plugin-custom-pages.js.map +1 -0
- package/lib/zudoku.plugin-markdown.js +93 -27
- package/lib/zudoku.plugin-markdown.js.map +1 -1
- package/lib/zudoku.plugin-openapi.js +8 -8
- package/lib/zudoku.plugin-redirect.js +1 -1
- package/package.json +71 -69
- package/src/app/entry.client.tsx +4 -2
- package/src/app/entry.server.tsx +4 -0
- package/src/app/main.css +4 -0
- package/src/app/main.tsx +12 -28
- package/src/app/standalone.tsx +1 -1
- package/src/lib/authentication/state.ts +17 -0
- package/src/lib/components/Banner.tsx +12 -2
- package/src/lib/components/ErrorPage.tsx +0 -2
- package/src/lib/components/Header.tsx +13 -3
- package/src/lib/components/InlineCode.tsx +10 -0
- package/src/lib/components/Layout.tsx +2 -1
- package/src/lib/components/MobileTopNavigation.tsx +2 -0
- package/src/lib/components/SlotletProvider.tsx +20 -4
- package/src/lib/components/TopNavigation.tsx +58 -24
- package/src/lib/components/context/ZudokuContext.ts +28 -20
- package/src/lib/components/index.ts +1 -1
- package/src/lib/components/navigation/Sidebar.tsx +5 -5
- package/src/lib/components/navigation/SidebarCategory.tsx +1 -3
- package/src/lib/components/navigation/SidebarItem.tsx +1 -3
- package/src/lib/components/navigation/utils.ts +11 -16
- package/src/lib/core/DevPortalContext.ts +4 -3
- package/src/lib/core/plugins.ts +2 -0
- package/src/lib/oas/graphql/index.ts +35 -23
- package/src/lib/oas/parser/index.ts +1 -0
- package/src/lib/plugins/{custom-page → custom-pages}/index.tsx +3 -3
- package/src/lib/plugins/markdown/MdxPage.tsx +2 -2
- package/src/lib/plugins/markdown/index.tsx +49 -12
- package/src/lib/plugins/markdown/resolver.ts +92 -0
- package/src/lib/plugins/openapi/Endpoint.tsx +86 -22
- package/src/lib/plugins/openapi/OperationList.tsx +4 -2
- package/src/lib/plugins/openapi/PlaygroundDialogWrapper.tsx +3 -0
- package/src/lib/plugins/openapi/RequestBodySidecarBox.tsx +1 -1
- package/src/lib/plugins/openapi/Route.tsx +1 -2
- package/src/lib/plugins/openapi/Sidecar.tsx +19 -4
- package/src/lib/plugins/openapi/SimpleSelect.tsx +10 -2
- package/src/lib/plugins/openapi/client/createMemoryClient.ts +1 -6
- package/src/lib/plugins/openapi/client/createWorkerClient.ts +1 -6
- package/src/lib/plugins/openapi/client/worker.ts +2 -2
- package/src/lib/plugins/openapi/graphql/gql.ts +11 -3
- package/src/lib/plugins/openapi/graphql/graphql.ts +113 -1
- package/src/lib/plugins/openapi/index.tsx +4 -7
- package/src/lib/plugins/openapi/playground/Playground.tsx +39 -5
- package/src/lib/plugins/openapi/playground/ResponseTab.tsx +0 -1
- package/src/lib/plugins/openapi/playground/createUrl.ts +6 -1
- package/src/lib/ui/Callout.tsx +7 -6
- package/src/lib/ui/Drawer.tsx +38 -36
- package/src/lib/util/useScrollToAnchor.ts +1 -1
- package/dist/lib/plugins/custom-page/index.js.map +0 -1
- package/dist/lib/plugins/markdown/generateRoutes.d.ts +0 -3
- package/dist/lib/plugins/markdown/generateRoutes.js +0 -21
- package/dist/lib/plugins/markdown/generateRoutes.js.map +0 -1
- package/dist/lib/plugins/openapi/playground/Editor.d.ts +0 -1
- package/dist/lib/plugins/openapi/playground/Editor.js +0 -5
- package/dist/lib/plugins/openapi/playground/Editor.js.map +0 -1
- package/dist/lib/plugins/openapi/util/urql.d.ts +0 -7
- package/dist/lib/plugins/openapi/util/urql.js +0 -8
- package/dist/lib/plugins/openapi/util/urql.js.map +0 -1
- package/dist/lib/util/slugify.d.ts +0 -2
- package/dist/lib/util/slugify.js +0 -3
- package/dist/lib/util/slugify.js.map +0 -1
- package/dist/vite/plugin-icons.d.ts +0 -3
- package/dist/vite/plugin-icons.js +0 -47
- package/dist/vite/plugin-icons.js.map +0 -1
- package/lib/ErrorPage-knunPbKI.js +0 -18
- package/lib/ErrorPage-knunPbKI.js.map +0 -1
- package/lib/Input-B1kkVL1R.js +0 -2198
- package/lib/Input-B1kkVL1R.js.map +0 -1
- package/lib/Markdown-B4aR03g6.js.map +0 -1
- package/lib/MdxPage-BcftTg5g.js.map +0 -1
- package/lib/OperationList-Da36LrGl.js.map +0 -1
- package/lib/Route-CWj1ECzh.js.map +0 -1
- package/lib/SidebarBadge-DdvT2qep.js +0 -498
- package/lib/SidebarBadge-DdvT2qep.js.map +0 -1
- package/lib/ZudokuContext-em1gHkIY.js +0 -1084
- package/lib/ZudokuContext-em1gHkIY.js.map +0 -1
- package/lib/_commonjsHelpers-BkfeUUK-.js +0 -29
- package/lib/_commonjsHelpers-BkfeUUK-.js.map +0 -1
- package/lib/assets/index-B9EWVYfo.js.map +0 -1
- package/lib/assets/worker-TYRbYl6N.js.map +0 -1
- package/lib/index-BG0g4WW0.js.map +0 -1
- package/lib/index-BoXX7LeD.js.map +0 -1
- package/lib/index-CLd8ycZz.js.map +0 -1
- package/lib/index-DIkaYL-l.js.map +0 -1
- package/lib/router-D2p7Olpn.js +0 -2971
- package/lib/router-D2p7Olpn.js.map +0 -1
- package/lib/slugify-DbLhpSPt.js +0 -28
- package/lib/slugify-DbLhpSPt.js.map +0 -1
- package/lib/state-BUM4jc0J.js +0 -288
- package/lib/state-BUM4jc0J.js.map +0 -1
- package/lib/urql-YhcsXYy8.js +0 -1591
- package/lib/urql-YhcsXYy8.js.map +0 -1
- package/lib/utils-DtEHoAvg.js.map +0 -1
- package/lib/zudoku.plugin-custom-page.js.map +0 -1
- package/src/lib/plugins/markdown/generateRoutes.tsx +0 -38
- package/src/lib/plugins/openapi/playground/Editor.tsx +0 -4
- package/src/lib/plugins/openapi/util/urql.ts +0 -8
- package/src/lib/util/slugify.ts +0 -3
|
@@ -70,14 +70,22 @@ export const Header = memo(function HeaderInner() {
|
|
|
70
70
|
{page?.logo && (
|
|
71
71
|
<>
|
|
72
72
|
<img
|
|
73
|
-
src={
|
|
73
|
+
src={
|
|
74
|
+
/https?:\/\//.test(page.logo.src.light)
|
|
75
|
+
? page.logo.src.light
|
|
76
|
+
: import.meta.env.BASE_URL + page.logo.src.light
|
|
77
|
+
}
|
|
74
78
|
alt={page.logo.alt ?? page.pageTitle}
|
|
75
79
|
style={{ width: page.logo.width }}
|
|
76
80
|
className={cn("h-10", isDark && "hidden")}
|
|
77
81
|
loading="lazy"
|
|
78
82
|
/>
|
|
79
83
|
<img
|
|
80
|
-
src={
|
|
84
|
+
src={
|
|
85
|
+
/https?:\/\//.test(page.logo.src.dark)
|
|
86
|
+
? page.logo.src.dark
|
|
87
|
+
: import.meta.env.BASE_URL + page.logo.src.dark
|
|
88
|
+
}
|
|
81
89
|
alt={page.logo.alt ?? page.pageTitle}
|
|
82
90
|
style={{ width: page.logo.width }}
|
|
83
91
|
className={cn("h-10", !isDark && "hidden")}
|
|
@@ -92,7 +100,7 @@ export const Header = memo(function HeaderInner() {
|
|
|
92
100
|
</Link>
|
|
93
101
|
</div>
|
|
94
102
|
<div className="grid grid-cols-2 md:grid-cols-[--sidecar-grid-cols] items-center gap-8">
|
|
95
|
-
<div className="w-full justify-center flex">
|
|
103
|
+
<div className="w-full justify-center hidden md:flex ">
|
|
96
104
|
<Search />
|
|
97
105
|
</div>
|
|
98
106
|
|
|
@@ -133,7 +141,9 @@ export const Header = memo(function HeaderInner() {
|
|
|
133
141
|
</div>
|
|
134
142
|
</div>
|
|
135
143
|
</div>
|
|
144
|
+
<Slotlet name="top-navigation-before" />
|
|
136
145
|
<TopNavigation />
|
|
146
|
+
<Slotlet name="top-navigation-after" />
|
|
137
147
|
</div>
|
|
138
148
|
</header>
|
|
139
149
|
);
|
|
@@ -4,11 +4,21 @@ import { cn } from "../util/cn.js";
|
|
|
4
4
|
export const InlineCode = ({
|
|
5
5
|
className,
|
|
6
6
|
children,
|
|
7
|
+
selectOnClick,
|
|
7
8
|
}: {
|
|
8
9
|
className?: string;
|
|
9
10
|
children: ReactNode;
|
|
11
|
+
selectOnClick?: boolean;
|
|
10
12
|
}) => (
|
|
11
13
|
<code
|
|
14
|
+
onClick={(e) => {
|
|
15
|
+
if (!selectOnClick) return;
|
|
16
|
+
const selection = window.getSelection();
|
|
17
|
+
const range = document.createRange();
|
|
18
|
+
range.selectNodeContents(e.currentTarget);
|
|
19
|
+
selection?.removeAllRanges();
|
|
20
|
+
selection?.addRange(range);
|
|
21
|
+
}}
|
|
12
22
|
className={cn(
|
|
13
23
|
"font-mono border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 whitespace-nowrap",
|
|
14
24
|
className,
|
|
@@ -49,11 +49,12 @@ export const Layout = ({ children }: { children?: ReactNode }) => {
|
|
|
49
49
|
</Helmet>
|
|
50
50
|
<Slotlet name="layout-before-head" />
|
|
51
51
|
<Header />
|
|
52
|
+
<Slotlet name="layout-after-head" />
|
|
52
53
|
|
|
53
54
|
<div className="w-full max-w-screen-2xl mx-auto px-10 lg:px-12">
|
|
54
55
|
<Suspense
|
|
55
56
|
fallback={
|
|
56
|
-
<main className="grid h-
|
|
57
|
+
<main className="grid h-[calc(100vh-var(--header-height))] place-items-center">
|
|
57
58
|
<Spinner />
|
|
58
59
|
</main>
|
|
59
60
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
DrawerTrigger,
|
|
11
11
|
} from "../ui/Drawer.js";
|
|
12
12
|
import { useZudoku } from "./context/ZudokuContext.js";
|
|
13
|
+
import { Search } from "./Search.js";
|
|
13
14
|
|
|
14
15
|
export const MobileTopNavigation = () => {
|
|
15
16
|
const { topNavigation } = useZudoku();
|
|
@@ -27,6 +28,7 @@ export const MobileTopNavigation = () => {
|
|
|
27
28
|
<VisuallyHidden>
|
|
28
29
|
<DrawerTitle>Navigation</DrawerTitle>
|
|
29
30
|
</VisuallyHidden>
|
|
31
|
+
<Search />
|
|
30
32
|
<ul className="flex flex-col items-center gap-4 p-4">
|
|
31
33
|
{topNavigation.map((item) => (
|
|
32
34
|
<li key={item.label}>
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
type ComponentType,
|
|
3
|
+
type ReactElement,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useContext,
|
|
6
|
+
} from "react";
|
|
2
7
|
import { isValidElementType } from "react-is";
|
|
3
|
-
|
|
8
|
+
import { useLocation } from "react-router-dom";
|
|
9
|
+
export type Slotlets = Record<
|
|
10
|
+
string,
|
|
11
|
+
ReactNode | ReactElement | ComponentType<SlotletComponentProps>
|
|
12
|
+
>;
|
|
4
13
|
|
|
5
14
|
const SlotletContext = React.createContext<Slotlets | undefined>({});
|
|
6
15
|
|
|
@@ -18,13 +27,20 @@ export const SlotletProvider = ({
|
|
|
18
27
|
);
|
|
19
28
|
};
|
|
20
29
|
|
|
30
|
+
export type SlotletComponentProps = {
|
|
31
|
+
location: Location;
|
|
32
|
+
};
|
|
33
|
+
|
|
21
34
|
export const Slotlet = ({ name }: { name: string }) => {
|
|
22
35
|
const context = useContext(SlotletContext);
|
|
23
36
|
const componentOrElement = context?.[name];
|
|
37
|
+
const location = useLocation();
|
|
24
38
|
|
|
25
39
|
if (isValidElementType(componentOrElement)) {
|
|
26
|
-
return React.createElement(componentOrElement
|
|
40
|
+
return React.createElement(componentOrElement, {
|
|
41
|
+
location,
|
|
42
|
+
});
|
|
27
43
|
}
|
|
28
44
|
|
|
29
|
-
return componentOrElement;
|
|
45
|
+
return componentOrElement as ReactNode;
|
|
30
46
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { cx } from "class-variance-authority";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
2
|
+
import { Suspense } from "react";
|
|
3
|
+
import { Link } from "react-router-dom";
|
|
4
|
+
import { TopNavigationItem } from "../../config/validators/validate.js";
|
|
5
|
+
import { joinPath } from "../util/joinPath.js";
|
|
6
|
+
import { useCurrentNavigation, useZudoku } from "./context/ZudokuContext.js";
|
|
7
|
+
import { traverseSidebar } from "./navigation/utils.js";
|
|
5
8
|
|
|
6
9
|
export const TopNavigation = () => {
|
|
7
10
|
const { topNavigation } = useZudoku();
|
|
@@ -12,26 +15,57 @@ export const TopNavigation = () => {
|
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
return (
|
|
15
|
-
<
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
18
|
+
<Suspense>
|
|
19
|
+
<nav className="hidden lg:block border-b text-sm px-12 h-[--top-nav-height]">
|
|
20
|
+
<ul className="flex flex-row items-center gap-8">
|
|
21
|
+
{topNavigation.map((item) => (
|
|
22
|
+
<li key={item.id}>
|
|
23
|
+
<TopNavItem {...item} />
|
|
24
|
+
</li>
|
|
25
|
+
))}
|
|
26
|
+
</ul>
|
|
27
|
+
</nav>
|
|
28
|
+
</Suspense>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const TopNavItem = ({ id, label, default: defaultLink }: TopNavigationItem) => {
|
|
33
|
+
const { sidebars } = useZudoku();
|
|
34
|
+
const nav = useCurrentNavigation();
|
|
35
|
+
const currentSidebar = sidebars[id];
|
|
36
|
+
|
|
37
|
+
// TODO: This is a bit of a hack to get the first link in the sidebar
|
|
38
|
+
// We should really process this when we load the config so we can validate
|
|
39
|
+
// that the sidebar is actually set. In this case we just fall back to linking
|
|
40
|
+
// to the id if we can't resolve a sidebar.
|
|
41
|
+
const first =
|
|
42
|
+
defaultLink ??
|
|
43
|
+
(currentSidebar
|
|
44
|
+
? traverseSidebar(currentSidebar, (item) => {
|
|
45
|
+
if (item.type === "doc") return joinPath(item.id);
|
|
46
|
+
})
|
|
47
|
+
: joinPath(id));
|
|
48
|
+
|
|
49
|
+
if (!first) {
|
|
50
|
+
throw new Error(
|
|
51
|
+
`No links found in top navigation for top navigation '${id}'. Check that the sidebar isn't empty or that a default link set.`,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Manually set the active sidebar based on our logic of what is active
|
|
56
|
+
const isActive = nav.data.topNavItem?.id === id;
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<Link
|
|
60
|
+
className={cx(
|
|
61
|
+
"block py-3.5 font-medium -mb-px border-b-2",
|
|
62
|
+
isActive
|
|
63
|
+
? "border-primary text-foreground"
|
|
64
|
+
: "border-transparent text-foreground/75 hover:text-foreground hover:border-accent-foreground/25",
|
|
65
|
+
)}
|
|
66
|
+
to={first}
|
|
67
|
+
>
|
|
68
|
+
{label}
|
|
69
|
+
</Link>
|
|
36
70
|
);
|
|
37
71
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { useQuery, useSuspenseQuery } from "@tanstack/react-query";
|
|
2
2
|
import { createContext, useContext } from "react";
|
|
3
|
-
import { useLocation } from "react-router-dom";
|
|
3
|
+
import { matchPath, useLocation } from "react-router-dom";
|
|
4
4
|
import { DevPortalContext } from "../../core/DevPortalContext.js";
|
|
5
|
+
import { joinPath } from "../../util/joinPath.js";
|
|
6
|
+
import { traverseSidebar } from "../navigation/utils.js";
|
|
5
7
|
|
|
6
8
|
export const ZudokuReactContext = createContext<DevPortalContext | undefined>(
|
|
7
9
|
undefined,
|
|
@@ -25,34 +27,40 @@ export const useApiIdentities = () => {
|
|
|
25
27
|
});
|
|
26
28
|
};
|
|
27
29
|
|
|
28
|
-
export const
|
|
29
|
-
const { topNavigation } = useZudoku();
|
|
30
|
+
export const useCurrentNavigation = () => {
|
|
31
|
+
const { getPluginSidebar, sidebars, topNavigation } = useZudoku();
|
|
30
32
|
const location = useLocation();
|
|
31
33
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
+
const currentSidebarItem = Object.entries(sidebars).find(([, sidebar]) => {
|
|
35
|
+
return traverseSidebar(sidebar, (item) => {
|
|
36
|
+
const itemId =
|
|
37
|
+
item.type === "doc"
|
|
38
|
+
? joinPath(item.id)
|
|
39
|
+
: item.type === "category" && item.link
|
|
40
|
+
? joinPath(item.link.id)
|
|
41
|
+
: undefined;
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const location = useLocation();
|
|
43
|
+
if (itemId === location.pathname) {
|
|
44
|
+
return item;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
const currentTopNavItem =
|
|
49
|
+
topNavigation.find((t) => t.id === currentSidebarItem?.[0]) ??
|
|
50
|
+
topNavigation.find((item) => matchPath(item.id, location.pathname));
|
|
44
51
|
|
|
45
52
|
return useSuspenseQuery({
|
|
46
53
|
queryFn: async () => {
|
|
47
|
-
const pluginSidebar =
|
|
48
|
-
? await getPluginSidebar(path)
|
|
49
|
-
: await getPluginSidebar(location.pathname);
|
|
54
|
+
const pluginSidebar = await getPluginSidebar(location.pathname);
|
|
50
55
|
|
|
51
56
|
return {
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
sidebar: [
|
|
58
|
+
...(currentSidebarItem ? currentSidebarItem[1] : []),
|
|
59
|
+
...pluginSidebar,
|
|
60
|
+
],
|
|
61
|
+
topNavItem: currentTopNavItem,
|
|
54
62
|
};
|
|
55
63
|
},
|
|
56
|
-
queryKey: ["navigation",
|
|
64
|
+
queryKey: ["navigation", location.pathname],
|
|
57
65
|
});
|
|
58
66
|
};
|
|
@@ -16,7 +16,7 @@ export const useMDXComponents = /*@__PURE__*/ useMDXComponentsImport;
|
|
|
16
16
|
export const Callout = /*@__PURE__*/ CalloutImport;
|
|
17
17
|
export const DevPortal = /*@__PURE__*/ DevPortalImport;
|
|
18
18
|
export const Layout = /*@__PURE__*/ LayoutImport;
|
|
19
|
-
export const Link = /*@__PURE__*/ LinkImport;
|
|
19
|
+
export const Link: typeof LinkImport = /*@__PURE__*/ LinkImport;
|
|
20
20
|
export const RouterError = /*@__PURE__*/ RouterErrorImport;
|
|
21
21
|
export const ServerError = /*@__PURE__*/ ServerErrorImport;
|
|
22
22
|
export const Bootstrap = /*@__PURE__*/ BootstrapImport;
|
|
@@ -2,23 +2,23 @@ import { useRef } from "react";
|
|
|
2
2
|
|
|
3
3
|
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
|
4
4
|
import { DrawerContent, DrawerTitle } from "../../ui/Drawer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { useCurrentNavigation } from "../context/ZudokuContext.js";
|
|
6
6
|
import { Slotlet } from "../SlotletProvider.js";
|
|
7
7
|
import { SidebarItem } from "./SidebarItem.js";
|
|
8
8
|
import { SidebarWrapper } from "./SidebarWrapper.js";
|
|
9
9
|
|
|
10
10
|
export const Sidebar = () => {
|
|
11
11
|
const navRef = useRef<HTMLDivElement | null>(null);
|
|
12
|
-
const navigation =
|
|
12
|
+
const navigation = useCurrentNavigation();
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
15
|
<>
|
|
16
16
|
<SidebarWrapper
|
|
17
17
|
ref={navRef}
|
|
18
|
-
pushMainContent={navigation.data.
|
|
18
|
+
pushMainContent={navigation.data.sidebar.length > 0}
|
|
19
19
|
>
|
|
20
20
|
<Slotlet name="zudoku-before-navigation" />
|
|
21
|
-
{navigation.data.
|
|
21
|
+
{navigation.data.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.data.
|
|
33
|
+
{navigation.data.sidebar.map((item) => (
|
|
34
34
|
<SidebarItem key={item.label} item={item} />
|
|
35
35
|
))}
|
|
36
36
|
</DrawerContent>
|
|
@@ -5,7 +5,6 @@ import { NavLink } from "react-router-dom";
|
|
|
5
5
|
import type { SidebarItemCategory } from "../../../config/validators/SidebarSchema.js";
|
|
6
6
|
import { cn } from "../../util/cn.js";
|
|
7
7
|
import { joinPath } from "../../util/joinPath.js";
|
|
8
|
-
import { useTopNavigationItem } from "../context/ZudokuContext.js";
|
|
9
8
|
import { navigationListItem, SidebarItem } from "./SidebarItem.js";
|
|
10
9
|
import { useIsCategoryOpen } from "./utils.js";
|
|
11
10
|
|
|
@@ -16,7 +15,6 @@ export const SidebarCategory = ({
|
|
|
16
15
|
category: SidebarItemCategory;
|
|
17
16
|
level: number;
|
|
18
17
|
}) => {
|
|
19
|
-
const topNavItem = useTopNavigationItem();
|
|
20
18
|
const isCategoryOpen = useIsCategoryOpen(category);
|
|
21
19
|
const [hasInteracted, setHasInteracted] = useState(false);
|
|
22
20
|
|
|
@@ -79,7 +77,7 @@ export const SidebarCategory = ({
|
|
|
79
77
|
)}
|
|
80
78
|
{category.link?.type === "doc" ? (
|
|
81
79
|
<NavLink
|
|
82
|
-
to={joinPath(
|
|
80
|
+
to={joinPath(category.link.id)}
|
|
83
81
|
className="flex-1"
|
|
84
82
|
onClick={() => setHasInteracted(true)}
|
|
85
83
|
>
|
|
@@ -7,7 +7,6 @@ import { cn } from "../../util/cn.js";
|
|
|
7
7
|
import { joinPath } from "../../util/joinPath.js";
|
|
8
8
|
import { AnchorLink } from "../AnchorLink.js";
|
|
9
9
|
import { useViewportAnchor } from "../context/ViewportAnchorContext.js";
|
|
10
|
-
import { useTopNavigationItem } from "../context/ZudokuContext.js";
|
|
11
10
|
import { SidebarBadge } from "./SidebarBadge.js";
|
|
12
11
|
import { SidebarCategory } from "./SidebarCategory.js";
|
|
13
12
|
|
|
@@ -40,7 +39,6 @@ export const SidebarItem = ({
|
|
|
40
39
|
basePath?: string;
|
|
41
40
|
level?: number;
|
|
42
41
|
}) => {
|
|
43
|
-
const topNavItem = useTopNavigationItem();
|
|
44
42
|
const { activeAnchor } = useViewportAnchor();
|
|
45
43
|
const [searchParams] = useSearchParams();
|
|
46
44
|
|
|
@@ -53,7 +51,7 @@ export const SidebarItem = ({
|
|
|
53
51
|
className={({ isActive }) =>
|
|
54
52
|
navigationListItem({ isActive, isTopLevel: level === 0 })
|
|
55
53
|
}
|
|
56
|
-
to={joinPath(
|
|
54
|
+
to={joinPath(item.id)}
|
|
57
55
|
>
|
|
58
56
|
{item.icon && <item.icon size={16} className="align-[-0.125em]" />}
|
|
59
57
|
{item.badge ? (
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
SidebarItemCategory,
|
|
5
5
|
} from "../../../config/validators/SidebarSchema.js";
|
|
6
6
|
import { joinPath } from "../../util/joinPath.js";
|
|
7
|
-
import {
|
|
7
|
+
import { useCurrentNavigation } from "../context/ZudokuContext.js";
|
|
8
8
|
|
|
9
9
|
export type TraverseCallback<T> = (
|
|
10
10
|
item: SidebarItem,
|
|
@@ -42,15 +42,12 @@ export const traverseSidebarItem = <T>(
|
|
|
42
42
|
|
|
43
43
|
export const useCurrentItem = () => {
|
|
44
44
|
const location = useLocation();
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
const currentSidebar =
|
|
45
|
+
const nav = useCurrentNavigation();
|
|
46
|
+
|
|
47
|
+
const currentSidebar = nav.data.sidebar;
|
|
48
48
|
|
|
49
49
|
return traverseSidebar(currentSidebar, (item) => {
|
|
50
|
-
if (
|
|
51
|
-
item.type === "doc" &&
|
|
52
|
-
joinPath(topNavItem?.id, item.id) === location.pathname
|
|
53
|
-
) {
|
|
50
|
+
if (item.type === "doc" && joinPath(item.id) === location.pathname) {
|
|
54
51
|
return item;
|
|
55
52
|
}
|
|
56
53
|
});
|
|
@@ -58,18 +55,17 @@ export const useCurrentItem = () => {
|
|
|
58
55
|
|
|
59
56
|
export const useIsCategoryOpen = (category: SidebarItemCategory) => {
|
|
60
57
|
const location = useLocation();
|
|
61
|
-
const topNavItem = useTopNavigationItem();
|
|
62
58
|
|
|
63
59
|
return traverseSidebarItem(category, (item) => {
|
|
64
60
|
if (item.type === "category" && item.link) {
|
|
65
|
-
const categoryLinkPath = joinPath(
|
|
61
|
+
const categoryLinkPath = joinPath(item.link.id);
|
|
66
62
|
if (categoryLinkPath === location.pathname) {
|
|
67
63
|
return true;
|
|
68
64
|
}
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
if (item.type === "doc") {
|
|
72
|
-
const docPath = joinPath(
|
|
68
|
+
const docPath = joinPath(item.id);
|
|
73
69
|
if (docPath === location.pathname) {
|
|
74
70
|
return true;
|
|
75
71
|
}
|
|
@@ -82,9 +78,8 @@ export const usePrevNext = (): {
|
|
|
82
78
|
next?: { label: string; id: string };
|
|
83
79
|
} => {
|
|
84
80
|
const currentId = useLocation().pathname;
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const currentSidebar = topNavItem?.id ? sidebars[topNavItem.id] : [];
|
|
81
|
+
const nav = useCurrentNavigation();
|
|
82
|
+
const currentSidebar = nav.data.sidebar;
|
|
88
83
|
|
|
89
84
|
let prev;
|
|
90
85
|
let next;
|
|
@@ -94,9 +89,9 @@ export const usePrevNext = (): {
|
|
|
94
89
|
traverseSidebar(currentSidebar, (item) => {
|
|
95
90
|
const itemId =
|
|
96
91
|
item.type === "doc"
|
|
97
|
-
? joinPath(
|
|
92
|
+
? joinPath(item.id)
|
|
98
93
|
: item.type === "category" && item.link
|
|
99
|
-
? joinPath(
|
|
94
|
+
? joinPath(item.link.id)
|
|
100
95
|
: undefined;
|
|
101
96
|
|
|
102
97
|
if (!itemId) return;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryClient } from "@tanstack/react-query";
|
|
2
2
|
import { ReactNode } from "react";
|
|
3
3
|
import type { SidebarConfig } from "../../config/validators/SidebarSchema.js";
|
|
4
|
+
import { TopNavigationItem } from "../../config/validators/validate.js";
|
|
4
5
|
import { type AuthenticationProvider } from "../authentication/authentication.js";
|
|
5
6
|
import type { ComponentsContextType } from "../components/context/ComponentsContext.js";
|
|
6
7
|
import { Slotlets } from "../components/SlotletProvider.js";
|
|
@@ -51,7 +52,7 @@ type Page = Partial<{
|
|
|
51
52
|
};
|
|
52
53
|
banner?: {
|
|
53
54
|
message: ReactNode;
|
|
54
|
-
color?: "note" | "tip" | "info" | "caution" | "danger";
|
|
55
|
+
color?: "note" | "tip" | "info" | "caution" | "danger" | (string & {});
|
|
55
56
|
dismissible?: boolean;
|
|
56
57
|
};
|
|
57
58
|
}>;
|
|
@@ -60,7 +61,7 @@ export type ZudokuContextOptions = {
|
|
|
60
61
|
metadata?: Metadata;
|
|
61
62
|
page?: Page;
|
|
62
63
|
authentication?: AuthenticationProvider;
|
|
63
|
-
topNavigation?:
|
|
64
|
+
topNavigation?: TopNavigationItem[];
|
|
64
65
|
sidebars?: SidebarConfig;
|
|
65
66
|
plugins?: DevPortalPlugin[];
|
|
66
67
|
slotlets?: Slotlets;
|
|
@@ -72,7 +73,7 @@ export type ZudokuContextOptions = {
|
|
|
72
73
|
|
|
73
74
|
export class DevPortalContext {
|
|
74
75
|
public plugins: NonNullable<ZudokuContextOptions["plugins"]>;
|
|
75
|
-
public sidebars:
|
|
76
|
+
public sidebars: SidebarConfig;
|
|
76
77
|
public topNavigation: NonNullable<ZudokuContextOptions["topNavigation"]>;
|
|
77
78
|
public meta: ZudokuContextOptions["metadata"];
|
|
78
79
|
public page: ZudokuContextOptions["page"];
|
package/src/lib/core/plugins.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import SchemaBuilder from "@pothos/core";
|
|
3
|
+
import {
|
|
4
|
+
slugifyWithCounter,
|
|
5
|
+
type CountableSlugify,
|
|
6
|
+
} from "@sindresorhus/slugify";
|
|
3
7
|
import { GraphQLJSON, GraphQLJSONObject } from "graphql-type-json";
|
|
4
8
|
import { createYoga, type YogaServerOptions } from "graphql-yoga";
|
|
5
9
|
import { LRUCache } from "lru-cache";
|
|
6
10
|
import hashit from "object-hash";
|
|
7
|
-
import slugify from "../../util/slugify.js";
|
|
8
11
|
import {
|
|
9
12
|
HttpMethods,
|
|
10
13
|
validate,
|
|
@@ -15,6 +18,7 @@ import {
|
|
|
15
18
|
type ParameterObject,
|
|
16
19
|
type PathsObject,
|
|
17
20
|
type SchemaObject,
|
|
21
|
+
type ServerObject,
|
|
18
22
|
type TagObject,
|
|
19
23
|
} from "../parser/index.js";
|
|
20
24
|
|
|
@@ -35,7 +39,12 @@ type OperationLike = {
|
|
|
35
39
|
path: string;
|
|
36
40
|
method: string;
|
|
37
41
|
};
|
|
38
|
-
|
|
42
|
+
|
|
43
|
+
export const createOperationSlug = (
|
|
44
|
+
slugify: CountableSlugify,
|
|
45
|
+
operation: OperationLike,
|
|
46
|
+
tag?: string,
|
|
47
|
+
) => {
|
|
39
48
|
const summary =
|
|
40
49
|
(operation.summary ?? "") +
|
|
41
50
|
(operation.operationId
|
|
@@ -46,13 +55,13 @@ export const slugifyOperation = (operation: OperationLike, tag?: string) => {
|
|
|
46
55
|
return slugify(
|
|
47
56
|
(tag ? tag + "-" : "") +
|
|
48
57
|
(summary || `${operation.method}-${operation.path}`),
|
|
49
|
-
{ lower: true, trim: true },
|
|
50
58
|
);
|
|
51
59
|
};
|
|
52
60
|
|
|
53
|
-
const cache = new LRUCache<string,
|
|
61
|
+
const cache = new LRUCache<string, OpenAPIDocument>({
|
|
54
62
|
ttl: 60 * 10 * 1000,
|
|
55
63
|
ttlAutopurge: true,
|
|
64
|
+
fetchMethod: (_key, _oldValue, { context }) => validate(context as string),
|
|
56
65
|
});
|
|
57
66
|
|
|
58
67
|
const builder = new SchemaBuilder<{
|
|
@@ -88,6 +97,8 @@ const getAllTags = (schema: OpenAPIDocument): TagObject[] => {
|
|
|
88
97
|
};
|
|
89
98
|
|
|
90
99
|
const getAllOperations = (paths?: PathsObject, tag?: string) => {
|
|
100
|
+
const slugify = slugifyWithCounter();
|
|
101
|
+
|
|
91
102
|
return Object.entries(paths ?? {}).flatMap(([path, value]) =>
|
|
92
103
|
HttpMethods.flatMap((method) => {
|
|
93
104
|
if (!value?.[method]) return [];
|
|
@@ -109,21 +120,20 @@ const getAllOperations = (paths?: PathsObject, tag?: string) => {
|
|
|
109
120
|
...operationParameters,
|
|
110
121
|
];
|
|
111
122
|
|
|
123
|
+
const slugData = {
|
|
124
|
+
summary: operation.summary,
|
|
125
|
+
operationId: operation.operationId,
|
|
126
|
+
path,
|
|
127
|
+
method,
|
|
128
|
+
};
|
|
129
|
+
|
|
112
130
|
return {
|
|
113
131
|
...operation,
|
|
114
132
|
method,
|
|
115
133
|
path,
|
|
116
134
|
parameters,
|
|
117
135
|
tags: operation.tags ?? [],
|
|
118
|
-
slug:
|
|
119
|
-
{
|
|
120
|
-
summary: operation.summary,
|
|
121
|
-
operationId: operation.operationId,
|
|
122
|
-
path,
|
|
123
|
-
method,
|
|
124
|
-
},
|
|
125
|
-
tag,
|
|
126
|
-
),
|
|
136
|
+
slug: createOperationSlug(slugify, slugData, tag),
|
|
127
137
|
};
|
|
128
138
|
}),
|
|
129
139
|
);
|
|
@@ -150,6 +160,13 @@ const SchemaTag = builder.objectRef<TagObject>("SchemaTag").implement({
|
|
|
150
160
|
}),
|
|
151
161
|
});
|
|
152
162
|
|
|
163
|
+
const ServerItem = builder.objectRef<ServerObject>("Server").implement({
|
|
164
|
+
fields: (t) => ({
|
|
165
|
+
url: t.exposeString("url"),
|
|
166
|
+
description: t.exposeString("description", { nullable: true }),
|
|
167
|
+
}),
|
|
168
|
+
});
|
|
169
|
+
|
|
153
170
|
const PathItem = builder
|
|
154
171
|
.objectRef<{
|
|
155
172
|
path: string;
|
|
@@ -363,6 +380,10 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
363
380
|
fields: (t) => ({
|
|
364
381
|
openapi: t.string({ resolve: (root) => root.openapi }),
|
|
365
382
|
url: t.string({ resolve: (root) => root.servers?.at(0)?.url ?? "/" }),
|
|
383
|
+
servers: t.field({
|
|
384
|
+
type: [ServerItem],
|
|
385
|
+
resolve: (root) => root.servers ?? [],
|
|
386
|
+
}),
|
|
366
387
|
title: t.string({ resolve: (root) => root.info.title }),
|
|
367
388
|
version: t.string({ resolve: (root) => root.info.version }),
|
|
368
389
|
description: t.string({
|
|
@@ -409,16 +430,7 @@ const Schema = builder.objectRef<OpenAPIDocument>("Schema").implement({
|
|
|
409
430
|
|
|
410
431
|
const loadOpenAPISchema = async (input: NonNullable<unknown>) => {
|
|
411
432
|
const hash = hashit(input);
|
|
412
|
-
|
|
413
|
-
if (cache.has(hash)) {
|
|
414
|
-
return cache.get(hash)!;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
const schema = validate(input);
|
|
418
|
-
|
|
419
|
-
cache.set(hash, schema);
|
|
420
|
-
|
|
421
|
-
return schema;
|
|
433
|
+
return await cache.forceFetch(hash, { context: input });
|
|
422
434
|
};
|
|
423
435
|
|
|
424
436
|
const SchemaSource = builder.enumType("SchemaType", {
|
|
@@ -20,6 +20,7 @@ export type TagObject = DeepOmitReference<OpenAPIV3_1.TagObject>;
|
|
|
20
20
|
export type ExampleObject = DeepOmitReference<OpenAPIV3_1.ExampleObject>;
|
|
21
21
|
export type EncodingObject = DeepOmitReference<OpenAPIV3_1.EncodingObject>;
|
|
22
22
|
export type SchemaObject = DeepOmitReference<OpenAPIV3_1.SchemaObject>;
|
|
23
|
+
export type ServerObject = DeepOmitReference<OpenAPIV3_1.ServerObject>;
|
|
23
24
|
|
|
24
25
|
export const HttpMethods = Object.values(OpenAPIV3.HttpMethods);
|
|
25
26
|
|