mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
OpenAPI: Generate Python objects for code examples
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-openapi': patch
|
||||
---
|
||||
|
||||
Generate Python objects for code examples
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './generate-file';
|
||||
export * from './types';
|
||||
export type { MediaAdapter } from './media/adapter';
|
||||
export type { MediaAdapter } from '@/requests/media/adapter';
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
CollapsibleTrigger,
|
||||
} from 'fumadocs-ui/components/ui/collapsible';
|
||||
import { ChevronDown, LoaderCircle } from 'lucide-react';
|
||||
import { encodeRequestData, type RequestData } from '@/requests/_shared';
|
||||
import { encodeRequestData } from '@/requests/media/encode';
|
||||
import { buttonVariants } from 'fumadocs-ui/components/ui/button';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import {
|
||||
@@ -70,6 +70,7 @@ import {
|
||||
} from '@/ui/components/select';
|
||||
import { labelVariants } from '@/ui/components/input';
|
||||
import type { ParsedSchema } from '@/utils/schema';
|
||||
import type { RequestData } from '@/requests/types';
|
||||
|
||||
interface FormValues {
|
||||
path: Record<string, unknown>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RequestData } from '@/requests/_shared';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import type { RequestData } from '@/requests/types';
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
|
||||
export interface FetchOptions extends RequestData {
|
||||
proxyUrl?: string;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
processDocumentCached,
|
||||
type ProcessedDocument,
|
||||
} from '@/utils/process-document';
|
||||
import { defaultAdapters } from '@/media/adapter';
|
||||
import { defaultAdapters } from '@/requests/media/adapter';
|
||||
import type { SharedOpenAPIOptions } from '@/server';
|
||||
|
||||
export interface ApiPageProps extends SharedOpenAPIOptions {
|
||||
|
||||
@@ -7,12 +7,9 @@ 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';
|
||||
import {
|
||||
encodeRequestData,
|
||||
type RawRequestData,
|
||||
type RequestData,
|
||||
} from '@/requests/_shared';
|
||||
import { defaultSamples } from '@/requests';
|
||||
import type { RawRequestData, RequestData } from '@/requests/types';
|
||||
import { defaultSamples } from '@/requests/generators';
|
||||
import { encodeRequestData } from '@/requests/media/encode';
|
||||
|
||||
interface CustomProperty {
|
||||
'x-codeSamples'?: CodeSample[];
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { MethodInformation, RenderContext } from '@/types';
|
||||
import type { ResolvedSchema } from '@/utils/schema';
|
||||
import { getPreferredType } from '@/utils/schema';
|
||||
import { sample } from 'openapi-sampler';
|
||||
import { type RawRequestData } from '@/requests/_shared';
|
||||
import type { RawRequestData } from '@/requests/types';
|
||||
|
||||
export function getRequestData(
|
||||
path: string,
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
getAPIExamples,
|
||||
} from '@/render/operation/api-example';
|
||||
import { MethodLabel } from '@/ui/components/method-label';
|
||||
import { type SampleGenerator } from '@/requests/_shared';
|
||||
import { type SampleGenerator } from '@/requests/types';
|
||||
import { getTypescriptSchema } from '@/utils/get-typescript-schema';
|
||||
import { CopyResponseTypeScript } from '@/ui/client';
|
||||
import { SelectTab, SelectTabs, SelectTabTrigger } from '@/ui/select-tabs';
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import type { NoReference } from '@/utils/schema';
|
||||
import type { ParameterObject } from '@/types';
|
||||
|
||||
export type SampleGenerator<ServerContext = unknown> = (
|
||||
url: string,
|
||||
data: RequestData,
|
||||
context: {
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
server: ServerContext;
|
||||
},
|
||||
) => string;
|
||||
|
||||
export interface RawRequestData {
|
||||
method: string;
|
||||
|
||||
path: Record<string, unknown>;
|
||||
query: Record<string, unknown>;
|
||||
header: Record<string, unknown>;
|
||||
cookie: Record<string, unknown>;
|
||||
|
||||
body?: unknown;
|
||||
bodyMediaType?: string;
|
||||
}
|
||||
|
||||
interface EncodedParameter {
|
||||
readonly value: string | string[];
|
||||
}
|
||||
|
||||
export interface RequestData {
|
||||
method: string;
|
||||
|
||||
path: Record<string, EncodedParameter>;
|
||||
query: Record<string, EncodedParameter>;
|
||||
header: Record<string, EncodedParameter>;
|
||||
cookie: Record<string, EncodedParameter>;
|
||||
|
||||
body?: unknown;
|
||||
bodyMediaType?: string;
|
||||
}
|
||||
|
||||
const FormDelimiter = {
|
||||
spaceDelimited: ' ',
|
||||
pipeDelimited: '|',
|
||||
};
|
||||
|
||||
const PathPrefix = {
|
||||
label: '.',
|
||||
matrix: ';',
|
||||
};
|
||||
|
||||
export function ident(code: string, tab: number = 1) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map((v) => ' '.repeat(tab) + v)
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
export function encodeRequestData(
|
||||
from: RawRequestData,
|
||||
adapters: Record<string, MediaAdapter>,
|
||||
parameters: NoReference<ParameterObject>[],
|
||||
): RequestData {
|
||||
function getMediaEncoder(field: NoReference<ParameterObject>) {
|
||||
if (!field.content) return;
|
||||
|
||||
for (const k in field.content) {
|
||||
if (k in adapters) {
|
||||
return (v: unknown) => String(adapters[k].encode({ body: v }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeObject(
|
||||
parentKey: string,
|
||||
value: object,
|
||||
deep: boolean,
|
||||
output: Record<string, EncodedParameter>,
|
||||
) {
|
||||
for (const k in value) {
|
||||
const prop: unknown = value[k as keyof object];
|
||||
if (prop == null) continue;
|
||||
|
||||
const key = deep ? `${parentKey}[${k}]` : k;
|
||||
if (!deep || typeof prop !== 'object') {
|
||||
output[key] = {
|
||||
value: String(prop),
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
writeObject(key, value, deep, output);
|
||||
}
|
||||
}
|
||||
|
||||
function write(
|
||||
key: string,
|
||||
value: unknown,
|
||||
output: Record<string, EncodedParameter> = {},
|
||||
field?: NoReference<ParameterObject>,
|
||||
): Record<string, EncodedParameter> {
|
||||
if (!field) {
|
||||
output[key] = { value: String(value) };
|
||||
return output;
|
||||
}
|
||||
|
||||
const encoder = getMediaEncoder(field);
|
||||
if (encoder) {
|
||||
output[key] = { value: encoder(value) };
|
||||
return output;
|
||||
}
|
||||
|
||||
const explode = field.explode ?? true;
|
||||
let prefix = '';
|
||||
let sep = ',';
|
||||
|
||||
if (field.in === 'path') {
|
||||
const style = field.style ?? 'simple';
|
||||
|
||||
if (style in PathPrefix) {
|
||||
prefix = PathPrefix[style as keyof typeof PathPrefix];
|
||||
|
||||
if (explode) sep = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
// header & cookie doesn't support explode for array values
|
||||
if (explode && field.in !== 'header' && field.in !== 'cookie') {
|
||||
output[key] = {
|
||||
value: prefix + value.map(String),
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
if (field.in === 'query') {
|
||||
const style = field.style ?? 'form';
|
||||
|
||||
if (style in FormDelimiter)
|
||||
sep = FormDelimiter[style as keyof typeof FormDelimiter];
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + value.map(String).join(sep),
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && value) {
|
||||
// header & path creates key-value pairs
|
||||
if (explode && (field.in === 'header' || field.in === 'path')) {
|
||||
output[key] = {
|
||||
value:
|
||||
prefix +
|
||||
Object.entries(value)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join(sep),
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
if (explode || field.style === 'deepObject') {
|
||||
writeObject(key, value, field.style === 'deepObject', output);
|
||||
return output;
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + Object.entries(value).flat().join(sep),
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + String(value),
|
||||
};
|
||||
return output;
|
||||
}
|
||||
|
||||
const result: Partial<RequestData> = {
|
||||
method: from.method,
|
||||
body: from.body,
|
||||
bodyMediaType: from.bodyMediaType,
|
||||
};
|
||||
|
||||
for (const type of ['cookie', 'query', 'header', 'path'] as const) {
|
||||
const out = {};
|
||||
for (const k in from[type]) {
|
||||
const value = from[type][k];
|
||||
if (value == null) continue;
|
||||
|
||||
const field = parameters.find((p) => p.name === k && p.in === type);
|
||||
write(k, value, out, field);
|
||||
}
|
||||
|
||||
result[type] = out;
|
||||
}
|
||||
|
||||
return result as RequestData;
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
'use client';
|
||||
import type { SampleGenerator } from '@/requests/_shared';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
|
||||
export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const s: string[] = [];
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
import { escapeString, inputToString } from '@/utils/input-to-string';
|
||||
import { ident, type SampleGenerator } from '@/requests/_shared';
|
||||
import { escapeString, ident, inputToString } from '@/requests/string-utils';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
|
||||
export const generator: SampleGenerator = (url, data) => {
|
||||
const s: string[] = [];
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
import { ident, type SampleGenerator } from '@/requests/_shared';
|
||||
import { ident } from '@/requests/string-utils';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
|
||||
export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const imports = ['fmt', 'net/http', 'io/ioutil'];
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
import type { CodeSample } from '@/render/operation';
|
||||
import * as CURL from '@/requests/curl';
|
||||
import * as JS from '@/requests/javascript';
|
||||
import * as Go from '@/requests/go';
|
||||
import * as Python from '@/requests/python';
|
||||
import * as Java from '@/requests/java';
|
||||
import * as CSharp from '@/requests/csharp';
|
||||
import * as CURL from './curl';
|
||||
import * as JS from './javascript';
|
||||
import * as Go from './go';
|
||||
import * as Python from './python';
|
||||
import * as Java from './java';
|
||||
import * as CSharp from './csharp';
|
||||
|
||||
export const defaultSamples: CodeSample[] = [
|
||||
{
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
import { ident, type SampleGenerator } from '@/requests/_shared';
|
||||
import { ident } from '@/requests/string-utils';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
|
||||
export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const s: string[] = [];
|
||||
+2
-1
@@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
import { ident, type SampleGenerator } from '@/requests/_shared';
|
||||
import { ident } from '@/requests/string-utils';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
|
||||
export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const s: string[] = [];
|
||||
+11
-7
@@ -1,11 +1,15 @@
|
||||
'use client';
|
||||
import { type SampleGenerator } from '@/requests/_shared';
|
||||
import type { SampleGenerator } from '@/requests/types';
|
||||
import { generatePythonObject } from '@/requests/to-python-object';
|
||||
|
||||
export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
const headers: Record<string, string> = {};
|
||||
const imports = new Set<string>();
|
||||
const params = [`"${data.method}"`, 'url'];
|
||||
let body: string | undefined;
|
||||
|
||||
imports.add('requests');
|
||||
|
||||
if (data.body && data.bodyMediaType && data.bodyMediaType in mediaAdapters) {
|
||||
headers['Content-Type'] = data.bodyMediaType;
|
||||
|
||||
@@ -16,9 +20,7 @@ export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
},
|
||||
);
|
||||
|
||||
if (body && data.bodyMediaType === 'application/json') {
|
||||
params.push('json = body');
|
||||
} else if (body) {
|
||||
if (body) {
|
||||
params.push('data = body');
|
||||
}
|
||||
}
|
||||
@@ -28,7 +30,7 @@ export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
}
|
||||
|
||||
if (Object.keys(headers).length > 0) {
|
||||
params.push(`headers = ${JSON.stringify(headers, null, 2)}`);
|
||||
params.push(`headers = ${generatePythonObject(headers, imports)}`);
|
||||
}
|
||||
|
||||
const inputCookies = Object.entries(data.cookie);
|
||||
@@ -39,10 +41,12 @@ export const generator: SampleGenerator = (url, data, { mediaAdapters }) => {
|
||||
cookies[k] = v.value as string;
|
||||
}
|
||||
|
||||
params.push(`cookies = ${JSON.stringify(cookies, null, 2)}`);
|
||||
params.push(`cookies = ${generatePythonObject(cookies, imports)}`);
|
||||
}
|
||||
|
||||
return `import requests
|
||||
return `${Array.from(imports)
|
||||
.map((name) => 'import ' + name)
|
||||
.join('\n')}
|
||||
|
||||
url = ${JSON.stringify(url)}
|
||||
${body ?? ''}
|
||||
+1
-4
@@ -1,4 +1,4 @@
|
||||
import { escapeString, inputToString } from '@/utils/input-to-string';
|
||||
import { escapeString, inputToString } from '@/requests/string-utils';
|
||||
// @ts-expect-error -- untyped
|
||||
import js2xml from 'xml-js/lib/js2xml';
|
||||
|
||||
@@ -251,9 +251,6 @@ function str(
|
||||
}
|
||||
|
||||
if (ctx.lang === 'python') {
|
||||
if (mediaType === 'application/json')
|
||||
return `body = ${JSON.stringify(init, null, 2)}`;
|
||||
|
||||
return `body = ${escapeString(inputToString(init, mediaType), '"""')}`;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
import type { NoReference } from '@/utils/schema';
|
||||
import type { ParameterObject } from '@/types';
|
||||
import type { RawRequestData, RequestData } from '@/requests/types';
|
||||
|
||||
export interface EncodedParameter {
|
||||
readonly value: string | string[];
|
||||
}
|
||||
|
||||
const FormDelimiter = {
|
||||
spaceDelimited: ' ',
|
||||
pipeDelimited: '|',
|
||||
};
|
||||
|
||||
const PathPrefix = {
|
||||
label: '.',
|
||||
matrix: ';',
|
||||
};
|
||||
|
||||
export function encodeRequestData(
|
||||
from: RawRequestData,
|
||||
adapters: Record<string, MediaAdapter>,
|
||||
parameters: NoReference<ParameterObject>[],
|
||||
): RequestData {
|
||||
const result: Partial<RequestData> = {
|
||||
method: from.method,
|
||||
body: from.body,
|
||||
bodyMediaType: from.bodyMediaType,
|
||||
};
|
||||
|
||||
for (const type of ['cookie', 'query', 'header', 'path'] as const) {
|
||||
const output: Record<string, EncodedParameter> = {};
|
||||
|
||||
for (const key in from[type]) {
|
||||
const value = from[type][key];
|
||||
if (value == null) continue;
|
||||
|
||||
const field = parameters.find((p) => p.name === key && p.in === type);
|
||||
if (!field) {
|
||||
output[key] = { value: String(value) };
|
||||
continue;
|
||||
}
|
||||
|
||||
const encoder = getMediaEncoder(field, adapters);
|
||||
if (encoder) {
|
||||
output[key] = { value: encoder(value) };
|
||||
continue;
|
||||
}
|
||||
|
||||
const explode = field.explode ?? true;
|
||||
let prefix = '';
|
||||
let sep = ',';
|
||||
|
||||
if (field.in === 'path') {
|
||||
const style = field.style ?? 'simple';
|
||||
|
||||
if (style in PathPrefix) {
|
||||
prefix = PathPrefix[style as keyof typeof PathPrefix];
|
||||
|
||||
if (explode) sep = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
// header & cookie doesn't support explode for array values
|
||||
if (explode && field.in !== 'header' && field.in !== 'cookie') {
|
||||
output[key] = {
|
||||
value: prefix + value.map(String),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
if (field.in === 'query') {
|
||||
const style = field.style ?? 'form';
|
||||
|
||||
if (style in FormDelimiter)
|
||||
sep = FormDelimiter[style as keyof typeof FormDelimiter];
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + value.map(String).join(sep),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && value) {
|
||||
// header & path creates key-value pairs
|
||||
if (explode && (field.in === 'header' || field.in === 'path')) {
|
||||
output[key] = {
|
||||
value:
|
||||
prefix +
|
||||
Object.entries(value)
|
||||
.map(([k, v]) => `${k}=${v}`)
|
||||
.join(sep),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
if (explode || field.style === 'deepObject') {
|
||||
writeObject(key, value, field.style === 'deepObject', output);
|
||||
continue;
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + Object.entries(value).flat().join(sep),
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
output[key] = {
|
||||
value: prefix + String(value),
|
||||
};
|
||||
}
|
||||
|
||||
result[type] = output;
|
||||
}
|
||||
|
||||
return result as RequestData;
|
||||
}
|
||||
|
||||
function getMediaEncoder(
|
||||
field: NoReference<ParameterObject>,
|
||||
adapters: Record<string, MediaAdapter>,
|
||||
) {
|
||||
if (!field.content) return;
|
||||
|
||||
for (const k in field.content) {
|
||||
if (k in adapters) {
|
||||
return (v: unknown) => String(adapters[k].encode({ body: v }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function writeObject(
|
||||
parentKey: string,
|
||||
value: object,
|
||||
deep: boolean,
|
||||
output: Record<string, EncodedParameter>,
|
||||
) {
|
||||
for (const k in value) {
|
||||
const prop: unknown = value[k as keyof object];
|
||||
if (prop == null) continue;
|
||||
|
||||
const key = deep ? `${parentKey}[${k}]` : k;
|
||||
if (!deep || typeof prop !== 'object') {
|
||||
output[key] = {
|
||||
value: String(prop),
|
||||
};
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
writeObject(key, value, deep, output);
|
||||
}
|
||||
}
|
||||
+7
@@ -47,3 +47,10 @@ export function escapeString(str: string, delimit?: string): string {
|
||||
|
||||
return `${delimit}${str.replaceAll(delimit, `\\${delimit}`)}${delimit}`;
|
||||
}
|
||||
|
||||
export function ident(code: string, tab: number = 1) {
|
||||
return code
|
||||
.split('\n')
|
||||
.map((v) => ' '.repeat(tab) + v)
|
||||
.join('\n');
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export function generatePythonObject(v: unknown, imports = new Set()): string {
|
||||
if (v === null) {
|
||||
return 'None';
|
||||
} else if (typeof v === 'boolean') {
|
||||
return v ? 'True' : 'False';
|
||||
} else if (typeof v === 'string') {
|
||||
return JSON.stringify(v);
|
||||
} else if (typeof v === 'number') {
|
||||
return v.toString();
|
||||
} else if (Array.isArray(v)) {
|
||||
const items = v.map((item) => generatePythonObject(item, imports));
|
||||
return `[${items.join(', ')}]`;
|
||||
} else if (v instanceof Date) {
|
||||
imports.add('datetime');
|
||||
return `datetime.datetime(${v.getFullYear()}, ${v.getMonth() + 1}, ${v.getDate()}, ${v.getHours()}, ${v.getMinutes()}, ${v.getSeconds()}, ${v.getMilliseconds()})`;
|
||||
} else if (typeof v === 'object') {
|
||||
const entries = Object.entries(v).map(
|
||||
([key, value]) =>
|
||||
` ${JSON.stringify(key)}: ${generatePythonObject(value, imports)}`,
|
||||
);
|
||||
return `{\n${entries.join(', \n')}\n}`;
|
||||
} else {
|
||||
throw new Error(`Unsupported type: ${typeof v}`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
import type { EncodedParameter } from '@/requests/media/encode';
|
||||
|
||||
export type SampleGenerator<ServerContext = unknown> = (
|
||||
url: string,
|
||||
data: RequestData,
|
||||
context: {
|
||||
mediaAdapters: Record<string, MediaAdapter>;
|
||||
server: ServerContext;
|
||||
},
|
||||
) => string;
|
||||
|
||||
export interface RawRequestData {
|
||||
method: string;
|
||||
|
||||
path: Record<string, unknown>;
|
||||
query: Record<string, unknown>;
|
||||
header: Record<string, unknown>;
|
||||
cookie: Record<string, unknown>;
|
||||
|
||||
body?: unknown;
|
||||
bodyMediaType?: string;
|
||||
}
|
||||
|
||||
export interface RequestData {
|
||||
method: string;
|
||||
|
||||
path: Record<string, EncodedParameter>;
|
||||
query: Record<string, EncodedParameter>;
|
||||
header: Record<string, EncodedParameter>;
|
||||
cookie: Record<string, EncodedParameter>;
|
||||
|
||||
body?: unknown;
|
||||
bodyMediaType?: string;
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import type {
|
||||
HighlightOptionsCommon,
|
||||
HighlightOptionsThemes,
|
||||
} from 'fumadocs-core/highlight';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
import type { MethodInformation } from '@/types';
|
||||
import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
|
||||
import {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { default as Slugger } from 'github-slugger';
|
||||
import { type Renderer } from '@/render/renderer';
|
||||
import type { NoReference } from '@/utils/schema';
|
||||
import type { ProcessedDocument } from '@/utils/process-document';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
import type { SharedOpenAPIOptions } from '@/server';
|
||||
|
||||
export type Document = V3_1.Document;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import type { RenderContext, ServerObject } from '@/types';
|
||||
import { defaultAdapters, type MediaAdapter } from '@/media/adapter';
|
||||
import { defaultAdapters, type MediaAdapter } from '@/requests/media/adapter';
|
||||
|
||||
export interface ApiProviderProps
|
||||
extends Omit<ApiContextType, 'mediaAdapters'> {
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
resolveServerUrl,
|
||||
withBase,
|
||||
} from '@/utils/url';
|
||||
import type { RawRequestData, RequestData } from '@/requests/_shared';
|
||||
import type { RawRequestData, RequestData } from '@/requests/types';
|
||||
|
||||
type UpdateListener = (data: RawRequestData, encoded: RequestData) => void;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { HTMLAttributes } from 'react';
|
||||
import type { RootProps } from '@/render/renderer';
|
||||
import { ApiProvider } from '@/ui/lazy';
|
||||
import { cn } from 'fumadocs-ui/utils/cn';
|
||||
import type { MediaAdapter } from '@/media/adapter';
|
||||
import type { MediaAdapter } from '@/requests/media/adapter';
|
||||
|
||||
export function Root({
|
||||
children,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { RequestData } from '@/requests/_shared';
|
||||
import type { RequestData } from '@/requests/types';
|
||||
|
||||
export function joinURL(base: string, pathname: string): string {
|
||||
if (pathname.startsWith('/')) pathname = pathname.slice(1);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import * as Python from '@/requests/python';
|
||||
import * as Go from '@/requests/go';
|
||||
import * as Curl from '@/requests/curl';
|
||||
import * as JS from '@/requests/javascript';
|
||||
import type { RequestData } from '@/requests/_shared';
|
||||
import { defaultAdapters } from '@/media/adapter';
|
||||
import * as Python from '@/requests/generators/python';
|
||||
import * as Go from '@/requests/generators/go';
|
||||
import * as Curl from '@/requests/generators/curl';
|
||||
import * as JS from '@/requests/generators/javascript';
|
||||
import type { RequestData } from '@/requests/types';
|
||||
import { defaultAdapters } from '@/requests/media/adapter';
|
||||
import { resolveRequestData } from '@/utils/url';
|
||||
|
||||
describe('Code Sample Generators', () => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import requests
|
||||
|
||||
url = "http://localhost:8080/hello_world?search=ai"
|
||||
body = {
|
||||
body = """{
|
||||
"id": "id"
|
||||
}
|
||||
response = requests.request("GET", url, json = body, headers = {
|
||||
"Content-Type": "application/json",
|
||||
}"""
|
||||
response = requests.request("GET", url, data = body, headers = {
|
||||
"Content-Type": "application/json",
|
||||
"authorization": "Bearer"
|
||||
}, cookies = {
|
||||
"mode": "light"
|
||||
|
||||
@@ -2,11 +2,11 @@ import { describe, expect, test } from 'vitest';
|
||||
import { combineSchema } from '@/utils/combine-schema';
|
||||
import {
|
||||
joinURL,
|
||||
withBase,
|
||||
resolveServerUrl,
|
||||
resolveRequestData,
|
||||
resolveServerUrl,
|
||||
withBase,
|
||||
} from '@/utils/url';
|
||||
import type { RequestData } from '@/requests/_shared';
|
||||
import type { RequestData } from '@/requests/types';
|
||||
|
||||
describe('Merge object schemas', () => {
|
||||
test('Merge single object', () => {
|
||||
|
||||
Reference in New Issue
Block a user