fumadocs-openapi 5.7.4 → 5.8.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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { OpenAPIV3 } from 'openapi-types';
1
+ import { OpenAPIV3_1, OpenAPIV3 } from 'openapi-types';
2
2
  import Slugger from 'github-slugger';
3
3
  import { ComponentType, ReactNode } from 'react';
4
4
  import { CodeToHastOptionsCommon, CodeOptionsThemes, BuiltinTheme } from 'shiki';
@@ -72,6 +72,7 @@ interface APIInfoProps {
72
72
  method: string;
73
73
  route: string;
74
74
  baseUrls: string[];
75
+ head: ReactNode;
75
76
  children: ReactNode;
76
77
  }
77
78
  interface PropertyProps {
@@ -127,6 +128,11 @@ interface Renderer {
127
128
  APIPlayground: ComponentType<APIPlaygroundProps>;
128
129
  }
129
130
 
131
+ type NoReference<T> = T extends (infer I)[] ? NoReference<I>[] : T extends ReferenceObject ? Exclude<T, ReferenceObject> : T extends object ? {
132
+ [K in keyof T]: NoReference<T[K]>;
133
+ } : T;
134
+ type ParsedSchema = OpenAPIV3_1.SchemaObject;
135
+
130
136
  /**
131
137
  * Sample info of endpoint
132
138
  */
@@ -137,7 +143,7 @@ interface EndpointSample {
137
143
  url: string;
138
144
  method: string;
139
145
  body?: {
140
- schema: OpenAPIV3.SchemaObject;
146
+ schema: ParsedSchema;
141
147
  mediaType: string;
142
148
  sample: unknown;
143
149
  };
@@ -147,12 +153,12 @@ interface EndpointSample {
147
153
  interface ResponseSample {
148
154
  mediaType: string;
149
155
  sample: unknown;
150
- schema: OpenAPIV3.SchemaObject;
156
+ schema: ParsedSchema;
151
157
  }
152
158
  interface ParameterSample {
153
159
  name: string;
154
160
  in: string;
155
- schema: OpenAPIV3.SchemaObject;
161
+ schema: ParsedSchema;
156
162
  sample: unknown;
157
163
  }
158
164
 
@@ -162,22 +168,38 @@ interface CodeSample {
162
168
  source: string | ((endpoint: EndpointSample) => string | undefined) | false;
163
169
  }
164
170
 
171
+ type Document = OpenAPIV3_1.Document;
172
+ type OperationObject = OpenAPIV3_1.OperationObject;
173
+ type ParameterObject = OpenAPIV3_1.ParameterObject;
174
+ type SecurityRequirementObject = OpenAPIV3_1.SecurityRequirementObject;
175
+ type SecuritySchemeObject = OpenAPIV3_1.SecuritySchemeObject;
176
+ type ReferenceObject = OpenAPIV3_1.ReferenceObject;
177
+ type PathItemObject = OpenAPIV3_1.PathItemObject;
178
+ type TagObject = OpenAPIV3_1.TagObject;
165
179
  interface RouteInformation {
166
180
  path: string;
167
181
  summary?: string;
168
182
  description?: string;
169
183
  methods: MethodInformation[];
170
184
  }
171
- interface MethodInformation extends OpenAPIV3.OperationObject {
172
- parameters: OpenAPIV3.ParameterObject[];
185
+ type MethodInformation = NoReference<OperationObject> & {
173
186
  method: string;
174
- }
187
+ };
175
188
  type Awaitable<T> = T | Promise<T>;
189
+ /**
190
+ * Dereferenced value and its original `$ref` value
191
+ */
192
+ type DereferenceMap = Map<unknown, string>;
176
193
  interface RenderContext {
177
194
  renderer: Renderer;
178
- document: OpenAPIV3.Document;
195
+ /**
196
+ * dereferenced schema
197
+ */
198
+ document: NoReference<Document>;
179
199
  baseUrl: string;
200
+ baseUrls: string[];
180
201
  slugger: Slugger;
202
+ dereferenceMap: DereferenceMap;
181
203
  /**
182
204
  * Generate TypeScript definitions from response schema.
183
205
  *
@@ -194,24 +216,26 @@ interface RenderContext {
194
216
  shikiOptions?: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BuiltinTheme>;
195
217
  }
196
218
 
219
+ type DocumentInput = string | OpenAPIV3_1.Document | OpenAPIV3.Document;
220
+
221
+ interface WebhookItem {
222
+ name: string;
223
+ method: OpenAPIV3_1.HttpMethods;
224
+ }
225
+ interface OperationItem {
226
+ path: string;
227
+ method: OpenAPIV3_1.HttpMethods;
228
+ }
229
+
197
230
  type DocumentContext = {
198
231
  type: 'tag';
199
- tag: OpenAPIV3.TagObject | undefined;
200
- routes: RouteInformation[];
232
+ tag: TagObject | undefined;
201
233
  } | {
202
234
  type: 'operation';
203
- /**
204
- * information of the route
205
- */
206
- route: RouteInformation;
207
- /**
208
- * information of the method (API Endpoint)
209
- */
210
- endpoint: MethodInformation;
211
235
  } | {
212
236
  type: 'file';
213
- routes: RouteInformation[];
214
237
  };
238
+
215
239
  interface GenerateOptions {
216
240
  /**
217
241
  * Additional imports of your MDX components.
@@ -238,14 +262,22 @@ interface GenerateTagOutput {
238
262
  tag: string;
239
263
  content: string;
240
264
  }
241
- interface GenerateOperationOutput {
265
+ type GeneratePageOutput = {
266
+ type: 'operation';
267
+ pathItem: NoReference<PathItemObject>;
268
+ operation: NoReference<OperationObject>;
269
+ item: OperationItem;
242
270
  content: string;
243
- method: MethodInformation;
244
- route: RouteInformation;
245
- }
246
- declare function generateAll(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<string>;
247
- declare function generateOperations(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<GenerateOperationOutput[]>;
248
- declare function generateTags(pathOrDocument: string | OpenAPIV3.Document, options?: GenerateOptions): Promise<GenerateTagOutput[]>;
271
+ } | {
272
+ type: 'webhook';
273
+ pathItem: NoReference<PathItemObject>;
274
+ operation: NoReference<OperationObject>;
275
+ item: WebhookItem;
276
+ content: string;
277
+ };
278
+ declare function generateAll(pathOrDocument: DocumentInput, options?: GenerateOptions): Promise<string>;
279
+ declare function generatePages(pathOrDocument: DocumentInput, options?: GenerateOptions): Promise<GeneratePageOutput[]>;
280
+ declare function generateTags(pathOrDocument: DocumentInput, options?: GenerateOptions): Promise<GenerateTagOutput[]>;
249
281
 
250
282
  interface Config extends GenerateOptions {
251
283
  /**
@@ -284,4 +316,4 @@ interface Config extends GenerateOptions {
284
316
  }
285
317
  declare function generateFiles(options: Config): Promise<void>;
286
318
 
287
- export { type Config, type DocumentContext, type GenerateOperationOutput, type GenerateOptions, type GenerateTagOutput, type MethodInformation, type RenderContext, type RouteInformation, generateAll, generateFiles, generateOperations, generateTags };
319
+ export { type Config, type DereferenceMap, type Document, type GenerateOptions, type GeneratePageOutput, type GenerateTagOutput, type MethodInformation, type OperationObject, type ParameterObject, type PathItemObject, type ReferenceObject, type RenderContext, type RouteInformation, type SecurityRequirementObject, type SecuritySchemeObject, type TagObject, generateAll, generateFiles, generatePages, generateTags };
package/dist/index.js CHANGED
@@ -1,29 +1,11 @@
1
1
  import { resolve, join, parse, dirname } from 'node:path';
2
- import Parser from '@apidevtools/json-schema-ref-parser';
3
2
  import { dump } from 'js-yaml';
4
3
  import Slugger from 'github-slugger';
4
+ import Parser from '@apidevtools/json-schema-ref-parser';
5
+ import { upgrade } from '@scalar/openapi-parser';
5
6
  import { mkdir, writeFile } from 'node:fs/promises';
6
7
  import fg from 'fast-glob';
7
8
 
8
- function noRef(v) {
9
- return v;
10
- }
11
-
12
- /**
13
- * Summarize method endpoint information
14
- */ function createMethod(method, path, operation) {
15
- return {
16
- description: path.description,
17
- summary: path.summary,
18
- ...operation,
19
- parameters: [
20
- ...noRef(operation.parameters ?? []),
21
- ...noRef(path.parameters ?? [])
22
- ],
23
- method: method.toUpperCase()
24
- };
25
- }
26
-
27
9
  const methodKeys = [
28
10
  'get',
29
11
  'post',
@@ -32,38 +14,34 @@ const methodKeys = [
32
14
  'head',
33
15
  'put'
34
16
  ];
35
- /**
36
- * Build the route information of tags, use `.get('all')` to get all entries
37
- */ function buildRoutes(document) {
38
- const map = new Map();
39
- for (const [path, pathItem] of Object.entries(document.paths)){
17
+ function getAPIPageItems(document) {
18
+ const result = {
19
+ webhooks: [],
20
+ operations: []
21
+ };
22
+ for (const [path, pathItem] of Object.entries(document.paths ?? {})){
40
23
  if (!pathItem) continue;
41
- const methodMap = new Map();
42
24
  for (const methodKey of methodKeys){
43
- const operation = pathItem[methodKey];
44
- if (!operation) continue;
45
- const info = createMethod(methodKey, pathItem, operation);
46
- const tags = operation.tags ?? [];
47
- for (const tag of [
48
- ...tags,
49
- 'all'
50
- ]){
51
- const list = methodMap.get(tag) ?? [];
52
- list.push(info);
53
- methodMap.set(tag, list);
54
- }
55
- }
56
- for (const [tag, methods] of methodMap.entries()){
57
- const list = map.get(tag) ?? [];
58
- list.push({
59
- ...pathItem,
25
+ if (!pathItem[methodKey]) continue;
26
+ result.operations.push({
27
+ method: methodKey,
60
28
  path,
61
- methods
29
+ tags: pathItem[methodKey]?.tags
30
+ });
31
+ }
32
+ }
33
+ for (const [name, pathItem] of Object.entries(document.webhooks ?? {})){
34
+ if (!pathItem) continue;
35
+ for (const methodKey of methodKeys){
36
+ if (!pathItem[methodKey]) continue;
37
+ result.webhooks.push({
38
+ method: methodKey,
39
+ name,
40
+ tags: pathItem[methodKey]?.tags
62
41
  });
63
- map.set(tag, list);
64
42
  }
65
43
  }
66
- return map;
44
+ return result;
67
45
  }
68
46
 
69
47
  function idToTitle(id) {
@@ -83,10 +61,11 @@ function generateDocument(options) {
83
61
  const out = [];
84
62
  const extend = frontmatter?.(options.title, options.description, options.context);
85
63
  let meta;
86
- if (options.context.type === 'operation') {
64
+ if (options.page.operations?.length === 1) {
65
+ const operation = options.page.operations[0];
87
66
  meta = {
88
- method: options.context.endpoint.method,
89
- route: options.context.route.path
67
+ method: operation.method.toUpperCase(),
68
+ route: operation.path
90
69
  };
91
70
  }
92
71
  const data = generateStaticData(options.dereferenced, options.page);
@@ -117,8 +96,8 @@ function generateStaticData(dereferenced, props) {
117
96
  headings: [],
118
97
  contents: []
119
98
  };
120
- for (const item of props.operations){
121
- const operation = dereferenced.paths[item.path]?.[item.method];
99
+ for (const item of props.operations ?? []){
100
+ const operation = dereferenced.paths?.[item.path]?.[item.method];
122
101
  if (!operation) continue;
123
102
  if (props.hasHead && operation.operationId) {
124
103
  const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path);
@@ -144,107 +123,156 @@ function generateStaticData(dereferenced, props) {
144
123
  };
145
124
  }
146
125
  function pageContent(props) {
147
- return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />`;
126
+ // filter extra properties in props
127
+ const operations = (props.operations ?? []).map((item)=>({
128
+ path: item.path,
129
+ method: item.method
130
+ }));
131
+ const webhooks = (props.webhooks ?? []).map((item)=>({
132
+ name: item.name,
133
+ method: item.method
134
+ }));
135
+ return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(operations)}} webhooks={${JSON.stringify(webhooks)}} hasHead={${JSON.stringify(props.hasHead)}} />`;
136
+ }
137
+
138
+ const cache = new Map();
139
+ /**
140
+ * process & reference input document to a Fumadocs OpenAPI compatible format
141
+ */ async function processDocument(document, disableCache = false) {
142
+ const cached = !disableCache && typeof document === 'string' ? cache.get(document) : null;
143
+ if (cached) return cached;
144
+ let bundled = await Parser.bundle(document, {
145
+ mutateInputSchema: false
146
+ });
147
+ bundled = upgrade(bundled).specification;
148
+ const dereferenceMap = new Map();
149
+ const dereferenced = await Parser.dereference(bundled, {
150
+ mutateInputSchema: true,
151
+ dereference: {
152
+ onDereference ($ref, schema) {
153
+ dereferenceMap.set(schema, $ref);
154
+ }
155
+ }
156
+ });
157
+ const processed = {
158
+ document: dereferenced,
159
+ dereferenceMap
160
+ };
161
+ if (!disableCache && typeof document === 'string') {
162
+ cache.set(document, processed);
163
+ }
164
+ return processed;
148
165
  }
149
166
 
150
167
  async function dereference(pathOrDocument, options) {
151
- return await Parser.dereference(// resolve paths
152
- typeof pathOrDocument === 'string' && !pathOrDocument.startsWith('http://') && !pathOrDocument.startsWith('https://') ? resolve(options.cwd ?? process.cwd(), pathOrDocument) : pathOrDocument);
168
+ return await processDocument(// resolve paths
169
+ typeof pathOrDocument === 'string' && !pathOrDocument.startsWith('http://') && !pathOrDocument.startsWith('https://') ? resolve(options.cwd ?? process.cwd(), pathOrDocument) : pathOrDocument).then((res)=>res.document);
153
170
  }
154
171
  async function generateAll(pathOrDocument, options = {}) {
155
172
  const document = await dereference(pathOrDocument, options);
156
- const routes = buildRoutes(document).get('all') ?? [];
157
- const operations = [];
158
- for (const route of routes){
159
- for (const method of route.methods){
160
- operations.push({
161
- method: method.method.toLowerCase(),
162
- path: route.path
163
- });
164
- }
165
- }
173
+ const items = getAPIPageItems(document);
166
174
  return generateDocument({
167
175
  ...options,
168
176
  dereferenced: document,
169
177
  title: document.info.title,
170
178
  description: document.info.description,
171
179
  page: {
172
- operations,
180
+ operations: items.operations,
181
+ webhooks: items.webhooks,
173
182
  hasHead: true,
174
183
  document: pathOrDocument
175
184
  },
176
185
  context: {
177
- type: 'file',
178
- routes
186
+ type: 'file'
179
187
  }
180
188
  });
181
189
  }
182
- async function generateOperations(pathOrDocument, options = {}) {
190
+ async function generatePages(pathOrDocument, options = {}) {
183
191
  const document = await dereference(pathOrDocument, options);
184
- const routes = buildRoutes(document).get('all') ?? [];
185
- return routes.flatMap((route)=>{
186
- return route.methods.map((method)=>{
187
- if (!method.operationId) throw new Error('Operation ID is required for generating docs.');
188
- const content = generateDocument({
192
+ const items = getAPIPageItems(document);
193
+ const result = [];
194
+ for (const item of items.operations){
195
+ const pathItem = document.paths?.[item.path];
196
+ if (!pathItem) continue;
197
+ const operation = pathItem[item.method];
198
+ if (!operation) continue;
199
+ result.push({
200
+ type: 'operation',
201
+ pathItem,
202
+ operation,
203
+ item,
204
+ content: generateDocument({
189
205
  ...options,
190
206
  page: {
191
207
  operations: [
192
- {
193
- path: route.path,
194
- method: method.method.toLowerCase()
195
- }
208
+ item
196
209
  ],
197
210
  hasHead: false,
198
211
  document: pathOrDocument
199
212
  },
200
213
  dereferenced: document,
201
- title: method.summary ?? idToTitle(method.operationId),
202
- description: method.description,
214
+ title: operation.summary ?? pathItem.summary ?? idToTitle(operation.operationId ?? 'unknown'),
215
+ description: operation.description ?? pathItem.description,
203
216
  context: {
204
- type: 'operation',
205
- endpoint: method,
206
- route
217
+ type: 'operation'
207
218
  }
208
- });
209
- return {
210
- content,
211
- route,
212
- method
213
- };
219
+ })
214
220
  });
215
- });
221
+ }
222
+ for (const item of items.webhooks){
223
+ const pathItem = document.webhooks?.[item.name];
224
+ if (!pathItem) continue;
225
+ const operation = pathItem[item.method];
226
+ if (!operation) continue;
227
+ result.push({
228
+ type: 'webhook',
229
+ pathItem,
230
+ operation,
231
+ item,
232
+ content: generateDocument({
233
+ ...options,
234
+ page: {
235
+ webhooks: [
236
+ item
237
+ ],
238
+ hasHead: false,
239
+ document: pathOrDocument
240
+ },
241
+ dereferenced: document,
242
+ title: operation.summary ?? pathItem.summary ?? idToTitle(item.name),
243
+ description: operation.description ?? pathItem.description,
244
+ context: {
245
+ type: 'operation'
246
+ }
247
+ })
248
+ });
249
+ }
250
+ return result;
216
251
  }
217
252
  async function generateTags(pathOrDocument, options = {}) {
218
253
  const document = await dereference(pathOrDocument, options);
219
- const tags = Array.from(buildRoutes(document).entries());
220
- return tags.filter(([tag])=>tag !== 'all').map(([tag, routes])=>{
221
- const info = document.tags?.find((t)=>t.name === tag);
222
- const operations = [];
223
- for (const route of routes){
224
- for (const method of route.methods){
225
- operations.push({
226
- method: method.method.toLowerCase(),
227
- path: route.path
228
- });
229
- }
230
- }
231
- const displayName = info && 'x-displayName' in info && typeof info['x-displayName'] === 'string' ? info['x-displayName'] : idToTitle(tag);
254
+ if (!document.tags) return [];
255
+ const items = getAPIPageItems(document);
256
+ return document.tags.map((tag)=>{
257
+ const webhooks = items.webhooks.filter((v)=>v.tags && v.tags.includes(tag.name));
258
+ const operations = items.operations.filter((v)=>v.tags && v.tags.includes(tag.name));
259
+ const displayName = tag && 'x-displayName' in tag && typeof tag['x-displayName'] === 'string' ? tag['x-displayName'] : idToTitle(tag.name);
232
260
  return {
233
- tag,
261
+ tag: tag.name,
234
262
  content: generateDocument({
235
263
  ...options,
236
264
  page: {
237
265
  document: pathOrDocument,
238
266
  operations,
267
+ webhooks,
239
268
  hasHead: true
240
269
  },
241
270
  dereferenced: document,
242
271
  title: displayName,
243
- description: info?.description,
272
+ description: tag?.description,
244
273
  context: {
245
274
  type: 'tag',
246
- tag: info,
247
- routes
275
+ tag
248
276
  }
249
277
  })
250
278
  };
@@ -272,7 +300,28 @@ async function generateFiles(options) {
272
300
  }),
273
301
  ...urlInputs
274
302
  ];
275
- await Promise.all(resolvedInputs.map(async (pathOrUrl)=>{
303
+ function getOutputPaths(name, result) {
304
+ const outPaths = [];
305
+ if (groupBy === 'tag') {
306
+ const tags = result.operation.tags;
307
+ if (tags && tags.length > 0) {
308
+ for (const tag of tags){
309
+ outPaths.push(join(outputDir, getFilename(tag), `${getFilename(name)}.mdx`));
310
+ }
311
+ } else {
312
+ outPaths.push(result.type === 'operation' ? join(outputDir, `${getFilename(name)}.mdx`) : join(outputDir, 'webhooks', `${getFilename(name)}.mdx`));
313
+ }
314
+ }
315
+ if (groupBy === 'route') {
316
+ const dir = result.pathItem.summary ? getFilename(result.pathItem.summary) : getFilenameFromRoute(result.type === 'operation' ? result.item.path : result.item.name);
317
+ outPaths.push(join(outputDir, dir, `${getFilename(name)}.mdx`));
318
+ }
319
+ if (groupBy === 'none') {
320
+ outPaths.push(join(outputDir, `${getFilename(name)}.mdx`));
321
+ }
322
+ return outPaths;
323
+ }
324
+ async function generateFromDocument(pathOrUrl) {
276
325
  if (per === 'file') {
277
326
  let filename = isUrl(pathOrUrl) ? 'index' : parse(pathOrUrl).name;
278
327
  if (nameFn) filename = nameFn('file', filename);
@@ -280,49 +329,41 @@ async function generateFiles(options) {
280
329
  const result = await generateAll(pathOrUrl, options);
281
330
  await write(outPath, result);
282
331
  console.log(`Generated: ${outPath}`);
283
- return;
284
332
  }
285
333
  if (per === 'operation') {
286
334
  const metaFiles = new Set();
287
- const results = await generateOperations(pathOrUrl, options);
288
- await Promise.all(results.map(async (result)=>{
289
- const outPaths = new Array();
290
- if (!result.method.operationId) return;
291
- const id = result.method.operationId.split('.').at(-1) ?? result.method.operationId;
292
- if (groupBy === 'tag' && result.method.tags && result.method.tags.length > 0) {
293
- for (const tag of result.method.tags){
294
- outPaths.push(join(outputDir, getFilename(tag), `${getFilename(id)}.mdx`));
295
- }
296
- } else if (groupBy === 'route') {
297
- const outPath = join(outputDir, result.route.summary ? getFilename(result.route.summary) : getFilenameFromRoute(result.route.path), `${getFilename(id)}.mdx`);
298
- const metaFile = join(dirname(outPath), 'meta.json');
299
- if (result.route.summary && !metaFiles.has(metaFile)) {
335
+ const results = await generatePages(pathOrUrl, options);
336
+ for (const result of results){
337
+ let name = result.type === 'operation' ? result.operation.operationId : result.item.name;
338
+ if (!name) return;
339
+ name = name.split('.').at(-1) ?? name;
340
+ for (const outPath of getOutputPaths(name, result)){
341
+ await write(outPath, result.content);
342
+ console.log(`Generated: ${outPath}`);
343
+ if (groupBy === 'route') {
344
+ const metaFile = join(dirname(outPath), 'meta.json');
345
+ if (!result.pathItem.summary || metaFiles.has(metaFile)) continue;
300
346
  metaFiles.add(metaFile);
301
347
  await write(metaFile, JSON.stringify({
302
- title: result.route.summary
303
- }));
348
+ title: result.pathItem.summary
349
+ }, null, 2));
304
350
  console.log(`Generated Meta: ${metaFile}`);
305
351
  }
306
- outPaths.push(outPath);
307
- } else {
308
- outPaths.push(join(outputDir, `${getFilename(id)}.mdx`));
309
- }
310
- for (const outPath of outPaths){
311
- await write(outPath, result.content);
312
- console.log(`Generated: ${outPath}`);
313
352
  }
314
- }));
315
- return;
353
+ }
316
354
  }
317
- const results = await generateTags(pathOrUrl, options);
318
- for (const result of results){
319
- let tagName = result.tag;
320
- tagName = nameFn?.('tag', tagName) ?? getFilename(tagName);
321
- const outPath = join(outputDir, `${tagName}.mdx`);
322
- await write(outPath, result.content);
323
- console.log(`Generated: ${outPath}`);
355
+ if (per === 'tag') {
356
+ const results = await generateTags(pathOrUrl, options);
357
+ for (const result of results){
358
+ let tagName = result.tag;
359
+ tagName = nameFn?.('tag', tagName) ?? getFilename(tagName);
360
+ const outPath = join(outputDir, `${tagName}.mdx`);
361
+ await write(outPath, result.content);
362
+ console.log(`Generated: ${outPath}`);
363
+ }
324
364
  }
325
- }));
365
+ }
366
+ await Promise.all(resolvedInputs.map(generateFromDocument));
326
367
  }
327
368
  function isUrl(input) {
328
369
  return input.startsWith('https://') || input.startsWith('http://');
@@ -340,4 +381,4 @@ async function write(path, content) {
340
381
  await writeFile(path, content);
341
382
  }
342
383
 
343
- export { generateAll, generateFiles, generateOperations, generateTags };
384
+ export { generateAll, generateFiles, generatePages, generateTags };