mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
OpenAPI: support watch option
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'fumadocs-openapi': patch
|
||||
---
|
||||
|
||||
Support `watch` option
|
||||
@@ -61,6 +61,7 @@
|
||||
"@scalar/json-magic": "^0.12.4",
|
||||
"@scalar/openapi-upgrader": "^0.2.2",
|
||||
"ajv": "^8.18.0",
|
||||
"chokidar": "^5.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"github-slugger": "^2.0.0",
|
||||
"hast-util-to-jsx-runtime": "^2.3.6",
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { OpenAPIServer } from '@/server';
|
||||
import { createGetUrl, getSlugs, PathUtils } from 'fumadocs-core/source';
|
||||
import { createAutoPreset, type SchemaToPagesOptions } from '@/utils/pages/preset-auto';
|
||||
import { fromSchema, type OutputGroup, type OutputEntry } from '@/utils/pages/builder';
|
||||
import type { DistributiveOmit } from './types';
|
||||
|
||||
export interface OutputFile {
|
||||
path: string;
|
||||
@@ -76,7 +77,15 @@ interface MetaOptions {
|
||||
groupStyle?: 'folder' | 'separator';
|
||||
}
|
||||
|
||||
export type Config = SchemaToPagesOptions & GenerateFilesConfig;
|
||||
export type Config = SchemaToPagesOptions &
|
||||
GenerateFilesConfig & {
|
||||
/**
|
||||
* Re-generate when **schema files are changed**, ignores custom input functions & URLs.
|
||||
*
|
||||
* Note: it is recommended to configure & use `chokidar` on your own, this is only for simple cases.
|
||||
*/
|
||||
watch?: boolean;
|
||||
};
|
||||
|
||||
interface BeforeWriteContext {
|
||||
readonly generated: Record<string, OutputFile[]>;
|
||||
@@ -85,12 +94,24 @@ interface BeforeWriteContext {
|
||||
}
|
||||
|
||||
export async function generateFiles(options: Config): Promise<void> {
|
||||
if (options.watch) {
|
||||
const { watch } = await import('chokidar');
|
||||
const subOptions: Config = { ...options, watch: false };
|
||||
|
||||
await generateFiles(subOptions);
|
||||
const targets = options.input._getWatchPaths();
|
||||
console.log(`[Fumadocs OpenAPI] watching ${targets.join(', ')}`);
|
||||
watch(targets, {
|
||||
ignoreInitial: true,
|
||||
}).on('all', () => generateFiles(subOptions));
|
||||
return;
|
||||
}
|
||||
|
||||
const files = await generateFilesOnly(options);
|
||||
const { output } = options;
|
||||
|
||||
await Promise.all(
|
||||
files.map(async (file) => {
|
||||
const filePath = path.join(output, file.path);
|
||||
const filePath = path.join(options.output, file.path);
|
||||
|
||||
await mkdir(path.dirname(filePath), { recursive: true });
|
||||
await writeFile(filePath, file.content);
|
||||
@@ -100,7 +121,7 @@ export async function generateFiles(options: Config): Promise<void> {
|
||||
}
|
||||
|
||||
export async function generateFilesOnly(
|
||||
options: SchemaToPagesOptions & Omit<GenerateFilesConfig, 'output'>,
|
||||
options: DistributiveOmit<Config, 'output'>,
|
||||
): Promise<OutputFile[]> {
|
||||
const schemas = await options.input.getSchemas();
|
||||
|
||||
@@ -115,7 +136,7 @@ export async function generateFilesOnly(
|
||||
const preset = createAutoPreset(options);
|
||||
for (const [id, schema] of entries) {
|
||||
const entries = fromSchema(id, schema, preset);
|
||||
const schemaFiles = (generated[id] ??= []);
|
||||
const schemaFiles: OutputFile[] = [];
|
||||
|
||||
generatedEntries[id] = entries;
|
||||
function scan(entry: OutputEntry) {
|
||||
@@ -131,6 +152,7 @@ export async function generateFilesOnly(
|
||||
}
|
||||
|
||||
for (const entry of entries) scan(entry);
|
||||
generated[id] = schemaFiles;
|
||||
files.push(...schemaFiles);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createProxy } from '@/server/proxy';
|
||||
import { processDocument, type ProcessedDocument } from '@/utils/process-document';
|
||||
import type { Document } from '@/types';
|
||||
import type { InlineCodeUsageGenerator } from '@/requests/generators';
|
||||
import fs from 'node:fs';
|
||||
|
||||
/**
|
||||
* schema id -> file path, URL, or downloaded schema object
|
||||
@@ -30,6 +31,8 @@ export interface OpenAPIServer {
|
||||
createProxy: typeof createProxy;
|
||||
getSchemas: () => Promise<ProcessedSchemaMap>;
|
||||
getSchema: (document: string) => Promise<ProcessedDocument>;
|
||||
/** @private internal API */
|
||||
_getWatchPaths: () => string[];
|
||||
readonly options: OpenAPIOptions;
|
||||
}
|
||||
|
||||
@@ -54,6 +57,10 @@ export function createOpenAPI(options: OpenAPIOptions = {}): OpenAPIServer {
|
||||
return {
|
||||
options,
|
||||
createProxy,
|
||||
_getWatchPaths() {
|
||||
const keys = Array.isArray(input) ? input : Object.keys(input);
|
||||
return keys.filter((key) => !URL.canParse(key) && fs.existsSync(key));
|
||||
},
|
||||
async getSchema(document) {
|
||||
const schemas = await this.getSchemas();
|
||||
if (document in schemas) return schemas[document];
|
||||
|
||||
Generated
+4
@@ -2509,6 +2509,9 @@ importers:
|
||||
ajv:
|
||||
specifier: ^8.18.0
|
||||
version: 8.18.0
|
||||
chokidar:
|
||||
specifier: ^5.0.0
|
||||
version: 5.0.0
|
||||
class-variance-authority:
|
||||
specifier: ^0.7.1
|
||||
version: 0.7.1
|
||||
@@ -7626,6 +7629,7 @@ packages:
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-AvXWYFO6j/ZQ7bhGm4X6eilq2JHsDVC90ZM32k2B7/srhC2gs3Sdki1QTbwrdRCo8o7eT+167vcB1yzOvPdbjA==}
|
||||
cpu: [arm64, x64]
|
||||
os: [darwin, linux, win32]
|
||||
hasBin: true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user