fumadocs-openapi 9.4.0 → 9.5.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.
@@ -0,0 +1,46 @@
1
+ import type { ProcessedDocument } from '../../utils/process-document.js';
2
+ import type { TagObject } from '../../types.js';
3
+ import type { OutputEntry } from '../../utils/schema-to-pages.js';
4
+ export interface PagesToTextOptions {
5
+ /**
6
+ * Additional imports of your MDX components.
7
+ */
8
+ imports?: {
9
+ names: string[];
10
+ from: string;
11
+ }[];
12
+ /**
13
+ * Customise frontmatter.
14
+ *
15
+ * A `full: true` property will be added by default.
16
+ */
17
+ frontmatter?: (title: string, description: string | undefined, context: DocumentContext) => Record<string, unknown>;
18
+ /**
19
+ * Add description to document body.
20
+ *
21
+ * We recommend but don't enable it by default because some OpenAPI schemas have invalid description that breaks MDX syntax.
22
+ *
23
+ * @defaultValue false
24
+ */
25
+ includeDescription?: boolean;
26
+ /**
27
+ * Add a comment to the top of generated files indicating they are auto-generated.
28
+ * - `true`: Adds a standardized comment
29
+ * - `false`: No comment is added
30
+ * - `string`: Adds the provided custom comment
31
+ *
32
+ * @defaultValue true
33
+ */
34
+ addGeneratedComment?: boolean | string;
35
+ }
36
+ export declare function toText(entry: OutputEntry, processed: ProcessedDocument, options?: PagesToTextOptions): string;
37
+ export declare function generateDocument(frontmatter: unknown, content: string, options: PagesToTextOptions): string;
38
+ export type DocumentContext = {
39
+ type: 'tag';
40
+ tag: TagObject | undefined;
41
+ } | {
42
+ type: 'operation';
43
+ } | {
44
+ type: 'file';
45
+ };
46
+ //# sourceMappingURL=to-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"to-text.d.ts","sourceRoot":"","sources":["../../../src/utils/pages/to-text.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,SAAS,CAAC;AAKnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,EAAE,CAAC;IAEJ;;;;OAIG;IACH,WAAW,CAAC,EAAE,CACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,eAAe,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CACxC;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,GAAE,kBAAuB,UAuEjC;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,MAAM,CA+BR;AAOD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5B,GACD;IACE,IAAI,EAAE,WAAW,CAAC;CACnB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
@@ -1,102 +1,53 @@
1
- import { getAPIPageItems } from './build-routes.js';
2
- import { idToTitle } from './utils/id-to-title.js';
1
+ import { idToTitle } from '../../utils/id-to-title.js';
3
2
  import { dump } from 'js-yaml';
4
3
  import Slugger from 'github-slugger';
5
- import { removeUndefined } from './utils/remove-undefined.js';
6
- export function generateAll(schemaId, processed, options = {}) {
7
- const { dereferenced } = processed;
8
- const items = getAPIPageItems(dereferenced);
9
- return generatePage(schemaId, processed, {
10
- operations: items.operations,
11
- webhooks: items.webhooks,
12
- hasHead: true,
13
- }, {
14
- ...options,
15
- title: dereferenced.info.title,
16
- description: dereferenced.info.description,
17
- }, {
18
- type: 'file',
19
- });
20
- }
21
- export function generatePages(schemaId, processed, options = {}) {
22
- const { dereferenced } = processed;
23
- const items = getAPIPageItems(dereferenced);
24
- const result = [];
25
- for (const item of items.operations) {
26
- const pathItem = dereferenced.paths?.[item.path];
27
- if (!pathItem)
28
- continue;
29
- const operation = pathItem[item.method];
30
- if (!operation)
31
- continue;
32
- result.push({
33
- type: 'operation',
34
- item,
35
- content: generatePage(schemaId, processed, {
36
- operations: [item],
4
+ import { removeUndefined } from '../../utils/remove-undefined.js';
5
+ export function toText(entry, processed, options = {}) {
6
+ switch (entry.type) {
7
+ case 'operation':
8
+ return generatePage(entry.schemaId, processed, {
9
+ operations: [entry.item],
37
10
  hasHead: false,
38
11
  }, {
39
12
  ...options,
40
- title: operation.summary ??
41
- pathItem.summary ??
42
- idToTitle(operation.operationId ?? 'unknown'),
43
- description: operation.description ?? pathItem.description,
13
+ ...entry.info,
44
14
  }, {
45
15
  type: 'operation',
46
- }),
47
- });
48
- }
49
- for (const item of items.webhooks) {
50
- const pathItem = dereferenced.webhooks?.[item.name];
51
- if (!pathItem)
52
- continue;
53
- const operation = pathItem[item.method];
54
- if (!operation)
55
- continue;
56
- result.push({
57
- type: 'webhook',
58
- item,
59
- content: generatePage(schemaId, processed, {
60
- webhooks: [item],
61
- hasHead: false,
16
+ });
17
+ case 'schema':
18
+ return generatePage(entry.schemaId, processed, {
19
+ operations: entry.operations,
20
+ webhooks: entry.webhooks,
21
+ hasHead: true,
62
22
  }, {
63
23
  ...options,
64
- title: operation.summary ?? pathItem.summary ?? idToTitle(item.name),
65
- description: operation.description ?? pathItem.description,
24
+ ...entry.info,
66
25
  }, {
67
- type: 'operation',
68
- }),
69
- });
70
- }
71
- return result;
72
- }
73
- export function generateTags(schemaId, processed, options = {}) {
74
- const { dereferenced } = processed;
75
- if (!dereferenced.tags)
76
- return [];
77
- const items = getAPIPageItems(dereferenced);
78
- return dereferenced.tags.map((tag) => {
79
- const webhooks = items.webhooks.filter((v) => v.tags && v.tags.includes(tag.name));
80
- const operations = items.operations.filter((v) => v.tags && v.tags.includes(tag.name));
81
- const displayName = tag && 'x-displayName' in tag && typeof tag['x-displayName'] === 'string'
82
- ? tag['x-displayName']
83
- : idToTitle(tag.name);
84
- return {
85
- tag: tag.name,
86
- content: generatePage(schemaId, processed, {
87
- operations,
88
- webhooks,
26
+ type: 'file',
27
+ });
28
+ case 'tag':
29
+ return generatePage(entry.schemaId, processed, {
30
+ operations: entry.operations,
31
+ webhooks: entry.webhooks,
89
32
  hasHead: true,
90
33
  }, {
91
34
  ...options,
92
- title: displayName,
93
- description: tag?.description,
35
+ ...entry.info,
94
36
  }, {
95
37
  type: 'tag',
96
- tag,
97
- }),
98
- };
99
- });
38
+ tag: entry.rawTag,
39
+ });
40
+ case 'webhook':
41
+ return generatePage(entry.schemaId, processed, {
42
+ webhooks: [entry.item],
43
+ hasHead: false,
44
+ }, {
45
+ ...options,
46
+ ...entry.info,
47
+ }, {
48
+ type: 'operation',
49
+ });
50
+ }
100
51
  }
101
52
  export function generateDocument(frontmatter, content, options) {
102
53
  const { addGeneratedComment = true, imports } = options;
@@ -0,0 +1,97 @@
1
+ import { type ProcessedDocument } from '../utils/process-document.js';
2
+ import type { OpenAPIServer } from '../server/index.js';
3
+ import type { OperationItem, WebhookItem } from '../render/api-page.js';
4
+ import type { TagObject } from '../types.js';
5
+ interface BaseEntry {
6
+ path: string;
7
+ schemaId: string;
8
+ info: {
9
+ title: string;
10
+ description?: string;
11
+ };
12
+ }
13
+ export interface OutputOperationEntry extends BaseEntry {
14
+ type: 'operation';
15
+ item: OperationItem;
16
+ }
17
+ export interface OutputWebhookEntry extends BaseEntry {
18
+ type: 'webhook';
19
+ item: WebhookItem;
20
+ }
21
+ export interface OutputTagEntry extends BaseEntry {
22
+ type: 'tag';
23
+ tag: string;
24
+ rawTag: TagObject;
25
+ operations: OperationItem[];
26
+ webhooks: WebhookItem[];
27
+ }
28
+ export interface OutputSchemaEntry extends BaseEntry {
29
+ type: 'schema';
30
+ operations: OperationItem[];
31
+ webhooks: WebhookItem[];
32
+ }
33
+ export type OutputEntry = OutputTagEntry | OutputOperationEntry | OutputWebhookEntry | OutputSchemaEntry;
34
+ interface OperationConfig extends BaseConfig {
35
+ /**
36
+ * Generate a page for each API endpoint/operation (default).
37
+ */
38
+ per?: 'operation';
39
+ /**
40
+ * Group output using folders (Only works on `operation` mode)
41
+ * - tag: `{tag}/{file}`
42
+ * - route: `{endpoint}/{method}` (it will ignore the `name` option)
43
+ * - none: `{file}` (default)
44
+ *
45
+ * @defaultValue 'none'
46
+ */
47
+ groupBy?: 'tag' | 'route' | 'none';
48
+ /**
49
+ * Specify name for output file
50
+ */
51
+ name?: NameFn<OutputOperationEntry | OutputWebhookEntry>;
52
+ }
53
+ interface TagConfig extends BaseConfig {
54
+ /**
55
+ * Generate a page for each tag.
56
+ */
57
+ per: 'tag';
58
+ /**
59
+ * Specify name for output file
60
+ */
61
+ name?: NameFn<OutputTagEntry>;
62
+ }
63
+ interface SchemaConfig extends BaseConfig {
64
+ /**
65
+ * Generate a page for each schema file.
66
+ */
67
+ per: 'file';
68
+ /**
69
+ * Specify name for output file
70
+ */
71
+ name?: NameFn<OutputSchemaEntry>;
72
+ }
73
+ export type SchemaToPagesOptions = SchemaConfig | TagConfig | OperationConfig;
74
+ type NameFn<Entry> = ((output: Entry, document: ProcessedDocument['dereferenced']) => string) | {
75
+ /**
76
+ * The version of algorithm used to generate file paths.
77
+ *
78
+ * v1: Fumadocs OpenAPI v8
79
+ * v2: Fumadocs OpenAPI v9
80
+ *
81
+ * @defaultValue v2
82
+ */
83
+ algorithm?: 'v2' | 'v1';
84
+ };
85
+ interface BaseConfig {
86
+ /**
87
+ * Custom function to convert names into file names.
88
+ *
89
+ * By default, it only escapes whitespaces and upper case (English) characters
90
+ */
91
+ slugify?: (name: string) => string;
92
+ }
93
+ export declare function serverToPages(server: OpenAPIServer, options: SchemaToPagesOptions): Promise<Record<string, OutputEntry[]>>;
94
+ export declare function schemaToPages(schemaId: string, processed: ProcessedDocument, options: SchemaToPagesOptions): OutputEntry[];
95
+ export declare function isUrl(schemaId: string): boolean;
96
+ export {};
97
+ //# sourceMappingURL=schema-to-pages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-to-pages.d.ts","sourceRoot":"","sources":["../../src/utils/schema-to-pages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGzC,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,MAAM,WAAW,oBAAqB,SAAQ,SAAS;IACrD,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,WAAW,kBAAmB,SAAQ,SAAS;IACnD,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAED,MAAM,MAAM,WAAW,GACnB,cAAc,GACd,oBAAoB,GACpB,kBAAkB,GAClB,iBAAiB,CAAC;AAEtB,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,EAAE,MAAM,CAAC,oBAAoB,GAAG,kBAAkB,CAAC,CAAC;CAC1D;AAED,UAAU,SAAU,SAAQ,UAAU;IACpC;;OAEG;IACH,GAAG,EAAE,KAAK,CAAC;IAEX;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;CAC/B;AAED,UAAU,YAAa,SAAQ,UAAU;IACvC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,iBAAiB,CAAC,CAAC;CAClC;AAED,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,SAAS,GAAG,eAAe,CAAC;AAE9E,KAAK,MAAM,CAAC,KAAK,IACb,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,cAAc,CAAC,KAAK,MAAM,CAAC,GACxE;IACE;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB,CAAC;AAEN,UAAU,UAAU;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAcxC;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,oBAAoB,GAC5B,WAAW,EAAE,CAoJf;AA2CD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE/C"}
@@ -0,0 +1,167 @@
1
+ import * as path from 'node:path';
2
+ import { idToTitle } from '../utils/id-to-title.js';
3
+ import { getAPIPageItems } from '../build-routes.js';
4
+ import { getTagDisplayName } from '../utils/schema.js';
5
+ export async function serverToPages(server, options) {
6
+ const schemas = await server.getSchemas();
7
+ const generated = {};
8
+ const entries = Object.entries(schemas);
9
+ if (entries.length === 0) {
10
+ throw new Error('No input files found.');
11
+ }
12
+ for (const [id, schema] of entries) {
13
+ generated[id] = schemaToPages(id, schema, options);
14
+ }
15
+ return generated;
16
+ }
17
+ export function schemaToPages(schemaId, processed, options) {
18
+ const files = [];
19
+ const { dereferenced } = processed;
20
+ const { slugify = defaultSlugify } = options;
21
+ let nameFn;
22
+ if (!options.name || typeof options.name !== 'function') {
23
+ const algorithm = options.name?.algorithm;
24
+ nameFn = (out, doc) => defaultNameFn(schemaId, out, doc, options, algorithm);
25
+ }
26
+ else {
27
+ nameFn = options.name;
28
+ }
29
+ function getOutputPaths(groupBy = 'none', entry) {
30
+ if (groupBy === 'route') {
31
+ return [
32
+ path.join(getOutputPathFromRoute(entry.type === 'operation' ? entry.item.path : entry.item.name), `${entry.item.method.toLowerCase()}.mdx`),
33
+ ];
34
+ }
35
+ const file = nameFn(entry, dereferenced);
36
+ if (groupBy === 'tag') {
37
+ let tags = entry.type === 'operation'
38
+ ? dereferenced.paths[entry.item.path][entry.item.method].tags
39
+ : dereferenced.webhooks[entry.item.name][entry.item.method].tags;
40
+ if (!tags || tags.length === 0) {
41
+ console.warn('When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.');
42
+ tags = ['unknown'];
43
+ }
44
+ return tags.map((tag) => path.join(slugify(tag), `${file}.mdx`));
45
+ }
46
+ return [`${file}.mdx`];
47
+ }
48
+ if (options.per === 'file') {
49
+ const items = getAPIPageItems(dereferenced);
50
+ const entry = {
51
+ type: 'schema',
52
+ schemaId,
53
+ path: '',
54
+ info: {
55
+ title: dereferenced.info.title,
56
+ description: dereferenced.info.description,
57
+ },
58
+ ...items,
59
+ };
60
+ entry.path = nameFn(entry, dereferenced) + '.mdx';
61
+ files.push(entry);
62
+ return files;
63
+ }
64
+ if (options.per === 'tag') {
65
+ const items = getAPIPageItems(dereferenced);
66
+ const tags = dereferenced.tags ?? [];
67
+ for (const tag of tags) {
68
+ const entry = {
69
+ type: 'tag',
70
+ path: '',
71
+ schemaId,
72
+ info: {
73
+ title: getTagDisplayName(tag),
74
+ description: tag.description,
75
+ },
76
+ webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name)),
77
+ operations: items.operations.filter((op) => op.tags?.includes(tag.name)),
78
+ tag: tag.name,
79
+ rawTag: tag,
80
+ };
81
+ entry.path = nameFn(entry, dereferenced) + '.mdx';
82
+ files.push(entry);
83
+ }
84
+ return files;
85
+ }
86
+ const results = getAPIPageItems(dereferenced);
87
+ for (const op of results.operations) {
88
+ const pathItem = dereferenced.paths[op.path];
89
+ const operation = pathItem[op.method];
90
+ const entry = {
91
+ type: 'operation',
92
+ schemaId,
93
+ item: op,
94
+ path: '',
95
+ info: {
96
+ title: operation.summary ??
97
+ pathItem.summary ??
98
+ idToTitle(operation.operationId ?? 'unknown'),
99
+ description: operation.description ?? pathItem.description,
100
+ },
101
+ };
102
+ for (const outputPath of getOutputPaths(options.groupBy, entry)) {
103
+ files.push({ ...entry, path: outputPath });
104
+ }
105
+ }
106
+ for (const webhook of results.webhooks) {
107
+ const pathItem = dereferenced.webhooks[webhook.name];
108
+ const operation = pathItem[webhook.method];
109
+ const entry = {
110
+ type: 'webhook',
111
+ schemaId,
112
+ info: {
113
+ title: operation.summary ?? pathItem.summary ?? idToTitle(webhook.name),
114
+ description: operation.description ?? pathItem.description,
115
+ },
116
+ item: webhook,
117
+ path: '',
118
+ };
119
+ for (const outputPath of getOutputPaths(options.groupBy, entry)) {
120
+ files.push({ ...entry, path: outputPath });
121
+ }
122
+ }
123
+ return files;
124
+ }
125
+ function defaultNameFn(schemaId, result, document, options, algorithm = 'v2') {
126
+ const { slugify = defaultSlugify } = options;
127
+ if (result.type === 'tag') {
128
+ return slugify(result.tag);
129
+ }
130
+ if (result.type === 'schema') {
131
+ return isUrl(schemaId)
132
+ ? 'index'
133
+ : path.basename(schemaId, path.extname(schemaId));
134
+ }
135
+ if (result.type === 'operation') {
136
+ const operation = document.paths[result.item.path][result.item.method];
137
+ if (algorithm === 'v2' && operation.operationId) {
138
+ return operation.operationId;
139
+ }
140
+ return path.join(getOutputPathFromRoute(result.item.path), result.item.method.toLowerCase());
141
+ }
142
+ const hook = document.webhooks[result.item.name][result.item.method];
143
+ if (algorithm === 'v2' && hook.operationId) {
144
+ return hook.operationId;
145
+ }
146
+ return slugify(result.item.name);
147
+ }
148
+ export function isUrl(schemaId) {
149
+ return schemaId.startsWith('https://') || schemaId.startsWith('http://');
150
+ }
151
+ function getOutputPathFromRoute(path) {
152
+ return path
153
+ .toLowerCase()
154
+ .replaceAll('.', '-')
155
+ .split('/')
156
+ .flatMap((v) => {
157
+ if (v.startsWith('{') && v.endsWith('}'))
158
+ return v.slice(1, -1);
159
+ if (v.length === 0)
160
+ return [];
161
+ return v;
162
+ })
163
+ .join('/');
164
+ }
165
+ function defaultSlugify(s) {
166
+ return s.replace(/\s+/g, '-').toLowerCase();
167
+ }
@@ -1,5 +1,5 @@
1
1
  import type { JSONSchema } from 'json-schema-typed/draft-2020-12';
2
- import type { ReferenceObject } from '../types.js';
2
+ import type { MethodInformation, OperationObject, PathItemObject, ReferenceObject, TagObject } from '../types.js';
3
3
  export type NoReference<T> = T extends (infer I)[] ? NoReference<I>[] : T extends ReferenceObject ? Exclude<T, ReferenceObject> : T extends object ? {
4
4
  [K in keyof T]: NoReference<T[K]>;
5
5
  } : T;
@@ -9,5 +9,10 @@ type NoReferenceJSONSchema<T> = T extends (infer I)[] ? NoReference<I>[] : T ext
9
9
  export type ParsedSchema = JSONSchema;
10
10
  export type ResolvedSchema = NoReferenceJSONSchema<ParsedSchema>;
11
11
  export declare function getPreferredType<B extends Record<string, unknown>>(body: B): keyof B | undefined;
12
+ export declare function getTagDisplayName(tag: TagObject): string;
13
+ /**
14
+ * Summarize method endpoint information
15
+ */
16
+ export declare function createMethod(method: string, path: NoReference<PathItemObject>, operation: NoReference<OperationObject>): MethodInformation;
12
17
  export {};
13
18
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAC9C,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,CAAC,SAAS,eAAe,GACvB,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,GAC3B,CAAC,SAAS,MAAM,GACd;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,GACD,CAAC,CAAC;AAEV,KAAK,qBAAqB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GACjD,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,GACf,CAAC,CAAC;AAER,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AACtC,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,IAAI,EAAE,CAAC,GACN,MAAM,CAAC,GAAG,SAAS,CAIrB"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,eAAe,EACf,SAAS,EACV,MAAM,SAAS,CAAC;AAGjB,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAC9C,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,CAAC,SAAS,eAAe,GACvB,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,GAC3B,CAAC,SAAS,MAAM,GACd;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,GACD,CAAC,CAAC;AAEV,KAAK,qBAAqB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GACjD,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACzB,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,GACf,CAAC,CAAC;AAER,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AACtC,MAAM,MAAM,cAAc,GAAG,qBAAqB,CAAC,YAAY,CAAC,CAAC;AAEjE,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,IAAI,EAAE,CAAC,GACN,MAAM,CAAC,GAAG,SAAS,CAIrB;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAIxD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,CAAC,cAAc,CAAC,EACjC,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,GACtC,iBAAiB,CAQnB"}
@@ -1,5 +1,23 @@
1
+ import { idToTitle } from '../utils/id-to-title.js';
1
2
  export function getPreferredType(body) {
2
3
  if ('application/json' in body)
3
4
  return 'application/json';
4
5
  return Object.keys(body)[0];
5
6
  }
7
+ export function getTagDisplayName(tag) {
8
+ return 'x-displayName' in tag && typeof tag['x-displayName'] === 'string'
9
+ ? tag['x-displayName']
10
+ : idToTitle(tag.name);
11
+ }
12
+ /**
13
+ * Summarize method endpoint information
14
+ */
15
+ export function createMethod(method, path, operation) {
16
+ return {
17
+ description: path.description,
18
+ summary: path.summary,
19
+ ...operation,
20
+ parameters: [...(operation.parameters ?? []), ...(path.parameters ?? [])],
21
+ method: method.toUpperCase(),
22
+ };
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "9.4.0",
3
+ "version": "9.5.0",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -50,8 +50,8 @@
50
50
  "@radix-ui/react-dialog": "^1.1.15",
51
51
  "@radix-ui/react-select": "^2.2.6",
52
52
  "@radix-ui/react-slot": "^1.2.3",
53
- "@scalar/json-magic": "^0.5.2",
54
- "@scalar/openapi-parser": "0.21.2",
53
+ "@scalar/json-magic": "^0.6.0",
54
+ "@scalar/openapi-parser": "0.22.1",
55
55
  "ajv": "^8.17.1",
56
56
  "class-variance-authority": "^0.7.1",
57
57
  "github-slugger": "^2.0.0",
@@ -60,26 +60,26 @@
60
60
  "js-yaml": "^4.1.0",
61
61
  "next-themes": "^0.4.6",
62
62
  "openapi-sampler": "^1.6.1",
63
- "react-hook-form": "^7.63.0",
63
+ "react-hook-form": "^7.64.0",
64
64
  "remark": "^15.0.1",
65
65
  "remark-rehype": "^11.1.2",
66
66
  "tinyglobby": "^0.2.15",
67
67
  "xml-js": "^1.6.11",
68
- "fumadocs-core": "15.8.2",
69
- "fumadocs-ui": "15.8.2"
68
+ "fumadocs-core": "15.8.4",
69
+ "fumadocs-ui": "15.8.4"
70
70
  },
71
71
  "devDependencies": {
72
- "@scalar/api-client-react": "^1.3.41",
72
+ "@scalar/api-client-react": "^1.3.44",
73
73
  "@types/js-yaml": "^4.0.9",
74
- "@types/node": "24.5.2",
74
+ "@types/node": "24.6.2",
75
75
  "@types/openapi-sampler": "^1.0.3",
76
- "@types/react": "^19.1.14",
76
+ "@types/react": "^19.2.0",
77
77
  "json-schema-typed": "^8.0.1",
78
78
  "openapi-types": "^12.1.3",
79
- "tailwindcss": "^4.1.13",
79
+ "tailwindcss": "^4.1.14",
80
80
  "tsc-alias": "^1.8.16",
81
- "tsconfig": "0.0.0",
82
- "eslint-config-custom": "0.0.0"
81
+ "eslint-config-custom": "0.0.0",
82
+ "tsconfig": "0.0.0"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "@scalar/api-client-react": "*",
@@ -1,69 +0,0 @@
1
- import type { OperationItem, WebhookItem } from './render/api-page.js';
2
- import type { ProcessedDocument } from './utils/process-document.js';
3
- import type { TagObject } from './types.js';
4
- export interface GenerateOptions {
5
- /**
6
- * Additional imports of your MDX components.
7
- */
8
- imports?: {
9
- names: string[];
10
- from: string;
11
- }[];
12
- /**
13
- * Customise frontmatter.
14
- *
15
- * A `full: true` property will be added by default.
16
- */
17
- frontmatter?: (title: string, description: string | undefined, context: DocumentContext) => Record<string, unknown>;
18
- /**
19
- * Add description to document body.
20
- *
21
- * We recommend but don't enable it by default because some OpenAPI schemas have invalid description that breaks MDX syntax.
22
- *
23
- * @defaultValue false
24
- */
25
- includeDescription?: boolean;
26
- /**
27
- * Add a comment to the top of generated files indicating they are auto-generated.
28
- * - `true`: Adds a standardized comment
29
- * - `false`: No comment is added
30
- * - `string`: Adds the provided custom comment
31
- *
32
- * @defaultValue true
33
- */
34
- addGeneratedComment?: boolean | string;
35
- cwd?: string;
36
- /**
37
- * Inline the entire OpenAPI document into the MDX file.
38
- *
39
- * @deprecated Use the new `input` API on `createOpenAPI()` instead.
40
- * @defaultValue false
41
- */
42
- inlineDocument?: boolean;
43
- }
44
- export interface GenerateTagOutput {
45
- tag: string;
46
- content: string;
47
- }
48
- export type GeneratePageOutput = {
49
- type: 'operation';
50
- item: OperationItem;
51
- content: string;
52
- } | {
53
- type: 'webhook';
54
- item: WebhookItem;
55
- content: string;
56
- };
57
- export declare function generateAll(schemaId: string, processed: ProcessedDocument, options?: GenerateOptions): string;
58
- export declare function generatePages(schemaId: string, processed: ProcessedDocument, options?: GenerateOptions): GeneratePageOutput[];
59
- export declare function generateTags(schemaId: string, processed: ProcessedDocument, options?: GenerateOptions): GenerateTagOutput[];
60
- export declare function generateDocument(frontmatter: unknown, content: string, options: Pick<GenerateOptions, 'addGeneratedComment' | 'imports'>): string;
61
- export type DocumentContext = {
62
- type: 'tag';
63
- tag: TagObject | undefined;
64
- } | {
65
- type: 'operation';
66
- } | {
67
- type: 'file';
68
- };
69
- //# sourceMappingURL=generate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../src/generate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,aAAa,EACb,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,SAAS,CAAC;AAMnD,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,OAAO,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,EAAE,CAAC;IAEJ;;;;OAIG;IACH,WAAW,CAAC,EAAE,CACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,SAAS,EAC/B,OAAO,EAAE,eAAe,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE7B;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAEvC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAC1B;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,GAAE,eAAoB,GAC5B,MAAM,CAqBR;AAED,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,GAAE,eAAoB,GAC5B,kBAAkB,EAAE,CAiEtB;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,GAAE,eAAoB,GAC5B,iBAAiB,EAAE,CAwCrB;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,OAAO,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,qBAAqB,GAAG,SAAS,CAAC,GAChE,MAAM,CA+BR;AAOD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5B,GACD;IACE,IAAI,EAAE,WAAW,CAAC;CACnB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
@@ -1,7 +0,0 @@
1
- import type { MethodInformation, OperationObject, PathItemObject } from '../types.js';
2
- import type { NoReference } from '../utils/schema.js';
3
- /**
4
- * Summarize method endpoint information
5
- */
6
- export declare function createMethod(method: string, path: NoReference<PathItemObject>, operation: NoReference<OperationObject>): MethodInformation;
7
- //# sourceMappingURL=create-method.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create-method.d.ts","sourceRoot":"","sources":["../../src/server/create-method.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,cAAc,EACf,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,CAAC,cAAc,CAAC,EACjC,SAAS,EAAE,WAAW,CAAC,eAAe,CAAC,GACtC,iBAAiB,CAQnB"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Summarize method endpoint information
3
- */
4
- export function createMethod(method, path, operation) {
5
- return {
6
- description: path.description,
7
- summary: path.summary,
8
- ...operation,
9
- parameters: [...(operation.parameters ?? []), ...(path.parameters ?? [])],
10
- method: method.toUpperCase(),
11
- };
12
- }