fumadocs-openapi 3.2.0 → 3.3.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.
Files changed (2) hide show
  1. package/dist/index.js +61 -35
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -281,39 +281,43 @@ function isObject(schema) {
281
281
  return schema.type === "object" || schema.properties !== void 0;
282
282
  }
283
283
  function schemaElement(name, schema, ctx) {
284
+ return render(name, schema, {
285
+ ...ctx,
286
+ stack: []
287
+ });
288
+ }
289
+ function render(name, schema, ctx) {
284
290
  if (schema.readOnly && !ctx.readOnly) return "";
285
291
  if (schema.writeOnly && !ctx.writeOnly) return "";
286
292
  const { renderer } = ctx.render;
287
293
  const child = [];
288
294
  function field(key, value) {
289
- child.push(span(`${key}: \`${value}\``));
295
+ child.push(span(`${key}: \`${value}\``));
290
296
  }
291
297
  if (isObject(schema) && ctx.parseObject) {
292
298
  const { additionalProperties, properties } = schema;
293
- if (additionalProperties) {
294
- if (additionalProperties === true) {
295
- child.push(
296
- renderer.Property(
297
- {
298
- name: "[key: string]",
299
- type: "any"
300
- },
301
- []
302
- )
303
- );
304
- } else {
305
- child.push(
306
- schemaElement("[key: string]", noRef(additionalProperties), {
307
- ...ctx,
308
- required: false,
309
- parseObject: false
310
- })
311
- );
312
- }
299
+ if (additionalProperties === true) {
300
+ child.push(
301
+ renderer.Property(
302
+ {
303
+ name: "[key: string]",
304
+ type: "any"
305
+ },
306
+ []
307
+ )
308
+ );
309
+ } else if (additionalProperties) {
310
+ child.push(
311
+ render("[key: string]", noRef(additionalProperties), {
312
+ ...ctx,
313
+ required: false,
314
+ parseObject: false
315
+ })
316
+ );
313
317
  }
314
318
  Object.entries(properties ?? {}).forEach(([key, value]) => {
315
319
  child.push(
316
- schemaElement(key, noRef(value), {
320
+ render(key, noRef(value), {
317
321
  ...ctx,
318
322
  required: schema.required?.includes(key) ?? false,
319
323
  parseObject: false
@@ -334,17 +338,38 @@ function schemaElement(name, schema, ctx) {
334
338
  schema.enum.map((value) => JSON.stringify(value)).join(" | ")
335
339
  );
336
340
  }
337
- const resolved = resolveObjectType(schema);
338
- if (resolved && !ctx.parseObject) {
341
+ if (isObject(schema) && !ctx.parseObject) {
339
342
  child.push(
340
343
  renderer.ObjectCollapsible({ name }, [
341
- schemaElement(name, resolved, {
344
+ render(name, schema, {
342
345
  ...ctx,
343
346
  parseObject: true,
344
347
  required: false
345
348
  })
346
349
  ])
347
350
  );
351
+ } else {
352
+ const mentionedObjectTypes = [
353
+ ...schema.anyOf ?? schema.oneOf ?? schema.allOf ?? [],
354
+ ...schema.not ? [schema.not] : [],
355
+ ...schema.type === "array" ? [schema.items] : []
356
+ ].map(noRef).filter((s) => isComplexType(s) && !ctx.stack.includes(s));
357
+ ctx.stack.push(schema);
358
+ child.push(
359
+ ...mentionedObjectTypes.map(
360
+ (s, idx) => renderer.ObjectCollapsible(
361
+ { name: s.title ?? `Object ${(idx + 1).toString()}` },
362
+ [
363
+ render("element", noRef(s), {
364
+ ...ctx,
365
+ parseObject: true,
366
+ required: false
367
+ })
368
+ ]
369
+ )
370
+ )
371
+ );
372
+ ctx.stack.pop();
348
373
  }
349
374
  return renderer.Property(
350
375
  {
@@ -356,28 +381,29 @@ function schemaElement(name, schema, ctx) {
356
381
  child
357
382
  );
358
383
  }
359
- function resolveObjectType(schema) {
360
- if (isObject(schema)) return schema;
361
- if (schema.type === "array") {
362
- return resolveObjectType(noRef(schema.items));
363
- }
384
+ function isComplexType(schema) {
385
+ if (schema.anyOf ?? schema.oneOf ?? schema.allOf) return true;
386
+ return isObject(schema) || schema.type === "array";
364
387
  }
365
388
  function getSchemaType(schema) {
366
389
  if (schema.nullable) {
367
- if (!schema.type) return "null";
368
- return `${getSchemaType({ ...schema, nullable: false })} | null`;
390
+ const type = getSchemaType({ ...schema, nullable: false });
391
+ return type === "unknown" ? "null" : `${type} | null`;
369
392
  }
393
+ if (schema.title) return schema.title;
370
394
  if (schema.type === "array")
371
- return `array of ${getSchemaType(noRef(schema.items))}`;
395
+ return `array<${getSchemaType(noRef(schema.items))}>`;
372
396
  if (schema.oneOf)
373
397
  return schema.oneOf.map((one) => getSchemaType(noRef(one))).join(" | ");
374
398
  if (schema.allOf)
375
399
  return schema.allOf.map((one) => getSchemaType(noRef(one))).join(" & ");
376
- if (schema.anyOf)
400
+ if (schema.not) return `not ${getSchemaType(noRef(schema.not))}`;
401
+ if (schema.anyOf) {
377
402
  return `Any properties in ${schema.anyOf.map((one) => getSchemaType(noRef(one))).join(", ")}`;
403
+ }
378
404
  if (schema.type) return schema.type;
379
405
  if (isObject(schema)) return "object";
380
- throw new Error(`Cannot detect object type: ${JSON.stringify(schema)}`);
406
+ return "unknown";
381
407
  }
382
408
 
383
409
  // src/render/operation.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -20,12 +20,12 @@
20
20
  "@apidevtools/json-schema-ref-parser": "^11.6.4",
21
21
  "fast-glob": "^3.3.1",
22
22
  "js-yaml": "^4.1.0",
23
- "json-schema-to-typescript": "^14.0.5",
23
+ "json-schema-to-typescript": "^14.1.0",
24
24
  "openapi-sampler": "^1.5.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/js-yaml": "^4.0.9",
28
- "@types/node": "18.17.5",
28
+ "@types/node": "20.14.9",
29
29
  "@types/openapi-sampler": "^1.0.3",
30
30
  "openapi-types": "^12.1.3",
31
31
  "eslint-config-custom": "0.0.0",