fumadocs-openapi 5.0.3 → 5.1.0
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.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +149 -98
- package/dist/server/index.d.ts +13 -9
- package/dist/server/index.js +25 -10
- package/dist/ui/{client-client-BIwAR59x.js → client-client-34yX5eij.js} +2 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/{playground-client-CjCikhf6.js → playground-client-itvkUjgt.js} +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -221,6 +221,7 @@ interface GenerateOptions {
|
|
|
221
221
|
* A `full: true` property will be added by default.
|
|
222
222
|
*/
|
|
223
223
|
frontmatter?: (title: string, description: string | undefined, context: DocumentContext) => Record<string, unknown>;
|
|
224
|
+
cwd?: string;
|
|
224
225
|
}
|
|
225
226
|
interface GenerateTagOutput {
|
|
226
227
|
tag: string;
|
|
@@ -269,8 +270,7 @@ interface Config extends GenerateOptions {
|
|
|
269
270
|
* @defaultValue 'none'
|
|
270
271
|
*/
|
|
271
272
|
groupBy?: 'tag' | 'route' | 'none';
|
|
272
|
-
cwd?: string;
|
|
273
273
|
}
|
|
274
|
-
declare function generateFiles(
|
|
274
|
+
declare function generateFiles(options: Config): Promise<void>;
|
|
275
275
|
|
|
276
276
|
export { type Config, type DocumentContext, type GenerateOperationOutput, type GenerateOptions, type GenerateTagOutput, type MethodInformation, type RenderContext, type RouteInformation, generateAll, generateFiles, generateOperations, generateTags };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { resolve, join, parse, dirname } from 'node:path';
|
|
1
2
|
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
2
|
-
import Slugger from 'github-slugger';
|
|
3
3
|
import { dump } from 'js-yaml';
|
|
4
|
+
import Slugger from 'github-slugger';
|
|
4
5
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
5
|
-
import { join, parse, dirname } from 'node:path';
|
|
6
6
|
import fg from 'fast-glob';
|
|
7
7
|
|
|
8
8
|
function createMethod(method, operation) {
|
|
@@ -55,41 +55,110 @@ const methodKeys = [
|
|
|
55
55
|
return map;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function
|
|
58
|
+
function idToTitle(id) {
|
|
59
|
+
let result = [];
|
|
60
|
+
for (const c of id){
|
|
61
|
+
if (result.length === 0) result.push(c.toLocaleUpperCase());
|
|
62
|
+
else if (c === '.') result = [];
|
|
63
|
+
else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ') result.push(' ', c);
|
|
64
|
+
else if (c === '-') result.push(' ');
|
|
65
|
+
else result.push(c);
|
|
66
|
+
}
|
|
67
|
+
return result.join('');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function generateDocument(options) {
|
|
71
|
+
const { frontmatter } = options;
|
|
59
72
|
const out = [];
|
|
73
|
+
const extend = frontmatter?.(options.title, options.description, options.context);
|
|
74
|
+
let meta;
|
|
75
|
+
if (options.context.type === 'operation') {
|
|
76
|
+
meta = {
|
|
77
|
+
method: options.context.endpoint.method,
|
|
78
|
+
route: options.context.route.path
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const data = generateStaticData(options.dereferenced, options.page);
|
|
60
82
|
const banner = dump({
|
|
61
|
-
title:
|
|
62
|
-
description:
|
|
83
|
+
title: options.title,
|
|
84
|
+
description: options.description,
|
|
63
85
|
full: true,
|
|
64
|
-
...
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
...extend,
|
|
87
|
+
_openapi: {
|
|
88
|
+
...meta,
|
|
89
|
+
...data,
|
|
90
|
+
...extend?._openapi
|
|
91
|
+
}
|
|
69
92
|
}).trim();
|
|
70
93
|
if (banner.length > 0) out.push(`---\n${banner}\n---`);
|
|
71
94
|
const imports = options.imports?.map((item)=>`import { ${item.names.join(', ')} } from ${JSON.stringify(item.from)};`).join('\n');
|
|
72
95
|
if (imports) {
|
|
73
96
|
out.push(imports);
|
|
74
97
|
}
|
|
75
|
-
out.push(
|
|
98
|
+
out.push(pageContent(data, options.page));
|
|
76
99
|
return out.join('\n\n');
|
|
77
100
|
}
|
|
101
|
+
function generateStaticData(dereferenced, props) {
|
|
102
|
+
const slugger = new Slugger();
|
|
103
|
+
const toc = [];
|
|
104
|
+
const structuredData = {
|
|
105
|
+
headings: [],
|
|
106
|
+
contents: []
|
|
107
|
+
};
|
|
108
|
+
for (const item of props.operations){
|
|
109
|
+
const operation = dereferenced.paths[item.path]?.[item.method];
|
|
110
|
+
if (!operation) continue;
|
|
111
|
+
if (props.hasHead && operation.operationId) {
|
|
112
|
+
const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path);
|
|
113
|
+
const id = slugger.slug(title);
|
|
114
|
+
toc.push({
|
|
115
|
+
depth: 2,
|
|
116
|
+
title,
|
|
117
|
+
url: `#${id}`
|
|
118
|
+
});
|
|
119
|
+
structuredData.headings.push({
|
|
120
|
+
content: title,
|
|
121
|
+
id
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (operation.description) structuredData.contents.push({
|
|
125
|
+
content: operation.description,
|
|
126
|
+
heading: structuredData.headings.at(-1)?.id
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
toc,
|
|
131
|
+
structuredData
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function pageContent(data, props) {
|
|
135
|
+
// modify toc and structured data if possible
|
|
136
|
+
// it may not be compatible with other content sources except Fumadocs MDX
|
|
137
|
+
// TODO: Maybe add to frontmatter and let developers to handle them?
|
|
138
|
+
return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />
|
|
78
139
|
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
140
|
+
export function startup() {
|
|
141
|
+
if (typeof toc !== 'undefined') {
|
|
142
|
+
// toc might be immutable
|
|
143
|
+
while (toc.length > 0) toc.pop()
|
|
144
|
+
toc.push(...${JSON.stringify(data.toc)})
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (typeof structuredData !== 'undefined') {
|
|
148
|
+
structuredData.headings = ${JSON.stringify(data.structuredData.headings)}
|
|
149
|
+
structuredData.contents = ${JSON.stringify(data.structuredData.contents)}
|
|
87
150
|
}
|
|
88
|
-
return result.join('');
|
|
89
151
|
}
|
|
90
152
|
|
|
153
|
+
{startup()}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function dereference(pathOrDocument, options) {
|
|
157
|
+
return await Parser.dereference(// resolve paths
|
|
158
|
+
typeof pathOrDocument === 'string' && !pathOrDocument.startsWith('http://') && !pathOrDocument.startsWith('https://') ? resolve(options.cwd ?? process.cwd(), pathOrDocument) : pathOrDocument);
|
|
159
|
+
}
|
|
91
160
|
async function generateAll(pathOrDocument, options = {}) {
|
|
92
|
-
const document = await
|
|
161
|
+
const document = await dereference(pathOrDocument, options);
|
|
93
162
|
const routes = buildRoutes(document).get('all') ?? [];
|
|
94
163
|
const operations = [];
|
|
95
164
|
for (const route of routes){
|
|
@@ -100,12 +169,16 @@ async function generateAll(pathOrDocument, options = {}) {
|
|
|
100
169
|
});
|
|
101
170
|
}
|
|
102
171
|
}
|
|
103
|
-
return generateDocument(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}), options, {
|
|
172
|
+
return generateDocument({
|
|
173
|
+
...options,
|
|
174
|
+
dereferenced: document,
|
|
107
175
|
title: document.info.title,
|
|
108
176
|
description: document.info.description,
|
|
177
|
+
page: {
|
|
178
|
+
operations,
|
|
179
|
+
hasHead: true,
|
|
180
|
+
document: pathOrDocument
|
|
181
|
+
},
|
|
109
182
|
context: {
|
|
110
183
|
type: 'file',
|
|
111
184
|
routes
|
|
@@ -113,20 +186,24 @@ async function generateAll(pathOrDocument, options = {}) {
|
|
|
113
186
|
});
|
|
114
187
|
}
|
|
115
188
|
async function generateOperations(pathOrDocument, options = {}) {
|
|
116
|
-
const document = await
|
|
189
|
+
const document = await dereference(pathOrDocument, options);
|
|
117
190
|
const routes = buildRoutes(document).get('all') ?? [];
|
|
118
191
|
return routes.flatMap((route)=>{
|
|
119
192
|
return route.methods.map((method)=>{
|
|
120
193
|
if (!method.operationId) throw new Error('Operation ID is required for generating docs.');
|
|
121
|
-
const content = generateDocument(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
194
|
+
const content = generateDocument({
|
|
195
|
+
...options,
|
|
196
|
+
page: {
|
|
197
|
+
operations: [
|
|
198
|
+
{
|
|
199
|
+
path: route.path,
|
|
200
|
+
method: method.method.toLowerCase()
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
hasHead: false,
|
|
204
|
+
document: pathOrDocument
|
|
205
|
+
},
|
|
206
|
+
dereferenced: document,
|
|
130
207
|
title: method.summary ?? idToTitle(method.operationId),
|
|
131
208
|
description: method.description,
|
|
132
209
|
context: {
|
|
@@ -144,7 +221,7 @@ async function generateOperations(pathOrDocument, options = {}) {
|
|
|
144
221
|
});
|
|
145
222
|
}
|
|
146
223
|
async function generateTags(pathOrDocument, options = {}) {
|
|
147
|
-
const document = await
|
|
224
|
+
const document = await dereference(pathOrDocument, options);
|
|
148
225
|
const tags = Array.from(buildRoutes(document).entries());
|
|
149
226
|
return tags.filter(([tag])=>tag !== 'all').map(([tag, routes])=>{
|
|
150
227
|
const info = document.tags?.find((t)=>t.name === tag);
|
|
@@ -159,10 +236,14 @@ async function generateTags(pathOrDocument, options = {}) {
|
|
|
159
236
|
}
|
|
160
237
|
return {
|
|
161
238
|
tag,
|
|
162
|
-
content: generateDocument(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
239
|
+
content: generateDocument({
|
|
240
|
+
...options,
|
|
241
|
+
page: {
|
|
242
|
+
document: pathOrDocument,
|
|
243
|
+
operations,
|
|
244
|
+
hasHead: true
|
|
245
|
+
},
|
|
246
|
+
dereferenced: document,
|
|
166
247
|
title: idToTitle(tag),
|
|
167
248
|
description: info?.description,
|
|
168
249
|
context: {
|
|
@@ -174,74 +255,41 @@ async function generateTags(pathOrDocument, options = {}) {
|
|
|
174
255
|
};
|
|
175
256
|
});
|
|
176
257
|
}
|
|
177
|
-
function pageContent(doc, props) {
|
|
178
|
-
const slugger = new Slugger();
|
|
179
|
-
const toc = [];
|
|
180
|
-
const structuredData = {
|
|
181
|
-
headings: [],
|
|
182
|
-
contents: []
|
|
183
|
-
};
|
|
184
|
-
for (const item of props.operations){
|
|
185
|
-
const operation = doc.paths[item.path]?.[item.method];
|
|
186
|
-
if (!operation) continue;
|
|
187
|
-
if (props.hasHead && operation.operationId) {
|
|
188
|
-
const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path);
|
|
189
|
-
const id = slugger.slug(title);
|
|
190
|
-
toc.push({
|
|
191
|
-
depth: 2,
|
|
192
|
-
title,
|
|
193
|
-
url: `#${id}`
|
|
194
|
-
});
|
|
195
|
-
structuredData.headings.push({
|
|
196
|
-
content: title,
|
|
197
|
-
id
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
if (operation.description) structuredData.contents.push({
|
|
201
|
-
content: operation.description,
|
|
202
|
-
heading: structuredData.headings.at(-1)?.id
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
// modify toc and structured data if possible
|
|
206
|
-
// it may not be compatible with other content sources except Fumadocs MDX
|
|
207
|
-
// TODO: Maybe add to frontmatter and let developers to handle them?
|
|
208
|
-
return `<APIPage operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />
|
|
209
|
-
|
|
210
|
-
export function startup() {
|
|
211
|
-
if (typeof toc !== 'undefined') {
|
|
212
|
-
// toc might be immutable
|
|
213
|
-
while (toc.length > 0) toc.pop()
|
|
214
|
-
toc.push(...${JSON.stringify(toc)})
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (typeof structuredData !== 'undefined') {
|
|
218
|
-
structuredData.headings = ${JSON.stringify(structuredData.headings)}
|
|
219
|
-
structuredData.contents = ${JSON.stringify(structuredData.contents)}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
258
|
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
async function generateFiles({ input, output, name: nameFn, per = 'file', cwd = process.cwd(), groupBy = 'none', ...options }) {
|
|
259
|
+
async function generateFiles(options) {
|
|
260
|
+
const { input, output, name: nameFn, per = 'file', groupBy = 'none', cwd = process.cwd() } = options;
|
|
227
261
|
const outputDir = join(cwd, output);
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
262
|
+
const urlInputs = [];
|
|
263
|
+
const fileInputs = [];
|
|
264
|
+
for (const v of typeof input === 'string' ? [
|
|
265
|
+
input
|
|
266
|
+
] : input){
|
|
267
|
+
if (isUrl(v)) {
|
|
268
|
+
urlInputs.push(v);
|
|
269
|
+
} else {
|
|
270
|
+
fileInputs.push(v);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const resolvedInputs = [
|
|
274
|
+
...await fg.glob(fileInputs, {
|
|
275
|
+
cwd,
|
|
276
|
+
absolute: false
|
|
277
|
+
}),
|
|
278
|
+
...urlInputs
|
|
279
|
+
];
|
|
280
|
+
await Promise.all(resolvedInputs.map(async (pathOrUrl)=>{
|
|
233
281
|
if (per === 'file') {
|
|
234
|
-
let filename = parse(
|
|
282
|
+
let filename = isUrl(pathOrUrl) ? 'index' : parse(pathOrUrl).name;
|
|
235
283
|
if (nameFn) filename = nameFn('file', filename);
|
|
236
284
|
const outPath = join(outputDir, `${filename}.mdx`);
|
|
237
|
-
const result = await generateAll(
|
|
285
|
+
const result = await generateAll(pathOrUrl, options);
|
|
238
286
|
await write(outPath, result);
|
|
239
287
|
console.log(`Generated: ${outPath}`);
|
|
240
288
|
return;
|
|
241
289
|
}
|
|
242
290
|
if (per === 'operation') {
|
|
243
291
|
const metaFiles = new Set();
|
|
244
|
-
const results = await generateOperations(
|
|
292
|
+
const results = await generateOperations(pathOrUrl, options);
|
|
245
293
|
await Promise.all(results.map(async (result)=>{
|
|
246
294
|
let outPath;
|
|
247
295
|
if (!result.method.operationId) return;
|
|
@@ -267,7 +315,7 @@ async function generateFiles({ input, output, name: nameFn, per = 'file', cwd =
|
|
|
267
315
|
}));
|
|
268
316
|
return;
|
|
269
317
|
}
|
|
270
|
-
const results = await generateTags(
|
|
318
|
+
const results = await generateTags(pathOrUrl, options);
|
|
271
319
|
for (const result of results){
|
|
272
320
|
let tagName = result.tag;
|
|
273
321
|
tagName = nameFn?.('tag', tagName) ?? getFilename(tagName);
|
|
@@ -277,6 +325,9 @@ async function generateFiles({ input, output, name: nameFn, per = 'file', cwd =
|
|
|
277
325
|
}
|
|
278
326
|
}));
|
|
279
327
|
}
|
|
328
|
+
function isUrl(input) {
|
|
329
|
+
return input.startsWith('https://') || input.startsWith('http://');
|
|
330
|
+
}
|
|
280
331
|
function getFilenameFromRoute(path) {
|
|
281
332
|
return path.replaceAll('.', '/').split('/').filter((v)=>!v.startsWith('{') && !v.endsWith('}')).at(-1) ?? '';
|
|
282
333
|
}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -181,25 +181,29 @@ interface RenderContext {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
interface ApiPageProps extends Pick<RenderContext, 'generateCodeSamples' | 'generateTypeScriptSchema'> {
|
|
184
|
-
document: OpenAPIV3.Document;
|
|
184
|
+
document: string | OpenAPIV3.Document;
|
|
185
185
|
/**
|
|
186
|
-
* An array of
|
|
186
|
+
* An array of operations
|
|
187
187
|
*/
|
|
188
|
-
operations:
|
|
189
|
-
path: string;
|
|
190
|
-
method: OpenAPIV3.HttpMethods;
|
|
191
|
-
}[];
|
|
188
|
+
operations: Operation[];
|
|
192
189
|
hasHead: boolean;
|
|
193
190
|
renderer?: Partial<Renderer>;
|
|
194
191
|
}
|
|
192
|
+
interface Operation {
|
|
193
|
+
path: string;
|
|
194
|
+
method: OpenAPIV3.HttpMethods;
|
|
195
|
+
}
|
|
195
196
|
|
|
196
197
|
interface OpenAPIOptions extends Omit<Partial<ApiPageProps>, 'document'> {
|
|
197
|
-
|
|
198
|
+
/**
|
|
199
|
+
* @deprecated Pass document to `APIPage` instead
|
|
200
|
+
*/
|
|
201
|
+
documentOrPath?: string | OpenAPIV3.Document;
|
|
198
202
|
}
|
|
199
203
|
interface OpenAPIServer {
|
|
200
|
-
APIPage: FC<
|
|
204
|
+
APIPage: FC<ApiPageProps>;
|
|
201
205
|
}
|
|
202
|
-
declare function createOpenAPI(options
|
|
206
|
+
declare function createOpenAPI(options?: OpenAPIOptions): OpenAPIServer;
|
|
203
207
|
|
|
204
208
|
/**
|
|
205
209
|
* Source API Integration
|
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
-
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
3
2
|
import Slugger from 'github-slugger';
|
|
3
|
+
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
4
4
|
import { createElement, Fragment, useMemo } from 'react';
|
|
5
5
|
import { sample } from 'openapi-sampler';
|
|
6
6
|
import { compile } from 'json-schema-to-typescript';
|
|
@@ -1001,8 +1001,17 @@ const defaultRenderer = {
|
|
|
1001
1001
|
APIPlayground
|
|
1002
1002
|
};
|
|
1003
1003
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1004
|
+
const cache = new Map();
|
|
1005
|
+
async function APIPage(props) {
|
|
1006
|
+
const { operations, hasHead = true } = props;
|
|
1007
|
+
let document;
|
|
1008
|
+
if (typeof props.document === 'string') {
|
|
1009
|
+
const cached = cache.get(props.document);
|
|
1010
|
+
document = cached ?? await Parser.dereference(props.document);
|
|
1011
|
+
cache.set(props.document, document);
|
|
1012
|
+
} else {
|
|
1013
|
+
document = await Parser.dereference(props.document);
|
|
1014
|
+
}
|
|
1006
1015
|
const ctx = getContext(document, props);
|
|
1007
1016
|
return /*#__PURE__*/ jsx(ctx.renderer.Root, {
|
|
1008
1017
|
baseUrl: ctx.baseUrl,
|
|
@@ -1033,12 +1042,11 @@ function getContext(document, options) {
|
|
|
1033
1042
|
};
|
|
1034
1043
|
}
|
|
1035
1044
|
|
|
1036
|
-
function createOpenAPI(options) {
|
|
1037
|
-
const document = Parser.dereference(options.documentOrPath);
|
|
1045
|
+
function createOpenAPI(options = {}) {
|
|
1038
1046
|
return {
|
|
1039
|
-
APIPage
|
|
1047
|
+
APIPage (props) {
|
|
1040
1048
|
return /*#__PURE__*/ jsx(APIPage, {
|
|
1041
|
-
|
|
1049
|
+
...options,
|
|
1042
1050
|
...props
|
|
1043
1051
|
});
|
|
1044
1052
|
}
|
|
@@ -1078,8 +1086,15 @@ function getBadgeColor(method) {
|
|
|
1078
1086
|
*/ const attachFile = (node, file)=>{
|
|
1079
1087
|
if (!file) return node;
|
|
1080
1088
|
const data = file.data.data;
|
|
1081
|
-
|
|
1082
|
-
|
|
1089
|
+
let method;
|
|
1090
|
+
if ('_openapi' in data && typeof data._openapi === 'object') {
|
|
1091
|
+
const meta = data._openapi;
|
|
1092
|
+
method = meta.method;
|
|
1093
|
+
} else if ('method' in data && typeof data.method === 'string') {
|
|
1094
|
+
method = data.method;
|
|
1095
|
+
}
|
|
1096
|
+
if (method) {
|
|
1097
|
+
const color = getBadgeColor(method);
|
|
1083
1098
|
node.name = /*#__PURE__*/ jsxs(Fragment$1, {
|
|
1084
1099
|
children: [
|
|
1085
1100
|
node.name,
|
|
@@ -1089,7 +1104,7 @@ function getBadgeColor(method) {
|
|
|
1089
1104
|
className: 'ms-auto text-nowrap',
|
|
1090
1105
|
color
|
|
1091
1106
|
}),
|
|
1092
|
-
children:
|
|
1107
|
+
children: method
|
|
1093
1108
|
})
|
|
1094
1109
|
]
|
|
1095
1110
|
});
|
|
@@ -64,7 +64,7 @@ function useSchemaContext() {
|
|
|
64
64
|
return ctx;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
const APIPlayground = dynamic(()=>import('./playground-client-
|
|
67
|
+
const APIPlayground = dynamic(()=>import('./playground-client-itvkUjgt.js').then((mod)=>mod.APIPlayground));
|
|
68
68
|
function Root({ children, baseUrl, className, ...props }) {
|
|
69
69
|
return /*#__PURE__*/ jsx("div", {
|
|
70
70
|
className: cn('flex flex-col gap-24 text-sm text-fd-muted-foreground', className),
|
|
@@ -87,6 +87,7 @@ function CopyRouteButton({ className, route, ...props }) {
|
|
|
87
87
|
className
|
|
88
88
|
})),
|
|
89
89
|
onClick: onCopy,
|
|
90
|
+
"aria-label": "Copy route path",
|
|
90
91
|
...props,
|
|
91
92
|
children: checked ? /*#__PURE__*/ jsx(Check, {
|
|
92
93
|
className: "size-3"
|
package/dist/ui/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { cn } from 'fumadocs-ui/components/api';
|
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
4
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
|
-
import { C as CopyRouteButton } from './client-client-
|
|
7
|
-
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-
|
|
6
|
+
import { C as CopyRouteButton } from './client-client-34yX5eij.js';
|
|
7
|
+
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-34yX5eij.js';
|
|
8
8
|
|
|
9
9
|
const badgeVariants = cva('rounded border px-1.5 py-1 text-xs font-medium leading-[12px]', {
|
|
10
10
|
variants: {
|
|
@@ -6,7 +6,7 @@ import { FormProvider, Controller, useFormContext, useFieldArray, useForm, useWa
|
|
|
6
6
|
import useSWRImmutable from 'swr/immutable';
|
|
7
7
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
8
8
|
import { cn, buttonVariants } from 'fumadocs-ui/components/api';
|
|
9
|
-
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-
|
|
9
|
+
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-34yX5eij.js';
|
|
10
10
|
import { Slot } from '@radix-ui/react-slot';
|
|
11
11
|
import { cva } from 'class-variance-authority';
|
|
12
12
|
import { CircleCheckIcon, CircleXIcon, ChevronDown, ChevronUp, Check, Trash2, Plus } from 'lucide-react';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dist"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@apidevtools/json-schema-ref-parser": "^11.
|
|
47
|
+
"@apidevtools/json-schema-ref-parser": "^11.7.0",
|
|
48
48
|
"@mdx-js/mdx": "^3.0.1",
|
|
49
49
|
"@radix-ui/react-select": "^2.1.1",
|
|
50
50
|
"@radix-ui/react-slot": "^1.1.0",
|
|
@@ -54,21 +54,21 @@
|
|
|
54
54
|
"github-slugger": "^2.0.0",
|
|
55
55
|
"js-yaml": "^4.1.0",
|
|
56
56
|
"json-schema-to-typescript": "^15.0.0",
|
|
57
|
-
"lucide-react": "^0.
|
|
57
|
+
"lucide-react": "^0.427.0",
|
|
58
58
|
"openapi-sampler": "^1.5.1",
|
|
59
|
-
"react-hook-form": "^7.52.
|
|
59
|
+
"react-hook-form": "^7.52.2",
|
|
60
60
|
"remark": "^15.0.0",
|
|
61
|
-
"shiki": "^1.
|
|
61
|
+
"shiki": "^1.12.1",
|
|
62
62
|
"swr": "^2.2.5",
|
|
63
|
-
"fumadocs-core": "13.2.
|
|
64
|
-
"fumadocs-ui": "13.2.
|
|
63
|
+
"fumadocs-core": "13.2.1",
|
|
64
|
+
"fumadocs-ui": "13.2.1"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/js-yaml": "^4.0.9",
|
|
68
68
|
"@types/node": "20.14.12",
|
|
69
69
|
"@types/openapi-sampler": "^1.0.3",
|
|
70
70
|
"@types/react": "^18.3.3",
|
|
71
|
-
"bunchee": "^5.3.
|
|
71
|
+
"bunchee": "^5.3.2",
|
|
72
72
|
"next": "^14.2.5",
|
|
73
73
|
"openapi-types": "^12.1.3",
|
|
74
74
|
"eslint-config-custom": "0.0.0",
|