fumadocs-openapi 9.3.0 → 9.3.2
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/generate-file.d.ts +11 -4
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +57 -46
- package/dist/utils/url.d.ts.map +1 -1
- package/dist/utils/url.js +12 -3
- package/package.json +6 -6
package/dist/generate-file.d.ts
CHANGED
|
@@ -68,9 +68,16 @@ interface IndexItem {
|
|
|
68
68
|
title?: string;
|
|
69
69
|
description?: string;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
71
|
+
* Specify linked pages:
|
|
72
|
+
* - items in `inputs` to include all generated pages of a specific schema.
|
|
73
|
+
* - specific Markdown/MDX files.
|
|
72
74
|
*/
|
|
73
|
-
only?: string[];
|
|
75
|
+
only?: (string | OutputFile)[];
|
|
76
|
+
}
|
|
77
|
+
interface HookContext {
|
|
78
|
+
files: OutputFile[];
|
|
79
|
+
readonly generated: Record<string, OutputFile[]>;
|
|
80
|
+
readonly documents: Record<string, ProcessedDocument>;
|
|
74
81
|
}
|
|
75
82
|
interface BaseConfig extends GenerateOptions {
|
|
76
83
|
/**
|
|
@@ -91,7 +98,7 @@ interface BaseConfig extends GenerateOptions {
|
|
|
91
98
|
* Generate index files with cards linking to generated pages.
|
|
92
99
|
*/
|
|
93
100
|
index?: {
|
|
94
|
-
items: IndexItem[];
|
|
101
|
+
items: IndexItem[] | ((ctx: HookContext) => IndexItem[]);
|
|
95
102
|
/**
|
|
96
103
|
* Generate URLs for cards
|
|
97
104
|
*/
|
|
@@ -106,7 +113,7 @@ interface BaseConfig extends GenerateOptions {
|
|
|
106
113
|
/**
|
|
107
114
|
* Can add/change/remove output files before writing to file system
|
|
108
115
|
**/
|
|
109
|
-
beforeWrite?: (files: OutputFile[]) => void | Promise<void>;
|
|
116
|
+
beforeWrite?: (this: HookContext, files: OutputFile[]) => void | Promise<void>;
|
|
110
117
|
}
|
|
111
118
|
export declare function generateFiles(options: Config): Promise<void>;
|
|
112
119
|
export declare function generateFilesOnly(options: Config): Promise<OutputFile[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-file.d.ts","sourceRoot":"","sources":["../src/generate-file.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAEvB,KAAK,iBAAiB,EAEvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C,UAAU,kBAAkB;IAC1B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,eAAgB,SAAQ,UAAU;IAC1C;;OAEG;IACH,GAAG,CAAC,EAAE,WAAW,CAAC;IAElB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,CAAC;IAEnC;;OAEG;IACH,IAAI,CAAC,EACD,CAAC,CACC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,KACpC,MAAM,CAAC,GACZ,QAAQ,CAAC;CACd;AAED,UAAU,SAAU,SAAQ,UAAU;IACpC;;OAEG;IACH,GAAG,EAAE,KAAK,CAAC;IAEX;;OAEG;IACH,IAAI,CAAC,EACD,CAAC,CACC,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,KACpC,MAAM,CAAC,GACZ,QAAQ,CAAC;CACd;AAED,UAAU,UAAW,SAAQ,UAAU;IACrC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,IAAI,CAAC,EACD,CAAC,CACC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,iBAAiB,CAAC,UAAU,CAAC,KACpC,MAAM,CAAC,GACZ,QAAQ,CAAC;CACd;AAED,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;AAE9D,UAAU,QAAQ;IAChB;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-file.d.ts","sourceRoot":"","sources":["../src/generate-file.ts"],"names":[],"mappings":"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"}
|
package/dist/generate-file.js
CHANGED
|
@@ -17,40 +17,52 @@ export async function generateFilesOnly(options) {
|
|
|
17
17
|
const { cwd = process.cwd(), beforeWrite } = options;
|
|
18
18
|
const input = typeof options.input === 'string' ? [options.input] : options.input;
|
|
19
19
|
let schemas = {};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
async function resolveInput(item) {
|
|
21
|
+
if (isUrl(item)) {
|
|
22
|
+
schemas[item] = await processDocumentCached(item);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const resolved = await glob(item, { cwd, absolute: true });
|
|
26
|
+
if (resolved.length > 1) {
|
|
27
|
+
console.warn('glob patterns in `input` are deprecated, please specify your schemas explicitly.');
|
|
28
|
+
for (let i = 0; i < resolved.length; i++) {
|
|
29
|
+
schemas[`${item}[${i}]`] = await processDocumentCached(item);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (resolved.length === 1) {
|
|
33
|
+
schemas[item] = await processDocumentCached(resolved[0]);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new Error(`input not found: ${item}`);
|
|
28
37
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
await Promise.all(
|
|
32
|
-
schemas[item] = await processDocumentCached(path.join(cwd, item));
|
|
33
|
-
}));
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(input)) {
|
|
40
|
+
await Promise.all(input.map(resolveInput));
|
|
34
41
|
}
|
|
35
42
|
else {
|
|
36
43
|
schemas = await input.getSchemas();
|
|
37
44
|
}
|
|
38
|
-
const
|
|
39
|
-
|
|
45
|
+
const generated = {};
|
|
46
|
+
const files = [];
|
|
47
|
+
const entries = Object.entries(schemas);
|
|
48
|
+
if (entries.length === 0) {
|
|
40
49
|
throw new Error('No input files found.');
|
|
41
50
|
}
|
|
42
|
-
const
|
|
43
|
-
const files = [];
|
|
44
|
-
for (const [id, schema] of resolvedSchemas) {
|
|
51
|
+
for (const [id, schema] of entries) {
|
|
45
52
|
const result = generateFromDocument(id, schema, options);
|
|
46
53
|
files.push(...result);
|
|
47
|
-
|
|
54
|
+
generated[id] = result;
|
|
48
55
|
}
|
|
56
|
+
const context = {
|
|
57
|
+
files,
|
|
58
|
+
generated,
|
|
59
|
+
documents: schemas,
|
|
60
|
+
};
|
|
49
61
|
if (options.index) {
|
|
50
|
-
|
|
62
|
+
writeIndexFiles(context, options);
|
|
51
63
|
}
|
|
52
|
-
beforeWrite?.(files);
|
|
53
|
-
return files;
|
|
64
|
+
await beforeWrite?.call(context, context.files);
|
|
65
|
+
return context.files;
|
|
54
66
|
}
|
|
55
67
|
function generateFromDocument(schemaId, processed, options) {
|
|
56
68
|
const files = [];
|
|
@@ -171,11 +183,10 @@ function getOutputPathFromRoute(path) {
|
|
|
171
183
|
})
|
|
172
184
|
.join('/') ?? '');
|
|
173
185
|
}
|
|
174
|
-
function
|
|
175
|
-
const files = [];
|
|
186
|
+
function writeIndexFiles(context, options) {
|
|
176
187
|
const { index, output, cwd = process.cwd() } = options;
|
|
177
188
|
if (!index)
|
|
178
|
-
return
|
|
189
|
+
return;
|
|
179
190
|
const { items, url } = index;
|
|
180
191
|
let urlFn;
|
|
181
192
|
if (typeof url === 'object') {
|
|
@@ -186,25 +197,25 @@ function generateIndexFiles(generatedFiles, options) {
|
|
|
186
197
|
else {
|
|
187
198
|
urlFn = url;
|
|
188
199
|
}
|
|
189
|
-
function fileContent(
|
|
200
|
+
function fileContent(index) {
|
|
201
|
+
const generatedPages = context.generated;
|
|
190
202
|
const content = [];
|
|
191
203
|
content.push('<Cards>');
|
|
192
|
-
const files =
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
const files = new Map();
|
|
205
|
+
const only = index.only ?? Object.keys(context.generated);
|
|
206
|
+
for (const item of only) {
|
|
207
|
+
if (typeof item === 'object') {
|
|
208
|
+
files.set(item.path, item);
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const result = generatedPages[item];
|
|
212
|
+
if (!result)
|
|
213
|
+
throw new Error(`${item} does not exist on "input", available: ${Object.keys(generatedPages).join(', ')}.`);
|
|
214
|
+
for (const file of result) {
|
|
215
|
+
files.set(file.path, file);
|
|
201
216
|
}
|
|
202
217
|
}
|
|
203
|
-
|
|
204
|
-
for (const value of generatedFiles.values())
|
|
205
|
-
files.push(...value);
|
|
206
|
-
}
|
|
207
|
-
for (const file of files) {
|
|
218
|
+
for (const file of files.values()) {
|
|
208
219
|
const isContent = file.path.endsWith('.mdx') || file.path.endsWith('.md');
|
|
209
220
|
if (!isContent)
|
|
210
221
|
continue;
|
|
@@ -215,18 +226,18 @@ function generateIndexFiles(generatedFiles, options) {
|
|
|
215
226
|
}
|
|
216
227
|
content.push('</Cards>');
|
|
217
228
|
return generateDocument({
|
|
218
|
-
title:
|
|
219
|
-
description:
|
|
229
|
+
title: index.title ?? 'Overview',
|
|
230
|
+
description: index.description,
|
|
220
231
|
}, content.join('\n'), options);
|
|
221
232
|
}
|
|
222
233
|
const outputDir = path.join(cwd, output);
|
|
223
|
-
for (const item of items) {
|
|
224
|
-
|
|
225
|
-
|
|
234
|
+
for (const item of typeof items === 'function' ? items(context) : items) {
|
|
235
|
+
const outPath = path.join(outputDir, path.extname(item.path).length === 0 ? `${item.path}.mdx` : item.path);
|
|
236
|
+
context.files.push({
|
|
237
|
+
path: outPath,
|
|
226
238
|
content: fileContent(item),
|
|
227
239
|
});
|
|
228
240
|
}
|
|
229
|
-
return files;
|
|
230
241
|
}
|
|
231
242
|
function defaultSlugify(s) {
|
|
232
243
|
return s.replace(/\s+/g, '-').toLowerCase();
|
package/dist/utils/url.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAMR;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,WAAW,GAC3B,MAAM,
|
|
1
|
+
{"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAMR;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,WAAW,GAC3B,MAAM,CAoCR"}
|
package/dist/utils/url.js
CHANGED
|
@@ -25,6 +25,7 @@ export function resolveServerUrl(template, variables) {
|
|
|
25
25
|
return template;
|
|
26
26
|
}
|
|
27
27
|
export function resolveRequestData(pathname, { path, query }) {
|
|
28
|
+
// First, resolve path parameters in the pathname
|
|
28
29
|
for (const key in path) {
|
|
29
30
|
const param = path[key];
|
|
30
31
|
if (Array.isArray(param.value)) {
|
|
@@ -34,17 +35,25 @@ export function resolveRequestData(pathname, { path, query }) {
|
|
|
34
35
|
pathname = pathname.replace(`{${key}}`, param.value);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
// Check if pathname already contains query parameters (legacy API support)
|
|
39
|
+
const [pathPart, existingQueryString] = pathname.split('?', 2);
|
|
40
|
+
// Parse existing query parameters from the pathname if they exist
|
|
41
|
+
const searchParams = new URLSearchParams(existingQueryString || '');
|
|
42
|
+
// Add new query parameters from the RequestData
|
|
38
43
|
for (const key in query) {
|
|
39
44
|
const param = query[key];
|
|
40
45
|
if (Array.isArray(param.value)) {
|
|
46
|
+
// Remove existing parameter first to avoid duplicates
|
|
47
|
+
searchParams.delete(key);
|
|
41
48
|
for (const item of param.value) {
|
|
42
49
|
searchParams.append(key, item);
|
|
43
50
|
}
|
|
44
51
|
}
|
|
45
52
|
else {
|
|
46
|
-
|
|
53
|
+
// Set (replace if exists) the parameter value
|
|
54
|
+
searchParams.set(key, param.value);
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
|
-
|
|
57
|
+
// Return the reconstructed URL
|
|
58
|
+
return searchParams.size > 0 ? `${pathPart}?${searchParams}` : pathPart;
|
|
50
59
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.2",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -62,18 +62,18 @@
|
|
|
62
62
|
"react-hook-form": "^7.62.0",
|
|
63
63
|
"remark": "^15.0.1",
|
|
64
64
|
"remark-rehype": "^11.1.2",
|
|
65
|
-
"shiki": "^3.
|
|
65
|
+
"shiki": "^3.12.0",
|
|
66
66
|
"tinyglobby": "^0.2.14",
|
|
67
67
|
"xml-js": "^1.6.11",
|
|
68
|
-
"fumadocs-core": "15.7.
|
|
69
|
-
"fumadocs-ui": "15.7.
|
|
68
|
+
"fumadocs-core": "15.7.5",
|
|
69
|
+
"fumadocs-ui": "15.7.5"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@scalar/api-client-react": "^1.3.
|
|
72
|
+
"@scalar/api-client-react": "^1.3.31",
|
|
73
73
|
"@types/js-yaml": "^4.0.9",
|
|
74
74
|
"@types/node": "24.3.0",
|
|
75
75
|
"@types/openapi-sampler": "^1.0.3",
|
|
76
|
-
"@types/react": "^19.1.
|
|
76
|
+
"@types/react": "^19.1.12",
|
|
77
77
|
"json-schema-typed": "^8.0.1",
|
|
78
78
|
"openapi-types": "^12.1.3",
|
|
79
79
|
"tailwindcss": "^4.1.12",
|