fumadocs-openapi 9.0.4 → 9.0.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 (69) hide show
  1. package/dist/playground/auth/oauth-dialog.d.ts +4 -2
  2. package/dist/playground/auth/oauth-dialog.d.ts.map +1 -1
  3. package/dist/playground/auth/oauth-dialog.js +113 -26
  4. package/dist/playground/client.d.ts.map +1 -1
  5. package/dist/playground/client.js +105 -69
  6. package/dist/playground/fetcher.d.ts +6 -1
  7. package/dist/playground/fetcher.d.ts.map +1 -1
  8. package/dist/playground/fetcher.js +2 -4
  9. package/dist/playground/index.js +26 -15
  10. package/dist/playground/inputs.d.ts +8 -2
  11. package/dist/playground/inputs.d.ts.map +1 -1
  12. package/dist/playground/inputs.js +32 -31
  13. package/dist/render/api-page.d.ts.map +1 -1
  14. package/dist/render/api-page.js +2 -10
  15. package/dist/render/heading.d.ts +1 -1
  16. package/dist/render/heading.d.ts.map +1 -1
  17. package/dist/render/heading.js +3 -3
  18. package/dist/render/markdown.d.ts +2 -2
  19. package/dist/render/markdown.d.ts.map +1 -1
  20. package/dist/render/markdown.js +4 -2
  21. package/dist/render/operation/index.d.ts.map +1 -1
  22. package/dist/render/operation/index.js +68 -58
  23. package/dist/render/renderer.d.ts.map +1 -1
  24. package/dist/render/renderer.js +3 -3
  25. package/dist/render/schema.d.ts.map +1 -1
  26. package/dist/render/schema.js +7 -8
  27. package/dist/requests/_shared.d.ts +0 -1
  28. package/dist/requests/_shared.d.ts.map +1 -1
  29. package/dist/requests/_shared.js +0 -4
  30. package/dist/requests/curl.d.ts.map +1 -1
  31. package/dist/requests/curl.js +3 -2
  32. package/dist/requests/go.d.ts.map +1 -1
  33. package/dist/requests/go.js +3 -2
  34. package/dist/requests/javascript.d.ts.map +1 -1
  35. package/dist/requests/javascript.js +3 -2
  36. package/dist/requests/python.d.ts.map +1 -1
  37. package/dist/requests/python.js +2 -2
  38. package/dist/types.d.ts +0 -1
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/ui/components/accordion.d.ts +8 -0
  41. package/dist/ui/components/accordion.d.ts.map +1 -0
  42. package/dist/ui/components/accordion.js +20 -0
  43. package/dist/ui/components/input.js +1 -1
  44. package/dist/ui/components/select.js +1 -1
  45. package/dist/ui/contexts/api.js +1 -1
  46. package/dist/ui/contexts/code-example.d.ts.map +1 -1
  47. package/dist/ui/contexts/code-example.js +4 -2
  48. package/dist/ui/index.d.ts.map +1 -1
  49. package/dist/ui/index.js +5 -3
  50. package/dist/ui/select-tabs.d.ts +13 -0
  51. package/dist/ui/select-tabs.d.ts.map +1 -0
  52. package/dist/ui/select-tabs.js +20 -0
  53. package/dist/ui/server-select.d.ts.map +1 -1
  54. package/dist/ui/server-select.js +24 -19
  55. package/dist/utils/schema-to-string.d.ts.map +1 -1
  56. package/dist/utils/schema-to-string.js +10 -1
  57. package/dist/utils/schema.d.ts +0 -1
  58. package/dist/utils/schema.d.ts.map +1 -1
  59. package/dist/utils/schema.js +0 -10
  60. package/dist/utils/url.d.ts +10 -0
  61. package/dist/utils/url.d.ts.map +1 -0
  62. package/dist/utils/url.js +51 -0
  63. package/package.json +10 -9
  64. package/dist/utils/get-pathname-from-input.d.ts +0 -2
  65. package/dist/utils/get-pathname-from-input.d.ts.map +0 -1
  66. package/dist/utils/get-pathname-from-input.js +0 -27
  67. package/dist/utils/server-url.d.ts +0 -2
  68. package/dist/utils/server-url.d.ts.map +0 -1
  69. package/dist/utils/server-url.js +0 -7
@@ -1,10 +1,12 @@
1
1
  import type { OpenAPIV3_1 } from 'openapi-types';
2
2
  export interface AuthDialogProps {
3
- flow: keyof OpenAPIV3_1.OAuth2SecurityScheme['flows'];
4
3
  scheme: OpenAPIV3_1.OAuth2SecurityScheme;
4
+ scopes: string[];
5
+ open: boolean;
6
+ setOpen: (v: boolean) => void;
5
7
  setToken: (token: string) => void;
6
8
  children: React.ReactNode;
7
9
  }
8
- export declare function OauthDialog({ flow, scheme, setToken, children, }: AuthDialogProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function OauthDialog({ scheme, scopes, setToken, children, open, setOpen, }: AuthDialogProps): import("react/jsx-runtime").JSX.Element;
9
11
  export declare const OauthDialogTrigger: import("react").ForwardRefExoticComponent<import("@radix-ui/react-dialog").DialogTriggerProps & import("react").RefAttributes<HTMLButtonElement>>;
10
12
  //# sourceMappingURL=oauth-dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-dialog.d.ts","sourceRoot":"","sources":["../../../src/playground/auth/oauth-dialog.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQjD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,WAAW,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC;IAEzC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAaD,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAQ,GACT,EAAE,eAAe,2CAkKjB;AAED,eAAO,MAAM,kBAAkB,mJAAgB,CAAC"}
1
+ {"version":3,"file":"oauth-dialog.d.ts","sourceRoot":"","sources":["../../../src/playground/auth/oauth-dialog.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAiBjD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC,oBAAoB,CAAC;IACzC,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9B,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAuCD,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,OAAO,GACR,EAAE,eAAe,2CAwSjB;AAED,eAAO,MAAM,kBAAkB,mJAAgB,CAAC"}
@@ -6,15 +6,38 @@ import { useQuery } from '../../utils/use-query.js';
6
6
  import { useEffect, useState } from 'react';
7
7
  import { cn } from 'fumadocs-ui/utils/cn';
8
8
  import { buttonVariants } from 'fumadocs-ui/components/ui/button';
9
- export function OauthDialog({ flow, scheme, setToken, children, }) {
10
- const [open, setOpen] = useState(false);
9
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../../ui/components/select.js';
10
+ const FlowTypes = {
11
+ password: {
12
+ name: 'Resource Owner Password Flow',
13
+ description: 'Authenticate using username and password.',
14
+ },
15
+ clientCredentials: {
16
+ name: 'Client Credentials',
17
+ description: 'Intended for the server-to-server authentication.',
18
+ },
19
+ authorizationCode: {
20
+ name: 'Authorization code',
21
+ description: 'Authenticate with 3rd party services',
22
+ },
23
+ implicit: {
24
+ name: 'Implicit',
25
+ description: 'Retrieve the access token directly.',
26
+ },
27
+ };
28
+ export function OauthDialog({ scheme, scopes, setToken, children, open, setOpen, }) {
29
+ const [type, setType] = useState(() => {
30
+ return Object.keys(scheme.flows)[0];
31
+ });
11
32
  const form = useForm({
12
33
  defaultValues: {
13
34
  clientId: '',
14
35
  clientSecret: '',
36
+ username: '',
37
+ password: '',
15
38
  },
16
39
  });
17
- const tokenQuery = useQuery(async (code, state) => {
40
+ const authCodeCallback = useQuery(async (code, state) => {
18
41
  const value = scheme.flows.authorizationCode;
19
42
  const res = await fetch(value.tokenUrl, {
20
43
  method: 'POST',
@@ -32,59 +55,123 @@ export function OauthDialog({ flow, scheme, setToken, children, }) {
32
55
  });
33
56
  if (!res.ok)
34
57
  throw new Error(await res.text());
35
- const { access_token } = (await res.json());
36
- setToken(access_token);
58
+ const { access_token, token_type = 'Bearer' } = (await res.json());
59
+ setToken(`${token_type} ${access_token}`);
37
60
  setOpen(false);
38
61
  });
39
62
  useEffect(() => {
40
- const params = new URLSearchParams(window.location.search);
41
- const code = params.get('code');
42
- const state = params.get('state');
43
- if (!code || !state || flow !== 'authorizationCode')
44
- return;
45
- const parsedState = JSON.parse(state);
46
- setOpen(true);
47
- form.setValue('clientId', parsedState.client_id);
48
- form.setValue('clientSecret', parsedState.client_secret);
49
- tokenQuery.start(code, parsedState);
50
- window.history.replaceState(null, '', window.location.pathname);
63
+ if (scheme.flows.authorizationCode) {
64
+ const params = new URLSearchParams(window.location.search);
65
+ const state = params.get('state');
66
+ const code = params.get('code');
67
+ if (state && code) {
68
+ const parsedState = JSON.parse(state);
69
+ setOpen(true);
70
+ form.setValue('clientId', parsedState.client_id);
71
+ form.setValue('clientSecret', parsedState.client_secret);
72
+ authCodeCallback.start(code, parsedState);
73
+ window.history.replaceState(null, '', window.location.pathname);
74
+ return;
75
+ }
76
+ }
77
+ if (scheme.flows.implicit && window.location.hash.length > 1) {
78
+ const params = new URLSearchParams(window.location.hash.slice(1));
79
+ const state = params.get('state');
80
+ const token = params.get('access_token');
81
+ const type = params.get('token_type') ?? 'Bearer';
82
+ if (state && token) {
83
+ const parsedState = JSON.parse(state);
84
+ form.setValue('clientId', parsedState.client_id);
85
+ setToken(`${type} ${token}`);
86
+ window.history.replaceState(null, '', window.location.pathname);
87
+ }
88
+ }
51
89
  // eslint-disable-next-line react-hooks/exhaustive-deps -- first page load only
52
90
  }, []);
53
91
  const authorize = useQuery(async (values) => {
54
- if (flow === 'authorizationCode') {
55
- const value = scheme.flows[flow];
92
+ if (type === 'implicit') {
93
+ const value = scheme.flows[type];
94
+ const params = new URLSearchParams();
95
+ params.set('response_type', 'token');
96
+ params.set('client_id', values.clientId);
97
+ params.set('redirect_uri', window.location.href);
98
+ params.set('scope', scopes.join('+'));
99
+ params.set('state', JSON.stringify({
100
+ client_id: values.clientId,
101
+ redirect_uri: window.location.href,
102
+ }));
103
+ window.location.replace(`${value.authorizationUrl}?${params.toString()}`);
104
+ return;
105
+ }
106
+ if (type === 'authorizationCode') {
107
+ const value = scheme.flows[type];
56
108
  const params = new URLSearchParams();
57
109
  params.set('response_type', 'code');
58
110
  params.set('client_id', values.clientId);
59
111
  params.set('redirect_uri', window.location.href);
60
- params.set('scope', Object.keys(value.scopes).join('+'));
112
+ params.set('scope', scopes.join('+'));
61
113
  params.set('state', JSON.stringify({
62
114
  client_id: values.clientId,
63
115
  client_secret: values.clientSecret,
64
116
  redirect_uri: window.location.href,
65
117
  }));
66
118
  window.location.replace(`${value.authorizationUrl}?${params.toString()}`);
119
+ return;
120
+ }
121
+ let res;
122
+ if (type === 'password') {
123
+ const value = scheme.flows[type];
124
+ res = await fetch(value.tokenUrl, {
125
+ method: 'POST',
126
+ headers: {
127
+ 'Content-Type': 'application/x-www-form-urlencoded',
128
+ },
129
+ body: new URLSearchParams({
130
+ grant_type: 'password',
131
+ username: values.username,
132
+ password: values.password,
133
+ scope: scopes.join('+'),
134
+ }),
135
+ });
67
136
  }
68
- if (flow === 'clientCredentials') {
69
- const value = scheme.flows[flow];
70
- await fetch(value.tokenUrl, {
137
+ if (type === 'clientCredentials') {
138
+ const value = scheme.flows[type];
139
+ res = await fetch(value.tokenUrl, {
71
140
  method: 'POST',
72
141
  headers: {
73
142
  'Content-Type': 'application/x-www-form-urlencoded',
74
143
  },
75
144
  body: new URLSearchParams({
76
145
  grant_type: 'client_credentials',
77
- scope: Object.keys(value.scopes).join('+'),
146
+ client_id: values.clientId,
147
+ client_secret: values.clientSecret,
148
+ scope: scopes.join('+'),
78
149
  }),
79
150
  });
80
151
  }
152
+ if (res) {
153
+ if (!res.ok)
154
+ throw new Error(await res.text());
155
+ const { access_token, token_type = 'Bearer' } = (await res.json());
156
+ setToken(`${token_type} ${access_token}`);
157
+ setOpen(false);
158
+ }
81
159
  });
82
160
  const onSubmit = form.handleSubmit((values) => {
83
161
  return authorize.start(values);
84
162
  });
85
- const isLoading = authorize.isLoading || tokenQuery.isLoading;
86
- return (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [children, _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Authorization" }), _jsx(DialogDescription, { children: "Obtain the access token for API." })] }), _jsxs("form", { className: "flex flex-col gap-6", onSubmit: onSubmit, children: [(flow === 'authorizationCode' || flow === 'clientCredentials') && (_jsxs(_Fragment, { children: [_jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "client_id", className: cn(labelVariants()), children: "Client ID" }), _jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client ID of your OAuth application." }), _jsx(Input, { id: "client_id", placeholder: "Enter value", type: "text", disabled: isLoading, ...form.register('clientId', { required: true }) })] }), _jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "client_secret", className: cn(labelVariants()), children: "Client Secret" }), _jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client secret of your OAuth application." }), _jsx(Input, { id: "client_secret", placeholder: "Enter value", type: "password", disabled: isLoading, ...form.register('clientSecret', { required: true }) })] })] })), tokenQuery.error ? (_jsx("p", { className: "text-red-400 font-medium text-sm", children: String(tokenQuery.error) })) : null, _jsx("button", { disabled: isLoading, className: cn(buttonVariants({
163
+ const isLoading = authorize.isLoading || authCodeCallback.isLoading;
164
+ const error = authCodeCallback.error ?? authorize.error;
165
+ return (_jsxs(Dialog, { open: open, onOpenChange: setOpen, children: [children, _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Authorization" }), _jsx(DialogDescription, { children: "Obtain the access token for API." })] }), _jsxs("form", { className: "flex flex-col gap-6", onSubmit: (e) => {
166
+ void onSubmit(e);
167
+ e.stopPropagation();
168
+ }, children: [_jsxs(Select, { value: type, onValueChange: setType, children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: Object.keys(scheme.flows).map((key) => {
169
+ const { name, description } = FlowTypes[key];
170
+ return (_jsxs(SelectItem, { value: key, children: [_jsx("p", { className: "font-medium", children: name }), _jsx("p", { className: "text-fd-muted-foreground", children: description })] }, key));
171
+ }) })] }), (type === 'authorizationCode' ||
172
+ type === 'clientCredentials' ||
173
+ type === 'implicit') && (_jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "client_id", className: cn(labelVariants()), children: "Client ID" }), _jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client ID of your OAuth application." }), _jsx(Input, { id: "client_id", placeholder: "Enter value", type: "text", autoComplete: "off", disabled: isLoading, ...form.register('clientId', { required: true }) })] })), (type === 'authorizationCode' || type === 'clientCredentials') && (_jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "client_secret", className: cn(labelVariants()), children: "Client Secret" }), _jsx("p", { className: "text-fd-muted-foreground text-sm", children: "The client secret of your OAuth application." }), _jsx(Input, { id: "client_secret", placeholder: "Enter value", type: "password", autoComplete: "off", disabled: isLoading, ...form.register('clientSecret', { required: true }) })] })), type === 'password' && (_jsxs(_Fragment, { children: [_jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "username", className: cn(labelVariants()), children: "Username" }), _jsx(Input, { id: "username", placeholder: "Enter value", type: "text", disabled: isLoading, autoComplete: "off", ...form.register('username', { required: true }) })] }), _jsxs("fieldset", { className: "flex flex-col gap-1.5", children: [_jsx("label", { htmlFor: "password", className: cn(labelVariants()), children: "Client Secret" }), _jsx(Input, { id: "password", placeholder: "Enter value", type: "password", autoComplete: "off", disabled: isLoading, ...form.register('password', { required: true }) })] })] })), error ? (_jsx("p", { className: "text-red-400 font-medium text-sm", children: String(error) })) : null, _jsx("button", { type: "submit", disabled: isLoading, className: cn(buttonVariants({
87
174
  color: 'primary',
88
- })), children: tokenQuery.isLoading ? 'Fetching token...' : 'Submit' })] })] })] }));
175
+ })), children: authCodeCallback.isLoading ? 'Fetching token...' : 'Submit' })] })] })] }));
89
176
  }
90
177
  export const OauthDialogTrigger = DialogTrigger;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/playground/client.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EAAE,EAEP,KAAK,cAAc,EAEnB,KAAK,YAAY,EAKlB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,oBAAoB,CAAC;AA2B5B,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,WAAW,CAAC,KAAK,SAAS,SAAS,CAAC,UAAU,CAAC,EAAE,IAAI;IACpE,MAAM,EAAE,CAAC,KAAK,EAAE;QACd;;WAEG;QACH,IAAI,EAAE,IAAI,CAAC;QACX,KAAK,EAAE,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAChD,UAAU,EAAE,oBAAoB,CAAC;QACjC,SAAS,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;KAC3C,KAAK,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,eAAe,CAAC;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,UAAU,EAAE,aAAa,EAAE,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,aAAa,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,WAAW,CACrB,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,EACnC,cAAc,CACf,CAAC;QACF,IAAI,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;KAC3C,CAAC;IAEF,UAAU,CAAC,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,EAAE,CAAC;YAAE,IAAI,EAAE,WAAW,CAAA;SAAE,CAAC,CAAC;KAC1C,CAAC,CAAC;CACJ;AAsBD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,MAAc,EACd,UAAU,EACV,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EAAE,EAAE,aAAoC,EAAO,EACzD,GAAG,IAAI,EACR,EAAE,WAAW,2CAgLb"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/playground/client.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EAAE,EAEP,KAAK,cAAc,EAEnB,KAAK,YAAY,EAKlB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACrB,SAAS,EACT,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACd,MAAM,oBAAoB,CAAC;AAwC5B,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,WAAW,CAAC,KAAK,SAAS,SAAS,CAAC,UAAU,CAAC,EAAE,IAAI;IACpE,MAAM,EAAE,CAAC,KAAK,EAAE;QACd;;WAEG;QACH,IAAI,EAAE,IAAI,CAAC;QACX,KAAK,EAAE,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAChD,UAAU,EAAE,oBAAoB,CAAC;QACjC,SAAS,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;KAC3C,KAAK,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,WAAY,SAAQ,cAAc,CAAC,eAAe,CAAC;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;IAC9B,UAAU,EAAE,aAAa,EAAE,EAAE,CAAC;IAC9B,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,aAAa,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,MAAM,CAAC,EAAE;QACP,SAAS,CAAC,EAAE,WAAW,CACrB,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,EACnC,cAAc,CACf,CAAC;QACF,IAAI,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;KAC3C,CAAC;IAEF,UAAU,CAAC,EAAE,OAAO,CAAC;QACnB,aAAa,EAAE,EAAE,CAAC;YAAE,IAAI,EAAE,WAAW,CAAA;SAAE,CAAC,CAAC;KAC1C,CAAC,CAAC;CACJ;AAgCD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,KAAK,EACL,MAAc,EACd,UAAU,EACV,UAAU,EACV,IAAI,EACJ,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EAAE,EAAE,aAAoC,EAAO,EACzD,GAAG,IAAI,EACR,EAAE,WAAW,2CA2Kb"}
@@ -3,9 +3,9 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { Fragment, lazy, useEffect, useMemo, useState, } from 'react';
4
4
  import { Controller, FormProvider, useForm, useFormContext, } from 'react-hook-form';
5
5
  import { useApiContext, useServerSelectContext } from '../ui/contexts/api.js';
6
- import { FieldSet, JsonInput } from './inputs.js';
6
+ import { FieldInput, FieldSet, JsonInput, ObjectInput } from './inputs.js';
7
7
  import { getStatusInfo } from './status-info.js';
8
- import { getUrl } from '../utils/server-url.js';
8
+ import { joinURL, resolveRequestData, resolveServerUrl, withBase, } from '../utils/url.js';
9
9
  import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock';
10
10
  import { MethodLabel } from '../ui/components/method-label.js';
11
11
  import { useQuery } from '../utils/use-query.js';
@@ -17,6 +17,8 @@ import { SchemaProvider, useResolvedSchema, } from '../playground/schema.js';
17
17
  import { useRequestDataUpdater, useRequestInitialData, } from '../ui/contexts/code-example.js';
18
18
  import { useEffectEvent } from 'fumadocs-core/utils/use-effect-event';
19
19
  import { useOnChange } from 'fumadocs-core/utils/use-on-change';
20
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '../ui/components/select.js';
21
+ import { labelVariants } from '../ui/components/input.js';
20
22
  const AuthPrefix = '__fumadocs_auth';
21
23
  function toRequestData(method, mediaType, value) {
22
24
  return {
@@ -30,6 +32,12 @@ function toRequestData(method, mediaType, value) {
30
32
  };
31
33
  }
32
34
  const ServerSelect = lazy(() => import('../ui/server-select.js'));
35
+ const OauthDialog = lazy(() => import('./auth/oauth-dialog.js').then((mod) => ({
36
+ default: mod.OauthDialog,
37
+ })));
38
+ const OauthDialogTrigger = lazy(() => import('./auth/oauth-dialog.js').then((mod) => ({
39
+ default: mod.OauthDialogTrigger,
40
+ })));
33
41
  export default function Client({ route, method = 'GET', securities, parameters, body, fields, references, proxyUrl, components: { ResultDisplay = DefaultResultDisplay } = {}, ...rest }) {
34
42
  const { server } = useServerSelectContext();
35
43
  const requestData = useRequestInitialData();
@@ -50,37 +58,51 @@ export default function Client({ route, method = 'GET', securities, parameters,
50
58
  });
51
59
  const testQuery = useQuery(async (input) => {
52
60
  const fetcher = await import('./fetcher.js').then((mod) => mod.createBrowserFetcher(mediaAdapters));
53
- const serverUrl = server
54
- ? getUrl(server.url, server.variables)
55
- : window.location.origin;
56
- return fetcher.fetch(`${serverUrl}${route}`, {
61
+ const data = toRequestData(method, body?.mediaType, input);
62
+ return fetcher.fetch(joinURL(withBase(server ? resolveServerUrl(server.url, server.variables) : '/', window.location.origin), resolveRequestData(route, data)), {
57
63
  proxyUrl,
58
- ...toRequestData(method, body?.mediaType, input),
64
+ ...data,
59
65
  });
60
66
  });
61
- function initAuthValues() {
67
+ function initAuthValues(values, inputs) {
62
68
  for (const item of inputs) {
63
- let value = item.defaultValue;
64
- const stored = localStorage.getItem(AuthPrefix + item.original.id);
65
- if (stored) {
66
- const parsed = JSON.parse(stored);
67
- if (typeof parsed === typeof item.defaultValue)
68
- value = parsed;
69
- }
70
- // @ts-expect-error -- safe
71
- form.setValue(item.fieldName, value);
69
+ manipulateValues(values, item.fieldName, () => {
70
+ const stored = localStorage.getItem(AuthPrefix + item.original.id);
71
+ if (stored) {
72
+ const parsed = JSON.parse(stored);
73
+ if (typeof parsed === typeof item.defaultValue)
74
+ return parsed;
75
+ }
76
+ return item.defaultValue;
77
+ });
72
78
  }
79
+ return values;
73
80
  }
74
81
  useOnChange(defaultValues, () => {
75
82
  fieldInfoMap.clear();
76
- form.reset(defaultValues);
77
- initAuthValues();
83
+ form.reset(initAuthValues(defaultValues, inputs));
84
+ });
85
+ useOnChange(inputs, (current, previous) => {
86
+ form.reset((values) => {
87
+ for (const item of previous) {
88
+ if (current.some(({ original }) => original.id === item.original.id)) {
89
+ continue;
90
+ }
91
+ manipulateValues(values, item.fieldName, () => undefined);
92
+ }
93
+ return initAuthValues(values, current);
94
+ });
78
95
  });
79
- useOnChange(inputs, (_, previous) => {
80
- for (const item of previous) {
81
- form.reset((values) => manipulateValues(values, item.fieldName, () => undefined));
96
+ const onUpdateDebounced = useEffectEvent((values) => {
97
+ for (const item of inputs) {
98
+ const value = item.fieldName
99
+ .split('.')
100
+ .reduce((v, seg) => v[seg], values);
101
+ if (value) {
102
+ localStorage.setItem(AuthPrefix + item.original.id, JSON.stringify(value));
103
+ }
82
104
  }
83
- initAuthValues();
105
+ updater.setData(toRequestData(method, body?.mediaType, mapInputs(values)));
84
106
  });
85
107
  useEffect(() => {
86
108
  let timer = null;
@@ -91,27 +113,36 @@ export default function Client({ route, method = 'GET', securities, parameters,
91
113
  callback({ values }) {
92
114
  if (timer)
93
115
  window.clearTimeout(timer);
94
- timer = window.setTimeout(() => {
95
- for (const item of inputs) {
96
- const value = item.fieldName
97
- .split('.')
98
- .reduce((v, seg) => v[seg], values);
99
- if (value) {
100
- localStorage.setItem(AuthPrefix + item.original.id, JSON.stringify(value));
101
- }
102
- }
103
- updater.setData(toRequestData(method, body?.mediaType, mapInputs(values)));
104
- }, timer ? 400 : 0);
116
+ timer = window.setTimeout(() => onUpdateDebounced(values), timer ? 400 : 0);
105
117
  },
106
118
  });
107
- initAuthValues();
119
+ form.reset((values) => initAuthValues(values, inputs));
108
120
  return () => subscription();
109
121
  // eslint-disable-next-line react-hooks/exhaustive-deps -- mounted once only
110
122
  }, []);
111
123
  const onSubmit = form.handleSubmit((value) => {
112
124
  testQuery.start(mapInputs(value));
113
125
  });
114
- return (_jsx(FormProvider, { ...form, children: _jsx(SchemaProvider, { fieldInfoMap: fieldInfoMap, references: references, children: _jsxs("form", { ...rest, className: cn('not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground', rest.className), onSubmit: onSubmit, children: [_jsx(ServerSelect, {}), _jsxs("div", { className: "flex flex-row items-center gap-2 text-sm p-3 pb-0", children: [_jsx(MethodLabel, { children: method }), _jsx(Route, { route: route, className: "flex-1" }), _jsx("button", { type: "submit", className: cn(buttonVariants({ color: 'primary', size: 'sm' }), 'px-3 py-1.5'), disabled: testQuery.isLoading, children: testQuery.isLoading ? (_jsx(LoaderCircle, { className: "size-4 animate-spin" })) : ('Send') })] }), securities.length > 0 && (_jsxs("div", { className: "m-3 p-3 border bg-fd-muted rounded-lg", children: [_jsxs("div", { className: "flex gap-4 items-center justify-between mb-4", children: [_jsx("p", { className: "text-sm font-medium", children: "Authorization" }), _jsx("select", { value: securityId.toString(), onChange: (e) => setSecurityId(Number(e.target.value)), className: "text-xs font-mono px-2 py-1.5 outline-none", children: securities.map((security, i) => (_jsx("option", { value: i, children: security.map((item) => item.id).join(' & ') }, i))) })] }), _jsx("div", { className: "flex flex-col gap-4", children: inputs.map((input) => (_jsx(Fragment, { children: input.children }, input.fieldName))) })] })), _jsx(FormBody, { body: body, fields: fields, parameters: parameters }), testQuery.data ? _jsx(ResultDisplay, { data: testQuery.data }) : null] }) }) }));
126
+ return (_jsx(FormProvider, { ...form, children: _jsx(SchemaProvider, { fieldInfoMap: fieldInfoMap, references: references, children: _jsxs("form", { ...rest, className: cn('not-prose flex flex-col rounded-xl border shadow-md overflow-hidden bg-fd-card text-fd-card-foreground', rest.className), onSubmit: onSubmit, children: [_jsx(ServerSelect, {}), _jsxs("div", { className: "flex flex-row items-center gap-2 text-sm p-3 pb-0", children: [_jsx(MethodLabel, { children: method }), _jsx(Route, { route: route, className: "flex-1" }), _jsx("button", { type: "submit", className: cn(buttonVariants({ color: 'primary', size: 'sm' }), 'px-3 py-1.5'), disabled: testQuery.isLoading, children: testQuery.isLoading ? (_jsx(LoaderCircle, { className: "size-4 animate-spin" })) : ('Send') })] }), securities.length > 0 && (_jsx(SecurityTabs, { securities: securities, securityId: securityId, setSecurityId: setSecurityId, children: inputs.map((input) => (_jsx(Fragment, { children: input.children }, input.fieldName))) })), _jsx(FormBody, { body: body, fields: fields, parameters: parameters }), testQuery.data ? _jsx(ResultDisplay, { data: testQuery.data }) : null] }) }) }));
127
+ }
128
+ function SecurityTabs({ securities, setSecurityId, securityId, children, }) {
129
+ const [open, setOpen] = useState(false);
130
+ const form = useFormContext();
131
+ const result = (_jsxs(CollapsiblePanel, { title: "Authorization", children: [_jsxs(Select, { value: securityId.toString(), onValueChange: (v) => setSecurityId(Number(v)), children: [_jsx(SelectTrigger, { children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: securities.map((security, i) => (_jsx(SelectItem, { value: i.toString(), children: security.map((item) => item.id).join(' & ') }, i))) })] }), children] }));
132
+ for (let i = 0; i < securities.length; i++) {
133
+ const security = securities[i];
134
+ for (const item of security) {
135
+ if (item.type === 'oauth2') {
136
+ return (_jsx(OauthDialog, { scheme: item, scopes: item.scopes, open: open, setOpen: (v) => {
137
+ setOpen(v);
138
+ if (v) {
139
+ setSecurityId(i);
140
+ }
141
+ }, setToken: (token) => form.setValue('header.Authorization', token), children: result }));
142
+ }
143
+ }
144
+ }
145
+ return result;
115
146
  }
116
147
  const paramNames = ['Headers', 'Cookies', 'Query', 'Path'];
117
148
  const paramTypes = ['header', 'cookie', 'query', 'path'];
@@ -142,7 +173,7 @@ function BodyInput({ field: _field }) {
142
173
  color: 'ghost',
143
174
  size: 'sm',
144
175
  className: 'p-2',
145
- })), onClick: () => setIsJson(false), type: "button", children: "Close JSON Editor" }) })) : (_jsx(FieldSet, { field: field, fieldName: "body", name: _jsx("button", { className: cn(buttonVariants({
176
+ })), onClick: () => setIsJson(false), type: "button", children: "Close JSON Editor" }) })) : (_jsx(FieldSet, { field: field, fieldName: "body", collapsible: false, name: _jsx("button", { className: cn(buttonVariants({
146
177
  color: 'secondary',
147
178
  size: 'sm',
148
179
  className: 'p-2',
@@ -153,15 +184,16 @@ function BodyInput({ field: _field }) {
153
184
  *
154
185
  * @returns a new manipulated object
155
186
  */
156
- function manipulateValues(values, fieldName, update) {
157
- const root = { ...values };
187
+ function manipulateValues(values, fieldName, update, clone = false) {
188
+ const root = clone ? { ...values } : values;
158
189
  let current = root;
159
190
  const segments = fieldName.split('.');
160
191
  for (let i = 0; i < segments.length; i++) {
161
192
  const segment = segments[i];
162
193
  if (i !== segments.length - 1) {
163
194
  let v = current[segment];
164
- v = { ...v };
195
+ if (clone)
196
+ v = { ...v };
165
197
  current[segment] = v;
166
198
  current = v;
167
199
  continue;
@@ -197,10 +229,8 @@ function useAuthInputs(securities) {
197
229
  }
198
230
  return out;
199
231
  },
200
- children: (_jsx(FieldSet, { name: "Authorization (header)", field: {
232
+ children: (_jsx(ObjectInput, { field: {
201
233
  type: 'object',
202
- required: ['username', 'password'],
203
- description: security.description,
204
234
  properties: {
205
235
  username: {
206
236
  type: 'string',
@@ -212,16 +242,29 @@ function useAuthInputs(securities) {
212
242
  }, fieldName: fieldName })),
213
243
  });
214
244
  }
215
- else if (security.type === 'http' || security.type === 'oauth2') {
245
+ else if (security.type === 'oauth2') {
216
246
  const fieldName = 'header.Authorization';
217
247
  result.push({
218
248
  fieldName: fieldName,
219
249
  original: security,
220
250
  defaultValue: 'Bearer ',
221
- children: (_jsxs(_Fragment, { children: [_jsx(FieldSet, { name: "Authorization (header)", fieldName: fieldName, field: {
222
- type: 'string',
223
- description: security.description ?? `The Authorization access token.`,
224
- } }), _jsx(OAuth, { authorization: security })] })),
251
+ children: (_jsxs("fieldset", { className: "flex flex-col gap-2", children: [_jsx("label", { htmlFor: fieldName, className: cn(labelVariants()), children: "Access Token" }), _jsxs("div", { className: "flex gap-2", children: [_jsx(FieldInput, { fieldName: fieldName, isRequired: true, field: {
252
+ type: 'string',
253
+ }, className: "flex-1" }), _jsx(OauthDialogTrigger, { type: "button", className: cn(buttonVariants({
254
+ size: 'sm',
255
+ color: 'secondary',
256
+ })), children: "Authorize" })] })] })),
257
+ });
258
+ }
259
+ else if (security.type === 'http') {
260
+ const fieldName = 'header.Authorization';
261
+ result.push({
262
+ fieldName: fieldName,
263
+ original: security,
264
+ defaultValue: 'Bearer ',
265
+ children: (_jsx(FieldSet, { name: "Authorization (header)", fieldName: fieldName, isRequired: true, field: {
266
+ type: 'string',
267
+ } })),
225
268
  });
226
269
  }
227
270
  else if (security.type === 'apiKey') {
@@ -230,13 +273,22 @@ function useAuthInputs(securities) {
230
273
  fieldName,
231
274
  defaultValue: '',
232
275
  original: security,
233
- children: (_jsx(FieldSet, { fieldName: fieldName, name: security.name, field: {
276
+ children: (_jsx(FieldSet, { fieldName: fieldName, name: `${security.name} (${security.in})`, isRequired: true, field: {
234
277
  type: 'string',
235
- description: security.description ?? `The API key in ${security.in}.`,
236
278
  } })),
237
279
  });
238
280
  }
239
- // TODO: handle OpenID connect
281
+ else {
282
+ const fieldName = 'header.Authorization';
283
+ result.push({
284
+ fieldName,
285
+ defaultValue: '',
286
+ original: security,
287
+ children: (_jsxs(_Fragment, { children: [_jsx(FieldSet, { name: "Authorization (header)", isRequired: true, fieldName: fieldName, field: {
288
+ type: 'string',
289
+ } }), _jsx("p", { className: "text-fd-muted-foreground text-xs", children: "OpenID Connect is not supported at the moment, you can still set an access token here." })] })),
290
+ });
291
+ }
240
292
  }
241
293
  return result;
242
294
  }, [securities]);
@@ -244,7 +296,7 @@ function useAuthInputs(securities) {
244
296
  for (const item of inputs) {
245
297
  if (!item.mapOutput)
246
298
  continue;
247
- values = manipulateValues(values, item.fieldName, item.mapOutput);
299
+ values = manipulateValues(values, item.fieldName, item.mapOutput, true);
248
300
  }
249
301
  return values;
250
302
  });
@@ -255,22 +307,6 @@ function renderCustomField(fieldName, info, field, key) {
255
307
  // @ts-expect-error we use string here
256
308
  render: (props) => field.render({ ...props, info }), name: fieldName }, key));
257
309
  }
258
- const OauthDialog = lazy(() => import('./auth/oauth-dialog.js').then((mod) => ({
259
- default: mod.OauthDialog,
260
- })));
261
- const OauthDialogTrigger = lazy(() => import('./auth/oauth-dialog.js').then((mod) => ({
262
- default: mod.OauthDialogTrigger,
263
- })));
264
- function OAuth({ authorization }) {
265
- const form = useFormContext();
266
- if (authorization.type !== 'oauth2')
267
- return;
268
- // only the first one, so it looks simpler :)
269
- const flow = Object.keys(authorization.flows)[0];
270
- return (_jsx(OauthDialog, { flow: flow, scheme: authorization, setToken: (token) => form.setValue('authorization', `Bearer ${token}`), children: _jsx(OauthDialogTrigger, { type: "button", className: cn(buttonVariants({
271
- color: 'secondary',
272
- })), children: "Auth Settings" }) }));
273
- }
274
310
  function Route({ route, ...props }) {
275
311
  const segments = route.split('/').filter((part) => part.length > 0);
276
312
  return (_jsx("div", { ...props, className: cn('flex flex-row items-center gap-0.5 overflow-auto text-nowrap', props.className), children: segments.map((part, index) => (_jsxs(Fragment, { children: [_jsx("span", { className: "text-fd-muted-foreground", children: "/" }), part.startsWith('{') && part.endsWith('}') ? (_jsx("code", { className: "bg-fd-primary/10 text-fd-primary", children: part })) : (_jsx("code", { className: "text-fd-foreground", children: part }))] }, index))) }));
@@ -278,7 +314,7 @@ function Route({ route, ...props }) {
278
314
  function DefaultResultDisplay({ data }) {
279
315
  const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);
280
316
  const { shikiOptions } = useApiContext();
281
- return (_jsxs("div", { className: "flex flex-col gap-3 border-t p-3", children: [_jsxs("div", { className: "inline-flex items-center gap-1.5 text-sm font-medium text-fd-foreground", children: [_jsx(statusInfo.icon, { className: cn('size-4', statusInfo.color) }), statusInfo.description] }), _jsx("p", { className: "text-sm text-fd-muted-foreground", children: data.status }), data.data ? (_jsx(DynamicCodeBlock, { lang: typeof data.data === 'string' && data.data.length > 50000
317
+ return (_jsxs("div", { className: "flex flex-col gap-3 p-3", children: [_jsxs("div", { className: "inline-flex items-center gap-1.5 text-sm font-medium text-fd-foreground", children: [_jsx(statusInfo.icon, { className: cn('size-4', statusInfo.color) }), statusInfo.description] }), _jsx("p", { className: "text-sm text-fd-muted-foreground", children: data.status }), data.data ? (_jsx(DynamicCodeBlock, { lang: typeof data.data === 'string' && data.data.length > 50000
282
318
  ? 'text'
283
319
  : data.type, code: typeof data.data === 'string'
284
320
  ? data.data
@@ -9,7 +9,12 @@ export interface FetchResult {
9
9
  data: unknown;
10
10
  }
11
11
  export interface Fetcher {
12
- fetch: (route: string, options: FetchOptions) => Promise<FetchResult>;
12
+ /**
13
+ * This method will not apply the path & search parameters from `options` to given `url`.
14
+ *
15
+ * @param url - The full URL of request.
16
+ */
17
+ fetch: (url: string, options: FetchOptions) => Promise<FetchResult>;
13
18
  }
14
19
  export declare function createBrowserFetcher(adapters: Record<string, MediaAdapter>): Fetcher;
15
20
  //# sourceMappingURL=fetcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/playground/fetcher.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACvE;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC,OAAO,CAkGT"}
1
+ {"version":3,"file":"fetcher.d.ts","sourceRoot":"","sources":["../../src/playground/fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB;;;;OAIG;IACH,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACrE;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GACrC,OAAO,CAgGT"}
@@ -1,7 +1,6 @@
1
- import { getPathnameFromInput } from '../utils/get-pathname-from-input.js';
2
1
  export function createBrowserFetcher(adapters) {
3
2
  return {
4
- async fetch(route, options) {
3
+ async fetch(url, options) {
5
4
  const headers = new Headers();
6
5
  if (options.bodyMediaType)
7
6
  headers.append('Content-Type', options.bodyMediaType);
@@ -11,9 +10,8 @@ export function createBrowserFetcher(adapters) {
11
10
  headers.append(key, paramValue.toString());
12
11
  }
13
12
  const proxyUrl = options.proxyUrl
14
- ? new URL(options.proxyUrl, window.location.origin)
13
+ ? new URL(options.proxyUrl, document.baseURI)
15
14
  : null;
16
- let url = getPathnameFromInput(route, options.path, options.query);
17
15
  if (proxyUrl) {
18
16
  proxyUrl.searchParams.append('url', url);
19
17
  url = proxyUrl.toString();
@@ -47,22 +47,32 @@ function writeReferences(schema, ctx, stack = new WeakMap()) {
47
47
  }
48
48
  const output = { ...schema };
49
49
  stack.set(schema, output);
50
- for (const name of ['items', 'additionalProperties']) {
50
+ for (const _n in output) {
51
+ const name = _n;
51
52
  if (!output[name])
52
53
  continue;
53
- output[name] = writeReferences(output[name], ctx, stack);
54
- }
55
- for (const name of ['oneOf', 'allOf', 'anyOf']) {
56
- if (!output[name])
57
- continue;
58
- output[name] = output[name].map((item) => writeReferences(item, ctx, stack));
59
- }
60
- for (const name of ['properties', 'patternProperties']) {
61
- if (!output[name])
62
- continue;
63
- output[name] = { ...output[name] };
64
- for (const key in output[name]) {
65
- output[name][key] = writeReferences(output[name][key], ctx, stack);
54
+ switch (name) {
55
+ case 'oneOf':
56
+ case 'allOf':
57
+ case 'anyOf':
58
+ output[name] = output[name].map((item) => writeReferences(item, ctx, stack));
59
+ continue;
60
+ case 'items':
61
+ case 'additionalProperties':
62
+ case 'not':
63
+ output[name] = writeReferences(output[name], ctx, stack);
64
+ continue;
65
+ case 'properties':
66
+ case 'patternProperties':
67
+ output[name] = { ...output[name] };
68
+ for (const key in output[name]) {
69
+ output[name][key] = writeReferences(output[name][key], ctx, stack);
70
+ }
71
+ continue;
72
+ default:
73
+ if (typeof output[name] === 'object' && !Array.isArray(output[name])) {
74
+ output[name] = { ...output[name] };
75
+ }
66
76
  }
67
77
  }
68
78
  return output;
@@ -84,7 +94,8 @@ function parseSecurities(method, { schema: { document } }) {
84
94
  id: key,
85
95
  });
86
96
  }
87
- result.push(list);
97
+ if (list.length > 0)
98
+ result.push(list);
88
99
  }
89
100
  return result;
90
101
  }