fumadocs-openapi 10.6.4 → 10.6.6

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 (231) hide show
  1. package/css/generated/shared.css +34 -7
  2. package/dist/_openapi/types.d.ts +1 -2
  3. package/dist/generate-file.d.ts +1 -2
  4. package/dist/generate-file.js +3 -4
  5. package/dist/i18n.d.ts +2 -2
  6. package/dist/i18n.js +1 -2
  7. package/dist/playground/auth.js +92 -0
  8. package/dist/playground/client.d.ts +5 -10
  9. package/dist/playground/client.js +280 -199
  10. package/dist/playground/components/inputs.js +0 -2
  11. package/dist/playground/components/oauth-dialog.js +125 -164
  12. package/dist/playground/components/server-select.js +0 -2
  13. package/dist/playground/components/spinner.js +14 -0
  14. package/dist/playground/fetcher.d.ts +1 -2
  15. package/dist/playground/fetcher.js +0 -2
  16. package/dist/playground/schema.d.ts +1 -2
  17. package/dist/playground/schema.js +24 -15
  18. package/dist/playground/status-info.js +0 -2
  19. package/dist/requests/generators/all.d.ts +1 -2
  20. package/dist/requests/generators/all.js +0 -2
  21. package/dist/requests/generators/csharp.d.ts +1 -2
  22. package/dist/requests/generators/csharp.js +2 -3
  23. package/dist/requests/generators/curl.d.ts +1 -2
  24. package/dist/requests/generators/curl.js +5 -7
  25. package/dist/requests/generators/go.d.ts +1 -2
  26. package/dist/requests/generators/go.js +5 -7
  27. package/dist/requests/generators/index.d.ts +1 -2
  28. package/dist/requests/generators/index.js +0 -2
  29. package/dist/requests/generators/java.d.ts +1 -2
  30. package/dist/requests/generators/java.js +4 -6
  31. package/dist/requests/generators/javascript.d.ts +1 -2
  32. package/dist/requests/generators/javascript.js +3 -5
  33. package/dist/requests/generators/python.d.ts +1 -2
  34. package/dist/requests/generators/python.js +5 -6
  35. package/dist/requests/media/adapter.d.ts +1 -2
  36. package/dist/requests/media/adapter.js +7 -9
  37. package/dist/requests/media/encode.d.ts +1 -2
  38. package/dist/requests/media/encode.js +0 -2
  39. package/dist/requests/media/resolve-adapter.js +0 -2
  40. package/dist/requests/string-utils.js +25 -6
  41. package/dist/requests/types.d.ts +4 -4
  42. package/dist/scalar/client.js +0 -2
  43. package/dist/scalar/index.d.ts +1 -2
  44. package/dist/scalar/index.js +0 -2
  45. package/dist/server/create.d.ts +2 -3
  46. package/dist/server/create.js +0 -2
  47. package/dist/server/proxy.d.ts +1 -2
  48. package/dist/server/proxy.js +0 -2
  49. package/dist/server/source-api.d.ts +1 -2
  50. package/dist/server/source-api.js +0 -2
  51. package/dist/types.d.ts +1 -2
  52. package/dist/ui/api-page.d.ts +1 -2
  53. package/dist/ui/api-page.js +3 -3
  54. package/dist/ui/base.d.ts +9 -6
  55. package/dist/ui/base.js +8 -5
  56. package/dist/ui/client/boundary.d.ts +1 -2
  57. package/dist/ui/client/boundary.js +0 -2
  58. package/dist/ui/client/boundary.lazy.js +2 -3
  59. package/dist/ui/client/full.js +0 -2
  60. package/dist/ui/client/i18n.js +0 -2
  61. package/dist/ui/client/index.d.ts +1 -2
  62. package/dist/ui/client/index.js +0 -2
  63. package/dist/ui/client/storage-key.js +1 -3
  64. package/dist/ui/components/accordion.js +0 -2
  65. package/dist/ui/components/codeblock.d.ts +1 -2
  66. package/dist/ui/components/codeblock.js +0 -2
  67. package/dist/ui/components/dialog.js +0 -2
  68. package/dist/ui/components/input.js +0 -2
  69. package/dist/ui/components/method-label.js +0 -2
  70. package/dist/ui/components/select-tab.js +0 -2
  71. package/dist/ui/components/select.js +0 -2
  72. package/dist/ui/contexts/api.d.ts +7 -5
  73. package/dist/ui/contexts/api.js +7 -4
  74. package/dist/ui/create-client.d.ts +1 -2
  75. package/dist/ui/create-client.js +6 -3
  76. package/dist/ui/index.d.ts +1 -2
  77. package/dist/ui/index.js +0 -2
  78. package/dist/ui/operation/client.js +0 -2
  79. package/dist/ui/operation/get-example-requests.d.ts +1 -2
  80. package/dist/ui/operation/get-example-requests.js +0 -2
  81. package/dist/ui/operation/index.js +0 -2
  82. package/dist/ui/operation/request-tabs.d.ts +10 -0
  83. package/dist/ui/operation/request-tabs.js +43 -39
  84. package/dist/ui/operation/response-tabs.d.ts +1 -2
  85. package/dist/ui/operation/response-tabs.js +0 -2
  86. package/dist/ui/operation/usage-tabs/client.d.ts +1 -2
  87. package/dist/ui/operation/usage-tabs/client.js +0 -2
  88. package/dist/ui/operation/usage-tabs/index.js +0 -2
  89. package/dist/ui/schema/client.d.ts +1 -2
  90. package/dist/ui/schema/client.js +0 -2
  91. package/dist/ui/schema/index.d.ts +3 -4
  92. package/dist/ui/schema/index.js +1 -3
  93. package/dist/utils/deep-equal.js +0 -2
  94. package/dist/utils/document/dereference.d.ts +1 -2
  95. package/dist/utils/document/dereference.js +0 -2
  96. package/dist/utils/document/process.d.ts +1 -2
  97. package/dist/utils/document/process.js +0 -2
  98. package/dist/utils/id-to-title.js +0 -2
  99. package/dist/utils/is-plain-object.js +0 -2
  100. package/dist/utils/pages/builder.d.ts +1 -2
  101. package/dist/utils/pages/builder.js +0 -2
  102. package/dist/utils/pages/preset-auto.d.ts +1 -2
  103. package/dist/utils/pages/preset-auto.js +0 -2
  104. package/dist/utils/pages/to-static-data.js +0 -2
  105. package/dist/utils/pages/to-text.d.ts +1 -2
  106. package/dist/utils/pages/to-text.js +5 -6
  107. package/dist/utils/remove-undefined.js +0 -2
  108. package/dist/utils/schema/dereference.js +22 -14
  109. package/dist/utils/schema/index.d.ts +4 -10
  110. package/dist/utils/schema/index.js +4 -11
  111. package/dist/utils/{merge-schema.js → schema/merge.js} +2 -4
  112. package/dist/utils/schema/pick.js +0 -2
  113. package/dist/utils/schema/ref.js +0 -2
  114. package/dist/utils/schema/resolve-ref.js +0 -2
  115. package/dist/utils/schema/to-string.js +4 -7
  116. package/dist/utils/url.js +0 -2
  117. package/dist/utils/use-query.js +2 -3
  118. package/package.json +2 -2
  119. package/dist/_openapi/types.d.ts.map +0 -1
  120. package/dist/generate-file.d.ts.map +0 -1
  121. package/dist/generate-file.js.map +0 -1
  122. package/dist/i18n.d.ts.map +0 -1
  123. package/dist/i18n.js.map +0 -1
  124. package/dist/playground/client.d.ts.map +0 -1
  125. package/dist/playground/client.js.map +0 -1
  126. package/dist/playground/components/inputs.js.map +0 -1
  127. package/dist/playground/components/oauth-dialog.js.map +0 -1
  128. package/dist/playground/components/server-select.js.map +0 -1
  129. package/dist/playground/fetcher.d.ts.map +0 -1
  130. package/dist/playground/fetcher.js.map +0 -1
  131. package/dist/playground/schema.d.ts.map +0 -1
  132. package/dist/playground/schema.js.map +0 -1
  133. package/dist/playground/status-info.js.map +0 -1
  134. package/dist/requests/generators/all.d.ts.map +0 -1
  135. package/dist/requests/generators/all.js.map +0 -1
  136. package/dist/requests/generators/csharp.d.ts.map +0 -1
  137. package/dist/requests/generators/csharp.js.map +0 -1
  138. package/dist/requests/generators/curl.d.ts.map +0 -1
  139. package/dist/requests/generators/curl.js.map +0 -1
  140. package/dist/requests/generators/go.d.ts.map +0 -1
  141. package/dist/requests/generators/go.js.map +0 -1
  142. package/dist/requests/generators/index.d.ts.map +0 -1
  143. package/dist/requests/generators/index.js.map +0 -1
  144. package/dist/requests/generators/java.d.ts.map +0 -1
  145. package/dist/requests/generators/java.js.map +0 -1
  146. package/dist/requests/generators/javascript.d.ts.map +0 -1
  147. package/dist/requests/generators/javascript.js.map +0 -1
  148. package/dist/requests/generators/python.d.ts.map +0 -1
  149. package/dist/requests/generators/python.js.map +0 -1
  150. package/dist/requests/media/adapter.d.ts.map +0 -1
  151. package/dist/requests/media/adapter.js.map +0 -1
  152. package/dist/requests/media/encode.d.ts.map +0 -1
  153. package/dist/requests/media/encode.js.map +0 -1
  154. package/dist/requests/media/resolve-adapter.js.map +0 -1
  155. package/dist/requests/string-utils.js.map +0 -1
  156. package/dist/requests/types.d.ts.map +0 -1
  157. package/dist/scalar/client.js.map +0 -1
  158. package/dist/scalar/index.d.ts.map +0 -1
  159. package/dist/scalar/index.js.map +0 -1
  160. package/dist/server/create.d.ts.map +0 -1
  161. package/dist/server/create.js.map +0 -1
  162. package/dist/server/proxy.d.ts.map +0 -1
  163. package/dist/server/proxy.js.map +0 -1
  164. package/dist/server/source-api.d.ts.map +0 -1
  165. package/dist/server/source-api.js.map +0 -1
  166. package/dist/types.d.ts.map +0 -1
  167. package/dist/ui/api-page.d.ts.map +0 -1
  168. package/dist/ui/api-page.js.map +0 -1
  169. package/dist/ui/base.d.ts.map +0 -1
  170. package/dist/ui/base.js.map +0 -1
  171. package/dist/ui/client/boundary.d.ts.map +0 -1
  172. package/dist/ui/client/boundary.js.map +0 -1
  173. package/dist/ui/client/boundary.lazy.js.map +0 -1
  174. package/dist/ui/client/full.js.map +0 -1
  175. package/dist/ui/client/i18n.js.map +0 -1
  176. package/dist/ui/client/index.d.ts.map +0 -1
  177. package/dist/ui/client/index.js.map +0 -1
  178. package/dist/ui/client/storage-key.js.map +0 -1
  179. package/dist/ui/components/accordion.js.map +0 -1
  180. package/dist/ui/components/codeblock.d.ts.map +0 -1
  181. package/dist/ui/components/codeblock.js.map +0 -1
  182. package/dist/ui/components/dialog.js.map +0 -1
  183. package/dist/ui/components/input.js.map +0 -1
  184. package/dist/ui/components/method-label.js.map +0 -1
  185. package/dist/ui/components/select-tab.js.map +0 -1
  186. package/dist/ui/components/select.js.map +0 -1
  187. package/dist/ui/contexts/api.d.ts.map +0 -1
  188. package/dist/ui/contexts/api.js.map +0 -1
  189. package/dist/ui/create-client.d.ts.map +0 -1
  190. package/dist/ui/create-client.js.map +0 -1
  191. package/dist/ui/index.d.ts.map +0 -1
  192. package/dist/ui/index.js.map +0 -1
  193. package/dist/ui/operation/client.js.map +0 -1
  194. package/dist/ui/operation/get-example-requests.d.ts.map +0 -1
  195. package/dist/ui/operation/get-example-requests.js.map +0 -1
  196. package/dist/ui/operation/index.js.map +0 -1
  197. package/dist/ui/operation/request-tabs.js.map +0 -1
  198. package/dist/ui/operation/response-tabs.d.ts.map +0 -1
  199. package/dist/ui/operation/response-tabs.js.map +0 -1
  200. package/dist/ui/operation/usage-tabs/client.d.ts.map +0 -1
  201. package/dist/ui/operation/usage-tabs/client.js.map +0 -1
  202. package/dist/ui/operation/usage-tabs/index.js.map +0 -1
  203. package/dist/ui/schema/client.d.ts.map +0 -1
  204. package/dist/ui/schema/client.js.map +0 -1
  205. package/dist/ui/schema/index.d.ts.map +0 -1
  206. package/dist/ui/schema/index.js.map +0 -1
  207. package/dist/utils/deep-equal.js.map +0 -1
  208. package/dist/utils/document/dereference.d.ts.map +0 -1
  209. package/dist/utils/document/dereference.js.map +0 -1
  210. package/dist/utils/document/process.d.ts.map +0 -1
  211. package/dist/utils/document/process.js.map +0 -1
  212. package/dist/utils/id-to-title.js.map +0 -1
  213. package/dist/utils/is-plain-object.js.map +0 -1
  214. package/dist/utils/merge-schema.js.map +0 -1
  215. package/dist/utils/pages/builder.d.ts.map +0 -1
  216. package/dist/utils/pages/builder.js.map +0 -1
  217. package/dist/utils/pages/preset-auto.d.ts.map +0 -1
  218. package/dist/utils/pages/preset-auto.js.map +0 -1
  219. package/dist/utils/pages/to-static-data.js.map +0 -1
  220. package/dist/utils/pages/to-text.d.ts.map +0 -1
  221. package/dist/utils/pages/to-text.js.map +0 -1
  222. package/dist/utils/remove-undefined.js.map +0 -1
  223. package/dist/utils/schema/dereference.js.map +0 -1
  224. package/dist/utils/schema/index.d.ts.map +0 -1
  225. package/dist/utils/schema/index.js.map +0 -1
  226. package/dist/utils/schema/pick.js.map +0 -1
  227. package/dist/utils/schema/ref.js.map +0 -1
  228. package/dist/utils/schema/resolve-ref.js.map +0 -1
  229. package/dist/utils/schema/to-string.js.map +0 -1
  230. package/dist/utils/url.js.map +0 -1
  231. package/dist/utils/use-query.js.map +0 -1
@@ -8,6 +8,7 @@ import { cn } from "../utils/cn.js";
8
8
  import { MethodLabel } from "../ui/components/method-label.js";
9
9
  import { useQuery } from "../utils/use-query.js";
10
10
  import { encodeRequestData } from "../requests/media/encode.js";
11
+ import { dereferenceSwallow } from "../utils/schema/dereference.js";
11
12
  import { SchemaProvider, anyFields, useResolvedSchema } from "./schema.js";
12
13
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/components/select.js";
13
14
  import { labelVariants } from "../ui/components/input.js";
@@ -16,39 +17,44 @@ import ServerSelect from "./components/server-select.js";
16
17
  import { FieldInput, FieldSet, JsonInput, ObjectInput } from "./components/inputs.js";
17
18
  import { ClientCodeBlock } from "../ui/components/codeblock.js";
18
19
  import { useOperationContext } from "../ui/operation/client.js";
19
- import { OauthDialog, OauthDialogTrigger } from "./components/oauth-dialog.js";
20
- import { dereferenceDocument } from "../utils/document/dereference.js";
20
+ import { useAuth } from "./auth.js";
21
+ import { OAuthDialog, OAuthDialogContent, OAuthDialogTrigger } from "./components/oauth-dialog.js";
22
+ import { Spinner } from "./components/spinner.js";
21
23
  import { Fragment, useEffect, useMemo, useRef, useState } from "react";
22
24
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
23
25
  import { ChevronDown, LoaderCircle } from "lucide-react";
24
26
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "fumadocs-ui/components/ui/collapsible";
25
27
  import { buttonVariants } from "fumadocs-ui/components/ui/button";
26
28
  import { StfProvider, useDataEngine, useFieldValue, useListener, useStf } from "@fumari/stf";
27
- import { objectGet, objectSet, stringifyFieldKey } from "@fumari/stf/lib/utils";
29
+ import { arrayStartsWith, objectGet, objectSet, stringifyFieldKey } from "@fumari/stf/lib/utils";
30
+ import { useOnChange } from "fumadocs-core/utils/use-on-change";
28
31
  //#region src/playground/client.tsx
29
- function getBodyInfo(operation) {
30
- const content = operation.requestBody?.content;
31
- if (!content) return;
32
- const mediaType = getPreferredType(content);
33
- if (mediaType) return {
34
- mediaType,
35
- schema: content[mediaType].schema ?? true
36
- };
37
- }
38
32
  function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly, readOnly, ...rest }) {
39
33
  const t = useTranslations();
40
- const schema = "processed" in doc ? doc.processed : useMemo(() => dereferenceDocument(doc.bundled), [doc.bundled]);
41
- const operation = schema.dereferenced.paths[route][method];
42
- const body = getBodyInfo(operation);
34
+ const { parameters, body } = useMemo(() => {
35
+ const operation = doc.paths[route][method];
36
+ const parameters = operation.parameters?.map((param) => dereferenceSwallow(param, doc)) ?? [];
37
+ let body;
38
+ if (operation.requestBody) {
39
+ const content = dereferenceSwallow(operation.requestBody, doc).content;
40
+ const mediaType = content ? getPreferredType(content) : void 0;
41
+ if (content && mediaType) body = {
42
+ mediaType,
43
+ schema: dereferenceSwallow(content[mediaType], doc).schema ?? true
44
+ };
45
+ }
46
+ return {
47
+ body,
48
+ parameters
49
+ };
50
+ }, [
51
+ doc,
52
+ route,
53
+ method
54
+ ]);
43
55
  const { example: exampleId, examples, setExampleData } = useOperationContext();
44
56
  const { server } = useServerContext();
45
- const storageKeys = useStorageKey();
46
- const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay, CollapsiblePanel = DefaultCollapsiblePanel } = {}, requestTimeout, fetchOptions = { requestTimeout }, transformAuthInputs, renderBodyField } = {} } } = useApiContext();
47
- const [securityId, setSecurityId] = useState(() => {
48
- const idx = securities.findIndex((s) => s.every((entry) => !entry.deprecated));
49
- return idx === -1 ? 0 : idx;
50
- });
51
- const { inputs, mapInputs, initAuthValues } = useAuthInputs(securities[securityId], transformAuthInputs);
57
+ const { mediaAdapters, client: { playground: { components: { ResultDisplay = DefaultResultDisplay, CollapsiblePanel = DefaultCollapsiblePanel } = {}, requestTimeout, fetchOptions = { requestTimeout }, renderBodyField } = {} } } = useApiContext();
52
58
  const defaultValues = useMemo(() => {
53
59
  const requestData = examples.find((example) => example.id === exampleId)?.data;
54
60
  return {
@@ -60,6 +66,7 @@ function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly,
60
66
  };
61
67
  }, [examples, exampleId]);
62
68
  const stf = useStf({ defaultValues });
69
+ const { inputs, requirementId, setRequirementId, mapInputs, initAuthInputs } = useAuthInputs(stf.dataEngine, securities);
63
70
  const testQuery = useQuery(async (input) => {
64
71
  const fetcher = await import("./fetcher.js").then((mod) => mod.createBrowserFetcher(mediaAdapters, {
65
72
  proxyUrl,
@@ -69,27 +76,25 @@ function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly,
69
76
  ...mapInputs(input),
70
77
  method,
71
78
  bodyMediaType: body?.mediaType
72
- }, mediaAdapters, operation.parameters);
79
+ }, mediaAdapters, parameters);
73
80
  return fetcher.fetch(joinURL(withBase(server ? resolveServerUrl(server.url, server.variables) : "/", window.location.origin), resolveRequestData(route, encoded)), encoded);
74
81
  });
75
82
  const timerRef = useRef(null);
83
+ const stfSync = useRef(false);
84
+ function triggerExampleUpdate() {
85
+ const data = {
86
+ ...mapInputs(stf.dataEngine.getData()),
87
+ method,
88
+ bodyMediaType: body?.mediaType
89
+ };
90
+ setExampleData(data, encodeRequestData(data, mediaAdapters, parameters));
91
+ }
76
92
  useListener({
77
93
  stf,
78
94
  onUpdate() {
95
+ if (!stfSync.current) return;
79
96
  if (timerRef.current) window.clearTimeout(timerRef.current);
80
- timerRef.current = window.setTimeout(() => {
81
- const values = stf.dataEngine.getData();
82
- for (const item of inputs) {
83
- const value = stf.dataEngine.get(item.fieldName);
84
- if (value) localStorage.setItem(storageKeys.AuthField(item), JSON.stringify(value));
85
- }
86
- const data = {
87
- ...mapInputs(values),
88
- method,
89
- bodyMediaType: body?.mediaType
90
- };
91
- setExampleData(data, encodeRequestData(data, mediaAdapters, operation.parameters));
92
- }, timerRef.current ? 400 : 0);
97
+ timerRef.current = window.setTimeout(triggerExampleUpdate, 400);
93
98
  }
94
99
  });
95
100
  useEffect(() => {
@@ -97,19 +102,25 @@ function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly,
97
102
  stf.dataEngine.reset(defaultValues);
98
103
  }, [defaultValues]);
99
104
  useEffect(() => {
100
- return initAuthValues(stf);
105
+ const reset = initAuthInputs();
106
+ triggerExampleUpdate();
107
+ stfSync.current = true;
108
+ return () => {
109
+ stfSync.current = false;
110
+ reset();
111
+ };
101
112
  }, [defaultValues, inputs]);
102
113
  return /* @__PURE__ */ jsx(StfProvider, {
103
114
  value: stf,
104
115
  children: /* @__PURE__ */ jsx(SchemaProvider, {
105
- schema,
116
+ doc,
106
117
  writeOnly,
107
118
  readOnly,
108
119
  children: /* @__PURE__ */ jsxs("form", {
109
120
  ...rest,
110
121
  className: cn("not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground", rest.className),
111
122
  onSubmit: (e) => {
112
- testQuery.start(mapInputs(stf.dataEngine.getData()));
123
+ testQuery.start(stf.dataEngine.getData());
113
124
  e.preventDefault();
114
125
  },
115
126
  children: [
@@ -137,13 +148,13 @@ function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly,
137
148
  data: testQuery.data,
138
149
  reset: testQuery.reset
139
150
  }) : null,
140
- securities.length > 0 && /* @__PURE__ */ jsx(SecurityTabs, {
151
+ securities.length > 0 && /* @__PURE__ */ jsx(SecurityRequirements, {
141
152
  securities,
142
- securityId,
143
- setSecurityId,
153
+ securityId: requirementId,
154
+ setSecurityId: setRequirementId,
144
155
  children: inputs.map((input) => /* @__PURE__ */ jsx(Fragment, { children: input.children }, stringifyFieldKey(input.fieldName)))
145
156
  }),
146
- /* @__PURE__ */ jsx(ParametersForm, { parameters: operation.parameters }),
157
+ /* @__PURE__ */ jsx(ParametersForm, { parameters }),
147
158
  body && /* @__PURE__ */ jsx(CollapsiblePanel, {
148
159
  "data-type": "body",
149
160
  title: t.body,
@@ -154,50 +165,62 @@ function PlaygroundClient({ route, method, securities, doc, proxyUrl, writeOnly,
154
165
  })
155
166
  });
156
167
  }
157
- function SecurityTabsSelectItem({ security }) {
158
- return /* @__PURE__ */ jsx("div", {
159
- className: "flex flex-col gap-2 max-w-[600px]",
160
- children: security.map((item) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
161
- className: cn("font-mono font-medium", item.deprecated && "text-fd-muted-foreground line-through"),
162
- children: item.id
163
- }), /* @__PURE__ */ jsx("p", {
164
- className: "text-fd-muted-foreground whitespace-pre-wrap",
165
- children: item.description
166
- })] }, item.id))
167
- });
168
- }
169
- function SecurityTabs({ securities, setSecurityId, securityId, children }) {
170
- const [open, setOpen] = useState(false);
171
- const engine = useDataEngine();
168
+ function SecurityRequirements({ securities, setSecurityId, securityId, children }) {
172
169
  const t = useTranslations();
170
+ const { isLoading, error } = useAuth();
171
+ const defaultOpen = isLoading || error != null;
172
+ const [open, setOpen] = useState(defaultOpen);
173
173
  const { CollapsiblePanel = DefaultCollapsiblePanel } = useApiContext().client.playground?.components ?? {};
174
- const result = /* @__PURE__ */ jsxs(CollapsiblePanel, {
175
- title: t.authorization,
174
+ useOnChange(defaultOpen, () => {
175
+ if (defaultOpen) setOpen(true);
176
+ });
177
+ return /* @__PURE__ */ jsxs(CollapsiblePanel, {
178
+ title: /* @__PURE__ */ jsxs(Fragment$1, { children: [t.authorization, isLoading && /* @__PURE__ */ jsxs("span", {
179
+ className: "border-s ps-2 inline-flex items-center gap-1.5 text-fd-muted-foreground text-xs font-mono",
180
+ children: [
181
+ /* @__PURE__ */ jsx(Spinner, {}),
182
+ " ",
183
+ t.fetchingToken
184
+ ]
185
+ })] }),
176
186
  "data-type": "authorization",
177
- children: [/* @__PURE__ */ jsxs(Select, {
178
- value: securityId.toString(),
179
- onValueChange: (v) => setSecurityId(Number(v)),
180
- children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { children: /* @__PURE__ */ jsx(SecurityTabsSelectItem, { security: securities[securityId] }) }) }), /* @__PURE__ */ jsx(SelectContent, { children: securities.map((security, i) => /* @__PURE__ */ jsx(SelectItem, {
181
- value: i.toString(),
182
- children: /* @__PURE__ */ jsx(SecurityTabsSelectItem, { security })
183
- }, i)) })]
184
- }), children]
187
+ open,
188
+ onOpenChange: setOpen,
189
+ children: [
190
+ error != null && /* @__PURE__ */ jsxs("div", {
191
+ className: "p-2 border rounded-lg bg-fd-secondary",
192
+ children: [/* @__PURE__ */ jsx("p", {
193
+ className: "text-fd-muted-foreground font-medium mb-1",
194
+ children: t.fetchTokenError
195
+ }), /* @__PURE__ */ jsx("p", { children: String(error) })]
196
+ }),
197
+ /* @__PURE__ */ jsxs(Select, {
198
+ value: securityId.toString(),
199
+ onValueChange: (v) => setSecurityId(Number(v)),
200
+ children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { children: /* @__PURE__ */ jsx(SecurityRequirement, { requirement: securities[securityId] }) }) }), /* @__PURE__ */ jsx(SelectContent, { children: securities.map((security, i) => /* @__PURE__ */ jsx(SelectItem, {
201
+ value: i.toString(),
202
+ children: /* @__PURE__ */ jsx(SecurityRequirement, { requirement: security })
203
+ }, i)) })]
204
+ }),
205
+ children
206
+ ]
207
+ });
208
+ }
209
+ function SecurityRequirement({ requirement }) {
210
+ const { schemes } = useApiContext();
211
+ return /* @__PURE__ */ jsx("div", {
212
+ className: "flex flex-col gap-2 max-w-[600px]",
213
+ children: requirement.map((item) => {
214
+ const scheme = schemes[item.id];
215
+ return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
216
+ className: cn("font-mono font-medium", scheme.deprecated && "text-fd-muted-foreground line-through"),
217
+ children: item.id
218
+ }), /* @__PURE__ */ jsx("p", {
219
+ className: "text-fd-muted-foreground whitespace-pre-wrap",
220
+ children: scheme.description
221
+ })] }, item.id);
222
+ })
185
223
  });
186
- for (let i = 0; i < securities.length; i++) {
187
- const security = securities[i];
188
- for (const item of security) if (item.type === "oauth2") return /* @__PURE__ */ jsx(OauthDialog, {
189
- scheme: item,
190
- scopes: item.scopes,
191
- open,
192
- setOpen: (v) => {
193
- setOpen(v);
194
- if (v) setSecurityId(i);
195
- },
196
- setToken: (token) => engine.update(["header", "Authorization"], token),
197
- children: result
198
- });
199
- }
200
- return result;
201
224
  }
202
225
  const ParamTypes = [
203
226
  "path",
@@ -220,7 +243,7 @@ function ParameterItem({ type, parameters }) {
220
243
  }, stringifyFieldKey(fieldName));
221
244
  });
222
245
  }
223
- function ParametersForm({ parameters = [] }) {
246
+ function ParametersForm({ parameters }) {
224
247
  const { components: { CollapsiblePanel = DefaultCollapsiblePanel } = {} } = useApiContext().client.playground ?? {};
225
248
  const t = useTranslations();
226
249
  const displayNames = {
@@ -278,98 +301,97 @@ function BodyInput({ field: _field }) {
278
301
  })
279
302
  });
280
303
  }
281
- function useAuthInputs(securities, transform) {
304
+ function useAuthInputs(engine, requirements) {
305
+ const authCtx = useAuth();
282
306
  const storageKeys = useStorageKey();
283
307
  const t = useTranslations();
284
- const inputs = useMemo(() => {
285
- const result = [];
286
- if (!securities) return result;
287
- for (const security of securities) if (security.type === "http" && security.scheme === "basic") {
288
- const fieldName = ["header", "Authorization"];
289
- result.push({
290
- fieldName,
291
- original: security,
292
- defaultValue: {
293
- username: "",
294
- password: ""
295
- },
296
- mapOutput(out) {
297
- if (out && typeof out === "object") {
298
- const obj = out;
299
- return `Basic ${btoa(`${obj.username ?? ""}:${obj.password ?? ""}`)}`;
300
- }
301
- return out;
302
- },
303
- children: /* @__PURE__ */ jsx(ObjectInput, {
304
- field: {
305
- type: "object",
306
- properties: {
307
- username: { type: "string" },
308
- password: { type: "string" }
308
+ const { schemes, client: { playground: { transformAuthInputs } = {} } } = useApiContext();
309
+ const [requirementId, setRequirementId] = useState(() => {
310
+ if (requirements.length === 0) return -1;
311
+ const idx = requirements.findIndex((s) => s.every((item) => !schemes[item.id].deprecated));
312
+ return idx !== -1 ? idx : 0;
313
+ });
314
+ const requirement = requirementId === -1 ? null : requirements[requirementId];
315
+ let inputs = useMemo(() => {
316
+ if (!requirement) return [];
317
+ return requirement.map((item) => {
318
+ const scheme = schemes[item.id];
319
+ if (scheme.type === "http" && scheme.scheme === "basic") {
320
+ const fieldName = ["header", "Authorization"];
321
+ return {
322
+ fieldName,
323
+ schemeId: item.id,
324
+ storageKey: storageKeys.AuthField(item.id),
325
+ defaultValue: {
326
+ username: "",
327
+ password: ""
328
+ },
329
+ mapOutput(out) {
330
+ if (out && typeof out === "object") {
331
+ const obj = out;
332
+ return `Basic ${btoa(`${obj.username ?? ""}:${obj.password ?? ""}`)}`;
309
333
  }
334
+ return out;
310
335
  },
311
- fieldName
312
- })
313
- });
314
- } else if (security.type === "oauth2") {
315
- const fieldName = ["header", "Authorization"];
316
- result.push({
317
- fieldName,
318
- original: security,
319
- defaultValue: "Bearer ",
320
- children: /* @__PURE__ */ jsxs("fieldset", {
321
- className: "flex flex-col gap-2",
322
- children: [/* @__PURE__ */ jsx("label", {
323
- htmlFor: stringifyFieldKey(fieldName),
324
- className: cn(labelVariants()),
325
- children: t.accessToken
326
- }), /* @__PURE__ */ jsxs("div", {
327
- className: "flex gap-2",
328
- children: [/* @__PURE__ */ jsx(FieldInput, {
329
- fieldName,
330
- field: { type: "string" },
331
- className: "flex-1"
332
- }), /* @__PURE__ */ jsx(OauthDialogTrigger, {
333
- type: "button",
334
- className: cn(buttonVariants({
335
- size: "sm",
336
- color: "secondary"
337
- })),
338
- children: t.authorize
339
- })]
340
- })]
341
- })
342
- });
343
- } else if (security.type === "http") {
344
- const fieldName = ["header", "Authorization"];
345
- result.push({
346
- fieldName,
347
- original: security,
348
- defaultValue: "Bearer ",
349
- children: /* @__PURE__ */ jsx(FieldSet, {
350
- name: `${t.authorization} (${t.header})`,
336
+ children: /* @__PURE__ */ jsx(ObjectInput, {
337
+ field: {
338
+ type: "object",
339
+ properties: {
340
+ username: { type: "string" },
341
+ password: { type: "string" }
342
+ }
343
+ },
344
+ fieldName
345
+ })
346
+ };
347
+ }
348
+ if (scheme.type === "oauth2") {
349
+ const fieldName = ["header", "Authorization"];
350
+ return {
351
351
  fieldName,
352
- field: { type: "string" }
353
- })
354
- });
355
- } else if (security.type === "apiKey") {
356
- const fieldName = [security.in, security.name];
357
- result.push({
358
- fieldName,
359
- defaultValue: "",
360
- original: security,
361
- children: /* @__PURE__ */ jsx(FieldSet, {
352
+ schemeId: item.id,
353
+ storageKey: storageKeys.AuthField(item.id),
354
+ defaultValue: "Bearer ",
355
+ children: /* @__PURE__ */ jsx(OAuth2Input, {
356
+ fieldName,
357
+ security: item
358
+ })
359
+ };
360
+ }
361
+ if (scheme.type === "http") {
362
+ const fieldName = ["header", "Authorization"];
363
+ return {
362
364
  fieldName,
363
- name: `${security.name} (${security.in})`,
364
- field: { type: "string" }
365
- })
366
- });
367
- } else {
365
+ schemeId: item.id,
366
+ storageKey: storageKeys.AuthField(item.id),
367
+ defaultValue: "Bearer ",
368
+ children: /* @__PURE__ */ jsx(FieldSet, {
369
+ name: `${t.authorization} (${t.header})`,
370
+ fieldName,
371
+ field: { type: "string" }
372
+ })
373
+ };
374
+ }
375
+ if (scheme.type === "apiKey") {
376
+ const fieldName = [scheme.in, scheme.name];
377
+ return {
378
+ fieldName,
379
+ schemeId: item.id,
380
+ defaultValue: "",
381
+ storageKey: storageKeys.AuthField(item.id),
382
+ children: /* @__PURE__ */ jsx(FieldSet, {
383
+ fieldName,
384
+ name: `${scheme.name} (${scheme.in})`,
385
+ field: { type: "string" }
386
+ })
387
+ };
388
+ }
368
389
  const fieldName = ["header", "Authorization"];
369
- result.push({
390
+ return {
370
391
  fieldName,
392
+ schemeId: item.id,
371
393
  defaultValue: "",
372
- original: security,
394
+ storageKey: storageKeys.AuthField(item.id),
373
395
  children: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(FieldSet, {
374
396
  name: `${t.authorization} (${t.header})`,
375
397
  fieldName,
@@ -378,45 +400,106 @@ function useAuthInputs(securities, transform) {
378
400
  className: "text-fd-muted-foreground text-xs",
379
401
  children: t.openIdUnsupported
380
402
  })] })
381
- });
382
- }
383
- return transform ? transform(result) : result;
403
+ };
404
+ });
384
405
  }, [
385
- securities,
386
- transform,
406
+ requirement,
407
+ storageKeys,
408
+ schemes,
387
409
  t
388
410
  ]);
389
- const mapInputs = (values) => {
390
- const cloned = structuredClone(values);
391
- for (const item of inputs) {
392
- if (!item.mapOutput) continue;
393
- objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));
394
- }
395
- return cloned;
396
- };
397
- const initAuthValues = (stf) => {
398
- const { dataEngine } = stf;
399
- for (const item of inputs) {
400
- const stored = localStorage.getItem(storageKeys.AuthField(item));
401
- if (stored) {
402
- const parsed = JSON.parse(stored);
403
- if (typeof parsed === typeof item.defaultValue) {
404
- dataEngine.init(item.fieldName, parsed);
405
- continue;
406
- }
411
+ if (transformAuthInputs) inputs = transformAuthInputs(inputs);
412
+ useListener({
413
+ stf: engine,
414
+ onUpdate(key) {
415
+ for (const item of inputs) {
416
+ if (!arrayStartsWith(item.fieldName, key)) continue;
417
+ const value = engine.get(item.fieldName);
418
+ if (value != null) localStorage.setItem(item.storageKey, JSON.stringify(value));
407
419
  }
408
- dataEngine.init(item.fieldName, item.defaultValue);
409
420
  }
410
- return () => {
411
- for (const item of inputs) stf.dataEngine.delete(item.fieldName);
412
- };
413
- };
421
+ });
422
+ useOnChange(authCtx.updatedSchemeId, () => {
423
+ const { updatedSchemeId } = authCtx;
424
+ if (!updatedSchemeId) return;
425
+ const { token } = authCtx.store[updatedSchemeId];
426
+ const input = inputs.find((input) => input.schemeId === updatedSchemeId);
427
+ if (input) {
428
+ engine.update(input.fieldName, token);
429
+ return;
430
+ }
431
+ const idx = requirements.findIndex((requirement) => requirement.some((item) => item.id === updatedSchemeId));
432
+ if (idx !== -1) {
433
+ localStorage.setItem(storageKeys.AuthField(updatedSchemeId), JSON.stringify(token));
434
+ setRequirementId(idx);
435
+ }
436
+ });
414
437
  return {
415
438
  inputs,
416
- mapInputs,
417
- initAuthValues
439
+ requirementId,
440
+ setRequirementId,
441
+ mapInputs(values) {
442
+ const cloned = structuredClone(values);
443
+ for (const item of inputs) {
444
+ if (!item.mapOutput) continue;
445
+ objectSet(cloned, item.fieldName, item.mapOutput(objectGet(cloned, item.fieldName)));
446
+ }
447
+ return cloned;
448
+ },
449
+ initAuthInputs() {
450
+ for (const item of inputs) {
451
+ const stored = localStorage.getItem(item.storageKey);
452
+ if (stored) {
453
+ const parsed = JSON.parse(stored);
454
+ if (typeof parsed === typeof item.defaultValue) {
455
+ engine.init(item.fieldName, parsed);
456
+ continue;
457
+ }
458
+ }
459
+ engine.init(item.fieldName, item.defaultValue);
460
+ }
461
+ return () => {
462
+ for (const item of inputs) engine.delete(item.fieldName);
463
+ };
464
+ }
418
465
  };
419
466
  }
467
+ function OAuth2Input({ fieldName, security }) {
468
+ const [open, setOpen] = useState(false);
469
+ const engine = useDataEngine();
470
+ const t = useTranslations();
471
+ return /* @__PURE__ */ jsxs("fieldset", {
472
+ className: "flex flex-col gap-2",
473
+ children: [/* @__PURE__ */ jsx("label", {
474
+ htmlFor: stringifyFieldKey(fieldName),
475
+ className: cn(labelVariants()),
476
+ children: t.accessToken
477
+ }), /* @__PURE__ */ jsxs("div", {
478
+ className: "flex gap-2",
479
+ children: [/* @__PURE__ */ jsx(FieldInput, {
480
+ fieldName,
481
+ field: { type: "string" },
482
+ className: "flex-1"
483
+ }), /* @__PURE__ */ jsxs(OAuthDialog, {
484
+ open,
485
+ onOpenChange: setOpen,
486
+ children: [/* @__PURE__ */ jsx(OAuthDialogTrigger, {
487
+ type: "button",
488
+ className: cn(buttonVariants({
489
+ size: "sm",
490
+ color: "secondary"
491
+ })),
492
+ children: t.authorize
493
+ }), /* @__PURE__ */ jsx(OAuthDialogContent, {
494
+ setOpen,
495
+ schemeId: security.id,
496
+ scopes: security.scopes,
497
+ setToken: (token) => engine.update(["header", "Authorization"], token)
498
+ })]
499
+ })]
500
+ })]
501
+ });
502
+ }
420
503
  function Route({ route, ...props }) {
421
504
  return /* @__PURE__ */ jsx("div", {
422
505
  ...props,
@@ -488,5 +571,3 @@ const Custom = { useController(fieldName, options) {
488
571
  } };
489
572
  //#endregion
490
573
  export { Custom, DefaultCollapsiblePanel, DefaultResultDisplay, PlaygroundClient as default };
491
-
492
- //# sourceMappingURL=client.js.map
@@ -418,5 +418,3 @@ function ArrayInput({ fieldName, items: itemSchema, ...props }) {
418
418
  }
419
419
  //#endregion
420
420
  export { FieldInput, FieldSet, JsonInput, ObjectInput };
421
-
422
- //# sourceMappingURL=inputs.js.map