zudoku 0.1.1-dev.47 → 0.1.1-dev.49
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/App.js +5 -5
- package/dist/app/App.js.map +1 -1
- package/dist/app/main.js +8 -0
- package/dist/app/main.js.map +1 -1
- package/dist/cli/common/analytics/lib.js +1 -1
- package/dist/cli/common/analytics/lib.js.map +1 -1
- package/dist/cli/common/logger.js +1 -1
- package/dist/lib/authentication/clerk.js +0 -1
- package/dist/lib/authentication/clerk.js.map +1 -1
- package/dist/lib/authentication/openid.js +3 -2
- package/dist/lib/authentication/openid.js.map +1 -1
- package/dist/lib/components/Header.d.ts +1 -1
- package/dist/lib/components/Header.js +1 -1
- package/dist/lib/components/Header.js.map +1 -1
- package/dist/lib/components/Select.js +1 -1
- package/dist/lib/components/Select.js.map +1 -1
- package/dist/lib/components/context/ComponentsContext.d.ts +1 -1
- package/dist/lib/components/index.d.ts +0 -1
- package/dist/lib/components/index.js +0 -1
- package/dist/lib/components/index.js.map +1 -1
- package/dist/lib/components/navigation/SideNavigationItem.js +1 -2
- package/dist/lib/components/navigation/SideNavigationItem.js.map +1 -1
- package/dist/lib/components/navigation/SideNavigationWrapper.js +3 -1
- package/dist/lib/components/navigation/SideNavigationWrapper.js.map +1 -1
- package/dist/lib/core/DevPortalContext.d.ts +3 -5
- package/dist/lib/core/DevPortalContext.js.map +1 -1
- package/dist/lib/oas/graphql/index.js +2 -2
- package/dist/lib/oas/graphql/index.js.map +1 -1
- package/dist/lib/plugins/api-key/SettingsApiKeys.js +1 -1
- package/dist/lib/plugins/api-key/SettingsApiKeys.js.map +1 -1
- package/dist/lib/plugins/api-key/index.d.ts +2 -2
- package/dist/lib/plugins/api-key/index.js +2 -2
- package/dist/lib/plugins/api-key/index.js.map +1 -1
- package/dist/lib/plugins/markdown/MdxPage.js +7 -7
- package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
- package/dist/lib/plugins/openapi/ColorizedParam.js +1 -1
- package/dist/lib/plugins/openapi/MakeRequest.js +4 -4
- package/dist/lib/plugins/openapi/MakeRequest.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationList.js +8 -1
- package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
- package/dist/lib/plugins/openapi/OperationListItem.js +2 -2
- package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
- package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +1 -1
- package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
- package/dist/lib/plugins/openapi/SchemaListView.js +6 -6
- package/dist/lib/plugins/openapi/SchemaListView.js.map +1 -1
- package/dist/lib/plugins/openapi/Sidecar.js +2 -2
- package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.d.ts +2 -2
- package/dist/lib/plugins/openapi/graphql/gql.js +1 -1
- package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
- package/dist/lib/plugins/openapi/graphql/graphql.d.ts +8 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js +46 -0
- package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/PathParams.js +4 -4
- package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/Playground.d.ts +1 -0
- package/dist/lib/plugins/openapi/playground/Playground.js +29 -21
- package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
- package/dist/lib/plugins/openapi/playground/QueryParams.js +4 -5
- package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
- package/dist/lib/plugins/openapi/util/generateSchemaExample.js +0 -1
- package/dist/lib/plugins/openapi/util/generateSchemaExample.js.map +1 -1
- package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js +1 -0
- package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js.map +1 -1
- package/dist/lib/ui/Button.d.ts +3 -7
- package/dist/lib/ui/Button.js +3 -26
- package/dist/lib/ui/Button.js.map +1 -1
- package/dist/lib/ui/button-variants.d.ts +4 -0
- package/dist/lib/ui/button-variants.js +24 -0
- package/dist/lib/ui/button-variants.js.map +1 -0
- package/dist/lib/util/MdxComponents.js +7 -7
- package/dist/lib/util/MdxComponents.js.map +1 -1
- package/dist/ts.js +1 -2
- package/dist/ts.js.map +1 -1
- package/dist/vite/config.js +1 -1
- package/dist/vite/dev-server.js +5 -4
- package/dist/vite/dev-server.js.map +1 -1
- package/dist/vite/plugin-api.js +1 -1
- package/dist/vite/plugin-api.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-docs.js +1 -1
- package/dist/vite/plugin-docs.js.map +1 -1
- package/dist/vite/plugin-docs.test.js +1 -1
- package/dist/vite/plugin-docs.test.js.map +1 -1
- package/lib/{Spinner-DEkC7JSn.js → Spinner-DoNe5ql0.js} +18 -18
- package/lib/assets/{worker-W78u54MC.js → worker-BCcpCNJ7.js} +2 -2
- package/lib/zudoku.auth-clerk.js +1 -1
- package/lib/zudoku.components.js +278 -281
- package/lib/zudoku.openapi-worker.js +5 -5
- package/lib/zudoku.plugins.js +9963 -9732
- package/package.json +4 -1
- package/src/app/App.tsx +5 -5
- package/src/app/main.tsx +9 -0
- package/src/lib/authentication/clerk.ts +0 -1
- package/src/lib/authentication/openid.ts +4 -2
- package/src/lib/components/Header.tsx +1 -1
- package/src/lib/components/Select.tsx +3 -3
- package/src/lib/components/index.ts +0 -1
- package/src/lib/components/navigation/SideNavigationItem.tsx +1 -2
- package/src/lib/components/navigation/SideNavigationWrapper.tsx +18 -16
- package/src/lib/core/DevPortalContext.ts +3 -6
- package/src/lib/oas/graphql/index.ts +2 -2
- package/src/lib/plugins/api-key/SettingsApiKeys.tsx +1 -1
- package/src/lib/plugins/api-key/index.tsx +4 -4
- package/src/lib/plugins/markdown/MdxPage.tsx +13 -8
- package/src/lib/plugins/openapi/ColorizedParam.tsx +1 -1
- package/src/lib/plugins/openapi/MakeRequest.tsx +4 -4
- package/src/lib/plugins/openapi/OperationList.tsx +8 -1
- package/src/lib/plugins/openapi/OperationListItem.tsx +2 -2
- package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +1 -1
- package/src/lib/plugins/openapi/SchemaListView.tsx +9 -10
- package/src/lib/plugins/openapi/Sidecar.tsx +3 -3
- package/src/lib/plugins/openapi/graphql/gql.ts +3 -3
- package/src/lib/plugins/openapi/graphql/graphql.ts +54 -0
- package/src/lib/plugins/openapi/playground/PathParams.tsx +4 -4
- package/src/lib/plugins/openapi/playground/Playground.tsx +80 -36
- package/src/lib/plugins/openapi/playground/QueryParams.tsx +4 -6
- package/src/lib/plugins/openapi/util/generateSchemaExample.ts +0 -1
- package/src/lib/plugins/openapi/worker/createSharedWorkerClient.ts +1 -0
- package/src/lib/ui/Button.tsx +11 -42
- package/src/lib/ui/button-variants.ts +31 -0
- package/src/lib/util/MdxComponents.tsx +31 -7
- package/dist/lib/components/DynamicIcon.d.ts +0 -6
- package/dist/lib/components/DynamicIcon.js +0 -6
- package/dist/lib/components/DynamicIcon.js.map +0 -1
- package/dist/lib/oas/graphql/server.d.ts +0 -1
- package/dist/lib/oas/graphql/server.js +0 -8
- package/dist/lib/oas/graphql/server.js.map +0 -1
- package/src/lib/components/DynamicIcon.tsx +0 -60
- package/src/lib/oas/graphql/server.ts +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zudoku",
|
|
3
|
-
"version": "0.1.1-dev.
|
|
3
|
+
"version": "0.1.1-dev.49",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@monaco-editor/react": "^4.6.0",
|
|
55
55
|
"@pothos/core": "3.41.0",
|
|
56
56
|
"@radix-ui/react-select": "2.1.1",
|
|
57
|
+
"@radix-ui/react-visually-hidden": "1.1.0",
|
|
57
58
|
"@sentry/node": "8.11.0",
|
|
58
59
|
"@stefanprobst/rehype-extract-toc": "2.2.0",
|
|
59
60
|
"@tailwindcss/typography": "0.5.13",
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
"graphql": "16.9.0",
|
|
67
68
|
"graphql-type-json": "0.3.2",
|
|
68
69
|
"graphql-yoga": "5.2.0",
|
|
70
|
+
"loglevel": "^1.9.1",
|
|
69
71
|
"lru-cache": "10.2.0",
|
|
70
72
|
"mdx": "0.3.1",
|
|
71
73
|
"object-hash": "3.0.0",
|
|
@@ -108,6 +110,7 @@
|
|
|
108
110
|
"@types/express": "^4.17.21",
|
|
109
111
|
"@types/har-format": "^1.2.15",
|
|
110
112
|
"@types/json-schema": "7.0.15",
|
|
113
|
+
"@types/loglevel": "^1.6.3",
|
|
111
114
|
"@types/mdx": "2.0.13",
|
|
112
115
|
"@types/node": "20.12.10",
|
|
113
116
|
"@types/object-hash": "^3.0.6",
|
package/src/app/App.tsx
CHANGED
|
@@ -4,10 +4,10 @@ import "./main.css";
|
|
|
4
4
|
import config from "virtual:zudoku-config";
|
|
5
5
|
|
|
6
6
|
// Virtual Plugins
|
|
7
|
+
import { configuredApiKeysPlugin } from "virtual:zudoku-api-keys-plugin";
|
|
7
8
|
import { configuredApiPlugins } from "virtual:zudoku-api-plugins";
|
|
8
9
|
import { configuredAuthProvider } from "virtual:zudoku-auth";
|
|
9
10
|
import { configuredDocsPlugins } from "virtual:zudoku-docs-plugins";
|
|
10
|
-
import { configuredApiKeysPlugin } from "virtual:zudoku-api-keys-plugin";
|
|
11
11
|
import { configuredRedirectPlugin } from "virtual:zudoku-redirect-plugin";
|
|
12
12
|
|
|
13
13
|
// Base React Component
|
|
@@ -20,11 +20,11 @@ export default function App() {
|
|
|
20
20
|
return (
|
|
21
21
|
<DevPortal
|
|
22
22
|
meta={{
|
|
23
|
-
headerTitle: config
|
|
24
|
-
pageTitle: config
|
|
25
|
-
logo: config
|
|
23
|
+
headerTitle: config.ui?.headerTitle ?? "Developer Portal",
|
|
24
|
+
pageTitle: config.ui?.pageTitle ?? "%s | Dev Portal",
|
|
25
|
+
logo: config.ui?.logo ?? "https://cdn.zuplo.com/www/favicon.png",
|
|
26
26
|
favicon:
|
|
27
|
-
config
|
|
27
|
+
config.ui?.metadata?.favicon ??
|
|
28
28
|
"https://cdn.zuplo.com/www/favicon.png",
|
|
29
29
|
}}
|
|
30
30
|
navigation={config.navigation ?? []}
|
package/src/app/main.tsx
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import log from "loglevel";
|
|
1
2
|
import { StrictMode } from "react";
|
|
2
3
|
import { createRoot } from "react-dom/client";
|
|
3
4
|
import App from "./App.js";
|
|
4
5
|
|
|
6
|
+
log.setDefaultLevel("silent");
|
|
7
|
+
|
|
8
|
+
if (import.meta.env.DEV) {
|
|
9
|
+
log.setLevel("debug");
|
|
10
|
+
} else if (localStorage.getItem("ENABLE_DEBUG_LOGS")) {
|
|
11
|
+
log.setLevel("debug");
|
|
12
|
+
}
|
|
13
|
+
|
|
5
14
|
createRoot(document.getElementById("root")!).render(
|
|
6
15
|
<StrictMode>
|
|
7
16
|
<App />
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import logger from "loglevel";
|
|
1
2
|
import * as oauth from "oauth4webapi";
|
|
2
3
|
import { DevPortalContext } from "../core/DevPortalContext.js";
|
|
3
4
|
import { type AuthProvider } from "./authentication.js";
|
|
5
|
+
|
|
4
6
|
const algorithm = "oauth2";
|
|
5
7
|
|
|
6
8
|
const getAuthServerByIssuer = async (issuer: string) => {
|
|
@@ -140,7 +142,7 @@ export const openIdAuth = ({
|
|
|
140
142
|
state,
|
|
141
143
|
);
|
|
142
144
|
if (oauth.isOAuth2Error(params)) {
|
|
143
|
-
|
|
145
|
+
logger.error("Error Response", params);
|
|
144
146
|
throw new Error(); // Handle OAuth 2.0 redirect error
|
|
145
147
|
}
|
|
146
148
|
|
|
@@ -167,7 +169,7 @@ export const openIdAuth = ({
|
|
|
167
169
|
response,
|
|
168
170
|
);
|
|
169
171
|
if (oauth.isOAuth2Error(oauthResult)) {
|
|
170
|
-
|
|
172
|
+
logger.error("Error Response", oauthResult);
|
|
171
173
|
throw new Error(oauthResult.error);
|
|
172
174
|
}
|
|
173
175
|
|
|
@@ -5,7 +5,7 @@ import { TopNavigation } from "./TopNavigation.js";
|
|
|
5
5
|
import { useDevPortal } from "./context/DevPortalProvider.js";
|
|
6
6
|
import { useTheme } from "./context/ThemeContext.js";
|
|
7
7
|
|
|
8
|
-
export const Header = memo(()
|
|
8
|
+
export const Header = memo(function HeaderInner() {
|
|
9
9
|
const [isDark, toggleTheme] = useTheme();
|
|
10
10
|
const { isLoggedIn, email } = useDevPortalState();
|
|
11
11
|
const { login, logout, meta } = useDevPortal();
|
|
@@ -16,14 +16,14 @@ const SelectTrigger = React.forwardRef<
|
|
|
16
16
|
<SelectPrimitive.Trigger
|
|
17
17
|
ref={ref}
|
|
18
18
|
className={cn(
|
|
19
|
-
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50
|
|
19
|
+
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
20
20
|
className,
|
|
21
21
|
)}
|
|
22
22
|
{...props}
|
|
23
23
|
>
|
|
24
|
-
{children}
|
|
24
|
+
<span className="truncate">{children}</span>
|
|
25
25
|
<SelectPrimitive.Icon asChild>
|
|
26
|
-
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
26
|
+
<ChevronDown className="flex-shrink-0 h-4 w-4 opacity-50" />
|
|
27
27
|
</SelectPrimitive.Icon>
|
|
28
28
|
</SelectPrimitive.Trigger>
|
|
29
29
|
));
|
|
@@ -11,7 +11,6 @@ import type {
|
|
|
11
11
|
import { cn } from "../../util/cn.js";
|
|
12
12
|
import { joinPath } from "../../util/joinPath.js";
|
|
13
13
|
import { AnchorLink } from "../AnchorLink.js";
|
|
14
|
-
import { DynamicIcon, isValidIcon } from "../DynamicIcon.js";
|
|
15
14
|
import { useNavigationCollapsibleState } from "./useNavigationCollapsibleState.js";
|
|
16
15
|
import { checkHasActiveItem, isLinkItem, isPathItem } from "./util.js";
|
|
17
16
|
|
|
@@ -82,7 +81,7 @@ export const SideNavigationItem = ({
|
|
|
82
81
|
const linkContent = (
|
|
83
82
|
<div className="flex justify-between w-full">
|
|
84
83
|
<div className="flex items-center gap-2 truncate w-full">
|
|
85
|
-
{
|
|
84
|
+
{item.icon}
|
|
86
85
|
{typeof item.label !== "string" ? (
|
|
87
86
|
item.label
|
|
88
87
|
) : (
|
|
@@ -4,19 +4,21 @@ import { cn } from "../../util/cn.js";
|
|
|
4
4
|
export const SideNavigationWrapper = forwardRef<
|
|
5
5
|
HTMLDivElement,
|
|
6
6
|
PropsWithChildren<{ pushMainContent?: boolean; className?: string }>
|
|
7
|
-
>(({ children, className, pushMainContent }, ref)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
>(function SideNavigation({ children, className, pushMainContent }, ref) {
|
|
8
|
+
return (
|
|
9
|
+
<nav
|
|
10
|
+
// this data attribute is used in `Layout.tsx` to determine if side navigation
|
|
11
|
+
// is present for the current page so the main content is pushed to the right
|
|
12
|
+
// it's also important to set `peer` class here.
|
|
13
|
+
// maybe this could be simplified by adjusting the layout
|
|
14
|
+
data-navigation={String(pushMainContent)}
|
|
15
|
+
className={cn(
|
|
16
|
+
"peer hidden lg:flex flex-col fixed text-sm overflow-y-auto shrink-0 p-[--padding-nav-item] -mx-[--padding-nav-item] pb-20 pt-[--padding-content-top] w-[--side-nav-width] h-[calc(100%-var(--header-height))] scroll-pt-2 gap-2",
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
ref={ref}
|
|
20
|
+
>
|
|
21
|
+
{children}
|
|
22
|
+
</nav>
|
|
23
|
+
);
|
|
24
|
+
});
|
|
@@ -14,12 +14,9 @@ import {
|
|
|
14
14
|
type NavigationPlugin,
|
|
15
15
|
} from "./plugins.js";
|
|
16
16
|
|
|
17
|
-
import type { LucideIcon } from "lucide-react";
|
|
18
|
-
import type { IconName } from "../components/DynamicIcon.js";
|
|
19
|
-
|
|
20
17
|
export interface ApiIdentity {
|
|
21
18
|
authorizeRequest: (request: Request) => Request;
|
|
22
|
-
|
|
19
|
+
label: string;
|
|
23
20
|
id: string;
|
|
24
21
|
}
|
|
25
22
|
|
|
@@ -27,7 +24,7 @@ type BaseNavigationCategoryItem = {
|
|
|
27
24
|
label: ReactNode;
|
|
28
25
|
title?: string;
|
|
29
26
|
muted?: boolean;
|
|
30
|
-
icon?: ReactNode
|
|
27
|
+
icon?: ReactNode;
|
|
31
28
|
};
|
|
32
29
|
|
|
33
30
|
export type PathNavigationCategoryItem = BaseNavigationCategoryItem & {
|
|
@@ -48,7 +45,7 @@ export type NavigationCategory = {
|
|
|
48
45
|
path?: string;
|
|
49
46
|
expanded?: boolean;
|
|
50
47
|
collapsible?: boolean;
|
|
51
|
-
icon?:
|
|
48
|
+
icon?: ReactNode;
|
|
52
49
|
children: NavigationCategoryItem[];
|
|
53
50
|
};
|
|
54
51
|
|
|
@@ -69,7 +69,7 @@ const getAllOperations = (paths?: PathsObject, tag?: string) => {
|
|
|
69
69
|
if (!value?.[method]) return [];
|
|
70
70
|
|
|
71
71
|
const operation = value[method] as OperationObject;
|
|
72
|
-
const pathParameters = value
|
|
72
|
+
const pathParameters = value.parameters ?? [];
|
|
73
73
|
const operationParameters = operation.parameters ?? [];
|
|
74
74
|
|
|
75
75
|
// parameters are inherited from the parent path object,
|
|
@@ -189,7 +189,7 @@ const ParameterItem = builder
|
|
|
189
189
|
resolve: (parent) =>
|
|
190
190
|
Object.entries(parent.examples ?? {}).map(([name, value]) => ({
|
|
191
191
|
name,
|
|
192
|
-
...value,
|
|
192
|
+
...(typeof value === "string" ? { value } : value),
|
|
193
193
|
})),
|
|
194
194
|
nullable: true,
|
|
195
195
|
}),
|
|
@@ -51,7 +51,7 @@ export const SettingsApiKeys = ({
|
|
|
51
51
|
|
|
52
52
|
<Card>
|
|
53
53
|
<ul className="grid grid-cols-[min-content_1fr_min-content] ">
|
|
54
|
-
{data
|
|
54
|
+
{data.map((key) => (
|
|
55
55
|
<li
|
|
56
56
|
className="border-b border-border p-5 grid grid-cols-subgrid col-span-full gap-2 items-center"
|
|
57
57
|
key={key.id}
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
type ApiIdentityPlugin,
|
|
4
4
|
type DevPortalPlugin,
|
|
5
5
|
} from "../../core/plugins.js";
|
|
6
|
-
import { SettingsApiKeys } from "./SettingsApiKeys.js";
|
|
7
6
|
import { CreateApiKey } from "./CreateApiKey.js";
|
|
7
|
+
import { SettingsApiKeys } from "./SettingsApiKeys.js";
|
|
8
8
|
|
|
9
9
|
export type ApiKeyResults = Promise<ApiKey[]>;
|
|
10
10
|
const DEFAULT_API_KEY_ENDPOINT =
|
|
@@ -25,9 +25,9 @@ export type ApiKeyService = {
|
|
|
25
25
|
) => Promise<void>;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
export type GetApiKeysOptions = ApiKeyService | { endpoint: string } |
|
|
28
|
+
export type GetApiKeysOptions = ApiKeyService | { endpoint: string } | object;
|
|
29
29
|
|
|
30
|
-
export type ApiKeyPluginOptions =
|
|
30
|
+
export type ApiKeyPluginOptions = object & GetApiKeysOptions;
|
|
31
31
|
|
|
32
32
|
export interface ApiKey {
|
|
33
33
|
id: string;
|
|
@@ -107,7 +107,7 @@ export const apiKeyPlugin = (
|
|
|
107
107
|
return request;
|
|
108
108
|
},
|
|
109
109
|
id: key.id,
|
|
110
|
-
|
|
110
|
+
label: key.description ?? key.id,
|
|
111
111
|
}));
|
|
112
112
|
},
|
|
113
113
|
getRoutes: () => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useMDXComponents } from "@mdx-js/react";
|
|
1
2
|
import { useMemo, type PropsWithChildren, type ReactNode } from "react";
|
|
2
3
|
import { CategoryHeading } from "../../components/CategoryHeading.js";
|
|
3
4
|
import { Heading } from "../../components/Heading.js";
|
|
@@ -6,20 +7,24 @@ import { useTopNavigationItem } from "../../components/context/DevPortalProvider
|
|
|
6
7
|
import { isPathItem } from "../../components/navigation/util.js";
|
|
7
8
|
import { Helmet } from "../../core/helmet.js";
|
|
8
9
|
import { Link, useLocation } from "../../core/router.js";
|
|
10
|
+
import type { MdxComponentsType } from "../../util/MdxComponents.js";
|
|
9
11
|
import { cn } from "../../util/cn.js";
|
|
10
12
|
import slugify from "../../util/slugify.js";
|
|
11
13
|
import { traverseNavigation } from "../../util/traverseNavigation.js";
|
|
12
14
|
import { Toc } from "./Toc.js";
|
|
13
15
|
import type { MDXImport } from "./index.js";
|
|
14
|
-
import { useMDXComponents } from "@mdx-js/react";
|
|
15
|
-
import type { MdxComponentsType } from "../../util/MdxComponents.js";
|
|
16
16
|
|
|
17
17
|
const MarkdownHeadings = {
|
|
18
18
|
h2: ({ children, id }) => (
|
|
19
|
-
<Heading level={2} id={id}
|
|
19
|
+
<Heading level={2} id={id} registerSidebarAnchor>
|
|
20
|
+
{children}
|
|
21
|
+
</Heading>
|
|
20
22
|
),
|
|
21
23
|
h3: ({ children, id }) => (
|
|
22
|
-
<Heading level={3} id={id}
|
|
24
|
+
<Heading level={3} id={id} registerSidebarAnchor>
|
|
25
|
+
{" "}
|
|
26
|
+
{children}
|
|
27
|
+
</Heading>
|
|
23
28
|
),
|
|
24
29
|
} satisfies MdxComponentsType;
|
|
25
30
|
|
|
@@ -43,9 +48,9 @@ export const MdxPage = ({
|
|
|
43
48
|
})
|
|
44
49
|
: undefined;
|
|
45
50
|
|
|
46
|
-
const title = frontmatter
|
|
47
|
-
const category = frontmatter
|
|
48
|
-
const hideToc = frontmatter
|
|
51
|
+
const title = frontmatter.title;
|
|
52
|
+
const category = frontmatter.category ?? categoryTitle;
|
|
53
|
+
const hideToc = frontmatter.toc === false;
|
|
49
54
|
|
|
50
55
|
const pageTitle =
|
|
51
56
|
tableOfContents.find((item) => item.depth === 1)?.value ?? title;
|
|
@@ -100,7 +105,7 @@ export const MdxPage = ({
|
|
|
100
105
|
{title}
|
|
101
106
|
</Heading>
|
|
102
107
|
)}
|
|
103
|
-
{frontmatter
|
|
108
|
+
{frontmatter.description && (
|
|
104
109
|
<p className="prose-lg">{frontmatter.description}</p>
|
|
105
110
|
)}
|
|
106
111
|
</header>
|
|
@@ -74,7 +74,7 @@ export const ColorizedParam = ({
|
|
|
74
74
|
className="absolute inset-0 border-b-2 transition-opacity duration-200 opacity-30 group-data-[active=true]:opacity-100"
|
|
75
75
|
style={{ borderColor, backgroundColor }}
|
|
76
76
|
/>
|
|
77
|
-
<span className="relative">{children
|
|
77
|
+
<span className="relative">{children ?? name}</span>
|
|
78
78
|
</span>
|
|
79
79
|
);
|
|
80
80
|
};
|
|
@@ -23,19 +23,19 @@ export const MakeRequest = ({
|
|
|
23
23
|
|
|
24
24
|
const headers = operation.parameters
|
|
25
25
|
?.filter((p) => p.in === "header")
|
|
26
|
-
|
|
26
|
+
.map((p) => ({
|
|
27
27
|
name: p.name,
|
|
28
|
-
value: "",
|
|
28
|
+
value: p.examples?.find((x) => x.value)?.value ?? "",
|
|
29
29
|
}));
|
|
30
30
|
const queryParams = operation.parameters
|
|
31
31
|
?.filter((p) => p.in === "query")
|
|
32
|
-
|
|
32
|
+
.map((p) => ({
|
|
33
33
|
name: p.name,
|
|
34
34
|
value: "",
|
|
35
35
|
}));
|
|
36
36
|
const pathParams = operation.parameters
|
|
37
37
|
?.filter((p) => p.in === "path")
|
|
38
|
-
|
|
38
|
+
.map((p) => ({
|
|
39
39
|
name: p.name,
|
|
40
40
|
value: "",
|
|
41
41
|
}));
|
|
@@ -24,6 +24,13 @@ export const OperationsFragment = graphql(/* GraphQL */ `
|
|
|
24
24
|
required
|
|
25
25
|
schema
|
|
26
26
|
style
|
|
27
|
+
examples {
|
|
28
|
+
name
|
|
29
|
+
description
|
|
30
|
+
externalValue
|
|
31
|
+
value
|
|
32
|
+
summary
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
requestBody {
|
|
29
36
|
content {
|
|
@@ -94,7 +101,7 @@ export const OperationList = () => {
|
|
|
94
101
|
</Heading>
|
|
95
102
|
<Markdown content={result.data.schema.description ?? ""} />
|
|
96
103
|
</div>
|
|
97
|
-
{result.data
|
|
104
|
+
{result.data.schema.tags
|
|
98
105
|
.filter((tag) => tag.operations.length > 0)
|
|
99
106
|
.map((tag) => (
|
|
100
107
|
<div key={tag.name}>
|
|
@@ -17,7 +17,7 @@ export const OperationListItem = ({
|
|
|
17
17
|
operationFragment: FragmentType<typeof OperationsFragment>;
|
|
18
18
|
}) => {
|
|
19
19
|
const operation = useFragment(OperationsFragment, operationFragment);
|
|
20
|
-
const groupedParameters = groupBy(operation
|
|
20
|
+
const groupedParameters = groupBy(operation.parameters ?? [], "in");
|
|
21
21
|
const first = operation.responses.find((re) => re.statusCode === "200");
|
|
22
22
|
return (
|
|
23
23
|
<div
|
|
@@ -37,7 +37,7 @@ export const OperationListItem = ({
|
|
|
37
37
|
{operation.parameters && operation.parameters.length > 0 && (
|
|
38
38
|
<div className="mt-4">
|
|
39
39
|
{PARAM_GROUPS.flatMap((group) =>
|
|
40
|
-
groupedParameters
|
|
40
|
+
groupedParameters[group].length ? (
|
|
41
41
|
<ParameterList
|
|
42
42
|
key={group}
|
|
43
43
|
id={operation.slug}
|
|
@@ -15,7 +15,7 @@ export const ResponsesSidecarBox = ({
|
|
|
15
15
|
const [tabIndex, setTabIndex] = useState(0);
|
|
16
16
|
|
|
17
17
|
const activeTab = responses[tabIndex];
|
|
18
|
-
const schema = activeTab
|
|
18
|
+
const schema = activeTab.content?.[0]?.schema as SchemaObject | undefined;
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<SidecarBox.Root>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Collapsible from "@radix-ui/react-collapsible";
|
|
2
|
+
import { ListPlusIcon } from "lucide-react";
|
|
2
3
|
import { useState } from "react";
|
|
3
|
-
import { cn } from "../../util/cn.js";
|
|
4
4
|
import { Markdown } from "../../components/Markdown.js";
|
|
5
|
-
import
|
|
5
|
+
import { SchemaObject } from "../../oas/parser/index.js";
|
|
6
6
|
import { Button } from "../../ui/Button.js";
|
|
7
|
-
import {
|
|
7
|
+
import { cn } from "../../util/cn.js";
|
|
8
8
|
|
|
9
9
|
export const SchemaListView = ({
|
|
10
10
|
name,
|
|
@@ -55,6 +55,7 @@ export const SchemaListView = ({
|
|
|
55
55
|
{Object.entries(groups).map(([group, properties]) => {
|
|
56
56
|
return (
|
|
57
57
|
<SchemaListViewItemGroup
|
|
58
|
+
key={group}
|
|
58
59
|
defaultOpen={defaultOpen}
|
|
59
60
|
group={group as any}
|
|
60
61
|
nestingLevel={level}
|
|
@@ -112,10 +113,11 @@ const SchemaListViewItemGroup = ({
|
|
|
112
113
|
<Collapsible.Content>
|
|
113
114
|
{properties.map(([propertyName, property]) => (
|
|
114
115
|
<SchemaListViewItem
|
|
116
|
+
key={propertyName}
|
|
115
117
|
property={property}
|
|
116
118
|
propertyName={propertyName}
|
|
117
119
|
nestingLevel={nestingLevel}
|
|
118
|
-
isRequired={required
|
|
120
|
+
isRequired={required.includes(propertyName)}
|
|
119
121
|
/>
|
|
120
122
|
))}
|
|
121
123
|
</Collapsible.Content>
|
|
@@ -149,19 +151,16 @@ const SchemaListViewItem = ({
|
|
|
149
151
|
</code>
|
|
150
152
|
|
|
151
153
|
{property.type && (
|
|
152
|
-
<span className="text-muted-foreground">{property.type}</span>
|
|
154
|
+
<span className="text-xs text-muted-foreground">{property.type}</span>
|
|
153
155
|
)}
|
|
154
156
|
{property.deprecated && (
|
|
155
|
-
<span className="text-muted-foreground">Deprecated</span>
|
|
157
|
+
<span className="text-xs text-muted-foreground">Deprecated</span>
|
|
156
158
|
)}
|
|
157
159
|
{!isRequired && (
|
|
158
160
|
<span className="py-px px-1.5 font-medium text-xs border border-border rounded-lg">
|
|
159
161
|
optional {property.required}
|
|
160
162
|
</span>
|
|
161
163
|
)}
|
|
162
|
-
{/*{property.type === "object" && (*/}
|
|
163
|
-
{/* <div className="absolute right-3">+</div>*/}
|
|
164
|
-
{/*)}*/}
|
|
165
164
|
</div>
|
|
166
165
|
{property.description && (
|
|
167
166
|
<Markdown
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { HTTPSnippet } from "@zudoku/httpsnippet";
|
|
1
2
|
import { Fragment, useMemo, useState } from "react";
|
|
2
3
|
import { SyntaxHighlight } from "../../components/SyntaxHighlight.js";
|
|
4
|
+
import type { SchemaObject } from "../../oas/parser/index.js";
|
|
3
5
|
import { cn } from "../../util/cn.js";
|
|
4
6
|
import { ColorizedParam } from "./ColorizedParam.js";
|
|
5
7
|
import { MakeRequest } from "./MakeRequest.js";
|
|
@@ -9,9 +11,7 @@ import { RequestBodySidecarBox } from "./RequestBodySidecarBox.js";
|
|
|
9
11
|
import { ResponsesSidecarBox } from "./ResponsesSidecarBox.js";
|
|
10
12
|
import { Select } from "./Select.js";
|
|
11
13
|
import * as SidecarBox from "./SidecarBox.js";
|
|
12
|
-
import { HTTPSnippet } from "@zudoku/httpsnippet";
|
|
13
14
|
import { generateSchemaExample } from "./util/generateSchemaExample.js";
|
|
14
|
-
import type { SchemaObject } from "../../oas/parser/index.js";
|
|
15
15
|
|
|
16
16
|
const getConverted = (snippet: HTTPSnippet, option: string) => {
|
|
17
17
|
let converted;
|
|
@@ -105,7 +105,7 @@ export const Sidecar = ({
|
|
|
105
105
|
} as never, // 👈 never touch this
|
|
106
106
|
);
|
|
107
107
|
|
|
108
|
-
return getConverted(snippet, option)
|
|
108
|
+
return getConverted(snippet, option);
|
|
109
109
|
}, [option, operation.method, operation.path, requestBodyContent]);
|
|
110
110
|
|
|
111
111
|
return (
|
|
@@ -15,7 +15,7 @@ import type { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-
|
|
|
15
15
|
const documents = {
|
|
16
16
|
"\n query getServerQuery($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n url\n }\n }\n":
|
|
17
17
|
types.GetServerQueryDocument,
|
|
18
|
-
"\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n":
|
|
18
|
+
"\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n":
|
|
19
19
|
types.OperationsFragmentFragmentDoc,
|
|
20
20
|
"\n query AllOperations($input: JSON!, $type: SchemaType!) {\n schema(input: $input, type: $type) {\n description\n title\n url\n version\n tags {\n name\n description\n operations {\n slug\n ...OperationsFragment\n }\n }\n }\n }\n":
|
|
21
21
|
types.AllOperationsDocument,
|
|
@@ -47,8 +47,8 @@ export function graphql(
|
|
|
47
47
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
48
48
|
*/
|
|
49
49
|
export function graphql(
|
|
50
|
-
source: "\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n",
|
|
51
|
-
): (typeof documents)["\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n"];
|
|
50
|
+
source: "\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n",
|
|
51
|
+
): (typeof documents)["\n fragment OperationsFragment on OperationItem {\n slug\n summary\n method\n description\n operationId\n contentTypes\n path\n parameters {\n name\n in\n description\n required\n schema\n style\n examples {\n name\n description\n externalValue\n value\n summary\n }\n }\n requestBody {\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n description\n required\n }\n responses {\n statusCode\n links\n description\n content {\n mediaType\n encoding {\n name\n }\n schema\n }\n }\n }\n"];
|
|
52
52
|
/**
|
|
53
53
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
54
54
|
*/
|
|
@@ -190,6 +190,14 @@ export type OperationsFragmentFragment = {
|
|
|
190
190
|
required?: boolean | null;
|
|
191
191
|
schema?: any | null;
|
|
192
192
|
style?: string | null;
|
|
193
|
+
examples?: Array<{
|
|
194
|
+
__typename?: "ExampleItem";
|
|
195
|
+
name: string;
|
|
196
|
+
description?: string | null;
|
|
197
|
+
externalValue?: string | null;
|
|
198
|
+
value?: string | null;
|
|
199
|
+
summary?: string | null;
|
|
200
|
+
}> | null;
|
|
193
201
|
}> | null;
|
|
194
202
|
requestBody?: {
|
|
195
203
|
__typename?: "RequestBodyObject";
|
|
@@ -301,6 +309,29 @@ export const OperationsFragmentFragmentDoc = {
|
|
|
301
309
|
{ kind: "Field", name: { kind: "Name", value: "required" } },
|
|
302
310
|
{ kind: "Field", name: { kind: "Name", value: "schema" } },
|
|
303
311
|
{ kind: "Field", name: { kind: "Name", value: "style" } },
|
|
312
|
+
{
|
|
313
|
+
kind: "Field",
|
|
314
|
+
name: { kind: "Name", value: "examples" },
|
|
315
|
+
selectionSet: {
|
|
316
|
+
kind: "SelectionSet",
|
|
317
|
+
selections: [
|
|
318
|
+
{ kind: "Field", name: { kind: "Name", value: "name" } },
|
|
319
|
+
{
|
|
320
|
+
kind: "Field",
|
|
321
|
+
name: { kind: "Name", value: "description" },
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
kind: "Field",
|
|
325
|
+
name: { kind: "Name", value: "externalValue" },
|
|
326
|
+
},
|
|
327
|
+
{ kind: "Field", name: { kind: "Name", value: "value" } },
|
|
328
|
+
{
|
|
329
|
+
kind: "Field",
|
|
330
|
+
name: { kind: "Name", value: "summary" },
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
},
|
|
334
|
+
},
|
|
304
335
|
],
|
|
305
336
|
},
|
|
306
337
|
},
|
|
@@ -590,6 +621,29 @@ export const AllOperationsDocument = {
|
|
|
590
621
|
{ kind: "Field", name: { kind: "Name", value: "required" } },
|
|
591
622
|
{ kind: "Field", name: { kind: "Name", value: "schema" } },
|
|
592
623
|
{ kind: "Field", name: { kind: "Name", value: "style" } },
|
|
624
|
+
{
|
|
625
|
+
kind: "Field",
|
|
626
|
+
name: { kind: "Name", value: "examples" },
|
|
627
|
+
selectionSet: {
|
|
628
|
+
kind: "SelectionSet",
|
|
629
|
+
selections: [
|
|
630
|
+
{ kind: "Field", name: { kind: "Name", value: "name" } },
|
|
631
|
+
{
|
|
632
|
+
kind: "Field",
|
|
633
|
+
name: { kind: "Name", value: "description" },
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
kind: "Field",
|
|
637
|
+
name: { kind: "Name", value: "externalValue" },
|
|
638
|
+
},
|
|
639
|
+
{ kind: "Field", name: { kind: "Name", value: "value" } },
|
|
640
|
+
{
|
|
641
|
+
kind: "Field",
|
|
642
|
+
name: { kind: "Name", value: "summary" },
|
|
643
|
+
},
|
|
644
|
+
],
|
|
645
|
+
},
|
|
646
|
+
},
|
|
593
647
|
],
|
|
594
648
|
},
|
|
595
649
|
},
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import { forwardRef, InputHTMLAttributes } from "react";
|
|
1
2
|
import { Control, useFieldArray, UseFormRegister } from "react-hook-form";
|
|
3
|
+
import { cn } from "../../../util/cn.js";
|
|
4
|
+
import { DATA_ATTR, usePastellizedColor } from "../ColorizedParam.js";
|
|
2
5
|
import { InlineInput } from "./InlineInput.js";
|
|
3
6
|
import { PlaygroundForm } from "./Playground.js";
|
|
4
|
-
import { DATA_ATTR, usePastellizedColor } from "../ColorizedParam.js";
|
|
5
|
-
import { forwardRef, InputHTMLAttributes } from "react";
|
|
6
|
-
import { cn } from "../../../util/cn.js";
|
|
7
7
|
|
|
8
8
|
type ParameterValueProps = {
|
|
9
9
|
part: string;
|
|
10
10
|
} & InputHTMLAttributes<HTMLInputElement>;
|
|
11
11
|
|
|
12
12
|
const ParameterValue = forwardRef<HTMLInputElement, ParameterValueProps>(
|
|
13
|
-
({ part, className, ...props }, ref)
|
|
13
|
+
function ParameterValue({ part, className, ...props }, ref) {
|
|
14
14
|
const color = usePastellizedColor(part);
|
|
15
15
|
return (
|
|
16
16
|
<InlineInput
|