fumadocs-openapi 5.11.8 → 6.0.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.
@@ -14,7 +14,7 @@ import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
14
14
  import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
15
15
  import * as Base from 'fumadocs-ui/components/codeblock';
16
16
  import { highlight } from 'fumadocs-core/server';
17
- import { Root, API, APIInfo, APIExample as APIExample$1, Property, ObjectCollapsible, APIPlayground } from '../ui/index.js';
17
+ import { APIPlayground, Root, API, APIInfo, APIExample as APIExample$1, Property, ObjectCollapsible } from '../ui/index.js';
18
18
  import { load, upgrade, dereference } from '@scalar/openapi-parser';
19
19
  import { fetchUrls } from '@scalar/openapi-parser/plugins/fetch-urls';
20
20
  import { readFiles } from '@scalar/openapi-parser/plugins/read-files';
@@ -54,7 +54,7 @@ function getSecurityPrefix(security) {
54
54
  if (security.type === 'oauth2') return 'Bearer';
55
55
  }
56
56
 
57
- function generateSample(path, method, { baseUrl, document }) {
57
+ function generateSample(path, method, { baseUrl, schema: { document } }) {
58
58
  const params = [];
59
59
  const responses = {};
60
60
  for (const param of method.parameters ?? []){
@@ -328,173 +328,6 @@ async function getTypescriptSchema(endpoint, code, dereferenceMap) {
328
328
  }
329
329
  }
330
330
 
331
- function Playground({ path, method, ctx }) {
332
- let currentId = 0;
333
- const bodyContent = method.requestBody?.content;
334
- const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
335
- const context = {
336
- allowFile: mediaType === 'multipart/form-data',
337
- references: {},
338
- nextId () {
339
- return String(currentId++);
340
- },
341
- registered: new WeakMap(),
342
- render: ctx
343
- };
344
- const bodySchema = bodyContent && mediaType && bodyContent[mediaType].schema ? toSchema(bodyContent[mediaType].schema, true, context) : undefined;
345
- const props = {
346
- authorization: getAuthorizationField(method, ctx),
347
- method: method.method,
348
- route: path,
349
- path: method.parameters?.filter((v)=>v.in === 'path').map((v)=>parameterToField(v, context)),
350
- query: method.parameters?.filter((v)=>v.in === 'query').map((v)=>parameterToField(v, context)),
351
- header: method.parameters?.filter((v)=>v.in === 'header').map((v)=>parameterToField(v, context)),
352
- body: bodySchema && mediaType ? {
353
- ...bodySchema,
354
- mediaType: mediaType
355
- } : undefined,
356
- schemas: context.references,
357
- proxyUrl: ctx.proxyUrl
358
- };
359
- return /*#__PURE__*/ jsx(ctx.renderer.APIPlayground, {
360
- ...props
361
- });
362
- }
363
- function getAuthorizationField(method, ctx) {
364
- const security = method.security ?? ctx.document.security ?? [];
365
- if (security.length === 0) return;
366
- const singular = security.find((requirements)=>Object.keys(requirements).length === 1);
367
- if (!singular) return;
368
- const scheme = getSecurities(singular, ctx.document)[0];
369
- return {
370
- type: 'string',
371
- name: scheme.type === 'apiKey' ? scheme.name : 'Authorization',
372
- authType: scheme.type,
373
- defaultValue: scheme.type === 'oauth2' || scheme.type === 'http' && scheme.scheme === 'bearer' ? 'Bearer' : 'Basic',
374
- isRequired: security.every((requirements)=>Object.keys(requirements).length > 0),
375
- description: 'The Authorization access token'
376
- };
377
- }
378
- function getIdFromSchema(schema, required, ctx) {
379
- const registered = ctx.registered.get(schema);
380
- if (registered === undefined) {
381
- const id = ctx.nextId();
382
- ctx.registered.set(schema, id);
383
- ctx.references[id] = toSchema(schema, required, ctx);
384
- return id;
385
- }
386
- return registered;
387
- }
388
- function parameterToField(v, ctx) {
389
- return {
390
- name: v.name,
391
- ...toSchema(v.schema ?? {
392
- type: 'string'
393
- }, v.required ?? false, ctx)
394
- };
395
- }
396
- function toReference(schema, required, ctx) {
397
- return {
398
- type: 'ref',
399
- isRequired: required,
400
- schema: getIdFromSchema(schema, false, ctx)
401
- };
402
- }
403
- function toSchema(schema, required, ctx) {
404
- if (schema.type === 'array') {
405
- return {
406
- type: 'array',
407
- description: schema.description ?? schema.title,
408
- isRequired: required,
409
- items: getIdFromSchema(schema.items, false, ctx)
410
- };
411
- }
412
- if (schema.type === 'object' || schema.properties !== undefined || schema.allOf !== undefined) {
413
- const properties = {};
414
- Object.entries(schema.properties ?? {}).forEach(([key, prop])=>{
415
- properties[key] = toReference(prop, schema.required?.includes(key) ?? false, ctx);
416
- });
417
- schema.allOf?.forEach((c)=>{
418
- const field = toSchema(c, true, ctx);
419
- if (field.type === 'object') Object.assign(properties, field.properties);
420
- });
421
- const additional = schema.additionalProperties;
422
- let additionalProperties;
423
- if (additional && typeof additional === 'object') {
424
- if ((!additional.type || additional.type.length === 0) && !additional.anyOf && !additional.allOf && !additional.oneOf) {
425
- additionalProperties = true;
426
- } else {
427
- additionalProperties = getIdFromSchema(additional, false, ctx);
428
- }
429
- } else {
430
- additionalProperties = additional;
431
- }
432
- return {
433
- type: 'object',
434
- isRequired: required,
435
- description: schema.description ?? schema.title,
436
- properties,
437
- additionalProperties
438
- };
439
- }
440
- if (schema.type === undefined) {
441
- const combine = schema.anyOf ?? schema.oneOf;
442
- if (combine) {
443
- return {
444
- type: 'switcher',
445
- description: schema.description ?? schema.title,
446
- items: Object.fromEntries(combine.map((item, idx)=>{
447
- return [
448
- item.title ?? item.type ?? `Item ${idx.toString()}`,
449
- toReference(item, true, ctx)
450
- ];
451
- })),
452
- isRequired: required
453
- };
454
- }
455
- return {
456
- type: 'null',
457
- isRequired: false
458
- };
459
- }
460
- if (ctx.allowFile && schema.type === 'string' && schema.format === 'binary') {
461
- return {
462
- type: 'file',
463
- isRequired: required,
464
- description: schema.description ?? schema.title
465
- };
466
- }
467
- if (Array.isArray(schema.type)) {
468
- const items = {};
469
- for (const type of schema.type){
470
- if (type === 'array') {
471
- items[type] = {
472
- type,
473
- items: 'items' in schema && schema.items ? toSchema(schema.items, false, ctx) : toSchema({}, required, ctx),
474
- isRequired: required
475
- };
476
- } else {
477
- items[type] = toSchema({
478
- ...schema,
479
- type
480
- }, true, ctx);
481
- }
482
- }
483
- return {
484
- type: 'switcher',
485
- description: schema.description ?? schema.title,
486
- items,
487
- isRequired: required
488
- };
489
- }
490
- return {
491
- type: schema.type === 'integer' ? 'number' : schema.type,
492
- defaultValue: schema.example ?? '',
493
- isRequired: required,
494
- description: schema.description ?? schema.title
495
- };
496
- }
497
-
498
331
  function idToTitle(id) {
499
332
  let result = [];
500
333
  for (const c of id){
@@ -606,17 +439,18 @@ function Schema({ name, schema, ctx }) {
606
439
  const parseObject = ctx.parseObject ?? true;
607
440
  const stack = ctx.stack ?? [];
608
441
  const { renderer } = ctx.render;
609
- const child = [];
610
442
  // object type
611
443
  if (isObject(schema) && parseObject && (schema.additionalProperties || schema.properties)) {
444
+ let body = null;
445
+ let footer = null;
612
446
  const { additionalProperties, properties } = schema;
613
447
  if (additionalProperties === true) {
614
- child.push(/*#__PURE__*/ jsx(renderer.Property, {
448
+ footer = /*#__PURE__*/ jsx(renderer.Property, {
615
449
  name: "[key: string]",
616
450
  type: "any"
617
- }, "additionalProperties"));
451
+ });
618
452
  } else if (additionalProperties) {
619
- child.push(/*#__PURE__*/ jsx(Schema, {
453
+ footer = /*#__PURE__*/ jsx(Schema, {
620
454
  name: "[key: string]",
621
455
  schema: additionalProperties,
622
456
  ctx: {
@@ -624,10 +458,10 @@ function Schema({ name, schema, ctx }) {
624
458
  required: false,
625
459
  parseObject: false
626
460
  }
627
- }, "additionalProperties"));
461
+ });
628
462
  }
629
463
  if (properties) {
630
- const rendered = Object.entries(properties).map(([key, value])=>{
464
+ body = Object.entries(properties).map(([key, value])=>{
631
465
  return /*#__PURE__*/ jsx(Schema, {
632
466
  name: key,
633
467
  schema: value,
@@ -638,9 +472,14 @@ function Schema({ name, schema, ctx }) {
638
472
  }
639
473
  }, key);
640
474
  });
641
- child.push(...rendered);
642
475
  }
643
- return child;
476
+ return /*#__PURE__*/ jsxs("div", {
477
+ className: "flex flex-col gap-4",
478
+ children: [
479
+ body,
480
+ footer
481
+ ]
482
+ });
644
483
  }
645
484
  if (schema.allOf && parseObject) {
646
485
  return /*#__PURE__*/ jsx(Schema, {
@@ -649,9 +488,7 @@ function Schema({ name, schema, ctx }) {
649
488
  ctx: ctx
650
489
  });
651
490
  }
652
- if (schema.description) child.push(/*#__PURE__*/ jsx(Markdown, {
653
- text: schema.description
654
- }, "description"));
491
+ let footer = null;
655
492
  const fields = [];
656
493
  for (const [key, value] of Object.entries(keys$1)){
657
494
  if (key in schema) {
@@ -667,21 +504,9 @@ function Schema({ name, schema, ctx }) {
667
504
  value: schema.enum.map((value)=>JSON.stringify(value)).join(' | ')
668
505
  });
669
506
  }
670
- if (fields.length > 0) child.push(/*#__PURE__*/ jsx("div", {
671
- className: "flex flex-col gap-2",
672
- children: fields.map((field)=>/*#__PURE__*/ jsxs("span", {
673
- children: [
674
- field.key,
675
- ": ",
676
- /*#__PURE__*/ jsx("code", {
677
- children: field.value
678
- })
679
- ]
680
- }, field.key))
681
- }, "fields"));
682
507
  if (isObject(schema) && !parseObject && !stack.includes(schema)) {
683
- child.push(/*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
684
- name: "Attributes",
508
+ footer = /*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
509
+ name: "Show Attributes",
685
510
  children: /*#__PURE__*/ jsx(Schema, {
686
511
  name: name,
687
512
  schema: schema,
@@ -695,7 +520,7 @@ function Schema({ name, schema, ctx }) {
695
520
  ]
696
521
  }
697
522
  })
698
- }, "attributes"));
523
+ });
699
524
  } else {
700
525
  const mentionedObjectTypes = [
701
526
  ...schema.anyOf ?? schema.oneOf ?? [],
@@ -706,9 +531,9 @@ function Schema({ name, schema, ctx }) {
706
531
  schema.items
707
532
  ] : []
708
533
  ].filter((s)=>isComplexType(s) && !stack.includes(s));
709
- const renderedMentionedTypes = mentionedObjectTypes.map((s, idx)=>{
534
+ footer = mentionedObjectTypes.map((s, idx)=>{
710
535
  return /*#__PURE__*/ jsx(renderer.ObjectCollapsible, {
711
- name: s.title ?? `Object ${(idx + 1).toString()}`,
536
+ name: s.title ?? (mentionedObjectTypes.length === 1 ? 'Show Attributes' : `Object ${idx + 1}`),
712
537
  children: /*#__PURE__*/ jsx(Schema, {
713
538
  name: "element",
714
539
  schema: s,
@@ -722,16 +547,32 @@ function Schema({ name, schema, ctx }) {
722
547
  required: false
723
548
  }
724
549
  })
725
- }, `mentioned:${idx.toString()}`);
550
+ }, idx);
726
551
  });
727
- child.push(...renderedMentionedTypes);
728
552
  }
729
- return /*#__PURE__*/ jsx(renderer.Property, {
553
+ return /*#__PURE__*/ jsxs(renderer.Property, {
730
554
  name: name,
731
555
  type: getSchemaType(schema, ctx),
732
556
  required: ctx.required,
733
557
  deprecated: schema.deprecated,
734
- children: child
558
+ children: [
559
+ schema.description ? /*#__PURE__*/ jsx(Markdown, {
560
+ text: schema.description
561
+ }) : null,
562
+ fields.length > 0 ? /*#__PURE__*/ jsx("div", {
563
+ className: "flex flex-col gap-2",
564
+ children: fields.map((field)=>/*#__PURE__*/ jsxs("span", {
565
+ children: [
566
+ field.key,
567
+ ": ",
568
+ /*#__PURE__*/ jsx("code", {
569
+ children: field.value
570
+ })
571
+ ]
572
+ }, field.key))
573
+ }) : null,
574
+ footer
575
+ ]
735
576
  });
736
577
  }
737
578
  /**
@@ -793,7 +634,7 @@ const methodKeys = [
793
634
 
794
635
  function Operation({ type = 'operation', path, method, ctx, hasHead, headingLevel = 2 }) {
795
636
  const body = method.requestBody;
796
- const security = method.security ?? ctx.document.security;
637
+ const security = method.security ?? ctx.schema.document.security;
797
638
  let headNode = null;
798
639
  let bodyNode = null;
799
640
  let responseNode = null;
@@ -923,7 +764,7 @@ function Operation({ type = 'operation', path, method, ctx, hasHead, headingLeve
923
764
  method: method.method,
924
765
  route: path,
925
766
  children: [
926
- type === 'operation' ? /*#__PURE__*/ jsx(Playground, {
767
+ type === 'operation' ? /*#__PURE__*/ jsx(ctx.renderer.APIPlayground, {
927
768
  path: path,
928
769
  method: method,
929
770
  ctx: ctx
@@ -1053,7 +894,7 @@ function WebhookCallback({ callback, ctx, headingLevel }) {
1053
894
  }
1054
895
  return out;
1055
896
  }
1056
- function AuthSection({ ctx: { document, renderer }, requirements }) {
897
+ function AuthSection({ ctx: { schema: { document }, renderer }, requirements }) {
1057
898
  let id = 0;
1058
899
  const info = [];
1059
900
  for (const requirement of requirements){
@@ -1125,7 +966,7 @@ function AuthSection({ ctx: { document, renderer }, requirements }) {
1125
966
  }
1126
967
  return info;
1127
968
  }
1128
- async function ResponseTabs({ endpoint, operation, ctx: { renderer, generateTypeScriptSchema, dereferenceMap } }) {
969
+ async function ResponseTabs({ endpoint, operation, ctx: { renderer, generateTypeScriptSchema, schema } }) {
1129
970
  const items = [];
1130
971
  const children = [];
1131
972
  if (!operation.responses) return null;
@@ -1144,7 +985,7 @@ async function ResponseTabs({ endpoint, operation, ctx: { renderer, generateType
1144
985
  if (generateTypeScriptSchema) {
1145
986
  ts = await generateTypeScriptSchema(endpoint, code);
1146
987
  } else if (generateTypeScriptSchema === undefined) {
1147
- ts = await getTypescriptSchema(endpoint, code, dereferenceMap);
988
+ ts = await getTypescriptSchema(endpoint, code, schema.dereferenceMap);
1148
989
  }
1149
990
  if (ts) {
1150
991
  types.push({
@@ -1192,6 +1033,165 @@ async function CodeBlock({ code, lang, options, ...rest }) {
1192
1033
  });
1193
1034
  }
1194
1035
 
1036
+ function Playground({ path, method, ctx }) {
1037
+ let currentId = 0;
1038
+ const bodyContent = method.requestBody?.content;
1039
+ const mediaType = bodyContent ? getPreferredType(bodyContent) : undefined;
1040
+ const context = {
1041
+ allowFile: mediaType === 'multipart/form-data',
1042
+ references: {},
1043
+ nextId () {
1044
+ return String(currentId++);
1045
+ },
1046
+ registered: new WeakMap(),
1047
+ render: ctx
1048
+ };
1049
+ const bodySchema = bodyContent && mediaType && bodyContent[mediaType].schema ? toSchema(bodyContent[mediaType].schema, true, context) : undefined;
1050
+ const props = {
1051
+ authorization: getAuthorizationField(method, ctx),
1052
+ method: method.method,
1053
+ route: path,
1054
+ path: method.parameters?.filter((v)=>v.in === 'path').map((v)=>parameterToField(v, context)),
1055
+ query: method.parameters?.filter((v)=>v.in === 'query').map((v)=>parameterToField(v, context)),
1056
+ header: method.parameters?.filter((v)=>v.in === 'header').map((v)=>parameterToField(v, context)),
1057
+ body: bodySchema && mediaType ? {
1058
+ ...bodySchema,
1059
+ mediaType: mediaType
1060
+ } : undefined,
1061
+ schemas: context.references,
1062
+ proxyUrl: ctx.proxyUrl
1063
+ };
1064
+ return /*#__PURE__*/ jsx(APIPlayground, {
1065
+ ...props
1066
+ });
1067
+ }
1068
+ function getAuthorizationField(method, { schema: { document } }) {
1069
+ const security = method.security ?? document.security ?? [];
1070
+ if (security.length === 0) return;
1071
+ const singular = security.find((requirements)=>Object.keys(requirements).length === 1);
1072
+ if (!singular) return;
1073
+ return getSecurities(singular, document)[0];
1074
+ }
1075
+ function getIdFromSchema(schema, required, ctx) {
1076
+ const registered = ctx.registered.get(schema);
1077
+ if (registered === undefined) {
1078
+ const id = ctx.nextId();
1079
+ ctx.registered.set(schema, id);
1080
+ ctx.references[id] = toSchema(schema, required, ctx);
1081
+ return id;
1082
+ }
1083
+ return registered;
1084
+ }
1085
+ function parameterToField(v, ctx) {
1086
+ return {
1087
+ name: v.name,
1088
+ ...toSchema(v.schema ?? {
1089
+ type: 'string'
1090
+ }, v.required ?? false, ctx)
1091
+ };
1092
+ }
1093
+ function toReference(schema, required, ctx) {
1094
+ return {
1095
+ type: 'ref',
1096
+ isRequired: required,
1097
+ schema: getIdFromSchema(schema, false, ctx)
1098
+ };
1099
+ }
1100
+ function toSchema(schema, required, ctx) {
1101
+ if (schema.type === 'array') {
1102
+ return {
1103
+ type: 'array',
1104
+ description: schema.description ?? schema.title,
1105
+ isRequired: required,
1106
+ items: getIdFromSchema(schema.items, false, ctx)
1107
+ };
1108
+ }
1109
+ if (schema.type === 'object' || schema.properties !== undefined || schema.allOf !== undefined) {
1110
+ const properties = {};
1111
+ Object.entries(schema.properties ?? {}).forEach(([key, prop])=>{
1112
+ properties[key] = toReference(prop, schema.required?.includes(key) ?? false, ctx);
1113
+ });
1114
+ schema.allOf?.forEach((c)=>{
1115
+ const field = toSchema(c, true, ctx);
1116
+ if (field.type === 'object') Object.assign(properties, field.properties);
1117
+ });
1118
+ const additional = schema.additionalProperties;
1119
+ let additionalProperties;
1120
+ if (additional && typeof additional === 'object') {
1121
+ if ((!additional.type || additional.type.length === 0) && !additional.anyOf && !additional.allOf && !additional.oneOf) {
1122
+ additionalProperties = true;
1123
+ } else {
1124
+ additionalProperties = getIdFromSchema(additional, false, ctx);
1125
+ }
1126
+ } else {
1127
+ additionalProperties = additional;
1128
+ }
1129
+ return {
1130
+ type: 'object',
1131
+ isRequired: required,
1132
+ description: schema.description ?? schema.title,
1133
+ properties,
1134
+ additionalProperties
1135
+ };
1136
+ }
1137
+ if (schema.type === undefined) {
1138
+ const combine = schema.anyOf ?? schema.oneOf;
1139
+ if (combine) {
1140
+ return {
1141
+ type: 'switcher',
1142
+ description: schema.description ?? schema.title,
1143
+ items: Object.fromEntries(combine.map((item, idx)=>{
1144
+ return [
1145
+ item.title ?? item.type ?? `Item ${idx.toString()}`,
1146
+ toReference(item, true, ctx)
1147
+ ];
1148
+ })),
1149
+ isRequired: required
1150
+ };
1151
+ }
1152
+ return {
1153
+ type: 'null',
1154
+ isRequired: false
1155
+ };
1156
+ }
1157
+ if (ctx.allowFile && schema.type === 'string' && schema.format === 'binary') {
1158
+ return {
1159
+ type: 'file',
1160
+ isRequired: required,
1161
+ description: schema.description ?? schema.title
1162
+ };
1163
+ }
1164
+ if (Array.isArray(schema.type)) {
1165
+ const items = {};
1166
+ for (const type of schema.type){
1167
+ if (type === 'array') {
1168
+ items[type] = {
1169
+ type,
1170
+ items: 'items' in schema && schema.items ? toSchema(schema.items, false, ctx) : toSchema({}, required, ctx),
1171
+ isRequired: required
1172
+ };
1173
+ } else {
1174
+ items[type] = toSchema({
1175
+ ...schema,
1176
+ type
1177
+ }, required, ctx);
1178
+ }
1179
+ }
1180
+ return {
1181
+ type: 'switcher',
1182
+ description: schema.description ?? schema.title,
1183
+ items,
1184
+ isRequired: required
1185
+ };
1186
+ }
1187
+ return {
1188
+ type: schema.type === 'integer' ? 'number' : schema.type,
1189
+ defaultValue: schema.example ?? '',
1190
+ isRequired: required,
1191
+ description: schema.description ?? schema.title
1192
+ };
1193
+ }
1194
+
1195
1195
  function createRenders(shikiOptions) {
1196
1196
  return {
1197
1197
  Root: (props)=>/*#__PURE__*/ jsx(Root, {
@@ -1200,7 +1200,12 @@ function createRenders(shikiOptions) {
1200
1200
  children: props.children
1201
1201
  }),
1202
1202
  API,
1203
- APIInfo,
1203
+ APIInfo: ({ children, head })=>/*#__PURE__*/ jsxs(APIInfo, {
1204
+ children: [
1205
+ head,
1206
+ children
1207
+ ]
1208
+ }),
1204
1209
  APIExample: APIExample$1,
1205
1210
  Responses: Tabs,
1206
1211
  Response: Tab,
@@ -1232,7 +1237,7 @@ function createRenders(shikiOptions) {
1232
1237
  options: shikiOptions
1233
1238
  })
1234
1239
  }),
1235
- APIPlayground
1240
+ APIPlayground: Playground
1236
1241
  };
1237
1242
  }
1238
1243
 
@@ -1258,7 +1263,8 @@ const cache = new Map();
1258
1263
  });
1259
1264
  const processed = {
1260
1265
  document: dereferenced,
1261
- dereferenceMap
1266
+ dereferenceMap,
1267
+ downloaded: loaded.specification
1262
1268
  };
1263
1269
  if (!disableCache && typeof document === 'string') {
1264
1270
  cache.set(document, processed);
@@ -1316,7 +1322,8 @@ async function APIPage(props) {
1316
1322
  ]
1317
1323
  });
1318
1324
  }
1319
- async function getContext({ document, dereferenceMap }, options = {}) {
1325
+ async function getContext(schema, options = {}) {
1326
+ const document = schema.document;
1320
1327
  const servers = document.servers && document.servers.length > 0 ? document.servers : [
1321
1328
  {
1322
1329
  url: 'https://example.com'
@@ -1324,8 +1331,7 @@ async function getContext({ document, dereferenceMap }, options = {}) {
1324
1331
  ];
1325
1332
  const server = servers[0];
1326
1333
  return {
1327
- document: document,
1328
- dereferenceMap,
1334
+ schema,
1329
1335
  proxyUrl: options.proxyUrl,
1330
1336
  showResponseSchema: options.showResponseSchema,
1331
1337
  renderer: {
@@ -0,0 +1,107 @@
1
+ 'use client';
2
+ import { useContext, createContext, useState, useRef, useEffect, useMemo } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+ import { cn } from 'fumadocs-ui/components/api';
5
+ import dynamic from 'next/dynamic';
6
+
7
+ const ApiContext = /*#__PURE__*/ createContext(undefined);
8
+ const ServerSelectContext = /*#__PURE__*/ createContext(undefined);
9
+ function useApiContext() {
10
+ const ctx = useContext(ApiContext);
11
+ if (!ctx) throw new Error('Component must be used under <ApiProvider />');
12
+ return ctx;
13
+ }
14
+ function useServerSelectContext() {
15
+ const ctx = useContext(ServerSelectContext);
16
+ if (!ctx) throw new Error('Component must be used under <ApiProvider />');
17
+ return ctx;
18
+ }
19
+ function ApiProvider({ defaultBaseUrl, children, ...props }) {
20
+ const [server, setServer] = useState(()=>{
21
+ const defaultItem = defaultBaseUrl ? props.servers.find((item)=>item.url === defaultBaseUrl) : undefined;
22
+ return defaultItem ? {
23
+ url: defaultItem.url,
24
+ variables: getDefaultValues(defaultItem)
25
+ } : null;
26
+ });
27
+ const serverRef = useRef(server);
28
+ serverRef.current = server;
29
+ useEffect(()=>{
30
+ const cached = localStorage.getItem('apiBaseUrl');
31
+ if (!cached) return;
32
+ try {
33
+ const obj = JSON.parse(cached);
34
+ if (!obj || typeof obj !== 'object') return;
35
+ setServer(obj);
36
+ } catch {
37
+ // ignore
38
+ }
39
+ }, []);
40
+ return /*#__PURE__*/ jsx(ApiContext.Provider, {
41
+ value: useMemo(()=>({
42
+ ...props,
43
+ serverRef
44
+ }), [
45
+ props
46
+ ]),
47
+ children: /*#__PURE__*/ jsx(ServerSelectContext.Provider, {
48
+ value: useMemo(()=>({
49
+ server,
50
+ setServerVariables (variables) {
51
+ setServer((prev)=>{
52
+ if (!prev) return null;
53
+ const updated = {
54
+ ...prev,
55
+ variables
56
+ };
57
+ localStorage.setItem('apiBaseUrl', JSON.stringify(updated));
58
+ return updated;
59
+ });
60
+ },
61
+ setServer (value) {
62
+ const obj = props.servers.find((item)=>item.url === value);
63
+ if (!obj) return;
64
+ const result = {
65
+ url: value,
66
+ variables: getDefaultValues(obj)
67
+ };
68
+ localStorage.setItem('apiBaseUrl', JSON.stringify(result));
69
+ setServer(result);
70
+ }
71
+ }), [
72
+ server,
73
+ props.servers
74
+ ]),
75
+ children: children
76
+ })
77
+ });
78
+ }
79
+ function getDefaultValues(server) {
80
+ return Object.fromEntries(Object.entries(server.variables ?? {}).map(([k, v])=>[
81
+ k,
82
+ v.default
83
+ ]));
84
+ }
85
+
86
+ const SchemaContext = /*#__PURE__*/ createContext(undefined);
87
+ function useSchemaContext() {
88
+ const ctx = useContext(SchemaContext);
89
+ if (!ctx) throw new Error('Missing provider');
90
+ return ctx;
91
+ }
92
+
93
+ const APIPlayground = dynamic(()=>import('./index-client-CehDtJk-.js').then(function (n) { return n.i; }).then((mod)=>mod.APIPlayground));
94
+ function Root({ children, baseUrl, className, shikiOptions, servers, ...props }) {
95
+ return /*#__PURE__*/ jsx("div", {
96
+ className: cn('flex flex-col gap-24 text-sm text-fd-muted-foreground', className),
97
+ ...props,
98
+ children: /*#__PURE__*/ jsx(ApiProvider, {
99
+ servers: servers,
100
+ shikiOptions: shikiOptions,
101
+ defaultBaseUrl: baseUrl,
102
+ children: children
103
+ })
104
+ });
105
+ }
106
+
107
+ export { APIPlayground as A, Root as R, SchemaContext as S, useApiContext as a, useServerSelectContext as b, useSchemaContext as u };