OpenAPI: Support integration with Fumadocs Source API

This commit is contained in:
fuma-nama
2024-08-02 14:10:25 +08:00
parent 5acebdd333
commit 6bb9d2d1e3
6 changed files with 129 additions and 22 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'fumadocs-openapi': minor
---
Support integration with Fumadocs Source API
@@ -56,7 +56,36 @@ node ./scripts/generate-docs.mjs
Fumadocs OpenAPI generates MDX content directly, you can use a formatter (e.g. Prettier) to format the output files.
### Features
### Generate Page Tree
You can add the `attachFile` to decorate the page tree with Source API.
It adds a badge to each page item.
```ts title="source.ts"
import { createMDXSource, defaultSchemas } from 'fumadocs-mdx';
import { z } from 'zod';
import { loader } from 'fumadocs-core/source';
import { attachFile } from 'fumadocs-openapi/source';
const frontmatter = defaultSchemas.frontmatter.extend({
method: z.string().optional(),
});
export const utils = loader({
source: createMDXSource(map, {
schema: {
frontmatter,
},
}),
pageTree: {
attachFile,
},
// other props
});
```
## Features
The official OpenAPI integration supports:
@@ -86,10 +115,32 @@ Path to the output directory.
Customise how the page is generated, default to `file`.
| mode | description |
| ---- | ------------------------------- |
| tag | Generate a page for each tag |
| file | Generate a page for each schema |
| mode | Generate a page for |
| --------- | ----------------------------------- |
| tag | each tag |
| file | each schema |
| operation | each operation (method of endpoint) |
```ts
import { generateFiles } from 'fumadocs-openapi';
void generateFiles({
per: 'tag',
});
```
### Group By Folder
In `operation` mode, you can group operations with folders.
```ts
import { generateFiles } from 'fumadocs-openapi';
void generateFiles({
per: 'operation',
groupByFolder: true,
});
```
### Name
@@ -99,8 +150,9 @@ A function that controls the output path of files.
import { generateFiles } from 'fumadocs-openapi';
void generateFiles({
input: ['./petstore.yaml'],
output: './content/docs',
name: (type, file) => {
return; // filename
},
});
```
@@ -127,7 +179,16 @@ void generateFiles({
### Frontmatter
Customise the frontmatter of MDX files.
By default, it includes a `full: true` property for Fumadocs UI.
By default, it includes:
| property | description |
| ------------- | ------------------------------------------------ |
| `title` | Page title |
| `description` | Page description |
| `full` | Always true, added for Fumadocs UI |
| `method` | Available method of operation (`operation` mode) |
| `route` | Route of operation (`operation` mode) |
```ts
import { generateFiles } from 'fumadocs-openapi';
+2 -13
View File
@@ -3,9 +3,9 @@ import { z } from 'zod';
import type { InferMetaType, InferPageType } from 'fumadocs-core/source';
import { loader } from 'fumadocs-core/source';
import { icons } from 'lucide-react';
import { attachFile } from 'fumadocs-openapi/source';
import { map } from '@/.map';
import { create } from '@/components/ui/icon';
import { ApiIndicator } from '@/components/ui/api-indicator';
const frontmatter = defaultSchemas.frontmatter.extend({
preview: z.string().optional(),
@@ -29,18 +29,7 @@ export const utils = loader({
},
}),
pageTree: {
attachFile(node, file) {
if (!file) return node;
const data = file.data.data as z.output<typeof frontmatter>;
if (!data.full) return node;
node.name = [
node.name,
' ',
ApiIndicator({ method: data.method ?? 'API' }),
];
return node;
},
attachFile,
},
});
+7
View File
@@ -19,6 +19,10 @@
"./ui": {
"import": "./dist/ui/index.js",
"types": "./dist/ui/index.d.ts"
},
"./source": {
"import": "./dist/source/index.js",
"types": "./dist/source/index.d.ts"
}
},
"main": "./dist/index.js",
@@ -30,6 +34,9 @@
],
"ui": [
"./dist/ui/index.d.ts"
],
"source": [
"./dist/source/index.d.ts"
]
}
},
+45
View File
@@ -0,0 +1,45 @@
import React from 'react';
import type { BuildPageTreeOptions } from 'fumadocs-core/source';
import { type ReactNode } from 'react';
import { cva } from 'class-variance-authority';
import { getBadgeColor } from '@/ui/shared';
/**
* Source API Integration
*
* Add this to page tree builder options
*/
export const attachFile: BuildPageTreeOptions['attachFile'] = (node, file) => {
if (!file) return node;
const data = file.data.data as object;
if ('method' in data && typeof data.method === 'string') {
node.name = [node.name, ' ', ApiIndicator({ method: data.method })];
}
return node;
};
const badgeVariants = cva('rounded-full border px-1.5 text-xs font-medium', {
variants: {
color: {
green: 'bg-green-400/20 text-green-600 dark:text-green-400',
yellow: 'bg-yellow-400/20 text-yellow-600 dark:text-yellow-400',
red: 'bg-red-400/20 text-red-600 dark:text-red-400',
blue: 'bg-blue-400/20 text-blue-600 dark:text-blue-400',
orange: 'bg-orange-400/20 text-orange-600 dark:text-orange-400',
},
},
});
function ApiIndicator({ method }: { method: string }): ReactNode {
const color = getBadgeColor(method);
return React.createElement(
'span',
{
className: badgeVariants({ className: 'ms-auto', color }),
},
method,
);
}
+1 -1
View File
@@ -1,7 +1,7 @@
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['./src/index.ts', './src/ui/index.ts'],
entry: ['./src/index.ts', './src/ui/index.ts', './src/source/index.ts'],
format: 'esm',
dts: true,
target: 'es2022',