fumadocs-openapi 10.3.3 → 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.
@@ -610,6 +610,7 @@
610
610
  @source inline("red");
611
611
  @source inline("redirect_uri");
612
612
  @source inline("ref");
613
+ @source inline("reference");
613
614
  @source inline("references");
614
615
  @source inline("refs");
615
616
  @source inline("registered");
@@ -854,6 +855,7 @@
854
855
  @source inline("typeVariants");
855
856
  @source inline("typeof");
856
857
  @source inline("types");
858
+ @source inline("unchanged");
857
859
  @source inline("undefined");
858
860
  @source inline("under");
859
861
  @source inline("underline");
@@ -880,6 +882,7 @@
880
882
  @source inline("useRef");
881
883
  @source inline("useResolvedSchema");
882
884
  @source inline("useSchemaScope");
885
+ @source inline("useServerContext");
883
886
  @source inline("useServerSelectContext");
884
887
  @source inline("useState");
885
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(() => {
@@ -77,9 +78,8 @@ function PlaygroundClient({ route, method = "GET", securities, parameters = [],
77
78
  }
78
79
  });
79
80
  useEffect(() => {
80
- return () => {
81
- stf.dataEngine.reset(defaultValues);
82
- };
81
+ if (stf.dataEngine.getData() === defaultValues) return;
82
+ stf.dataEngine.reset(defaultValues);
83
83
  }, [defaultValues]);
84
84
  useEffect(() => {
85
85
  return initAuthValues(stf);
@@ -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",
@@ -16,7 +16,7 @@ function UsageTabsProvider({ route, examples, defaultExampleId, children }) {
16
16
  value: useMemo(() => ({
17
17
  example,
18
18
  route,
19
- setExample: (newKey) => {
19
+ setExample(newKey) {
20
20
  const example = examples.find((example) => example.id === newKey);
21
21
  if (!example) return;
22
22
  setExample(newKey);
@@ -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.3",
3
+ "version": "10.3.5",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "Docs",
@@ -76,7 +76,7 @@
76
76
  "remark-rehype": "^11.1.2",
77
77
  "tailwind-merge": "^3.4.0",
78
78
  "xml-js": "^1.6.11",
79
- "@fumari/stf": "^0.0.2"
79
+ "@fumari/stf": "^0.0.3"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@scalar/api-client-react": "^1.3.91",
@@ -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.2",
94
- "fumadocs-ui": "16.5.2",
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
  }