fumadocs-openapi 10.3.4 → 10.3.5

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.
@@ -882,6 +882,7 @@
882
882
  @source inline("useRef");
883
883
  @source inline("useResolvedSchema");
884
884
  @source inline("useSchemaScope");
885
+ @source inline("useServerContext");
885
886
  @source inline("useServerSelectContext");
886
887
  @source inline("useState");
887
888
  @source inline("useStf");
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { joinURL, resolveRequestData, resolveServerUrl, withBase } from "../utils/url.js";
4
4
  import { useStorageKey } from "../ui/client/storage-key.js";
5
- import { useApiContext } from "../ui/contexts/api.js";
5
+ import { useApiContext, useServerContext } from "../ui/contexts/api.js";
6
6
  import { getStatusInfo } from "./status-info.js";
7
7
  import { cn } from "../utils/cn.js";
8
8
  import { MethodLabel } from "../ui/components/method-label.js";
@@ -29,7 +29,8 @@ const OauthDialogTrigger = lazy(() => import("./components/oauth-dialog.js").the
29
29
  function PlaygroundClient({ route, method = "GET", securities, parameters = [], body, references, proxyUrl, writeOnly, readOnly, ...rest }) {
30
30
  const { example: exampleId, examples, setExampleData } = useExampleRequests();
31
31
  const storageKeys = useStorageKey();
32
- const { mediaAdapters, serverRef, client: { playground: { components: { ResultDisplay = DefaultResultDisplay } = {}, requestTimeout = 10, transformAuthInputs } = {} } } = useApiContext();
32
+ const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay } = {}, requestTimeout = 10, transformAuthInputs } = {} } } = useApiContext();
33
+ const { serverRef } = useServerContext();
33
34
  const [securityId, setSecurityId] = useState(0);
34
35
  const { inputs, mapInputs, initAuthValues } = useAuthInputs(securities[securityId], transformAuthInputs);
35
36
  const defaultValues = useMemo(() => {
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { resolveServerUrl, withBase } from "../../utils/url.js";
4
- import { useApiContext, useServerSelectContext } from "../../ui/contexts/api.js";
4
+ import { useServerContext, useServerSelectContext } from "../../ui/contexts/api.js";
5
5
  import { cn } from "../../utils/cn.js";
6
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/components/select.js";
7
7
  import { Input, labelVariants } from "../../ui/components/input.js";
@@ -12,7 +12,7 @@ import { StfProvider, useFieldValue, useListener, useStf } from "@fumari/stf";
12
12
 
13
13
  //#region src/playground/components/server-select.tsx
14
14
  function ServerSelect(props) {
15
- const { servers } = useApiContext();
15
+ const { servers } = useServerContext();
16
16
  const { server, setServer, setServerVariables } = useServerSelectContext();
17
17
  const [open, setOpen] = useState(false);
18
18
  const [isMounted, setIsMounted] = useState(false);
package/dist/types.d.ts CHANGED
@@ -28,7 +28,6 @@ type MethodInformation = NoReference<OperationObject> & {
28
28
  'x-exclusiveCodeSample'?: string;
29
29
  };
30
30
  interface RenderContext extends Pick<OpenAPIOptions, 'proxyUrl'>, Omit<CreateAPIPageOptions, 'renderMarkdown'> {
31
- servers: NoReference<ServerObject>[];
32
31
  slugger: Slugger;
33
32
  /**
34
33
  * dereferenced schema
@@ -1,6 +1,6 @@
1
1
  import { createMethod } from "../utils/schema.js";
2
+ import { ApiProviderLazy, ServerProviderLazy } from "./contexts/api.lazy.js";
2
3
  import { Operation } from "./operation/index.js";
3
- import { ApiProviderLazy } from "./contexts/api.lazy.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
 
6
6
  //#region src/ui/api-page.tsx
@@ -46,11 +46,15 @@ async function APIPage({ showTitle: hasHead = false, showDescription, operations
46
46
  };
47
47
  })
48
48
  }, ctx);
49
+ let servers = ctx.schema.dereferenced.servers;
50
+ if (!servers || servers.length === 0) servers = [{ url: "/" }];
49
51
  return /* @__PURE__ */ jsx(ApiProviderLazy, {
50
- servers: ctx.servers,
51
52
  shikiOptions: ctx.shikiOptions,
52
53
  client: ctx.client ?? {},
53
- children: content
54
+ children: /* @__PURE__ */ jsx(ServerProviderLazy, {
55
+ servers,
56
+ children: content
57
+ })
54
58
  });
55
59
  }
56
60
 
package/dist/ui/base.js CHANGED
@@ -36,14 +36,11 @@ function createAPIPage(server, options) {
36
36
  let processed;
37
37
  if (typeof document === "string") processed = await server.getSchema(document);
38
38
  else processed = await document;
39
- const { dereferenced } = processed;
40
- const servers = dereferenced.servers && dereferenced.servers.length > 0 ? dereferenced.servers : [{ url: "/" }];
41
39
  const slugger = new Slugger();
42
40
  const ctx = {
43
41
  schema: processed,
44
42
  proxyUrl: server.options.proxyUrl,
45
43
  ...options,
46
- servers,
47
44
  mediaAdapters: {
48
45
  ...defaultAdapters,
49
46
  ...options.mediaAdapters
@@ -6,6 +6,7 @@ import { createContext, use, useEffect, useMemo, useRef, useState } from "react"
6
6
  import { jsx } from "react/jsx-runtime";
7
7
 
8
8
  //#region src/ui/contexts/api.tsx
9
+ const ServerContext = createContext(null);
9
10
  const ApiContext = createContext(null);
10
11
  const ServerSelectContext = createContext(null);
11
12
  function useApiContext() {
@@ -13,28 +14,34 @@ function useApiContext() {
13
14
  if (!ctx) throw new Error("Component must be used under <ApiProvider />");
14
15
  return ctx;
15
16
  }
17
+ function useServerContext() {
18
+ return use(ServerContext);
19
+ }
16
20
  function useServerSelectContext() {
17
21
  const ctx = use(ServerSelectContext);
18
22
  if (!ctx) throw new Error("Component must be used under <ApiProvider />");
19
23
  return ctx;
20
24
  }
21
- function ApiProvider({ defaultBaseUrl, children, servers, shikiOptions, client }) {
22
- const serverRef = useRef(null);
25
+ function ApiProvider({ children, shikiOptions, client }) {
23
26
  return /* @__PURE__ */ jsx(ApiContext, {
24
27
  value: useMemo(() => ({
25
- serverRef,
26
28
  shikiOptions,
27
29
  client,
28
30
  mediaAdapters: {
29
31
  ...defaultAdapters,
30
32
  ...client.mediaAdapters
31
- },
32
- servers
33
- }), [
33
+ }
34
+ }), [client, shikiOptions]),
35
+ children
36
+ });
37
+ }
38
+ function ServerProvider({ servers, defaultBaseUrl, children }) {
39
+ const serverRef = useRef(null);
40
+ return /* @__PURE__ */ jsx(ServerContext, {
41
+ value: useMemo(() => ({
34
42
  servers,
35
- client,
36
- shikiOptions
37
- ]),
43
+ serverRef
44
+ }), [servers]),
38
45
  children: /* @__PURE__ */ jsx(ServerSelectProvider, {
39
46
  defaultBaseUrl,
40
47
  children
@@ -42,7 +49,7 @@ function ApiProvider({ defaultBaseUrl, children, servers, shikiOptions, client }
42
49
  });
43
50
  }
44
51
  function ServerSelectProvider({ defaultBaseUrl, children }) {
45
- const { servers, serverRef } = useApiContext();
52
+ const { servers, serverRef } = use(ServerContext);
46
53
  const storageKeys = useStorageKey();
47
54
  const [server, setServer] = useState(() => {
48
55
  const defaultItem = defaultBaseUrl ? servers.find((item) => item.url === defaultBaseUrl) : servers[0];
@@ -101,4 +108,4 @@ function getDefaultValues(server) {
101
108
  }
102
109
 
103
110
  //#endregion
104
- export { ApiProvider, useApiContext, useServerSelectContext };
111
+ export { ApiProvider, ServerProvider, useApiContext, useServerContext, useServerSelectContext };
@@ -4,6 +4,7 @@ import { wrapLazy } from "../../utils/lazy.js";
4
4
 
5
5
  //#region src/ui/contexts/api.lazy.ts
6
6
  const ApiProviderLazy = wrapLazy(() => import("./api.js").then((mod) => ({ default: mod.ApiProvider })));
7
+ const ServerProviderLazy = wrapLazy(() => import("./api.js").then((mod) => ({ default: mod.ServerProvider })));
7
8
 
8
9
  //#endregion
9
- export { ApiProviderLazy };
10
+ export { ApiProviderLazy, ServerProviderLazy };
@@ -11,6 +11,7 @@ import { AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, Acc
11
11
  import { UsageTabs } from "./usage-tabs/index.js";
12
12
  import { CopyResponseTypeScript, SelectTab, SelectTabTrigger, SelectTabs } from "./client.js";
13
13
  import { RequestTabs, getExampleRequests } from "./request-tabs.js";
14
+ import { ServerProviderLazy } from "../contexts/api.lazy.js";
14
15
  import { Fragment } from "react";
15
16
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
17
 
@@ -211,7 +212,7 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
211
212
  });
212
213
  };
213
214
  const playgroundEnabled = ctx.playground?.enabled ?? true;
214
- const content = await renderOperationLayout({
215
+ let content = await renderOperationLayout({
215
216
  header: headNode,
216
217
  description: descriptionNode,
217
218
  authSchemes: authNode,
@@ -238,12 +239,17 @@ async function Operation({ type = "operation", path, method, ctx, showTitle, sho
238
239
  ctx
239
240
  })
240
241
  }, ctx, method);
241
- return /* @__PURE__ */ jsx(UsageTabsProviderLazy, {
242
+ content = /* @__PURE__ */ jsx(UsageTabsProviderLazy, {
242
243
  defaultExampleId: method["x-exclusiveCodeSample"] ?? method["x-selectedCodeSample"],
243
244
  route: path,
244
245
  examples: getExampleRequests(path, method, ctx),
245
246
  children: content
246
247
  });
248
+ if (method.servers) content = /* @__PURE__ */ jsx(ServerProviderLazy, {
249
+ servers: method.servers,
250
+ children: content
251
+ });
252
+ return content;
247
253
  } else {
248
254
  renderWebhookLayout ??= (slots) => /* @__PURE__ */ jsxs("div", {
249
255
  className: "flex flex-col-reverse gap-x-6 gap-y-4 @4xl:flex-row @4xl:items-start",
@@ -24,6 +24,7 @@ function createMethod(method, path, operation) {
24
24
  description: path.description,
25
25
  summary: path.summary,
26
26
  ...operation,
27
+ servers: operation.servers ?? path.servers,
27
28
  parameters: [...operation.parameters ?? [], ...path.parameters ?? []],
28
29
  method: method.toUpperCase()
29
30
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "10.3.4",
3
+ "version": "10.3.5",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "Docs",
@@ -90,8 +90,8 @@
90
90
  "tsdown": "^0.20.3",
91
91
  "@fumadocs/tailwind": "0.0.2",
92
92
  "eslint-config-custom": "0.0.0",
93
- "fumadocs-core": "16.5.4",
94
- "fumadocs-ui": "16.5.4",
93
+ "fumadocs-core": "16.6.0",
94
+ "fumadocs-ui": "16.6.0",
95
95
  "tsconfig": "0.0.0"
96
96
  },
97
97
  "peerDependencies": {
@@ -121,7 +121,7 @@
121
121
  "scripts": {
122
122
  "build": "tsdown --config-loader unrun",
123
123
  "clean": "rimraf dist",
124
- "dev": "tsdown --watch",
124
+ "dev": "tsdown --watch --clean false",
125
125
  "lint": "eslint .",
126
126
  "types:check": "tsc --noEmit"
127
127
  }