mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
OpenAPI: Lazy load media adapters on client side
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-openapi': patch
|
||||
---
|
||||
|
||||
Lazy load media adapters on client side
|
||||
@@ -1,150 +0,0 @@
|
||||
'use client';
|
||||
import { inputToString } from '@/utils/input-to-string';
|
||||
import type { MediaAdapter, MediaContext } from '@/media/adapter';
|
||||
|
||||
export const json: MediaAdapter = {
|
||||
encode(data) {
|
||||
return JSON.stringify(data.body);
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'json', ctx);
|
||||
},
|
||||
};
|
||||
export const xml: MediaAdapter = {
|
||||
async encode(data) {
|
||||
const { js2xml } = await import('xml-js');
|
||||
|
||||
return js2xml(data.body as Record<string, unknown>, {
|
||||
compact: true,
|
||||
spaces: 2,
|
||||
});
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'xml', ctx);
|
||||
},
|
||||
};
|
||||
|
||||
export const url: MediaAdapter = {
|
||||
encode(data) {
|
||||
if (typeof data.body !== 'object')
|
||||
throw new Error(
|
||||
`Input value must be object, received: ${typeof data.body}`,
|
||||
);
|
||||
|
||||
const params = new URLSearchParams();
|
||||
for (const key in data.body) {
|
||||
params.set(key, String(data.body[key as keyof object]));
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
if (ctx.lang === 'js') {
|
||||
return `const body = new URLSearchParams(${JSON.stringify(data.body, null, 2)})`;
|
||||
}
|
||||
|
||||
return str(data.body, 'url', ctx);
|
||||
},
|
||||
};
|
||||
|
||||
export const formData: MediaAdapter = {
|
||||
encode(data) {
|
||||
const formData = new FormData();
|
||||
const body = data.body as Record<string, unknown>;
|
||||
|
||||
if (typeof body !== 'object' || !body) {
|
||||
throw new Error(
|
||||
`Unsupported body type: ${typeof body}, expected: object`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const key in body) {
|
||||
const prop = body[key];
|
||||
|
||||
if (typeof prop === 'object' && prop instanceof File) {
|
||||
formData.set(key, prop);
|
||||
}
|
||||
|
||||
if (Array.isArray(prop) && prop.every((item) => item instanceof File)) {
|
||||
for (const item of prop) {
|
||||
formData.append(key, item);
|
||||
}
|
||||
}
|
||||
|
||||
if (prop && !(prop instanceof File)) {
|
||||
formData.set(key, JSON.stringify(prop));
|
||||
}
|
||||
}
|
||||
|
||||
return formData;
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
const s: string[] = [];
|
||||
if (ctx.lang === 'js') {
|
||||
s.push(`const body = new FormData();`);
|
||||
|
||||
for (const [key, value] of Object.entries(data.body as object)) {
|
||||
s.push(`body.set(${key}, ${inputToString(value)})`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.lang === 'go' && 'addImport' in ctx) {
|
||||
ctx.addImport('mime/multipart');
|
||||
ctx.addImport('bytes');
|
||||
|
||||
s.push('body := new(bytes.Buffer)');
|
||||
s.push('mp := multipart.NewWriter(payload)');
|
||||
|
||||
for (const [key, value] of Object.entries(data.body as object)) {
|
||||
s.push(
|
||||
`mp.WriteField("${key}", ${inputToString(value, 'json', 'backtick')})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.length > 0) return s.join('\n');
|
||||
},
|
||||
};
|
||||
|
||||
export const ndJson: MediaAdapter = {
|
||||
encode(data) {
|
||||
if (Array.isArray(data.body)) {
|
||||
return data.body.map((v) => JSON.stringify(v)).join('\n');
|
||||
}
|
||||
return JSON.stringify(data.body);
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'ndjson', ctx);
|
||||
},
|
||||
};
|
||||
|
||||
export const octet: MediaAdapter = {
|
||||
encode(data) {
|
||||
return data.body as BodyInit;
|
||||
},
|
||||
generateExample() {
|
||||
// not supported
|
||||
return undefined;
|
||||
},
|
||||
};
|
||||
|
||||
function str(
|
||||
init: unknown,
|
||||
format: 'xml' | 'json' | 'url' | 'ndjson',
|
||||
ctx: MediaContext,
|
||||
) {
|
||||
if (ctx.lang === 'js') {
|
||||
if (format === 'json') {
|
||||
return `const body = JSON.stringify(${JSON.stringify(init, null, 2)})`;
|
||||
}
|
||||
return `const body = ${inputToString(init, format, 'backtick')}`;
|
||||
}
|
||||
if (ctx.lang === 'python') {
|
||||
return `body = ${inputToString(init, format, 'python')}`;
|
||||
}
|
||||
if (ctx.lang === 'go' && 'addImport' in ctx) {
|
||||
ctx.addImport('strings');
|
||||
|
||||
return `body := strings.NewReader(${inputToString(init, format, 'backtick')})`;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
import { inputToString } from '@/utils/input-to-string';
|
||||
import type { RequestData } from '@/requests/_shared';
|
||||
import * as adapters from './adapter.client';
|
||||
|
||||
interface GoContext {
|
||||
lang: 'go';
|
||||
@@ -42,11 +43,155 @@ export interface MediaAdapter {
|
||||
generateExample: (data: RequestData, ctx: MediaContext) => string | undefined;
|
||||
}
|
||||
|
||||
export const defaultAdapters: Record<string, MediaAdapter> = {
|
||||
'application/json': adapters.json,
|
||||
'application/xml': adapters.xml,
|
||||
'application/x-ndjson': adapters.ndJson,
|
||||
'application/x-www-form-urlencoded': adapters.url,
|
||||
'multipart/form-data': adapters.formData,
|
||||
'application/octet-stream': adapters.octet,
|
||||
};
|
||||
export const defaultAdapters = {
|
||||
'application/json': {
|
||||
encode(data) {
|
||||
return JSON.stringify(data.body);
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'json', ctx);
|
||||
},
|
||||
},
|
||||
'application/xml': {
|
||||
async encode(data) {
|
||||
// @ts-expect-error -- untyped
|
||||
const { js2xml } = await import('xml-js/lib/js2xml');
|
||||
|
||||
return js2xml(data.body as Record<string, unknown>, {
|
||||
compact: true,
|
||||
spaces: 2,
|
||||
});
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'xml', ctx);
|
||||
},
|
||||
},
|
||||
'application/x-ndjson': {
|
||||
encode(data) {
|
||||
if (Array.isArray(data.body)) {
|
||||
return data.body.map((v) => JSON.stringify(v)).join('\n');
|
||||
}
|
||||
return JSON.stringify(data.body);
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
return str(data.body, 'ndjson', ctx);
|
||||
},
|
||||
},
|
||||
'application/x-www-form-urlencoded': {
|
||||
encode(data) {
|
||||
if (typeof data.body !== 'object')
|
||||
throw new Error(
|
||||
`Input value must be object, received: ${typeof data.body}`,
|
||||
);
|
||||
|
||||
const params = new URLSearchParams();
|
||||
for (const key in data.body) {
|
||||
params.set(key, String(data.body[key as keyof object]));
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
if (ctx.lang === 'js') {
|
||||
return `const body = new URLSearchParams(${JSON.stringify(data.body, null, 2)})`;
|
||||
}
|
||||
|
||||
return str(data.body, 'url', ctx);
|
||||
},
|
||||
},
|
||||
'multipart/form-data': {
|
||||
encode(data) {
|
||||
const formData = new FormData();
|
||||
const body = data.body as Record<string, unknown>;
|
||||
|
||||
if (typeof body !== 'object' || !body) {
|
||||
throw new Error(
|
||||
`Unsupported body type: ${typeof body}, expected: object`,
|
||||
);
|
||||
}
|
||||
|
||||
for (const key in body) {
|
||||
const prop = body[key];
|
||||
|
||||
if (typeof prop === 'object' && prop instanceof File) {
|
||||
formData.set(key, prop);
|
||||
}
|
||||
|
||||
if (Array.isArray(prop) && prop.every((item) => item instanceof File)) {
|
||||
for (const item of prop) {
|
||||
formData.append(key, item);
|
||||
}
|
||||
}
|
||||
|
||||
if (prop && !(prop instanceof File)) {
|
||||
formData.set(key, JSON.stringify(prop));
|
||||
}
|
||||
}
|
||||
|
||||
return formData;
|
||||
},
|
||||
generateExample(data, ctx) {
|
||||
if (ctx.lang === 'python') {
|
||||
return `body = ${JSON.stringify(data.body, null, 2)}`;
|
||||
}
|
||||
|
||||
const s: string[] = [];
|
||||
if (ctx.lang === 'js') {
|
||||
s.push(`const body = new FormData();`);
|
||||
|
||||
for (const [key, value] of Object.entries(data.body as object)) {
|
||||
s.push(`body.set(${key}, ${inputToString(value)})`);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.lang === 'go' && 'addImport' in ctx) {
|
||||
ctx.addImport('mime/multipart');
|
||||
ctx.addImport('bytes');
|
||||
|
||||
s.push('body := new(bytes.Buffer)');
|
||||
s.push('mp := multipart.NewWriter(payload)');
|
||||
|
||||
for (const [key, value] of Object.entries(data.body as object)) {
|
||||
s.push(
|
||||
`mp.WriteField("${key}", ${inputToString(value, 'json', 'backtick')})`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (s.length > 0) return s.join('\n');
|
||||
},
|
||||
},
|
||||
'application/octet-stream': {
|
||||
encode(data) {
|
||||
return data.body as BodyInit;
|
||||
},
|
||||
generateExample() {
|
||||
// not supported
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
} satisfies Record<string, MediaAdapter>;
|
||||
|
||||
function str(
|
||||
init: unknown,
|
||||
format: 'xml' | 'json' | 'url' | 'ndjson',
|
||||
ctx: MediaContext,
|
||||
) {
|
||||
if (ctx.lang === 'js') {
|
||||
if (format === 'json') {
|
||||
return `const body = JSON.stringify(${JSON.stringify(init, null, 2)})`;
|
||||
}
|
||||
return `const body = ${inputToString(init, format, 'backtick')}`;
|
||||
}
|
||||
|
||||
if (ctx.lang === 'python') {
|
||||
if (format === 'json') return `body = ${JSON.stringify(init, null, 2)}`;
|
||||
return `body = ${inputToString(init, format, 'python')}`;
|
||||
}
|
||||
|
||||
if (ctx.lang === 'go' && 'addImport' in ctx) {
|
||||
ctx.addImport('strings');
|
||||
|
||||
return `body := strings.NewReader(${inputToString(init, format, 'backtick')})`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
'use client';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
export const ClientLazy = dynamic(() => import('./client'));
|
||||
@@ -48,7 +48,6 @@ import {
|
||||
SchemaProvider,
|
||||
useResolvedSchema,
|
||||
} from '@/playground/schema';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
|
||||
interface FormValues {
|
||||
authorization:
|
||||
@@ -105,8 +104,6 @@ export type ClientProps = HTMLAttributes<HTMLFormElement> & {
|
||||
components?: Partial<{
|
||||
ResultDisplay: FC<{ data: FetchResult }>;
|
||||
}>;
|
||||
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
};
|
||||
|
||||
function toRequestData(
|
||||
@@ -136,7 +133,6 @@ export default function Client({
|
||||
fields,
|
||||
references,
|
||||
proxyUrl,
|
||||
mediaAdapters,
|
||||
components: { ResultDisplay = DefaultResultDisplay } = {},
|
||||
...rest
|
||||
}: ClientProps) {
|
||||
@@ -144,6 +140,7 @@ export default function Client({
|
||||
const requestData = useRequestData();
|
||||
const fieldInfoMap = useMemo(() => new Map<string, FieldInfo>(), []);
|
||||
const authInfo = usePersistentAuthInfo(authorization);
|
||||
const { mediaAdapters } = useApiContext();
|
||||
const defaultValues: FormValues = useMemo(
|
||||
() => ({
|
||||
authorization: authInfo.info,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { MethodInformation, RenderContext } from '@/types';
|
||||
import { getPreferredType, type ParsedSchema } from '@/utils/schema';
|
||||
import { getSecurities } from '@/utils/get-security';
|
||||
import { type ClientProps } from './client';
|
||||
import { ClientLazy } from '@/playground/client.lazy';
|
||||
import { ClientLazy } from '@/ui/lazy';
|
||||
|
||||
export type ParameterField = {
|
||||
name: string;
|
||||
@@ -51,7 +51,6 @@ export async function APIPlayground({
|
||||
authorization: getAuthorizationField(method, ctx),
|
||||
method: method.method,
|
||||
route: path,
|
||||
mediaAdapters: ctx.mediaAdapters,
|
||||
parameters: method.parameters?.map((v) => ({
|
||||
name: v.name,
|
||||
in: v.in as ParameterField['in'],
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type ProcessedDocument,
|
||||
} from '@/utils/process-document';
|
||||
import { getUrl } from '@/utils/server-url';
|
||||
import { defaultAdapters } from '@/media/adapter';
|
||||
import type { defaultAdapters } from '@/media/adapter';
|
||||
|
||||
type ApiPageContextProps = Pick<
|
||||
Partial<RenderContext>,
|
||||
@@ -159,7 +159,14 @@ export async function getContext(
|
||||
),
|
||||
servers,
|
||||
mediaAdapters: {
|
||||
...defaultAdapters,
|
||||
...({
|
||||
'application/octet-stream': true,
|
||||
'application/json': true,
|
||||
'multipart/form-data': true,
|
||||
'application/xml': true,
|
||||
'application/x-ndjson': true,
|
||||
'application/x-www-form-urlencoded': true,
|
||||
} satisfies Record<keyof typeof defaultAdapters, true>),
|
||||
...options.mediaAdapters,
|
||||
},
|
||||
slugger: new Slugger(),
|
||||
|
||||
@@ -3,10 +3,7 @@ import { type ReactNode } from 'react';
|
||||
import { Markdown } from '@/render/markdown';
|
||||
import { type CodeSample } from '@/render/operation/index';
|
||||
import { CodeBlock } from '@/render/codeblock';
|
||||
import {
|
||||
CodeExample,
|
||||
CodeExampleProvider,
|
||||
} from '@/ui/contexts/code-example.lazy';
|
||||
import { CodeExample, CodeExampleProvider } from '@/ui/lazy';
|
||||
import { getPreferredType, type NoReference } from '@/utils/schema';
|
||||
import { getRequestData } from '@/render/operation/get-request-data';
|
||||
import { sample } from 'openapi-sampler';
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from '@/ui';
|
||||
import type { RenderContext } from '@/types';
|
||||
import { APIPlayground, type APIPlaygroundProps } from '@/playground';
|
||||
import { CodeExampleSelector } from '@/ui/contexts/code-example.lazy';
|
||||
import { CodeExampleSelector } from '@/ui/lazy';
|
||||
|
||||
export interface ResponsesProps {
|
||||
items: string[];
|
||||
|
||||
@@ -6,23 +6,17 @@ export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const params = [`"${data.method}"`, 'url'];
|
||||
let body: string | undefined;
|
||||
|
||||
if (data.body && data.bodyMediaType) {
|
||||
if (data.bodyMediaType === 'application/json') {
|
||||
params.push(`json = ${JSON.stringify(data.body, null, 2)}`);
|
||||
} else if (data.bodyMediaType === 'multipart/form-data') {
|
||||
headers['Content-Type'] = data.bodyMediaType;
|
||||
if (data.body && data.bodyMediaType && data.bodyMediaType in mediaAdapters) {
|
||||
headers['Content-Type'] = data.bodyMediaType;
|
||||
|
||||
params.push(`data = ${JSON.stringify(data.body, null, 2)}`);
|
||||
} else if (data.bodyMediaType in mediaAdapters) {
|
||||
headers['Content-Type'] = data.bodyMediaType;
|
||||
body = mediaAdapters[data.bodyMediaType].generateExample(data, {
|
||||
lang: 'python',
|
||||
});
|
||||
|
||||
body = mediaAdapters[data.bodyMediaType].generateExample(data, {
|
||||
lang: 'python',
|
||||
});
|
||||
|
||||
if (body) {
|
||||
params.push('data = body');
|
||||
}
|
||||
if (body && data.bodyMediaType === 'application/json') {
|
||||
params.push('json = body');
|
||||
} else if (body) {
|
||||
params.push('data = body');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,5 +86,5 @@ export interface RenderContext {
|
||||
*/
|
||||
showResponseSchema?: boolean;
|
||||
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
mediaAdapters: Record<string, MediaAdapter | true>;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import { Check, Copy } from 'lucide-react';
|
||||
|
||||
export { ClientLazy as APIPlayground } from '@/playground/client.lazy';
|
||||
|
||||
export function CopyResponseTypeScript({ code }: { code: string }) {
|
||||
const [isChecked, onCopy] = useCopyButton(() => {
|
||||
void navigator.clipboard.writeText(code);
|
||||
|
||||
@@ -8,18 +8,13 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import type { RenderContext, ServerObject } from '@/types';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import { defaultAdapters, type MediaAdapter } from '@/media/adapter';
|
||||
|
||||
export interface ApiProviderProps {
|
||||
export interface ApiProviderProps extends ApiContextType {
|
||||
/**
|
||||
* Base URL for API requests
|
||||
*/
|
||||
defaultBaseUrl?: string;
|
||||
|
||||
servers: ServerObject[];
|
||||
shikiOptions: RenderContext['shikiOptions'];
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
@@ -28,7 +23,11 @@ export interface SelectedServer {
|
||||
variables: Record<string, string>;
|
||||
}
|
||||
|
||||
type ApiContextType = Omit<ApiProviderProps, 'children' | 'defaultBaseUrl'>;
|
||||
interface ApiContextType {
|
||||
servers: ServerObject[];
|
||||
shikiOptions: RenderContext['shikiOptions'];
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
}
|
||||
|
||||
interface ServerSelectType {
|
||||
server: SelectedServer | null;
|
||||
@@ -56,12 +55,14 @@ export function useServerSelectContext(): ServerSelectType {
|
||||
export function ApiProvider({
|
||||
defaultBaseUrl,
|
||||
children,
|
||||
...props
|
||||
servers,
|
||||
mediaAdapters,
|
||||
shikiOptions,
|
||||
}: ApiProviderProps) {
|
||||
const [server, setServer] = useState<SelectedServer | null>(() => {
|
||||
const defaultItem = defaultBaseUrl
|
||||
? props.servers.find((item) => item.url === defaultBaseUrl)
|
||||
: undefined;
|
||||
? servers.find((item) => item.url === defaultBaseUrl)
|
||||
: null;
|
||||
|
||||
return defaultItem
|
||||
? {
|
||||
@@ -86,7 +87,19 @@ export function ApiProvider({
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ApiContext.Provider value={props}>
|
||||
<ApiContext.Provider
|
||||
value={useMemo(
|
||||
() => ({
|
||||
shikiOptions,
|
||||
mediaAdapters: {
|
||||
...defaultAdapters,
|
||||
...mediaAdapters,
|
||||
},
|
||||
servers,
|
||||
}),
|
||||
[mediaAdapters, servers, shikiOptions],
|
||||
)}
|
||||
>
|
||||
<ServerSelectContext.Provider
|
||||
value={useMemo(
|
||||
() => ({
|
||||
@@ -101,7 +114,7 @@ export function ApiProvider({
|
||||
});
|
||||
},
|
||||
setServer(value) {
|
||||
const obj = props.servers.find((item) => item.url === value);
|
||||
const obj = servers.find((item) => item.url === value);
|
||||
if (!obj) return;
|
||||
|
||||
const result: SelectedServer = {
|
||||
@@ -113,7 +126,7 @@ export function ApiProvider({
|
||||
setServer(result);
|
||||
},
|
||||
}),
|
||||
[server, props.servers],
|
||||
[server, servers],
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
'use client';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
export const CodeExampleProvider = dynamic(() =>
|
||||
import('./code-example').then((mod) => mod.CodeExampleProvider),
|
||||
);
|
||||
export const CodeExample = dynamic(() =>
|
||||
import('./code-example').then((mod) => mod.CodeExample),
|
||||
);
|
||||
export const CodeExampleSelector = dynamic(() =>
|
||||
import('./code-example').then((mod) => mod.CodeExampleSelector),
|
||||
);
|
||||
@@ -7,9 +7,10 @@ import {
|
||||
CollapsibleTrigger,
|
||||
} from 'fumadocs-ui/components/ui/collapsible';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import { ApiProvider } from '@/ui/contexts/api';
|
||||
import { ApiProvider } from '@/ui/lazy';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
|
||||
export function Root({
|
||||
children,
|
||||
@@ -26,7 +27,13 @@ export function Root({
|
||||
{...props}
|
||||
>
|
||||
<ApiProvider
|
||||
mediaAdapters={ctx.mediaAdapters}
|
||||
mediaAdapters={
|
||||
Object.fromEntries(
|
||||
Object.entries(ctx.mediaAdapters).filter(
|
||||
([_, v]) => typeof v !== 'boolean',
|
||||
),
|
||||
) as Record<string, MediaAdapter>
|
||||
}
|
||||
servers={ctx.servers}
|
||||
shikiOptions={ctx.shikiOptions}
|
||||
defaultBaseUrl={ctx.baseUrl}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
'use client';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
export const CodeExampleProvider = dynamic(() =>
|
||||
import('./contexts/code-example').then((mod) => mod.CodeExampleProvider),
|
||||
);
|
||||
export const CodeExample = dynamic(() =>
|
||||
import('./contexts/code-example').then((mod) => mod.CodeExample),
|
||||
);
|
||||
export const CodeExampleSelector = dynamic(() =>
|
||||
import('./contexts/code-example').then((mod) => mod.CodeExampleSelector),
|
||||
);
|
||||
|
||||
export const ClientLazy = dynamic(() => import('@/playground/client'));
|
||||
|
||||
export const ApiProvider = dynamic(() =>
|
||||
import('./contexts/api').then((mod) => mod.ApiProvider),
|
||||
);
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type ElementCompact, js2xml } from 'xml-js';
|
||||
// @ts-expect-error -- nothing
|
||||
import js2xml from 'xml-js/lib/js2xml';
|
||||
|
||||
/**
|
||||
* Convert input value to hardcoded string (with quotes)
|
||||
@@ -47,5 +48,5 @@ export function inputToString(
|
||||
return getStr(params.toString());
|
||||
}
|
||||
|
||||
return getStr(js2xml(value as ElementCompact, { compact: true, spaces: 2 }));
|
||||
return getStr(js2xml(value, { compact: true, spaces: 2 }));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import requests
|
||||
|
||||
url = "http://localhost:8080/hello_world?search=ai"
|
||||
|
||||
response = requests.request("GET", url, json = {
|
||||
body = {
|
||||
"id": "id"
|
||||
}, headers = {
|
||||
"authorization": "Bearer"
|
||||
}
|
||||
response = requests.request("GET", url, json = body, headers = {
|
||||
"authorization": "Bearer",
|
||||
"Content-Type": "application/json"
|
||||
}, cookies = {
|
||||
"mode": "light"
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user