fumadocs-openapi 10.5.0 → 10.6.1

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 (125) hide show
  1. package/css/generated/shared.css +33 -21
  2. package/dist/generate-file.d.ts +10 -2
  3. package/dist/generate-file.d.ts.map +1 -1
  4. package/dist/generate-file.js +15 -3
  5. package/dist/generate-file.js.map +1 -1
  6. package/dist/playground/client.d.ts +32 -10
  7. package/dist/playground/client.d.ts.map +1 -1
  8. package/dist/playground/client.js +70 -60
  9. package/dist/playground/client.js.map +1 -1
  10. package/dist/playground/components/inputs.js +1 -1
  11. package/dist/playground/components/inputs.js.map +1 -1
  12. package/dist/playground/components/server-select.js +3 -4
  13. package/dist/playground/components/server-select.js.map +1 -1
  14. package/dist/playground/fetcher.d.ts +20 -1
  15. package/dist/playground/fetcher.d.ts.map +1 -1
  16. package/dist/playground/fetcher.js +28 -24
  17. package/dist/playground/fetcher.js.map +1 -1
  18. package/dist/playground/index.d.ts +3 -3
  19. package/dist/playground/index.d.ts.map +1 -1
  20. package/dist/playground/index.js +2 -2
  21. package/dist/playground/index.js.map +1 -1
  22. package/dist/playground/schema.d.ts +1 -0
  23. package/dist/playground/schema.d.ts.map +1 -1
  24. package/dist/playground/schema.js +10 -12
  25. package/dist/playground/schema.js.map +1 -1
  26. package/dist/requests/generators/python.d.ts +2 -1
  27. package/dist/requests/generators/python.d.ts.map +1 -1
  28. package/dist/requests/generators/python.js +13 -2
  29. package/dist/requests/generators/python.js.map +1 -1
  30. package/dist/scalar/index.d.ts +2 -1
  31. package/dist/scalar/index.d.ts.map +1 -1
  32. package/dist/server/create.d.ts +2 -0
  33. package/dist/server/create.d.ts.map +1 -1
  34. package/dist/server/create.js +11 -8
  35. package/dist/server/create.js.map +1 -1
  36. package/dist/server/proxy.d.ts +5 -2
  37. package/dist/server/proxy.d.ts.map +1 -1
  38. package/dist/server/proxy.js +41 -31
  39. package/dist/server/proxy.js.map +1 -1
  40. package/dist/server/source-api.d.ts +2 -0
  41. package/dist/server/source-api.d.ts.map +1 -1
  42. package/dist/server/source-api.js +10 -1
  43. package/dist/server/source-api.js.map +1 -1
  44. package/dist/types.d.ts +2 -4
  45. package/dist/types.d.ts.map +1 -1
  46. package/dist/ui/api-page.d.ts +1 -3
  47. package/dist/ui/api-page.d.ts.map +1 -1
  48. package/dist/ui/api-page.js +4 -6
  49. package/dist/ui/api-page.js.map +1 -1
  50. package/dist/ui/base.d.ts +20 -16
  51. package/dist/ui/base.d.ts.map +1 -1
  52. package/dist/ui/base.js +18 -9
  53. package/dist/ui/base.js.map +1 -1
  54. package/dist/ui/{full.client.js → client/full.js} +3 -3
  55. package/dist/ui/client/full.js.map +1 -0
  56. package/dist/ui/client/index.d.ts +1 -1
  57. package/dist/ui/client/index.js.map +1 -1
  58. package/dist/ui/client/storage-key.js.map +1 -1
  59. package/dist/ui/components/codeblock.d.ts +2 -2
  60. package/dist/ui/components/codeblock.d.ts.map +1 -1
  61. package/dist/ui/components/server-tab.js +43 -0
  62. package/dist/ui/components/server-tab.js.map +1 -0
  63. package/dist/ui/contexts/api.js +18 -35
  64. package/dist/ui/contexts/api.js.map +1 -1
  65. package/dist/ui/create-client.d.ts +26 -0
  66. package/dist/ui/create-client.d.ts.map +1 -0
  67. package/dist/ui/create-client.js +132 -0
  68. package/dist/ui/create-client.js.map +1 -0
  69. package/dist/ui/index.d.ts +10 -2
  70. package/dist/ui/index.d.ts.map +1 -0
  71. package/dist/ui/index.js +21 -1
  72. package/dist/ui/index.js.map +1 -0
  73. package/dist/ui/operation/client.js +44 -36
  74. package/dist/ui/operation/client.js.map +1 -1
  75. package/dist/ui/operation/{request-tabs.d.ts → get-example-requests.d.ts} +2 -4
  76. package/dist/ui/operation/get-example-requests.d.ts.map +1 -0
  77. package/dist/ui/operation/get-example-requests.js +83 -0
  78. package/dist/ui/operation/get-example-requests.js.map +1 -0
  79. package/dist/ui/operation/index.js +101 -63
  80. package/dist/ui/operation/index.js.map +1 -1
  81. package/dist/ui/operation/request-tabs.js +3 -81
  82. package/dist/ui/operation/request-tabs.js.map +1 -1
  83. package/dist/ui/operation/response-tabs.d.ts +1 -1
  84. package/dist/ui/operation/response-tabs.js +57 -54
  85. package/dist/ui/operation/response-tabs.js.map +1 -1
  86. package/dist/ui/operation/usage-tabs/client.js +7 -48
  87. package/dist/ui/operation/usage-tabs/client.js.map +1 -1
  88. package/dist/ui/operation/usage-tabs/index.js +14 -10
  89. package/dist/ui/operation/usage-tabs/index.js.map +1 -1
  90. package/dist/ui/operation/usage-tabs/lazy.js +1 -2
  91. package/dist/ui/operation/usage-tabs/lazy.js.map +1 -1
  92. package/dist/ui/schema/client.d.ts +0 -1
  93. package/dist/ui/schema/client.d.ts.map +1 -1
  94. package/dist/ui/schema/index.d.ts +1 -2
  95. package/dist/ui/schema/index.d.ts.map +1 -1
  96. package/dist/ui/schema/index.js +4 -2
  97. package/dist/ui/schema/index.js.map +1 -1
  98. package/dist/utils/pages/builder.d.ts +1 -1
  99. package/dist/utils/pages/builder.js +1 -1
  100. package/dist/utils/process-document.d.ts +1 -1
  101. package/dist/utils/process-document.js +1 -32
  102. package/dist/utils/process-document.js.map +1 -1
  103. package/dist/utils/schema/dereference.js +37 -0
  104. package/dist/utils/schema/dereference.js.map +1 -0
  105. package/dist/utils/{schema.d.ts → schema/index.d.ts} +3 -3
  106. package/dist/utils/schema/index.d.ts.map +1 -0
  107. package/dist/utils/{schema.js → schema/index.js} +3 -3
  108. package/dist/utils/schema/index.js.map +1 -0
  109. package/dist/utils/schema/resolve-ref.js +21 -0
  110. package/dist/utils/schema/resolve-ref.js.map +1 -0
  111. package/dist/utils/{schema-to-string.js → schema/to-string.js} +2 -2
  112. package/dist/utils/schema/to-string.js.map +1 -0
  113. package/package.json +10 -10
  114. package/dist/requests/to-python-object.js +0 -17
  115. package/dist/requests/to-python-object.js.map +0 -1
  116. package/dist/ui/full.client.js.map +0 -1
  117. package/dist/ui/full.d.ts +0 -11
  118. package/dist/ui/full.d.ts.map +0 -1
  119. package/dist/ui/full.js +0 -36
  120. package/dist/ui/full.js.map +0 -1
  121. package/dist/ui/operation/request-tabs.d.ts.map +0 -1
  122. package/dist/utils/schema-to-string.js.map +0 -1
  123. package/dist/utils/schema.d.ts.map +0 -1
  124. package/dist/utils/schema.js.map +0 -1
  125. /package/dist/utils/{schema-to-string.d.ts → schema/to-string.d.ts} +0 -0
@@ -3,22 +3,18 @@ import { defaultAdapters } from "../../requests/media/adapter.js";
3
3
  import { useStorageKey } from "../client/storage-key.js";
4
4
  import { createCodeUsageGeneratorRegistry } from "../../requests/generators/index.js";
5
5
  import { registerDefault } from "../../requests/generators/all.js";
6
- import { createContext, use, useEffect, useMemo, useRef, useState } from "react";
6
+ import { createContext, use, useEffect, useMemo, useState } from "react";
7
7
  import { jsx } from "react/jsx-runtime";
8
8
  //#region src/ui/contexts/api.tsx
9
- const ServerContext = createContext(null);
10
9
  const ApiContext = createContext(null);
11
- const ServerSelectContext = createContext(null);
10
+ const ServerContext = createContext(null);
12
11
  function useApiContext() {
13
12
  const ctx = use(ApiContext);
14
13
  if (!ctx) throw new Error("Component must be used under <ApiProvider />");
15
14
  return ctx;
16
15
  }
17
16
  function useServerContext() {
18
- return use(ServerContext);
19
- }
20
- function useServerSelectContext() {
21
- const ctx = use(ServerSelectContext);
17
+ const ctx = use(ServerContext);
22
18
  if (!ctx) throw new Error("Component must be used under <ApiProvider />");
23
19
  return ctx;
24
20
  }
@@ -44,41 +40,28 @@ function ApiProvider({ children, shikiOptions, client }) {
44
40
  children
45
41
  });
46
42
  }
47
- function ServerProvider({ servers, defaultBaseUrl, children }) {
48
- const serverRef = useRef(null);
49
- return /* @__PURE__ */ jsx(ServerContext, {
50
- value: useMemo(() => ({
51
- servers,
52
- serverRef
53
- }), [servers]),
54
- children: /* @__PURE__ */ jsx(ServerSelectProvider, {
55
- defaultBaseUrl,
56
- children
57
- })
58
- });
59
- }
60
- function ServerSelectProvider({ defaultBaseUrl, children }) {
61
- const { servers, serverRef } = use(ServerContext);
62
- const storageKeys = useStorageKey();
43
+ function ServerProvider({ servers, children }) {
44
+ const storageKey = useStorageKey().of("server-url");
63
45
  const [server, setServer] = useState(() => {
64
- const defaultItem = defaultBaseUrl ? servers.find((item) => item.url === defaultBaseUrl) : servers[0];
65
- return defaultItem ? {
46
+ if (!servers || servers.length === 0) return null;
47
+ const defaultItem = servers[0];
48
+ return {
66
49
  name: defaultItem.name,
67
50
  url: defaultItem.url,
68
51
  variables: getDefaultValues(defaultItem)
69
- } : null;
52
+ };
70
53
  });
71
- serverRef.current = server;
72
54
  useEffect(() => {
73
- const cached = localStorage.getItem(storageKeys.of("server-url"));
55
+ const cached = localStorage.getItem(storageKey);
74
56
  if (!cached) return;
75
57
  try {
76
58
  const obj = JSON.parse(cached);
77
59
  if (typeof obj === "object" && obj !== null && "url" in obj && typeof obj.url === "string" && "variables" in obj && typeof obj.variables === "object" && obj.variables !== null) setServer(obj);
78
60
  } catch {}
79
- }, [storageKeys]);
80
- return /* @__PURE__ */ jsx(ServerSelectContext, {
61
+ }, [storageKey]);
62
+ return /* @__PURE__ */ jsx(ServerContext, {
81
63
  value: useMemo(() => ({
64
+ servers,
82
65
  server,
83
66
  setServerVariables(variables) {
84
67
  setServer((prev) => {
@@ -87,25 +70,25 @@ function ServerSelectProvider({ defaultBaseUrl, children }) {
87
70
  ...prev,
88
71
  variables
89
72
  };
90
- localStorage.setItem(storageKeys.of("server-url"), JSON.stringify(updated));
73
+ localStorage.setItem(storageKey, JSON.stringify(updated));
91
74
  return updated;
92
75
  });
93
76
  },
94
77
  setServer(value) {
95
- const obj = servers.find((item) => item.url === value);
78
+ const obj = servers?.find((item) => item.url === value);
96
79
  if (!obj) return;
97
80
  const result = {
98
81
  name: obj.name,
99
82
  url: value,
100
83
  variables: getDefaultValues(obj)
101
84
  };
102
- localStorage.setItem(storageKeys.of("server-url"), JSON.stringify(result));
85
+ localStorage.setItem(storageKey, JSON.stringify(result));
103
86
  setServer(result);
104
87
  }
105
88
  }), [
106
89
  server,
107
90
  servers,
108
- storageKeys
91
+ storageKey
109
92
  ]),
110
93
  children
111
94
  });
@@ -117,6 +100,6 @@ function getDefaultValues(server) {
117
100
  return out;
118
101
  }
119
102
  //#endregion
120
- export { ApiProvider, ServerProvider, useApiContext, useServerContext, useServerSelectContext };
103
+ export { ApiProvider, ServerProvider, useApiContext, useServerContext };
121
104
 
122
105
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","names":[],"sources":["../../../src/ui/contexts/api.tsx"],"sourcesContent":["'use client';\nimport {\n createContext,\n type ReactNode,\n type RefObject,\n use,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { RenderContext, ServerObject } from '@/types';\nimport { defaultAdapters, type MediaAdapter } from '@/requests/media/adapter';\nimport type { NoReference } from '@/utils/schema';\nimport { useStorageKey } from '../client/storage-key';\nimport type { APIPageClientOptions } from '../client';\nimport {\n type CodeUsageGeneratorRegistry,\n createCodeUsageGeneratorRegistry,\n} from '@/requests/generators';\nimport { registerDefault } from '@/requests/generators/all';\n\ninterface InheritFromContext extends Pick<RenderContext, 'shikiOptions'> {\n client: APIPageClientOptions;\n}\n\nexport interface ServerProviderProps {\n /**\n * Base URL for API requests\n */\n defaultBaseUrl?: string;\n\n servers: NoReference<ServerObject>[];\n}\n\ninterface ServerContextType extends ServerProviderProps {\n /**\n * ref to selected API server (to query)\n */\n serverRef: RefObject<SelectedServer | null>;\n}\n\nconst ServerContext = createContext<ServerContextType | null>(null);\n\nexport type ApiProviderProps = InheritFromContext;\n\nexport interface SelectedServer {\n url: string;\n name?: string;\n variables: Record<string, string>;\n}\n\ninterface ApiContextType extends InheritFromContext {\n mediaAdapters: Record<string, MediaAdapter>;\n codeUsages: CodeUsageGeneratorRegistry;\n}\n\ninterface ServerSelectType {\n server: SelectedServer | null;\n setServer: (value: string) => void;\n setServerVariables: (value: Record<string, string>) => void;\n}\n\nconst ApiContext = createContext<ApiContextType | null>(null);\nconst ServerSelectContext = createContext<ServerSelectType | null>(null);\n\nexport function useApiContext(): ApiContextType {\n const ctx = use(ApiContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function useServerContext() {\n return use(ServerContext)!;\n}\n\nexport function useServerSelectContext(): ServerSelectType {\n const ctx = use(ServerSelectContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function ApiProvider({\n children,\n shikiOptions,\n client,\n}: ApiProviderProps & { children: ReactNode }) {\n return (\n <ApiContext\n value={useMemo(() => {\n let codeUsages: CodeUsageGeneratorRegistry;\n if (client.codeUsages) {\n codeUsages = createCodeUsageGeneratorRegistry(client.codeUsages);\n } else {\n codeUsages = createCodeUsageGeneratorRegistry();\n registerDefault(codeUsages);\n }\n\n return {\n shikiOptions,\n client,\n codeUsages,\n mediaAdapters: {\n ...defaultAdapters,\n ...client.mediaAdapters,\n },\n };\n }, [client, shikiOptions])}\n >\n {children}\n </ApiContext>\n );\n}\n\nexport function ServerProvider({\n servers,\n defaultBaseUrl,\n children,\n}: ServerProviderProps & { children: ReactNode }) {\n const serverRef = useRef<SelectedServer | null>(null);\n\n return (\n <ServerContext value={useMemo(() => ({ servers, serverRef }), [servers])}>\n <ServerSelectProvider defaultBaseUrl={defaultBaseUrl}>{children}</ServerSelectProvider>\n </ServerContext>\n );\n}\n\nfunction ServerSelectProvider({\n defaultBaseUrl,\n children,\n}: Pick<ServerProviderProps, 'defaultBaseUrl'> & {\n children: ReactNode;\n}) {\n const { servers, serverRef } = use(ServerContext)!;\n const storageKeys = useStorageKey();\n const [server, setServer] = useState<SelectedServer | null>(() => {\n const defaultItem = defaultBaseUrl\n ? servers.find((item) => item.url === defaultBaseUrl)\n : servers[0];\n\n return defaultItem\n ? {\n name: defaultItem.name,\n url: defaultItem.url!,\n variables: getDefaultValues(defaultItem),\n }\n : null;\n });\n serverRef.current = server;\n\n useEffect(() => {\n const cached = localStorage.getItem(storageKeys.of('server-url'));\n if (!cached) return;\n\n try {\n const obj: unknown = JSON.parse(cached);\n if (\n typeof obj === 'object' &&\n obj !== null &&\n 'url' in obj &&\n typeof obj.url === 'string' &&\n 'variables' in obj &&\n typeof obj.variables === 'object' &&\n obj.variables !== null\n ) {\n setServer(obj as SelectedServer);\n }\n } catch {\n // ignore\n }\n }, [storageKeys]);\n\n return (\n <ServerSelectContext\n value={useMemo(\n () => ({\n server,\n setServerVariables(variables) {\n setServer((prev) => {\n if (!prev) return null;\n\n const updated = { ...prev, variables };\n localStorage.setItem(storageKeys.of('server-url'), JSON.stringify(updated));\n return updated;\n });\n },\n setServer(value) {\n const obj = servers.find((item) => item.url === value);\n if (!obj) return;\n\n const result: SelectedServer = {\n name: obj.name,\n url: value,\n variables: getDefaultValues(obj),\n };\n\n localStorage.setItem(storageKeys.of('server-url'), JSON.stringify(result));\n setServer(result);\n },\n }),\n [server, servers, storageKeys],\n )}\n >\n {children}\n </ServerSelectContext>\n );\n}\n\nfunction getDefaultValues(server: NoReference<ServerObject>): Record<string, string> {\n const out: Record<string, string> = {};\n if (!server.variables) return out;\n\n for (const [k, v] of Object.entries(server.variables)) {\n if (v.default !== undefined) out[k] = String(v.default);\n }\n\n return out;\n}\n"],"mappings":";;;;;;;;AA0CA,MAAM,gBAAgB,cAAwC,KAAK;AAqBnE,MAAM,aAAa,cAAqC,KAAK;AAC7D,MAAM,sBAAsB,cAAuC,KAAK;AAExE,SAAgB,gBAAgC;CAC9C,MAAM,MAAM,IAAI,WAAW;AAC3B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,mBAAmB;AACjC,QAAO,IAAI,cAAc;;AAG3B,SAAgB,yBAA2C;CACzD,MAAM,MAAM,IAAI,oBAAoB;AACpC,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,YAAY,EAC1B,UACA,cACA,UAC6C;AAC7C,QACE,oBAAC,YAAD;EACE,OAAO,cAAc;GACnB,IAAI;AACJ,OAAI,OAAO,WACT,cAAa,iCAAiC,OAAO,WAAW;QAC3D;AACL,iBAAa,kCAAkC;AAC/C,oBAAgB,WAAW;;AAG7B,UAAO;IACL;IACA;IACA;IACA,eAAe;KACb,GAAG;KACH,GAAG,OAAO;KACX;IACF;KACA,CAAC,QAAQ,aAAa,CAAC;EAEzB;EACU,CAAA;;AAIjB,SAAgB,eAAe,EAC7B,SACA,gBACA,YACgD;CAChD,MAAM,YAAY,OAA8B,KAAK;AAErD,QACE,oBAAC,eAAD;EAAe,OAAO,eAAe;GAAE;GAAS;GAAW,GAAG,CAAC,QAAQ,CAAC;YACtE,oBAAC,sBAAD;GAAsC;GAAiB;GAAgC,CAAA;EACzE,CAAA;;AAIpB,SAAS,qBAAqB,EAC5B,gBACA,YAGC;CACD,MAAM,EAAE,SAAS,cAAc,IAAI,cAAc;CACjD,MAAM,cAAc,eAAe;CACnC,MAAM,CAAC,QAAQ,aAAa,eAAsC;EAChE,MAAM,cAAc,iBAChB,QAAQ,MAAM,SAAS,KAAK,QAAQ,eAAe,GACnD,QAAQ;AAEZ,SAAO,cACH;GACE,MAAM,YAAY;GAClB,KAAK,YAAY;GACjB,WAAW,iBAAiB,YAAY;GACzC,GACD;GACJ;AACF,WAAU,UAAU;AAEpB,iBAAgB;EACd,MAAM,SAAS,aAAa,QAAQ,YAAY,GAAG,aAAa,CAAC;AACjE,MAAI,CAAC,OAAQ;AAEb,MAAI;GACF,MAAM,MAAe,KAAK,MAAM,OAAO;AACvC,OACE,OAAO,QAAQ,YACf,QAAQ,QACR,SAAS,OACT,OAAO,IAAI,QAAQ,YACnB,eAAe,OACf,OAAO,IAAI,cAAc,YACzB,IAAI,cAAc,KAElB,WAAU,IAAsB;UAE5B;IAGP,CAAC,YAAY,CAAC;AAEjB,QACE,oBAAC,qBAAD;EACE,OAAO,eACE;GACL;GACA,mBAAmB,WAAW;AAC5B,eAAW,SAAS;AAClB,SAAI,CAAC,KAAM,QAAO;KAElB,MAAM,UAAU;MAAE,GAAG;MAAM;MAAW;AACtC,kBAAa,QAAQ,YAAY,GAAG,aAAa,EAAE,KAAK,UAAU,QAAQ,CAAC;AAC3E,YAAO;MACP;;GAEJ,UAAU,OAAO;IACf,MAAM,MAAM,QAAQ,MAAM,SAAS,KAAK,QAAQ,MAAM;AACtD,QAAI,CAAC,IAAK;IAEV,MAAM,SAAyB;KAC7B,MAAM,IAAI;KACV,KAAK;KACL,WAAW,iBAAiB,IAAI;KACjC;AAED,iBAAa,QAAQ,YAAY,GAAG,aAAa,EAAE,KAAK,UAAU,OAAO,CAAC;AAC1E,cAAU,OAAO;;GAEpB,GACD;GAAC;GAAQ;GAAS;GAAY,CAC/B;EAEA;EACmB,CAAA;;AAI1B,SAAS,iBAAiB,QAA2D;CACnF,MAAM,MAA8B,EAAE;AACtC,KAAI,CAAC,OAAO,UAAW,QAAO;AAE9B,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,OAAO,UAAU,CACnD,KAAI,EAAE,YAAY,KAAA,EAAW,KAAI,KAAK,OAAO,EAAE,QAAQ;AAGzD,QAAO"}
1
+ {"version":3,"file":"api.js","names":[],"sources":["../../../src/ui/contexts/api.tsx"],"sourcesContent":["'use client';\nimport { createContext, type ReactNode, use, useEffect, useMemo, useState } from 'react';\nimport type { RenderContext, ServerObject } from '@/types';\nimport { defaultAdapters, type MediaAdapter } from '@/requests/media/adapter';\nimport { useStorageKey } from '../client/storage-key';\nimport type { APIPageClientOptions } from '../client';\nimport {\n type CodeUsageGeneratorRegistry,\n createCodeUsageGeneratorRegistry,\n} from '@/requests/generators';\nimport { registerDefault } from '@/requests/generators/all';\n\ninterface InheritFromContext extends Pick<RenderContext, 'shikiOptions'> {\n client: APIPageClientOptions;\n}\n\ninterface ServerContextType {\n servers?: ServerObject[];\n server: SelectedServer | null;\n setServer: (value: string) => void;\n setServerVariables: (value: Record<string, string>) => void;\n}\n\nexport type ApiProviderProps = InheritFromContext;\n\nexport interface SelectedServer {\n url: string;\n name?: string;\n variables: Record<string, string>;\n}\n\ninterface ApiContextType extends InheritFromContext {\n mediaAdapters: Record<string, MediaAdapter>;\n codeUsages: CodeUsageGeneratorRegistry;\n}\n\nconst ApiContext = createContext<ApiContextType | null>(null);\nconst ServerContext = createContext<ServerContextType | null>(null);\n\nexport function useApiContext(): ApiContextType {\n const ctx = use(ApiContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function useServerContext() {\n const ctx = use(ServerContext);\n if (!ctx) throw new Error('Component must be used under <ApiProvider />');\n\n return ctx;\n}\n\nexport function ApiProvider({\n children,\n shikiOptions,\n client,\n}: ApiProviderProps & { children: ReactNode }) {\n return (\n <ApiContext\n value={useMemo(() => {\n let codeUsages: CodeUsageGeneratorRegistry;\n if (client.codeUsages) {\n codeUsages = createCodeUsageGeneratorRegistry(client.codeUsages);\n } else {\n codeUsages = createCodeUsageGeneratorRegistry();\n registerDefault(codeUsages);\n }\n\n return {\n shikiOptions,\n client,\n codeUsages,\n mediaAdapters: {\n ...defaultAdapters,\n ...client.mediaAdapters,\n },\n };\n }, [client, shikiOptions])}\n >\n {children}\n </ApiContext>\n );\n}\n\nexport function ServerProvider({\n servers,\n children,\n}: {\n servers?: ServerObject[];\n children: ReactNode;\n}) {\n const storageKey = useStorageKey().of('server-url');\n const [server, setServer] = useState<SelectedServer | null>(() => {\n if (!servers || servers.length === 0) return null;\n const defaultItem = servers[0];\n\n return {\n name: defaultItem.name,\n url: defaultItem.url!,\n variables: getDefaultValues(defaultItem),\n };\n });\n\n useEffect(() => {\n const cached = localStorage.getItem(storageKey);\n if (!cached) return;\n\n try {\n const obj: unknown = JSON.parse(cached);\n if (\n typeof obj === 'object' &&\n obj !== null &&\n 'url' in obj &&\n typeof obj.url === 'string' &&\n 'variables' in obj &&\n typeof obj.variables === 'object' &&\n obj.variables !== null\n ) {\n setServer(obj as SelectedServer);\n }\n } catch {\n // ignore\n }\n }, [storageKey]);\n\n return (\n <ServerContext\n value={useMemo(\n () => ({\n servers,\n server,\n setServerVariables(variables) {\n setServer((prev) => {\n if (!prev) return null;\n\n const updated = { ...prev, variables };\n localStorage.setItem(storageKey, JSON.stringify(updated));\n return updated;\n });\n },\n setServer(value) {\n const obj = servers?.find((item) => item.url === value);\n if (!obj) return;\n\n const result: SelectedServer = {\n name: obj.name,\n url: value,\n variables: getDefaultValues(obj),\n };\n\n localStorage.setItem(storageKey, JSON.stringify(result));\n setServer(result);\n },\n }),\n [server, servers, storageKey],\n )}\n >\n {children}\n </ServerContext>\n );\n}\n\nfunction getDefaultValues(server: ServerObject): Record<string, string> {\n const out: Record<string, string> = {};\n if (!server.variables) return out;\n\n for (const [k, v] of Object.entries(server.variables)) {\n if (v.default !== undefined) out[k] = String(v.default);\n }\n\n return out;\n}\n"],"mappings":";;;;;;;;AAoCA,MAAM,aAAa,cAAqC,KAAK;AAC7D,MAAM,gBAAgB,cAAwC,KAAK;AAEnE,SAAgB,gBAAgC;CAC9C,MAAM,MAAM,IAAI,WAAW;AAC3B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,mBAAmB;CACjC,MAAM,MAAM,IAAI,cAAc;AAC9B,KAAI,CAAC,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAEzE,QAAO;;AAGT,SAAgB,YAAY,EAC1B,UACA,cACA,UAC6C;AAC7C,QACE,oBAAC,YAAD;EACE,OAAO,cAAc;GACnB,IAAI;AACJ,OAAI,OAAO,WACT,cAAa,iCAAiC,OAAO,WAAW;QAC3D;AACL,iBAAa,kCAAkC;AAC/C,oBAAgB,WAAW;;AAG7B,UAAO;IACL;IACA;IACA;IACA,eAAe;KACb,GAAG;KACH,GAAG,OAAO;KACX;IACF;KACA,CAAC,QAAQ,aAAa,CAAC;EAEzB;EACU,CAAA;;AAIjB,SAAgB,eAAe,EAC7B,SACA,YAIC;CACD,MAAM,aAAa,eAAe,CAAC,GAAG,aAAa;CACnD,MAAM,CAAC,QAAQ,aAAa,eAAsC;AAChE,MAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;EAC7C,MAAM,cAAc,QAAQ;AAE5B,SAAO;GACL,MAAM,YAAY;GAClB,KAAK,YAAY;GACjB,WAAW,iBAAiB,YAAY;GACzC;GACD;AAEF,iBAAgB;EACd,MAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,MAAI,CAAC,OAAQ;AAEb,MAAI;GACF,MAAM,MAAe,KAAK,MAAM,OAAO;AACvC,OACE,OAAO,QAAQ,YACf,QAAQ,QACR,SAAS,OACT,OAAO,IAAI,QAAQ,YACnB,eAAe,OACf,OAAO,IAAI,cAAc,YACzB,IAAI,cAAc,KAElB,WAAU,IAAsB;UAE5B;IAGP,CAAC,WAAW,CAAC;AAEhB,QACE,oBAAC,eAAD;EACE,OAAO,eACE;GACL;GACA;GACA,mBAAmB,WAAW;AAC5B,eAAW,SAAS;AAClB,SAAI,CAAC,KAAM,QAAO;KAElB,MAAM,UAAU;MAAE,GAAG;MAAM;MAAW;AACtC,kBAAa,QAAQ,YAAY,KAAK,UAAU,QAAQ,CAAC;AACzD,YAAO;MACP;;GAEJ,UAAU,OAAO;IACf,MAAM,MAAM,SAAS,MAAM,SAAS,KAAK,QAAQ,MAAM;AACvD,QAAI,CAAC,IAAK;IAEV,MAAM,SAAyB;KAC7B,MAAM,IAAI;KACV,KAAK;KACL,WAAW,iBAAiB,IAAI;KACjC;AAED,iBAAa,QAAQ,YAAY,KAAK,UAAU,OAAO,CAAC;AACxD,cAAU,OAAO;;GAEpB,GACD;GAAC;GAAQ;GAAS;GAAW,CAC9B;EAEA;EACa,CAAA;;AAIpB,SAAS,iBAAiB,QAA8C;CACtE,MAAM,MAA8B,EAAE;AACtC,KAAI,CAAC,OAAO,UAAW,QAAO;AAE9B,MAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,OAAO,UAAU,CACnD,KAAI,EAAE,YAAY,KAAA,EAAW,KAAI,KAAK,OAAO,EAAE,QAAQ;AAGzD,QAAO"}
@@ -0,0 +1,26 @@
1
+ import { ApiPageProps } from "./api-page.js";
2
+ import { CreateAPIPageOptions } from "./base.js";
3
+ import { Document } from "../types.js";
4
+ import { FC } from "react";
5
+
6
+ //#region src/ui/create-client.d.ts
7
+ interface ClientApiPageProps extends Omit<ApiPageProps, 'document'> {
8
+ payload: ClientApiPagePayload;
9
+ }
10
+ interface ClientApiPagePayload {
11
+ bundled: Document;
12
+ proxyUrl?: string;
13
+ }
14
+ type CreateClientAPIPageOptions = Omit<Partial<CreateAPIPageOptions>, 'generateTypeScriptSchema'>;
15
+ /**
16
+ * Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.
17
+ */
18
+ declare function createClientAPIPage({
19
+ shiki,
20
+ shikiOptions,
21
+ generateTypeScriptDefinitions,
22
+ ...options
23
+ }?: CreateClientAPIPageOptions): FC<ClientApiPageProps>;
24
+ //#endregion
25
+ export { ClientApiPagePayload, ClientApiPageProps, CreateClientAPIPageOptions, createClientAPIPage };
26
+ //# sourceMappingURL=create-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-client.d.ts","names":[],"sources":["../../src/ui/create-client.tsx"],"mappings":";;;;;;UA6BiB,kBAAA,SAA2B,IAAA,CAAK,YAAA;EAC/C,OAAA,EAAS,oBAAA;AAAA;AAAA,UAGM,oBAAA;EACf,OAAA,EAAS,QAAA;EACT,QAAA;AAAA;AAAA,KAGU,0BAAA,GAA6B,IAAA,CACvC,OAAA,CAAQ,oBAAA;;;;iBAOM,mBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,6BAAA;EAAA,GAcG;AAAA,IACF,0BAAA,GAAkC,EAAA,CAAG,kBAAA"}
@@ -0,0 +1,132 @@
1
+ import { defaultAdapters } from "../requests/media/adapter.js";
2
+ import { ClientCodeBlock, ClientCodeBlockProvider } from "./components/codeblock.js";
3
+ import { dereferenceSync } from "../utils/schema/dereference.js";
4
+ import { APIPage } from "./api-page.js";
5
+ import { slug } from "github-slugger";
6
+ import { Children, useMemo } from "react";
7
+ import * as JsxRuntime from "react/jsx-runtime";
8
+ import { jsx } from "react/jsx-runtime";
9
+ import { Heading } from "fumadocs-ui/components/heading";
10
+ import { remarkGfm } from "fumadocs-core/mdx-plugins/remark-gfm";
11
+ import defaultMdxComponents from "fumadocs-ui/mdx";
12
+ import { remark } from "remark";
13
+ import remarkRehype from "remark-rehype";
14
+ import { toJsxRuntime } from "hast-util-to-jsx-runtime";
15
+ import { compile } from "@fumari/json-schema-ts";
16
+ import { defaultShikiFactory } from "fumadocs-core/highlight/shiki/full";
17
+ //#region src/ui/create-client.tsx
18
+ /**
19
+ * Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.
20
+ */
21
+ function createClientAPIPage({ shiki = defaultShikiFactory, shikiOptions = { themes: {
22
+ light: "github-light",
23
+ dark: "github-dark"
24
+ } }, generateTypeScriptDefinitions = (schema, ctx) => {
25
+ if (typeof schema !== "object") return;
26
+ try {
27
+ return compile(schema, {
28
+ name: "Response",
29
+ readOnly: ctx.readOnly,
30
+ writeOnly: ctx.writeOnly,
31
+ getSchemaId: ctx.schema.getRawRef
32
+ });
33
+ } catch (e) {
34
+ console.warn("Failed to generate typescript schema:", e);
35
+ }
36
+ }, ...options } = {}) {
37
+ let processor;
38
+ const mdxComponents = {
39
+ ...defaultMdxComponents,
40
+ img: void 0,
41
+ pre: MarkdownPre
42
+ };
43
+ function createMarkdownProcessor() {
44
+ function rehypeReact() {
45
+ this.compiler = (tree, file) => {
46
+ return toJsxRuntime(tree, {
47
+ development: false,
48
+ filePath: file.path,
49
+ ...JsxRuntime,
50
+ components: mdxComponents
51
+ });
52
+ };
53
+ }
54
+ return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);
55
+ }
56
+ return function ClientAPIPage({ payload, ...props }) {
57
+ const processed = useMemo(() => {
58
+ const dereferenceMap = /* @__PURE__ */ new Map();
59
+ return {
60
+ bundled: payload.bundled,
61
+ dereferenced: dereferenceSync(payload.bundled, (schema, ref) => {
62
+ dereferenceMap.set(schema, ref);
63
+ }),
64
+ getRawRef(obj) {
65
+ return dereferenceMap.get(obj);
66
+ }
67
+ };
68
+ }, [payload.bundled]);
69
+ const ctx = useMemo(() => ({
70
+ schema: processed,
71
+ proxyUrl: payload.proxyUrl,
72
+ shiki,
73
+ shikiOptions,
74
+ generateTypeScriptDefinitions,
75
+ ...options,
76
+ mediaAdapters: {
77
+ ...defaultAdapters,
78
+ ...options.mediaAdapters
79
+ },
80
+ renderHeading(depth, text, props) {
81
+ const id = typeof text === "string" ? slug(text) : props?.id;
82
+ if (!id) throw new Error("missing 'id' for non-string children");
83
+ if (options.renderHeading) return options.renderHeading({
84
+ id,
85
+ children: text,
86
+ ...props
87
+ }, depth);
88
+ return /* @__PURE__ */ jsx(Heading, {
89
+ id,
90
+ as: `h${depth}`,
91
+ ...props,
92
+ children: text
93
+ }, id);
94
+ },
95
+ renderMarkdown(text) {
96
+ if (options.renderMarkdown) return options.renderMarkdown(text);
97
+ processor ??= createMarkdownProcessor();
98
+ return processor.processSync({ value: text }).result;
99
+ },
100
+ renderCodeBlock(lang, code) {
101
+ if (options.renderCodeBlock) return options.renderCodeBlock({
102
+ lang,
103
+ code
104
+ });
105
+ return /* @__PURE__ */ jsx(ClientCodeBlock, {
106
+ lang,
107
+ code
108
+ });
109
+ }
110
+ }), [payload.proxyUrl, processed]);
111
+ return /* @__PURE__ */ jsx(ClientCodeBlockProvider, {
112
+ factory: shiki,
113
+ children: /* @__PURE__ */ jsx(APIPage, {
114
+ ...props,
115
+ ctx
116
+ })
117
+ });
118
+ };
119
+ }
120
+ function MarkdownPre(props) {
121
+ const codeProps = Children.only(props.children).props;
122
+ const content = codeProps.children;
123
+ if (typeof content !== "string") return null;
124
+ return /* @__PURE__ */ jsx(ClientCodeBlock, {
125
+ lang: codeProps.className?.split(" ").find((v) => v.startsWith("language-"))?.slice(9) ?? "text",
126
+ code: content.trimEnd()
127
+ });
128
+ }
129
+ //#endregion
130
+ export { createClientAPIPage };
131
+
132
+ //# sourceMappingURL=create-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-client.js","names":[],"sources":["../../src/ui/create-client.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport type { Document, RenderContext } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport { defaultAdapters } from '@/requests/media/adapter';\nimport {\n Children,\n type ComponentProps,\n type ReactElement,\n useMemo,\n type FC,\n type ReactNode,\n} from 'react';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { APIPage, type ApiPageProps } from './api-page';\nimport type { CreateAPIPageOptions } from './base';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\nimport { compile } from '@fumari/json-schema-ts';\nimport { ClientCodeBlock, ClientCodeBlockProvider } from './components/codeblock';\nimport { dereferenceSync } from '@/utils/schema/dereference';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport { slug } from 'github-slugger';\n\nexport interface ClientApiPageProps extends Omit<ApiPageProps, 'document'> {\n payload: ClientApiPagePayload;\n}\n\nexport interface ClientApiPagePayload {\n bundled: Document;\n proxyUrl?: string;\n}\n\nexport type CreateClientAPIPageOptions = Omit<\n Partial<CreateAPIPageOptions>,\n 'generateTypeScriptSchema'\n>;\n\n/**\n * Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.\n */\nexport function createClientAPIPage({\n shiki = defaultShikiFactory,\n shikiOptions = { themes: { light: 'github-light', dark: 'github-dark' } },\n generateTypeScriptDefinitions = (schema, ctx) => {\n if (typeof schema !== 'object') return;\n\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n },\n ...options\n}: CreateClientAPIPageOptions = {}): FC<ClientApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n const mdxComponents = {\n ...defaultMdxComponents,\n img: undefined,\n pre: MarkdownPre,\n };\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: mdxComponents,\n });\n };\n }\n\n return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);\n }\n\n return function ClientAPIPage({ payload, ...props }) {\n const processed = useMemo<ProcessedDocument>(() => {\n const dereferenceMap = new Map<object, string>();\n\n return {\n bundled: payload.bundled,\n dereferenced: dereferenceSync(payload.bundled as JSONSchema, (schema, ref) => {\n dereferenceMap.set(schema as object, ref);\n }) as NoReference<Document>,\n getRawRef(obj) {\n return dereferenceMap.get(obj);\n },\n };\n }, [payload.bundled]);\n\n const ctx: RenderContext = useMemo(\n () => ({\n schema: processed,\n proxyUrl: payload.proxyUrl,\n shiki,\n shikiOptions,\n generateTypeScriptDefinitions,\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n return processor.processSync({\n value: text,\n }).result as ReactNode;\n },\n renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n return <ClientCodeBlock lang={lang} code={code} />;\n },\n }),\n [payload.proxyUrl, processed],\n );\n\n return (\n <ClientCodeBlockProvider factory={shiki}>\n <APIPage {...props} ctx={ctx} />\n </ClientCodeBlockProvider>\n );\n };\n}\n\nfunction MarkdownPre(props: ComponentProps<'pre'>) {\n const code = Children.only(props.children) as ReactElement;\n const codeProps = code.props as ComponentProps<'code'>;\n const content = codeProps.children;\n if (typeof content !== 'string') return null;\n\n const lang =\n codeProps.className\n ?.split(' ')\n .find((v) => v.startsWith('language-'))\n ?.slice('language-'.length) ?? 'text';\n\n return <ClientCodeBlock lang={lang} code={content.trimEnd()} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA8CA,SAAgB,oBAAoB,EAClC,QAAQ,qBACR,eAAe,EAAE,QAAQ;CAAE,OAAO;CAAgB,MAAM;CAAe,EAAE,EACzE,iCAAiC,QAAQ,QAAQ;AAC/C,KAAI,OAAO,WAAW,SAAU;AAEhC,KAAI;AACF,SAAO,QAAQ,QAAQ;GACrB,MAAM;GACN,UAAU,IAAI;GACd,WAAW,IAAI;GACf,aAAa,IAAI,OAAO;GACzB,CAAC;UACK,GAAG;AACV,UAAQ,KAAK,yCAAyC,EAAE;;GAG5D,GAAG,YAC2B,EAAE,EAA0B;CAC1D,IAAI;CACJ,MAAM,gBAAgB;EACpB,GAAG;EACH,KAAK,KAAA;EACL,KAAK;EACN;CAED,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,aAAa,CAAC,IAAI,YAAY;;AAGnE,QAAO,SAAS,cAAc,EAAE,SAAS,GAAG,SAAS;EACnD,MAAM,YAAY,cAAiC;GACjD,MAAM,iCAAiB,IAAI,KAAqB;AAEhD,UAAO;IACL,SAAS,QAAQ;IACjB,cAAc,gBAAgB,QAAQ,UAAwB,QAAQ,QAAQ;AAC5E,oBAAe,IAAI,QAAkB,IAAI;MACzC;IACF,UAAU,KAAK;AACb,YAAO,eAAe,IAAI,IAAI;;IAEjC;KACA,CAAC,QAAQ,QAAQ,CAAC;EAErB,MAAM,MAAqB,eAClB;GACL,QAAQ;GACR,UAAU,QAAQ;GAClB;GACA;GACA;GACA,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,KAAK,KAAK,GAAG,OAAO;AAC1D,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,eAAe,MAAM;AACnB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAEvC,WAAO,UAAU,YAAY,EAC3B,OAAO,MACR,CAAC,CAAC;;GAEL,gBAAgB,MAAM,MAAM;AAC1B,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAGhD,WAAO,oBAAC,iBAAD;KAAuB;KAAY;KAAQ,CAAA;;GAErD,GACD,CAAC,QAAQ,UAAU,UAAU,CAC9B;AAED,SACE,oBAAC,yBAAD;GAAyB,SAAS;aAChC,oBAAC,SAAD;IAAS,GAAI;IAAY;IAAO,CAAA;GACR,CAAA;;;AAKhC,SAAS,YAAY,OAA8B;CAEjD,MAAM,YADO,SAAS,KAAK,MAAM,SAAS,CACnB;CACvB,MAAM,UAAU,UAAU;AAC1B,KAAI,OAAO,YAAY,SAAU,QAAO;AAQxC,QAAO,oBAAC,iBAAD;EAAiB,MALtB,UAAU,WACN,MAAM,IAAI,CACX,MAAM,MAAM,EAAE,WAAW,YAAY,CAAC,EACrC,MAAM,EAAmB,IAAI;EAEC,MAAM,QAAQ,SAAS;EAAI,CAAA"}
@@ -1,3 +1,11 @@
1
+ import { OpenAPIServer } from "../server/create.js";
1
2
  import { ApiPageProps, OperationItem, WebhookItem } from "./api-page.js";
2
- import { CreateAPIPageOptions, createAPIPage } from "./full.js";
3
- export { type ApiPageProps, CreateAPIPageOptions, type OperationItem, type WebhookItem, createAPIPage };
3
+ import { CreateAPIPageOptions as CreateAPIPageOptions$1, ServerApiPageProps } from "./base.js";
4
+ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
5
+
6
+ //#region src/ui/index.d.ts
7
+ type CreateAPIPageOptions = Partial<CreateAPIPageOptions$1>;
8
+ declare function createAPIPage(server: OpenAPIServer, options?: CreateAPIPageOptions): (props: ServerApiPageProps) => _$react_jsx_runtime0.JSX.Element;
9
+ //#endregion
10
+ export { type ApiPageProps, CreateAPIPageOptions, type OperationItem, type WebhookItem, createAPIPage };
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ui/index.tsx"],"mappings":";;;;;;KAKY,oBAAA,GAAuB,OAAA,CAAQ,sBAAA;AAAA,iBAE3B,aAAA,CAAc,MAAA,EAAQ,aAAA,EAAe,OAAA,GAAS,oBAAA,IAOhC,KAAA,EAAO,kBAAA,KAAuB,oBAAA,CAAA,GAAA,CAAA,OAAA"}
package/dist/ui/index.js CHANGED
@@ -1,2 +1,22 @@
1
- import { createAPIPage } from "./full.js";
1
+ import { createAPIPage as createAPIPage$1 } from "./base.js";
2
+ import { FullProvider } from "./client/full.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { defaultShikiFactory } from "fumadocs-core/highlight/shiki/full";
5
+ //#region src/ui/index.tsx
6
+ function createAPIPage(server, options = {}) {
7
+ const APIPage = createAPIPage$1(server, {
8
+ shiki: defaultShikiFactory,
9
+ shikiOptions: { themes: {
10
+ light: "github-light",
11
+ dark: "github-dark"
12
+ } },
13
+ ...options
14
+ });
15
+ return function APIPageFull(props) {
16
+ return /* @__PURE__ */ jsx(FullProvider, { children: /* @__PURE__ */ jsx(APIPage, { ...props }) });
17
+ };
18
+ }
19
+ //#endregion
2
20
  export { createAPIPage };
21
+
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["base.createAPIPage"],"sources":["../../src/ui/index.tsx"],"sourcesContent":["import type { OpenAPIServer } from '@/server';\nimport * as base from './base';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\nimport { FullProvider } from './client/full';\n\nexport type CreateAPIPageOptions = Partial<base.CreateAPIPageOptions>;\n\nexport function createAPIPage(server: OpenAPIServer, options: CreateAPIPageOptions = {}) {\n const APIPage = base.createAPIPage(server, {\n shiki: defaultShikiFactory,\n shikiOptions: { themes: { light: 'github-light', dark: 'github-dark' } },\n ...options,\n });\n\n return function APIPageFull(props: base.ServerApiPageProps) {\n return (\n <FullProvider>\n <APIPage {...props} />\n </FullProvider>\n );\n };\n}\n\nexport type { ApiPageProps, OperationItem, WebhookItem } from './api-page';\n"],"mappings":";;;;;AAOA,SAAgB,cAAc,QAAuB,UAAgC,EAAE,EAAE;CACvF,MAAM,UAAUA,gBAAmB,QAAQ;EACzC,OAAO;EACP,cAAc,EAAE,QAAQ;GAAE,OAAO;GAAgB,MAAM;GAAe,EAAE;EACxE,GAAG;EACJ,CAAC;AAEF,QAAO,SAAS,YAAY,OAAgC;AAC1D,SACE,oBAAC,cAAD,EAAA,UACE,oBAAC,SAAD,EAAS,GAAI,OAAS,CAAA,EACT,CAAA"}
@@ -1,13 +1,54 @@
1
1
  "use client";
2
2
  import { cn } from "../../utils/cn.js";
3
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../components/select.js";
4
3
  import { useTranslations } from "../client/i18n.js";
5
- import { createContext, use, useMemo, useState } from "react";
4
+ import { createContext, use, useMemo, useRef, useState } from "react";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
7
6
  import { Check, Copy } from "lucide-react";
8
7
  import { buttonVariants } from "fumadocs-ui/components/ui/button";
9
8
  import { useCopyButton } from "fumadocs-ui/utils/use-copy-button";
10
9
  //#region src/ui/operation/client.tsx
10
+ const OperationContext = createContext(null);
11
+ function OperationProvider({ route, examples, defaultExampleId, children }) {
12
+ const [example, setExample] = useState(() => defaultExampleId ?? examples.at(0)?.id);
13
+ const listeners = useRef([]);
14
+ return /* @__PURE__ */ jsx(OperationContext, {
15
+ value: useMemo(() => ({
16
+ example,
17
+ route,
18
+ setExample(newKey) {
19
+ const example = examples.find((example) => example.id === newKey);
20
+ if (!example) return;
21
+ setExample(newKey);
22
+ for (const listener of listeners.current) listener(example.data, example.encoded);
23
+ },
24
+ examples,
25
+ setExampleData(data, encoded) {
26
+ for (const item of examples) if (item.id === example) {
27
+ item.data = data;
28
+ item.encoded = encoded;
29
+ break;
30
+ }
31
+ for (const listener of listeners.current) listener(data, encoded);
32
+ },
33
+ removeListener(listener) {
34
+ listeners.current = listeners.current.filter((item) => item !== listener);
35
+ },
36
+ addListener(listener) {
37
+ const active = examples.find((item) => item.id === example);
38
+ listener(active.data, active.encoded);
39
+ listeners.current.push(listener);
40
+ }
41
+ }), [
42
+ example,
43
+ route,
44
+ examples
45
+ ]),
46
+ children
47
+ });
48
+ }
49
+ function useOperationContext() {
50
+ return use(OperationContext);
51
+ }
11
52
  function CopyTypeScriptPanel({ name, code, className }) {
12
53
  const [isChecked, onCopy] = useCopyButton(() => {
13
54
  navigator.clipboard.writeText(code);
@@ -33,40 +74,7 @@ function CopyTypeScriptPanel({ name, code, className }) {
33
74
  })]
34
75
  });
35
76
  }
36
- const Context = createContext(null);
37
- function SelectTabs({ defaultValue, children }) {
38
- const [type, setType] = useState(defaultValue ?? null);
39
- return /* @__PURE__ */ jsx(Context, {
40
- value: useMemo(() => ({
41
- type,
42
- setType
43
- }), [type]),
44
- children
45
- });
46
- }
47
- function SelectTab({ value, ...props }) {
48
- if (value !== use(Context)?.type) return;
49
- return /* @__PURE__ */ jsx("div", {
50
- ...props,
51
- children: props.children
52
- });
53
- }
54
- function SelectTabTrigger({ items, className, ...props }) {
55
- const { type, setType } = use(Context);
56
- return /* @__PURE__ */ jsxs(Select, {
57
- value: type ?? "",
58
- onValueChange: setType,
59
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
60
- className: cn("not-prose w-fit min-w-0 *:min-w-0", className),
61
- ...props,
62
- children: /* @__PURE__ */ jsx(SelectValue, {})
63
- }), /* @__PURE__ */ jsx(SelectContent, { children: items.map(({ label, value }) => /* @__PURE__ */ jsx(SelectItem, {
64
- value,
65
- children: label
66
- }, value)) })]
67
- });
68
- }
69
77
  //#endregion
70
- export { CopyTypeScriptPanel, SelectTab, SelectTabTrigger, SelectTabs };
78
+ export { CopyTypeScriptPanel, OperationProvider, useOperationContext };
71
79
 
72
80
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../../../src/ui/operation/client.tsx"],"sourcesContent":["'use client';\n\nimport { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { Check, Copy } from 'lucide-react';\nimport { type ComponentProps, createContext, type ReactNode, use, useMemo, useState } from 'react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@/ui/components/select';\nimport { useTranslations } from '@/ui/client/i18n';\n\nexport function CopyTypeScriptPanel({\n name,\n code,\n className,\n}: {\n code: string;\n name: 'response body' | 'request body';\n className?: string;\n}) {\n const [isChecked, onCopy] = useCopyButton(() => {\n void navigator.clipboard.writeText(code);\n });\n const t = useTranslations();\n const useTypeText = t.useTypeInTypeScript.replace('{name}', name);\n\n return (\n <div\n className={cn(\n 'flex items-start justify-between gap-2 bg-fd-card text-fd-card-foreground border rounded-xl p-3 not-prose mb-4 last:mb-0',\n className,\n )}\n >\n <div>\n <p className=\"font-medium text-sm mb-2\">{t.typeScriptDefinitions}</p>\n <p className=\"text-xs text-fd-muted-foreground\">{useTypeText}</p>\n </div>\n <button\n onClick={onCopy}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'p-2 gap-2',\n size: 'sm',\n }),\n )}\n >\n {isChecked ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {t.copy}\n </button>\n </div>\n );\n}\n\nconst Context = createContext<{\n type: string | null;\n setType: (type: string) => void;\n} | null>(null);\n\nexport function SelectTabs({\n defaultValue,\n children,\n}: {\n defaultValue?: string;\n children: ReactNode;\n}) {\n const [type, setType] = useState<string | null>(defaultValue ?? null);\n\n return <Context value={useMemo(() => ({ type, setType }), [type])}>{children}</Context>;\n}\n\nexport function SelectTab({\n value,\n ...props\n}: ComponentProps<'div'> & {\n value: string;\n}) {\n const ctx = use(Context);\n if (value !== ctx?.type) return;\n\n return <div {...props}>{props.children}</div>;\n}\n\nexport function SelectTabTrigger({\n items,\n className,\n ...props\n}: ComponentProps<typeof SelectTrigger> & {\n items: {\n label: ReactNode;\n value: string;\n }[];\n}) {\n const { type, setType } = use(Context)!;\n\n return (\n <Select value={type ?? ''} onValueChange={setType}>\n <SelectTrigger className={cn('not-prose w-fit min-w-0 *:min-w-0', className)} {...props}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {items.map(({ label, value }) => (\n <SelectItem key={value} value={value}>\n {label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n"],"mappings":";;;;;;;;;;AAgBA,SAAgB,oBAAoB,EAClC,MACA,MACA,aAKC;CACD,MAAM,CAAC,WAAW,UAAU,oBAAoB;AACzC,YAAU,UAAU,UAAU,KAAK;GACxC;CACF,MAAM,IAAI,iBAAiB;CAC3B,MAAM,cAAc,EAAE,oBAAoB,QAAQ,UAAU,KAAK;AAEjE,QACE,qBAAC,OAAD;EACE,WAAW,GACT,4HACA,UACD;YAJH,CAME,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,KAAD;GAAG,WAAU;aAA4B,EAAE;GAA0B,CAAA,EACrE,oBAAC,KAAD;GAAG,WAAU;aAAoC;GAAgB,CAAA,CAC7D,EAAA,CAAA,EACN,qBAAC,UAAD;GACE,SAAS;GACT,WAAW,GACT,eAAe;IACb,OAAO;IACP,WAAW;IACX,MAAM;IACP,CAAC,CACH;aARH,CAUG,YAAY,oBAAC,OAAD,EAAO,WAAU,YAAa,CAAA,GAAG,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA,EAC1E,EAAE,KACI;KACL;;;AAIV,MAAM,UAAU,cAGN,KAAK;AAEf,SAAgB,WAAW,EACzB,cACA,YAIC;CACD,MAAM,CAAC,MAAM,WAAW,SAAwB,gBAAgB,KAAK;AAErE,QAAO,oBAAC,SAAD;EAAS,OAAO,eAAe;GAAE;GAAM;GAAS,GAAG,CAAC,KAAK,CAAC;EAAG;EAAmB,CAAA;;AAGzF,SAAgB,UAAU,EACxB,OACA,GAAG,SAGF;AAED,KAAI,UADQ,IAAI,QAAQ,EACL,KAAM;AAEzB,QAAO,oBAAC,OAAD;EAAK,GAAI;YAAQ,MAAM;EAAe,CAAA;;AAG/C,SAAgB,iBAAiB,EAC/B,OACA,WACA,GAAG,SAMF;CACD,MAAM,EAAE,MAAM,YAAY,IAAI,QAAQ;AAEtC,QACE,qBAAC,QAAD;EAAQ,OAAO,QAAQ;EAAI,eAAe;YAA1C,CACE,oBAAC,eAAD;GAAe,WAAW,GAAG,qCAAqC,UAAU;GAAE,GAAI;aAChF,oBAAC,aAAD,EAAe,CAAA;GACD,CAAA,EAChB,oBAAC,eAAD,EAAA,UACG,MAAM,KAAK,EAAE,OAAO,YACnB,oBAAC,YAAD;GAA+B;aAC5B;GACU,EAFI,MAEJ,CACb,EACY,CAAA,CACT"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../../src/ui/operation/client.tsx"],"sourcesContent":["'use client';\n\nimport { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';\nimport { buttonVariants } from 'fumadocs-ui/components/ui/button';\nimport { cn } from '@/utils/cn';\nimport { Check, Copy } from 'lucide-react';\nimport { createContext, type ReactNode, use, useMemo, useRef, useState } from 'react';\nimport { useTranslations } from '@/ui/client/i18n';\nimport type { ExampleRequestItem } from './get-example-requests';\nimport type { RawRequestData, RequestData } from '@/requests/types';\n\nexport type ExampleUpdateListener = (data: RawRequestData, encoded: RequestData) => void;\n\nconst OperationContext = createContext<{\n route: string;\n examples: ExampleRequestItem[];\n example: string | undefined;\n setExample: (id: string) => void;\n setExampleData: (data: RawRequestData, encoded: RequestData) => void;\n\n addListener: (listener: ExampleUpdateListener) => void;\n removeListener: (listener: ExampleUpdateListener) => void;\n} | null>(null);\n\nexport function OperationProvider({\n route,\n examples,\n defaultExampleId,\n children,\n}: {\n route: string;\n examples: ExampleRequestItem[];\n defaultExampleId?: string;\n children: ReactNode;\n}) {\n const [example, setExample] = useState(() => defaultExampleId ?? examples.at(0)?.id);\n const listeners = useRef<ExampleUpdateListener[]>([]);\n\n return (\n <OperationContext\n value={useMemo(\n () => ({\n example,\n route,\n setExample(newKey: string) {\n const example = examples.find((example) => example.id === newKey);\n if (!example) return;\n\n setExample(newKey);\n for (const listener of listeners.current) {\n listener(example.data, example.encoded);\n }\n },\n examples,\n setExampleData(data, encoded) {\n for (const item of examples) {\n if (item.id === example) {\n // persistent changes\n item.data = data;\n item.encoded = encoded;\n break;\n }\n }\n\n for (const listener of listeners.current) {\n listener(data, encoded);\n }\n },\n removeListener(listener) {\n listeners.current = listeners.current.filter((item) => item !== listener);\n },\n addListener(listener) {\n // initial call to listeners to ensure their data is the latest\n // this is necessary to avoid race conditions between `useEffect()`\n const active = examples.find((item) => item.id === example)!;\n\n listener(active.data, active.encoded);\n listeners.current.push(listener);\n },\n }),\n [example, route, examples],\n )}\n >\n {children}\n </OperationContext>\n );\n}\n\nexport function useOperationContext() {\n return use(OperationContext)!;\n}\n\nexport function CopyTypeScriptPanel({\n name,\n code,\n className,\n}: {\n code: string;\n name: 'response body' | 'request body';\n className?: string;\n}) {\n const [isChecked, onCopy] = useCopyButton(() => {\n void navigator.clipboard.writeText(code);\n });\n const t = useTranslations();\n const useTypeText = t.useTypeInTypeScript.replace('{name}', name);\n\n return (\n <div\n className={cn(\n 'flex items-start justify-between gap-2 bg-fd-card text-fd-card-foreground border rounded-xl p-3 not-prose mb-4 last:mb-0',\n className,\n )}\n >\n <div>\n <p className=\"font-medium text-sm mb-2\">{t.typeScriptDefinitions}</p>\n <p className=\"text-xs text-fd-muted-foreground\">{useTypeText}</p>\n </div>\n <button\n onClick={onCopy}\n className={cn(\n buttonVariants({\n color: 'secondary',\n className: 'p-2 gap-2',\n size: 'sm',\n }),\n )}\n >\n {isChecked ? <Check className=\"size-3.5\" /> : <Copy className=\"size-3.5\" />}\n {t.copy}\n </button>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;AAaA,MAAM,mBAAmB,cASf,KAAK;AAEf,SAAgB,kBAAkB,EAChC,OACA,UACA,kBACA,YAMC;CACD,MAAM,CAAC,SAAS,cAAc,eAAe,oBAAoB,SAAS,GAAG,EAAE,EAAE,GAAG;CACpF,MAAM,YAAY,OAAgC,EAAE,CAAC;AAErD,QACE,oBAAC,kBAAD;EACE,OAAO,eACE;GACL;GACA;GACA,WAAW,QAAgB;IACzB,MAAM,UAAU,SAAS,MAAM,YAAY,QAAQ,OAAO,OAAO;AACjE,QAAI,CAAC,QAAS;AAEd,eAAW,OAAO;AAClB,SAAK,MAAM,YAAY,UAAU,QAC/B,UAAS,QAAQ,MAAM,QAAQ,QAAQ;;GAG3C;GACA,eAAe,MAAM,SAAS;AAC5B,SAAK,MAAM,QAAQ,SACjB,KAAI,KAAK,OAAO,SAAS;AAEvB,UAAK,OAAO;AACZ,UAAK,UAAU;AACf;;AAIJ,SAAK,MAAM,YAAY,UAAU,QAC/B,UAAS,MAAM,QAAQ;;GAG3B,eAAe,UAAU;AACvB,cAAU,UAAU,UAAU,QAAQ,QAAQ,SAAS,SAAS,SAAS;;GAE3E,YAAY,UAAU;IAGpB,MAAM,SAAS,SAAS,MAAM,SAAS,KAAK,OAAO,QAAQ;AAE3D,aAAS,OAAO,MAAM,OAAO,QAAQ;AACrC,cAAU,QAAQ,KAAK,SAAS;;GAEnC,GACD;GAAC;GAAS;GAAO;GAAS,CAC3B;EAEA;EACgB,CAAA;;AAIvB,SAAgB,sBAAsB;AACpC,QAAO,IAAI,iBAAiB;;AAG9B,SAAgB,oBAAoB,EAClC,MACA,MACA,aAKC;CACD,MAAM,CAAC,WAAW,UAAU,oBAAoB;AACzC,YAAU,UAAU,UAAU,KAAK;GACxC;CACF,MAAM,IAAI,iBAAiB;CAC3B,MAAM,cAAc,EAAE,oBAAoB,QAAQ,UAAU,KAAK;AAEjE,QACE,qBAAC,OAAD;EACE,WAAW,GACT,4HACA,UACD;YAJH,CAME,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,KAAD;GAAG,WAAU;aAA4B,EAAE;GAA0B,CAAA,EACrE,oBAAC,KAAD;GAAG,WAAU;aAAoC;GAAgB,CAAA,CAC7D,EAAA,CAAA,EACN,qBAAC,UAAD;GACE,SAAS;GACT,WAAW,GACT,eAAe;IACb,OAAO;IACP,WAAW;IACX,MAAM;IACP,CAAC,CACH;aARH,CAUG,YAAY,oBAAC,OAAD,EAAO,WAAU,YAAa,CAAA,GAAG,oBAAC,MAAD,EAAM,WAAU,YAAa,CAAA,EAC1E,EAAE,KACI;KACL"}
@@ -1,7 +1,5 @@
1
1
  import { RawRequestData, RequestData } from "../../requests/types.js";
2
- import { ReactNode } from "react";
3
-
4
- //#region src/ui/operation/request-tabs.d.ts
2
+ //#region src/ui/operation/get-example-requests.d.ts
5
3
  interface ExampleRequestItem {
6
4
  id: string;
7
5
  name: string;
@@ -11,4 +9,4 @@ interface ExampleRequestItem {
11
9
  }
12
10
  //#endregion
13
11
  export { ExampleRequestItem };
14
- //# sourceMappingURL=request-tabs.d.ts.map
12
+ //# sourceMappingURL=get-example-requests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-example-requests.d.ts","names":[],"sources":["../../../src/ui/operation/get-example-requests.ts"],"mappings":";;UAMiB,kBAAA;EACf,EAAA;EACA,IAAA;EACA,WAAA;EACA,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,WAAA;AAAA"}
@@ -0,0 +1,83 @@
1
+ import { getPreferredType, pickExample } from "../../utils/schema/index.js";
2
+ import { encodeRequestData } from "../../requests/media/encode.js";
3
+ import { sample } from "openapi-sampler";
4
+ //#region src/ui/operation/get-example-requests.ts
5
+ function getExampleRequests(path, operation, ctx) {
6
+ const requestBody = operation.requestBody;
7
+ const media = requestBody?.content ? getPreferredType(requestBody.content) : null;
8
+ const bodyOfType = media ? requestBody.content[media] : null;
9
+ if (bodyOfType?.examples) {
10
+ const result = [];
11
+ for (const [key, value] of Object.entries(bodyOfType.examples)) {
12
+ const data = getRequestData(path, operation, key, ctx);
13
+ result.push({
14
+ id: key,
15
+ name: value.summary || key,
16
+ description: value.description,
17
+ data,
18
+ encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? [])
19
+ });
20
+ }
21
+ if (result.length > 0) return result;
22
+ }
23
+ const data = getRequestData(path, operation, null, ctx);
24
+ return [{
25
+ id: "_default",
26
+ name: "Default",
27
+ description: typeof bodyOfType?.schema === "object" ? bodyOfType.schema.description : void 0,
28
+ data,
29
+ encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? [])
30
+ }];
31
+ }
32
+ function getRequestData(path, method, sampleKey, _ctx) {
33
+ const result = {
34
+ path: {},
35
+ cookie: {},
36
+ header: {},
37
+ query: {},
38
+ method: method.method
39
+ };
40
+ for (const param of method.parameters ?? []) {
41
+ let value = pickExample(param);
42
+ if (value === void 0 && param.required) {
43
+ if (param.schema) value = sample(param.schema);
44
+ else if (param.content) {
45
+ const type = getPreferredType(param.content);
46
+ const content = type ? param.content[type] : void 0;
47
+ if (!content || !content.schema) throw new Error(`Cannot find "${param.name}" parameter info for media type "${type}" in ${path} ${method.method}`);
48
+ value = sample(content.schema);
49
+ }
50
+ }
51
+ switch (param.in) {
52
+ case "cookie":
53
+ result.cookie[param.name] = value;
54
+ break;
55
+ case "header":
56
+ result.header[param.name] = value;
57
+ break;
58
+ case "query":
59
+ result.query[param.name] = value;
60
+ break;
61
+ default: result.path[param.name] = value;
62
+ }
63
+ }
64
+ if (method.requestBody?.content) {
65
+ const body = method.requestBody.content;
66
+ const type = getPreferredType(body);
67
+ if (!type) throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);
68
+ result.bodyMediaType = type;
69
+ const bodyOfType = body[type];
70
+ if (bodyOfType.examples && sampleKey) result.body = bodyOfType.examples[sampleKey].value;
71
+ else if (bodyOfType.example) result.body = bodyOfType.example;
72
+ else result.body = sample(bodyOfType?.schema ?? {}, {
73
+ skipReadOnly: method.method !== "GET",
74
+ skipWriteOnly: method.method === "GET",
75
+ skipNonRequired: true
76
+ });
77
+ }
78
+ return result;
79
+ }
80
+ //#endregion
81
+ export { getExampleRequests };
82
+
83
+ //# sourceMappingURL=get-example-requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-example-requests.js","names":[],"sources":["../../../src/ui/operation/get-example-requests.ts"],"sourcesContent":["import { encodeRequestData } from '@/requests/media/encode';\nimport type { RawRequestData, RequestData } from '@/requests/types';\nimport type { MethodInformation, RenderContext } from '@/types';\nimport { type NoReference, getPreferredType, pickExample } from '@/utils/schema';\nimport { sample } from 'openapi-sampler';\n\nexport interface ExampleRequestItem {\n id: string;\n name: string;\n description?: string;\n data: RawRequestData;\n encoded: RequestData;\n}\n\nexport function getExampleRequests(\n path: string,\n operation: NoReference<MethodInformation>,\n ctx: RenderContext,\n): ExampleRequestItem[] {\n const requestBody = operation.requestBody;\n const media = requestBody?.content ? getPreferredType(requestBody.content) : null;\n const bodyOfType = media ? requestBody!.content![media] : null;\n\n if (bodyOfType?.examples) {\n const result: ExampleRequestItem[] = [];\n\n for (const [key, value] of Object.entries(bodyOfType.examples)) {\n const data = getRequestData(path, operation, key, ctx);\n\n result.push({\n id: key,\n name: value.summary || key,\n description: value.description,\n data,\n encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? []),\n });\n }\n\n if (result.length > 0) return result;\n }\n\n const data = getRequestData(path, operation, null, ctx);\n return [\n {\n id: '_default',\n name: 'Default',\n description:\n typeof bodyOfType?.schema === 'object' ? bodyOfType.schema.description : undefined,\n data,\n encoded: encodeRequestData(data, ctx.mediaAdapters, operation.parameters ?? []),\n },\n ];\n}\n\nfunction getRequestData(\n path: string,\n method: NoReference<MethodInformation>,\n sampleKey: string | null,\n _ctx: RenderContext,\n): RawRequestData {\n const result: RawRequestData = {\n path: {},\n cookie: {},\n header: {},\n query: {},\n method: method.method,\n };\n\n for (const param of method.parameters ?? []) {\n let value = pickExample(param as never);\n\n if (value === undefined && param.required) {\n if (param.schema) {\n value = sample(param.schema as object);\n } else if (param.content) {\n const type = getPreferredType(param.content);\n const content = type ? param.content[type] : undefined;\n if (!content || !content.schema)\n throw new Error(\n `Cannot find \"${param.name}\" parameter info for media type \"${type}\" in ${path} ${method.method}`,\n );\n\n value = sample(content.schema as object);\n }\n }\n\n switch (param.in) {\n case 'cookie':\n result.cookie[param.name!] = value;\n break;\n case 'header':\n result.header[param.name!] = value;\n break;\n case 'query':\n result.query[param.name!] = value;\n break;\n default:\n result.path[param.name!] = value;\n }\n }\n\n if (method.requestBody?.content) {\n const body = method.requestBody.content;\n const type = getPreferredType(body);\n if (!type)\n throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);\n result.bodyMediaType = type as RawRequestData['bodyMediaType'];\n const bodyOfType = body[type];\n\n if (bodyOfType.examples && sampleKey) {\n result.body = bodyOfType.examples[sampleKey].value;\n } else if (bodyOfType.example) {\n result.body = bodyOfType.example;\n } else {\n result.body = sample((bodyOfType?.schema ?? {}) as object, {\n skipReadOnly: method.method !== 'GET',\n skipWriteOnly: method.method === 'GET',\n skipNonRequired: true,\n });\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAcA,SAAgB,mBACd,MACA,WACA,KACsB;CACtB,MAAM,cAAc,UAAU;CAC9B,MAAM,QAAQ,aAAa,UAAU,iBAAiB,YAAY,QAAQ,GAAG;CAC7E,MAAM,aAAa,QAAQ,YAAa,QAAS,SAAS;AAE1D,KAAI,YAAY,UAAU;EACxB,MAAM,SAA+B,EAAE;AAEvC,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,WAAW,SAAS,EAAE;GAC9D,MAAM,OAAO,eAAe,MAAM,WAAW,KAAK,IAAI;AAEtD,UAAO,KAAK;IACV,IAAI;IACJ,MAAM,MAAM,WAAW;IACvB,aAAa,MAAM;IACnB;IACA,SAAS,kBAAkB,MAAM,IAAI,eAAe,UAAU,cAAc,EAAE,CAAC;IAChF,CAAC;;AAGJ,MAAI,OAAO,SAAS,EAAG,QAAO;;CAGhC,MAAM,OAAO,eAAe,MAAM,WAAW,MAAM,IAAI;AACvD,QAAO,CACL;EACE,IAAI;EACJ,MAAM;EACN,aACE,OAAO,YAAY,WAAW,WAAW,WAAW,OAAO,cAAc,KAAA;EAC3E;EACA,SAAS,kBAAkB,MAAM,IAAI,eAAe,UAAU,cAAc,EAAE,CAAC;EAChF,CACF;;AAGH,SAAS,eACP,MACA,QACA,WACA,MACgB;CAChB,MAAM,SAAyB;EAC7B,MAAM,EAAE;EACR,QAAQ,EAAE;EACV,QAAQ,EAAE;EACV,OAAO,EAAE;EACT,QAAQ,OAAO;EAChB;AAED,MAAK,MAAM,SAAS,OAAO,cAAc,EAAE,EAAE;EAC3C,IAAI,QAAQ,YAAY,MAAe;AAEvC,MAAI,UAAU,KAAA,KAAa,MAAM;OAC3B,MAAM,OACR,SAAQ,OAAO,MAAM,OAAiB;YAC7B,MAAM,SAAS;IACxB,MAAM,OAAO,iBAAiB,MAAM,QAAQ;IAC5C,MAAM,UAAU,OAAO,MAAM,QAAQ,QAAQ,KAAA;AAC7C,QAAI,CAAC,WAAW,CAAC,QAAQ,OACvB,OAAM,IAAI,MACR,gBAAgB,MAAM,KAAK,mCAAmC,KAAK,OAAO,KAAK,GAAG,OAAO,SAC1F;AAEH,YAAQ,OAAO,QAAQ,OAAiB;;;AAI5C,UAAQ,MAAM,IAAd;GACE,KAAK;AACH,WAAO,OAAO,MAAM,QAAS;AAC7B;GACF,KAAK;AACH,WAAO,OAAO,MAAM,QAAS;AAC7B;GACF,KAAK;AACH,WAAO,MAAM,MAAM,QAAS;AAC5B;GACF,QACE,QAAO,KAAK,MAAM,QAAS;;;AAIjC,KAAI,OAAO,aAAa,SAAS;EAC/B,MAAM,OAAO,OAAO,YAAY;EAChC,MAAM,OAAO,iBAAiB,KAAK;AACnC,MAAI,CAAC,KACH,OAAM,IAAI,MAAM,+BAA+B,KAAK,GAAG,OAAO,OAAO,sBAAsB;AAC7F,SAAO,gBAAgB;EACvB,MAAM,aAAa,KAAK;AAExB,MAAI,WAAW,YAAY,UACzB,QAAO,OAAO,WAAW,SAAS,WAAW;WACpC,WAAW,QACpB,QAAO,OAAO,WAAW;MAEzB,QAAO,OAAO,OAAQ,YAAY,UAAU,EAAE,EAAa;GACzD,cAAc,OAAO,WAAW;GAChC,eAAe,OAAO,WAAW;GACjC,iBAAiB;GAClB,CAAC;;AAIN,QAAO"}