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.
Files changed (132) hide show
  1. package/dist/app/App.js +5 -5
  2. package/dist/app/App.js.map +1 -1
  3. package/dist/app/main.js +8 -0
  4. package/dist/app/main.js.map +1 -1
  5. package/dist/cli/common/analytics/lib.js +1 -1
  6. package/dist/cli/common/analytics/lib.js.map +1 -1
  7. package/dist/cli/common/logger.js +1 -1
  8. package/dist/lib/authentication/clerk.js +0 -1
  9. package/dist/lib/authentication/clerk.js.map +1 -1
  10. package/dist/lib/authentication/openid.js +3 -2
  11. package/dist/lib/authentication/openid.js.map +1 -1
  12. package/dist/lib/components/Header.d.ts +1 -1
  13. package/dist/lib/components/Header.js +1 -1
  14. package/dist/lib/components/Header.js.map +1 -1
  15. package/dist/lib/components/Select.js +1 -1
  16. package/dist/lib/components/Select.js.map +1 -1
  17. package/dist/lib/components/context/ComponentsContext.d.ts +1 -1
  18. package/dist/lib/components/index.d.ts +0 -1
  19. package/dist/lib/components/index.js +0 -1
  20. package/dist/lib/components/index.js.map +1 -1
  21. package/dist/lib/components/navigation/SideNavigationItem.js +1 -2
  22. package/dist/lib/components/navigation/SideNavigationItem.js.map +1 -1
  23. package/dist/lib/components/navigation/SideNavigationWrapper.js +3 -1
  24. package/dist/lib/components/navigation/SideNavigationWrapper.js.map +1 -1
  25. package/dist/lib/core/DevPortalContext.d.ts +3 -5
  26. package/dist/lib/core/DevPortalContext.js.map +1 -1
  27. package/dist/lib/oas/graphql/index.js +2 -2
  28. package/dist/lib/oas/graphql/index.js.map +1 -1
  29. package/dist/lib/plugins/api-key/SettingsApiKeys.js +1 -1
  30. package/dist/lib/plugins/api-key/SettingsApiKeys.js.map +1 -1
  31. package/dist/lib/plugins/api-key/index.d.ts +2 -2
  32. package/dist/lib/plugins/api-key/index.js +2 -2
  33. package/dist/lib/plugins/api-key/index.js.map +1 -1
  34. package/dist/lib/plugins/markdown/MdxPage.js +7 -7
  35. package/dist/lib/plugins/markdown/MdxPage.js.map +1 -1
  36. package/dist/lib/plugins/openapi/ColorizedParam.js +1 -1
  37. package/dist/lib/plugins/openapi/MakeRequest.js +4 -4
  38. package/dist/lib/plugins/openapi/MakeRequest.js.map +1 -1
  39. package/dist/lib/plugins/openapi/OperationList.js +8 -1
  40. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  41. package/dist/lib/plugins/openapi/OperationListItem.js +2 -2
  42. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  43. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js +1 -1
  44. package/dist/lib/plugins/openapi/ResponsesSidecarBox.js.map +1 -1
  45. package/dist/lib/plugins/openapi/SchemaListView.js +6 -6
  46. package/dist/lib/plugins/openapi/SchemaListView.js.map +1 -1
  47. package/dist/lib/plugins/openapi/Sidecar.js +2 -2
  48. package/dist/lib/plugins/openapi/Sidecar.js.map +1 -1
  49. package/dist/lib/plugins/openapi/graphql/gql.d.ts +2 -2
  50. package/dist/lib/plugins/openapi/graphql/gql.js +1 -1
  51. package/dist/lib/plugins/openapi/graphql/gql.js.map +1 -1
  52. package/dist/lib/plugins/openapi/graphql/graphql.d.ts +8 -0
  53. package/dist/lib/plugins/openapi/graphql/graphql.js +46 -0
  54. package/dist/lib/plugins/openapi/graphql/graphql.js.map +1 -1
  55. package/dist/lib/plugins/openapi/playground/PathParams.js +4 -4
  56. package/dist/lib/plugins/openapi/playground/PathParams.js.map +1 -1
  57. package/dist/lib/plugins/openapi/playground/Playground.d.ts +1 -0
  58. package/dist/lib/plugins/openapi/playground/Playground.js +29 -21
  59. package/dist/lib/plugins/openapi/playground/Playground.js.map +1 -1
  60. package/dist/lib/plugins/openapi/playground/QueryParams.js +4 -5
  61. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  62. package/dist/lib/plugins/openapi/util/generateSchemaExample.js +0 -1
  63. package/dist/lib/plugins/openapi/util/generateSchemaExample.js.map +1 -1
  64. package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js +1 -0
  65. package/dist/lib/plugins/openapi/worker/createSharedWorkerClient.js.map +1 -1
  66. package/dist/lib/ui/Button.d.ts +3 -7
  67. package/dist/lib/ui/Button.js +3 -26
  68. package/dist/lib/ui/Button.js.map +1 -1
  69. package/dist/lib/ui/button-variants.d.ts +4 -0
  70. package/dist/lib/ui/button-variants.js +24 -0
  71. package/dist/lib/ui/button-variants.js.map +1 -0
  72. package/dist/lib/util/MdxComponents.js +7 -7
  73. package/dist/lib/util/MdxComponents.js.map +1 -1
  74. package/dist/ts.js +1 -2
  75. package/dist/ts.js.map +1 -1
  76. package/dist/vite/config.js +1 -1
  77. package/dist/vite/dev-server.js +5 -4
  78. package/dist/vite/dev-server.js.map +1 -1
  79. package/dist/vite/plugin-api.js +1 -1
  80. package/dist/vite/plugin-api.js.map +1 -1
  81. package/dist/vite/plugin-component.js +1 -1
  82. package/dist/vite/plugin-component.js.map +1 -1
  83. package/dist/vite/plugin-docs.js +1 -1
  84. package/dist/vite/plugin-docs.js.map +1 -1
  85. package/dist/vite/plugin-docs.test.js +1 -1
  86. package/dist/vite/plugin-docs.test.js.map +1 -1
  87. package/lib/{Spinner-DEkC7JSn.js → Spinner-DoNe5ql0.js} +18 -18
  88. package/lib/assets/{worker-W78u54MC.js → worker-BCcpCNJ7.js} +2 -2
  89. package/lib/zudoku.auth-clerk.js +1 -1
  90. package/lib/zudoku.components.js +278 -281
  91. package/lib/zudoku.openapi-worker.js +5 -5
  92. package/lib/zudoku.plugins.js +9963 -9732
  93. package/package.json +4 -1
  94. package/src/app/App.tsx +5 -5
  95. package/src/app/main.tsx +9 -0
  96. package/src/lib/authentication/clerk.ts +0 -1
  97. package/src/lib/authentication/openid.ts +4 -2
  98. package/src/lib/components/Header.tsx +1 -1
  99. package/src/lib/components/Select.tsx +3 -3
  100. package/src/lib/components/index.ts +0 -1
  101. package/src/lib/components/navigation/SideNavigationItem.tsx +1 -2
  102. package/src/lib/components/navigation/SideNavigationWrapper.tsx +18 -16
  103. package/src/lib/core/DevPortalContext.ts +3 -6
  104. package/src/lib/oas/graphql/index.ts +2 -2
  105. package/src/lib/plugins/api-key/SettingsApiKeys.tsx +1 -1
  106. package/src/lib/plugins/api-key/index.tsx +4 -4
  107. package/src/lib/plugins/markdown/MdxPage.tsx +13 -8
  108. package/src/lib/plugins/openapi/ColorizedParam.tsx +1 -1
  109. package/src/lib/plugins/openapi/MakeRequest.tsx +4 -4
  110. package/src/lib/plugins/openapi/OperationList.tsx +8 -1
  111. package/src/lib/plugins/openapi/OperationListItem.tsx +2 -2
  112. package/src/lib/plugins/openapi/ResponsesSidecarBox.tsx +1 -1
  113. package/src/lib/plugins/openapi/SchemaListView.tsx +9 -10
  114. package/src/lib/plugins/openapi/Sidecar.tsx +3 -3
  115. package/src/lib/plugins/openapi/graphql/gql.ts +3 -3
  116. package/src/lib/plugins/openapi/graphql/graphql.ts +54 -0
  117. package/src/lib/plugins/openapi/playground/PathParams.tsx +4 -4
  118. package/src/lib/plugins/openapi/playground/Playground.tsx +80 -36
  119. package/src/lib/plugins/openapi/playground/QueryParams.tsx +4 -6
  120. package/src/lib/plugins/openapi/util/generateSchemaExample.ts +0 -1
  121. package/src/lib/plugins/openapi/worker/createSharedWorkerClient.ts +1 -0
  122. package/src/lib/ui/Button.tsx +11 -42
  123. package/src/lib/ui/button-variants.ts +31 -0
  124. package/src/lib/util/MdxComponents.tsx +31 -7
  125. package/dist/lib/components/DynamicIcon.d.ts +0 -6
  126. package/dist/lib/components/DynamicIcon.js +0 -6
  127. package/dist/lib/components/DynamicIcon.js.map +0 -1
  128. package/dist/lib/oas/graphql/server.d.ts +0 -1
  129. package/dist/lib/oas/graphql/server.js +0 -8
  130. package/dist/lib/oas/graphql/server.js.map +0 -1
  131. package/src/lib/components/DynamicIcon.tsx +0 -60
  132. 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.47",
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?.ui?.headerTitle ?? "Developer Portal",
24
- pageTitle: config?.ui?.pageTitle ?? "%s | Dev Portal",
25
- logo: config?.ui?.logo ?? "https://cdn.zuplo.com/www/favicon.png",
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?.ui?.metadata?.favicon ??
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 />
@@ -9,7 +9,6 @@ const clerkAuth = ({ clerkPubKey }: { clerkPubKey: string }): AuthProvider => {
9
9
  clerkApi = new Clerk(clerkPubKey);
10
10
 
11
11
  await clerkApi.load({});
12
- clerkApi.load({});
13
12
  })();
14
13
 
15
14
  return {
@@ -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
- console.error("Error Response", params);
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
- console.error("Error Response", oauthResult);
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 [&>span]:line-clamp-1",
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
  ));
@@ -1,4 +1,3 @@
1
1
  export { useMDXComponents } from "@mdx-js/react";
2
2
  export { DevPortal } from "./DevPortal.js";
3
- export { DynamicIcon } from "./DynamicIcon.js";
4
3
  export { Link } from "./Link.js";
@@ -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
- {isValidIcon(item.icon) && <DynamicIcon name={item.icon} size={16} />}
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
- <nav
9
- // this data attribute is used in `Layout.tsx` to determine if side navigation
10
- // is present for the current page so the main content is pushed to the right
11
- // it's also important to set `peer` class here.
12
- // maybe this could be simplified by adjusting the layout
13
- data-navigation={String(pushMainContent)}
14
- className={cn(
15
- "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",
16
- className,
17
- )}
18
- ref={ref}
19
- >
20
- {children}
21
- </nav>
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
- name: string;
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 | IconName;
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?: LucideIcon;
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?.parameters ?? [];
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?.map((key) => (
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 = {} & GetApiKeysOptions;
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
- name: key.id,
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} children={children} registerSidebarAnchor />
19
+ <Heading level={2} id={id} registerSidebarAnchor>
20
+ {children}
21
+ </Heading>
20
22
  ),
21
23
  h3: ({ children, id }) => (
22
- <Heading level={3} id={id} children={children} registerSidebarAnchor />
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?.title;
47
- const category = frontmatter?.category ?? categoryTitle;
48
- const hideToc = frontmatter?.toc === false;
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?.description && (
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 || name}</span>
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
- ?.map((p) => ({
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
- ?.map((p) => ({
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
- ?.map((p) => ({
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?.schema.tags
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?.parameters ?? [], "in");
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?.[group]?.length ? (
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?.content?.[0]?.schema as SchemaObject | undefined;
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 { SchemaObject } from "../../oas/parser/index.js";
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 * as Collapsible from "@radix-ui/react-collapsible";
5
+ import { SchemaObject } from "../../oas/parser/index.js";
6
6
  import { Button } from "../../ui/Button.js";
7
- import { ListPlusIcon } from "lucide-react";
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?.includes(propertyName) ?? false}
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