fumadocs-openapi 3.1.0 → 3.1.1

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 CHANGED
@@ -64,7 +64,12 @@ interface GenerateTagOutput {
64
64
  tag: string;
65
65
  content: string;
66
66
  }
67
+ interface GenerateOperationOutput {
68
+ id: string;
69
+ content: string;
70
+ }
67
71
  declare function generate(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<string>;
72
+ declare function generateOperations(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<GenerateOperationOutput[]>;
68
73
  declare function generateTags(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<GenerateTagOutput[]>;
69
74
 
70
75
  interface Config extends GenerateOptions {
@@ -83,7 +88,7 @@ interface Config extends GenerateOptions {
83
88
  *
84
89
  * @defaultValue file
85
90
  */
86
- per?: 'tag' | 'file';
91
+ per?: 'tag' | 'file' | 'operation';
87
92
  /**
88
93
  * Specify name for output file
89
94
  */
@@ -110,4 +115,4 @@ interface RenderContext {
110
115
 
111
116
  declare function createElement(name: string, props: object, ...child: string[]): string;
112
117
 
113
- export { type APIInfoProps, type Config, type GenerateOptions, type GenerateTagOutput, type MethodInformation, type ObjectCollapsibleProps, type PropertyProps, type RenderContext, type Renderer, type RequestProps, type ResponseProps, type ResponsesProps, type RouteInformation, createElement, defaultRenderer, generate, generateFiles, generateTags };
118
+ export { type APIInfoProps, type Config, type GenerateOperationOutput, type GenerateOptions, type GenerateTagOutput, type MethodInformation, type ObjectCollapsibleProps, type PropertyProps, type RenderContext, type Renderer, type RequestProps, type ResponseProps, type ResponsesProps, type RouteInformation, createElement, defaultRenderer, generate, generateFiles, generateOperations, generateTags };
package/dist/index.js CHANGED
@@ -72,6 +72,9 @@ function codeblock({ language, title }, child) {
72
72
  "```"
73
73
  ].join("\n");
74
74
  }
75
+ function heading(depth, child) {
76
+ return `${"#".repeat(depth)} ${child.trim()}`;
77
+ }
75
78
 
76
79
  // src/render/renderer.ts
77
80
  var defaultRenderer = {
@@ -375,23 +378,24 @@ function getSchemaType(schema) {
375
378
  }
376
379
 
377
380
  // src/render/operation.ts
378
- async function renderOperation(path, method, ctx) {
381
+ async function renderOperation(path, method, ctx, noTitle = false) {
382
+ let level = 2;
379
383
  const body = noRef(method.requestBody);
380
384
  const security = method.security ?? ctx.document.security;
381
385
  const info = [];
382
386
  const example = [];
383
387
  const title = method.summary ?? method.operationId;
384
- if (title) info.push(`## ${title}`);
388
+ if (title && !noTitle) info.push(heading(level++, title));
385
389
  if (method.description) info.push(p(method.description));
386
390
  if (security) {
387
- info.push("### Authorization");
391
+ info.push(heading(level, "Authorization"));
388
392
  info.push(getAuthSection(security, ctx));
389
393
  }
390
394
  if (body) {
391
395
  const bodySchema = getPreferredMedia(body.content)?.schema;
392
396
  if (!bodySchema) throw new Error();
393
397
  info.push(
394
- `### Request Body${!body.required ? " (Optional)" : ""}`,
398
+ heading(level, `Request Body ${!body.required ? "(Optional)" : ""}`),
395
399
  p(body.description),
396
400
  schemaElement("body", noRef(bodySchema), {
397
401
  parseObject: true,
@@ -435,7 +439,7 @@ async function renderOperation(path, method, ctx) {
435
439
  parameterGroups.set(groupName, group);
436
440
  }
437
441
  for (const [group, parameters] of Array.from(parameterGroups.entries())) {
438
- info.push(`### ${group}`, ...parameters);
442
+ info.push(heading(level, group), ...parameters);
439
443
  }
440
444
  info.push(getResponseTable(method));
441
445
  example.push(
@@ -584,6 +588,29 @@ async function generate(pathOrDocument, options = {}) {
584
588
  options
585
589
  );
586
590
  }
591
+ async function generateOperations(pathOrDocument, options = {}) {
592
+ const document = await Parser.dereference(pathOrDocument);
593
+ const routes = buildRoutes(document).get("all") ?? [];
594
+ const ctx = getContext(document, options);
595
+ return await Promise.all(
596
+ routes.flatMap((route) => {
597
+ return route.methods.map(async (method) => {
598
+ const content = renderPage(
599
+ method.summary ?? method.method,
600
+ method.description,
601
+ [await renderOperation(route.path, method, ctx, true)],
602
+ options
603
+ );
604
+ if (!method.operationId)
605
+ throw new Error("Operation ID is required for generating docs.");
606
+ return {
607
+ id: method.operationId,
608
+ content
609
+ };
610
+ });
611
+ })
612
+ );
613
+ }
587
614
  async function generateTags(pathOrDocument, options = {}) {
588
615
  const document = await Parser.dereference(pathOrDocument);
589
616
  const tags = Array.from(buildRoutes(document).entries());
@@ -640,10 +667,24 @@ async function generateFiles({
640
667
  console.log(`Generated: ${outPath}`);
641
668
  return;
642
669
  }
670
+ if (per === "operation") {
671
+ const results2 = await generateOperations(path, options);
672
+ await Promise.all(
673
+ results2.map(async (result) => {
674
+ const outPath = join(
675
+ outputDir,
676
+ filename,
677
+ `${getName(result.id)}.mdx`
678
+ );
679
+ await write(outPath, result.content);
680
+ console.log(`Generated: ${outPath}`);
681
+ })
682
+ );
683
+ }
643
684
  const results = await generateTags(path, options);
644
685
  for (const result of results) {
645
686
  let tagName = result.tag;
646
- tagName = nameFn?.("tag", tagName) ?? tagName.toLowerCase().replace(/\s+/g, "-");
687
+ tagName = nameFn?.("tag", tagName) ?? getName(tagName);
647
688
  const outPath = join(outputDir, filename, `${tagName}.mdx`);
648
689
  await write(outPath, result.content);
649
690
  console.log(`Generated: ${outPath}`);
@@ -651,6 +692,12 @@ async function generateFiles({
651
692
  })
652
693
  );
653
694
  }
695
+ function getName(s) {
696
+ return s.replace(
697
+ /[A-Z]/g,
698
+ (match, idx) => idx === 0 ? match : `-${match.toLowerCase()}`
699
+ ).replace(/\s+/g, "-").toLowerCase();
700
+ }
654
701
  async function write(path, content) {
655
702
  await mkdir(dirname(path), { recursive: true });
656
703
  await writeFile(path, content);
@@ -660,5 +707,6 @@ export {
660
707
  defaultRenderer,
661
708
  generate,
662
709
  generateFiles,
710
+ generateOperations,
663
711
  generateTags
664
712
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",