fumadocs-openapi 6.0.1 → 6.0.3

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 (155) hide show
  1. package/dist/build-routes.d.ts +15 -0
  2. package/dist/build-routes.d.ts.map +1 -0
  3. package/dist/build-routes.js +38 -0
  4. package/dist/generate-file.d.ts +38 -0
  5. package/dist/generate-file.d.ts.map +1 -0
  6. package/dist/generate-file.js +118 -0
  7. package/dist/generate.d.ts +48 -0
  8. package/dist/generate.d.ts.map +1 -0
  9. package/dist/generate.js +129 -0
  10. package/dist/index.d.ts +4 -274
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +3 -389
  13. package/dist/render/codeblock.d.ts +9 -0
  14. package/dist/render/codeblock.d.ts.map +1 -0
  15. package/dist/render/codeblock.js +13 -0
  16. package/dist/render/heading.d.ts +4 -0
  17. package/dist/render/heading.d.ts.map +1 -0
  18. package/dist/render/heading.js +6 -0
  19. package/dist/render/markdown.d.ts +5 -0
  20. package/dist/render/markdown.d.ts.map +1 -0
  21. package/dist/render/markdown.js +25 -0
  22. package/dist/render/operation.d.ts +17 -0
  23. package/dist/render/operation.d.ts.map +1 -0
  24. package/dist/render/operation.js +230 -0
  25. package/dist/render/playground.d.ts +66 -0
  26. package/dist/render/playground.d.ts.map +1 -0
  27. package/dist/render/playground.js +181 -0
  28. package/dist/render/renderer.d.ts +76 -0
  29. package/dist/render/renderer.d.ts.map +1 -0
  30. package/dist/render/renderer.js +23 -0
  31. package/dist/render/schema.d.ts +29 -0
  32. package/dist/render/schema.d.ts.map +1 -0
  33. package/dist/render/schema.js +151 -0
  34. package/dist/requests/curl.d.ts +3 -0
  35. package/dist/requests/curl.d.ts.map +1 -0
  36. package/dist/requests/curl.js +33 -0
  37. package/dist/requests/go.d.ts +3 -0
  38. package/dist/requests/go.d.ts.map +1 -0
  39. package/dist/requests/go.js +54 -0
  40. package/dist/requests/javascript.d.ts +3 -0
  41. package/dist/requests/javascript.d.ts.map +1 -0
  42. package/dist/requests/javascript.js +49 -0
  43. package/dist/requests/python.d.ts +3 -0
  44. package/dist/requests/python.d.ts.map +1 -0
  45. package/dist/requests/python.js +45 -0
  46. package/dist/scalar/client.d.ts +6 -0
  47. package/dist/scalar/client.d.ts.map +1 -0
  48. package/dist/scalar/client.js +25 -0
  49. package/dist/scalar/index.d.ts +4 -173
  50. package/dist/scalar/index.d.ts.map +1 -0
  51. package/dist/scalar/index.js +4 -11
  52. package/dist/server/api-page.d.ts +33 -0
  53. package/dist/server/api-page.d.ts.map +1 -0
  54. package/dist/server/api-page.js +59 -0
  55. package/dist/server/create-method.d.ts +7 -0
  56. package/dist/server/create-method.d.ts.map +1 -0
  57. package/dist/server/create-method.js +12 -0
  58. package/dist/server/create.d.ts +16 -0
  59. package/dist/server/create.d.ts.map +1 -0
  60. package/dist/server/create.js +11 -0
  61. package/dist/server/index.d.ts +3 -221
  62. package/dist/server/index.d.ts.map +1 -0
  63. package/dist/server/index.js +2 -1493
  64. package/dist/server/proxy.d.ts +8 -0
  65. package/dist/server/proxy.d.ts.map +1 -0
  66. package/dist/server/proxy.js +53 -0
  67. package/dist/server/source-api.d.ts +8 -0
  68. package/dist/server/source-api.d.ts.map +1 -0
  69. package/dist/server/source-api.js +34 -0
  70. package/dist/types.d.ts +60 -0
  71. package/dist/types.d.ts.map +1 -0
  72. package/dist/types.js +1 -0
  73. package/dist/ui/client.d.ts +22 -0
  74. package/dist/ui/client.d.ts.map +1 -0
  75. package/dist/ui/client.js +10 -0
  76. package/dist/ui/components/input.d.ts +6 -0
  77. package/dist/ui/components/input.d.ts.map +1 -0
  78. package/dist/ui/components/input.js +10 -0
  79. package/dist/ui/components/method-label.d.ts +5 -0
  80. package/dist/ui/components/method-label.d.ts.map +1 -0
  81. package/dist/ui/components/method-label.js +33 -0
  82. package/dist/ui/components/select.d.ts +14 -0
  83. package/dist/ui/components/select.d.ts.map +1 -0
  84. package/dist/ui/components/select.js +24 -0
  85. package/dist/ui/components/variants.d.ts +6 -0
  86. package/dist/ui/components/variants.d.ts.map +1 -0
  87. package/dist/ui/components/variants.js +26 -0
  88. package/dist/ui/contexts/api.d.ts +28 -0
  89. package/dist/ui/contexts/api.d.ts.map +1 -0
  90. package/dist/ui/contexts/api.js +74 -0
  91. package/dist/ui/contexts/schema.d.ts +17 -0
  92. package/dist/ui/contexts/schema.d.ts.map +1 -0
  93. package/dist/ui/contexts/schema.js +8 -0
  94. package/dist/ui/index.d.ts +12 -302
  95. package/dist/ui/index.d.ts.map +1 -0
  96. package/dist/ui/index.js +18 -98
  97. package/dist/ui/playground/fetcher.d.ts +34 -0
  98. package/dist/ui/playground/fetcher.d.ts.map +1 -0
  99. package/dist/ui/{fetcher-CsHhplmD.js → playground/fetcher.js} +45 -44
  100. package/dist/ui/playground/get-default-values.d.ts +4 -0
  101. package/dist/ui/playground/get-default-values.d.ts.map +1 -0
  102. package/dist/ui/playground/get-default-values.js +24 -0
  103. package/dist/ui/playground/index.d.ts +44 -0
  104. package/dist/ui/playground/index.d.ts.map +1 -0
  105. package/dist/ui/playground/index.js +187 -0
  106. package/dist/ui/playground/inputs.d.ts +23 -0
  107. package/dist/ui/playground/inputs.d.ts.map +1 -0
  108. package/dist/ui/playground/inputs.js +172 -0
  109. package/dist/ui/playground/resolve.d.ts +6 -0
  110. package/dist/ui/playground/resolve.d.ts.map +1 -0
  111. package/dist/ui/playground/resolve.js +14 -0
  112. package/dist/ui/playground/status-info.d.ts +8 -0
  113. package/dist/ui/playground/status-info.d.ts.map +1 -0
  114. package/dist/ui/playground/status-info.js +40 -0
  115. package/dist/ui/server-select.d.ts +3 -0
  116. package/dist/ui/server-select.d.ts.map +1 -0
  117. package/dist/ui/server-select.js +27 -0
  118. package/dist/utils/combine-schema.d.ts +6 -0
  119. package/dist/utils/combine-schema.d.ts.map +1 -0
  120. package/dist/utils/combine-schema.js +46 -0
  121. package/dist/utils/generate-document.d.ts +20 -0
  122. package/dist/utils/generate-document.d.ts.map +1 -0
  123. package/dist/utils/generate-document.js +82 -0
  124. package/dist/utils/generate-sample.d.ts +33 -0
  125. package/dist/utils/generate-sample.d.ts.map +1 -0
  126. package/dist/utils/generate-sample.js +97 -0
  127. package/dist/utils/get-security.d.ts +8 -0
  128. package/dist/utils/get-security.d.ts.map +1 -0
  129. package/dist/utils/get-security.js +23 -0
  130. package/dist/utils/get-typescript-schema.d.ts +4 -0
  131. package/dist/utils/get-typescript-schema.d.ts.map +1 -0
  132. package/dist/utils/get-typescript-schema.js +18 -0
  133. package/dist/utils/id-to-title.d.ts +2 -0
  134. package/dist/utils/id-to-title.d.ts.map +1 -0
  135. package/dist/utils/id-to-title.js +17 -0
  136. package/dist/utils/input-to-string.d.ts +5 -0
  137. package/dist/utils/input-to-string.d.ts.map +1 -0
  138. package/dist/utils/input-to-string.js +21 -0
  139. package/dist/utils/process-document.d.ts +14 -0
  140. package/dist/utils/process-document.d.ts.map +1 -0
  141. package/dist/utils/process-document.js +32 -0
  142. package/dist/utils/schema.d.ts +9 -0
  143. package/dist/utils/schema.d.ts.map +1 -0
  144. package/dist/utils/schema.js +16 -0
  145. package/dist/utils/server-url.d.ts +2 -0
  146. package/dist/utils/server-url.d.ts.map +1 -0
  147. package/dist/utils/server-url.js +7 -0
  148. package/dist/utils/use-query.d.ts +6 -0
  149. package/dist/utils/use-query.d.ts.map +1 -0
  150. package/dist/utils/use-query.js +22 -0
  151. package/package.json +8 -8
  152. package/dist/scalar/client-client-BXAjVueF.js +0 -93
  153. package/dist/ui/client-client-CYO00OiB.js +0 -107
  154. package/dist/ui/index-client-BUeWwFWK.js +0 -1116
  155. package/dist/ui/server-select-client-Ct_HJ46K.js +0 -86
@@ -0,0 +1,20 @@
1
+ import type { ApiPageProps } from '../server/api-page.js';
2
+ import type { GenerateOptions } from '../generate.js';
3
+ import type { Document, TagObject } from '../types.js';
4
+ import type { NoReference } from '../utils/schema.js';
5
+ export type DocumentContext = {
6
+ type: 'tag';
7
+ tag: TagObject | undefined;
8
+ } | {
9
+ type: 'operation';
10
+ } | {
11
+ type: 'file';
12
+ };
13
+ export declare function generateDocument(options: GenerateOptions & {
14
+ dereferenced: NoReference<Document>;
15
+ page: ApiPageProps;
16
+ title: string;
17
+ description?: string;
18
+ context: DocumentContext;
19
+ }): string;
20
+ //# sourceMappingURL=generate-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-document.d.ts","sourceRoot":"","sources":["../../src/utils/generate-document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAOlD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,SAAS,GAAG,SAAS,CAAC;CAC5B,GACD;IACE,IAAI,EAAE,WAAW,CAAC;CACnB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEN,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,GAAG;IACzB,YAAY,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,eAAe,CAAC;CAC1B,GACA,MAAM,CAkDR"}
@@ -0,0 +1,82 @@
1
+ import { dump } from 'js-yaml';
2
+ import Slugger from 'github-slugger';
3
+ import { idToTitle } from '../utils/id-to-title.js';
4
+ export function generateDocument(options) {
5
+ const { frontmatter, includeDescription = false } = options;
6
+ const out = [];
7
+ const extend = frontmatter?.(options.title, options.description, options.context);
8
+ let meta;
9
+ if (options.page.operations?.length === 1) {
10
+ const operation = options.page.operations[0];
11
+ meta = {
12
+ method: operation.method.toUpperCase(),
13
+ route: operation.path,
14
+ };
15
+ }
16
+ const data = generateStaticData(options.dereferenced, options.page);
17
+ const banner = dump({
18
+ title: options.title,
19
+ description: options.description,
20
+ full: true,
21
+ ...extend,
22
+ _openapi: {
23
+ ...meta,
24
+ ...data,
25
+ ...extend?._openapi,
26
+ },
27
+ }).trim();
28
+ if (banner.length > 0)
29
+ out.push(`---\n${banner}\n---`);
30
+ const imports = options.imports
31
+ ?.map((item) => `import { ${item.names.join(', ')} } from ${JSON.stringify(item.from)};`)
32
+ .join('\n');
33
+ if (imports) {
34
+ out.push(imports);
35
+ }
36
+ if (options.description && includeDescription)
37
+ out.push(options.description);
38
+ out.push(pageContent(options.page));
39
+ return out.join('\n\n');
40
+ }
41
+ function generateStaticData(dereferenced, props) {
42
+ const slugger = new Slugger();
43
+ const toc = [];
44
+ const structuredData = { headings: [], contents: [] };
45
+ for (const item of props.operations ?? []) {
46
+ const operation = dereferenced.paths?.[item.path]?.[item.method];
47
+ if (!operation)
48
+ continue;
49
+ if (props.hasHead && operation.operationId) {
50
+ const title = operation.summary ??
51
+ (operation.operationId ? idToTitle(operation.operationId) : item.path);
52
+ const id = slugger.slug(title);
53
+ toc.push({
54
+ depth: 2,
55
+ title,
56
+ url: `#${id}`,
57
+ });
58
+ structuredData.headings.push({
59
+ content: title,
60
+ id,
61
+ });
62
+ }
63
+ if (operation.description)
64
+ structuredData.contents.push({
65
+ content: operation.description,
66
+ heading: structuredData.headings.at(-1)?.id,
67
+ });
68
+ }
69
+ return { toc, structuredData };
70
+ }
71
+ function pageContent(props) {
72
+ // filter extra properties in props
73
+ const operations = (props.operations ?? []).map((item) => ({
74
+ path: item.path,
75
+ method: item.method,
76
+ }));
77
+ const webhooks = (props.webhooks ?? []).map((item) => ({
78
+ name: item.name,
79
+ method: item.method,
80
+ }));
81
+ return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(operations)}} webhooks={${JSON.stringify(webhooks)}} hasHead={${JSON.stringify(props.hasHead)}} />`;
82
+ }
@@ -0,0 +1,33 @@
1
+ import type { MethodInformation, RenderContext } from '../types.js';
2
+ import { type ParsedSchema } from '../utils/schema.js';
3
+ /**
4
+ * Sample info of endpoint
5
+ */
6
+ export interface EndpointSample {
7
+ /**
8
+ * Request URL, including path and query parameters
9
+ */
10
+ url: string;
11
+ method: string;
12
+ body?: {
13
+ schema: ParsedSchema;
14
+ mediaType: string;
15
+ sample: unknown;
16
+ };
17
+ responses: Record<string, ResponseSample>;
18
+ parameters: ParameterSample[];
19
+ }
20
+ interface ResponseSample {
21
+ mediaType: string;
22
+ sample: unknown;
23
+ schema: ParsedSchema;
24
+ }
25
+ interface ParameterSample {
26
+ name: string;
27
+ in: string;
28
+ schema: ParsedSchema;
29
+ sample: unknown;
30
+ }
31
+ export declare function generateSample(path: string, method: MethodInformation, { baseUrl, schema: { document } }: RenderContext): EndpointSample;
32
+ export {};
33
+ //# sourceMappingURL=generate-sample.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-sample.d.ts","sourceRoot":"","sources":["../../src/utils/generate-sample.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,gBAAgB,CAAC;AAGxB;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,YAAY,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AAED,UAAU,cAAc;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,iBAAiB,EACzB,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,GAC/C,cAAc,CA2GhB"}
@@ -0,0 +1,97 @@
1
+ import { sample } from 'openapi-sampler';
2
+ import { getPreferredType, } from '../utils/schema.js';
3
+ import { getSecurities, getSecurityPrefix } from '../utils/get-security.js';
4
+ export function generateSample(path, method, { baseUrl, schema: { document } }) {
5
+ const params = [];
6
+ const responses = {};
7
+ for (const param of method.parameters ?? []) {
8
+ if (param.schema) {
9
+ params.push({
10
+ name: param.name,
11
+ in: param.in,
12
+ schema: param.schema,
13
+ sample: param.example ?? sample(param.schema),
14
+ });
15
+ }
16
+ else if (param.content) {
17
+ const key = getPreferredType(param.content);
18
+ const content = key ? param.content[key] : undefined;
19
+ if (!key || !content)
20
+ throw new Error(`Cannot find parameter schema for ${param.name} in ${path} ${method.method}`);
21
+ params.push({
22
+ name: param.name,
23
+ in: param.in,
24
+ schema: content.schema ?? {},
25
+ sample: content.example ?? param.example ?? sample(content.schema),
26
+ });
27
+ }
28
+ }
29
+ const requirements = method.security ?? document.security;
30
+ if (requirements && requirements.length > 0) {
31
+ for (const security of getSecurities(requirements[0], document)) {
32
+ const prefix = getSecurityPrefix(security);
33
+ params.push({
34
+ name: security.type === 'apiKey' ? security.name : 'Authorization',
35
+ schema: {
36
+ type: 'string',
37
+ },
38
+ sample: prefix ? `${prefix} <token>` : '<token>',
39
+ in: 'header',
40
+ });
41
+ }
42
+ }
43
+ let bodyOutput;
44
+ if (method.requestBody) {
45
+ const body = method.requestBody.content;
46
+ const type = getPreferredType(body);
47
+ if (!type)
48
+ throw new Error(`Cannot find body schema for ${path} ${method.method}: missing media type`);
49
+ const schema = (type ? body[type].schema : undefined) ?? {};
50
+ bodyOutput = {
51
+ schema,
52
+ mediaType: type,
53
+ sample: body[type].example ?? generateBody(method.method, schema),
54
+ };
55
+ }
56
+ for (const [code, response] of Object.entries(method.responses ?? {})) {
57
+ const content = response.content;
58
+ if (!content)
59
+ continue;
60
+ const mediaType = getPreferredType(content);
61
+ if (!mediaType)
62
+ continue;
63
+ const responseSchema = content[mediaType].schema;
64
+ if (!responseSchema)
65
+ continue;
66
+ responses[code] = {
67
+ mediaType,
68
+ sample: content[mediaType].example ??
69
+ generateBody(method.method, responseSchema),
70
+ schema: responseSchema,
71
+ };
72
+ }
73
+ let pathWithParameters = path;
74
+ const queryParams = new URLSearchParams();
75
+ for (const param of params) {
76
+ const value = generateBody(method.method, param.schema);
77
+ if (param.in === 'query')
78
+ queryParams.append(param.name, String(value));
79
+ if (param.in === 'path')
80
+ pathWithParameters = pathWithParameters.replace(`{${param.name}}`, String(value));
81
+ }
82
+ if (queryParams.size > 0)
83
+ pathWithParameters = `${pathWithParameters}?${queryParams.toString()}`;
84
+ return {
85
+ url: new URL(`${baseUrl}${pathWithParameters}`).toString(),
86
+ body: bodyOutput,
87
+ responses,
88
+ method: method.method,
89
+ parameters: params,
90
+ };
91
+ }
92
+ function generateBody(method, schema) {
93
+ return sample(schema, {
94
+ skipReadOnly: method !== 'GET',
95
+ skipWriteOnly: method === 'GET',
96
+ });
97
+ }
@@ -0,0 +1,8 @@
1
+ import type { Document, SecurityRequirementObject, SecuritySchemeObject } from '../types.js';
2
+ import { type NoReference } from '../utils/schema.js';
3
+ export type Security = SecuritySchemeObject & {
4
+ scopes: string[];
5
+ };
6
+ export declare function getSecurities(requirement: NoReference<SecurityRequirementObject>, document: NoReference<Document>): Security[];
7
+ export declare function getSecurityPrefix(security: Security): string | undefined;
8
+ //# sourceMappingURL=get-security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-security.d.ts","sourceRoot":"","sources":["../../src/utils/get-security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,QAAQ,EACR,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,MAAM,QAAQ,GAAG,oBAAoB,GAAG;IAC5C,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAgB,aAAa,CAC3B,WAAW,EAAE,WAAW,CAAC,yBAAyB,CAAC,EACnD,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,GAC9B,QAAQ,EAAE,CAeZ;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS,CAQxE"}
@@ -0,0 +1,23 @@
1
+ export function getSecurities(requirement, document) {
2
+ const results = [];
3
+ const schemas = document.components?.securitySchemes ?? {};
4
+ for (const [key, scopes] of Object.entries(requirement)) {
5
+ if (!(key in schemas))
6
+ return [];
7
+ const schema = schemas[key];
8
+ results.push({
9
+ ...schema,
10
+ scopes,
11
+ });
12
+ }
13
+ return results;
14
+ }
15
+ export function getSecurityPrefix(security) {
16
+ if (security.type === 'http')
17
+ return {
18
+ basic: 'Basic',
19
+ bearer: 'Bearer',
20
+ }[security.scheme];
21
+ if (security.type === 'oauth2')
22
+ return 'Bearer';
23
+ }
@@ -0,0 +1,4 @@
1
+ import type { EndpointSample } from '../utils/generate-sample.js';
2
+ import { DereferenceMap } from '../types.js';
3
+ export declare function getTypescriptSchema(endpoint: EndpointSample, code: string, dereferenceMap: DereferenceMap): Promise<string | undefined>;
4
+ //# sourceMappingURL=get-typescript-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-typescript-schema.d.ts","sourceRoot":"","sources":["../../src/utils/get-typescript-schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,GAC7B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAmB7B"}
@@ -0,0 +1,18 @@
1
+ import { compile } from '@fumari/json-schema-to-typescript';
2
+ export async function getTypescriptSchema(endpoint, code, dereferenceMap) {
3
+ if (code in endpoint.responses) {
4
+ return compile(
5
+ // re-running on the same schema results in error
6
+ // because it uses `defineProperty` to define internal references
7
+ // we clone the schema to fix this problem
8
+ // @ts-expect-error any types
9
+ endpoint.responses[code].schema, 'Response', {
10
+ $refOptions: false,
11
+ schemaToId: dereferenceMap,
12
+ bannerComment: '',
13
+ additionalProperties: false,
14
+ format: true,
15
+ enableConstEnums: false,
16
+ });
17
+ }
18
+ }
@@ -0,0 +1,2 @@
1
+ export declare function idToTitle(id: string): string;
2
+ //# sourceMappingURL=id-to-title.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-to-title.d.ts","sourceRoot":"","sources":["../../src/utils/id-to-title.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAa5C"}
@@ -0,0 +1,17 @@
1
+ export function idToTitle(id) {
2
+ let result = [];
3
+ for (const c of id) {
4
+ if (result.length === 0)
5
+ result.push(c.toLocaleUpperCase());
6
+ // ignore the other parts surrounded with '.', like 'migrations.dev' -> 'dev'
7
+ else if (c === '.')
8
+ result = [];
9
+ else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ')
10
+ result.push(' ', c);
11
+ else if (c === '-')
12
+ result.push(' ');
13
+ else
14
+ result.push(c);
15
+ }
16
+ return result.join('');
17
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Convert input value to hardcoded string (with quotes)
3
+ */
4
+ export declare function inputToString(value: unknown, mediaType?: string, multiLine?: 'single-quote' | 'backtick' | 'none'): string;
5
+ //# sourceMappingURL=input-to-string.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-to-string.d.ts","sourceRoot":"","sources":["../../src/utils/input-to-string.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,SAAS,SAAqB,EAC9B,SAAS,GAAE,cAAc,GAAG,UAAU,GAAG,MAAe,GACvD,MAAM,CAqBR"}
@@ -0,0 +1,21 @@
1
+ import { js2xml } from 'xml-js';
2
+ /**
3
+ * Convert input value to hardcoded string (with quotes)
4
+ */
5
+ export function inputToString(value, mediaType = 'application/json', multiLine = 'none') {
6
+ const getStr = (v) => {
7
+ if (multiLine === 'none')
8
+ return JSON.stringify(v);
9
+ const delimit = multiLine === 'backtick' ? `\`` : `'`;
10
+ return `${delimit}${v.replaceAll(delimit, `\\${delimit}`)}${delimit}`;
11
+ };
12
+ if (typeof value === 'string')
13
+ return getStr(value);
14
+ if (mediaType === 'application/json' || mediaType === 'multipart/form-data') {
15
+ return getStr(JSON.stringify(value, null, 2));
16
+ }
17
+ if (mediaType === 'application/xml') {
18
+ return getStr(js2xml(value, { compact: true, spaces: 2 }));
19
+ }
20
+ throw new Error(`Unsupported media type: ${mediaType}`);
21
+ }
@@ -0,0 +1,14 @@
1
+ import type { DereferenceMap, Document } from '../types.js';
2
+ import type { NoReference } from '../utils/schema.js';
3
+ import type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';
4
+ export type DocumentInput = string | OpenAPIV3_1.Document | OpenAPIV3.Document;
5
+ export type ProcessedDocument = {
6
+ document: NoReference<Document>;
7
+ dereferenceMap: DereferenceMap;
8
+ downloaded: Document;
9
+ };
10
+ /**
11
+ * process & reference input document to a Fumadocs OpenAPI compatible format
12
+ */
13
+ export declare function processDocument(document: DocumentInput, disableCache?: boolean): Promise<ProcessedDocument>;
14
+ //# sourceMappingURL=process-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-document.d.ts","sourceRoot":"","sources":["../../src/utils/process-document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK5D,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,WAAW,CAAC,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;AAE/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,QAAQ,CAAC;CACtB,CAAC;AAIF;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,aAAa,EACvB,YAAY,UAAQ,GACnB,OAAO,CAAC,iBAAiB,CAAC,CA8B5B"}
@@ -0,0 +1,32 @@
1
+ import { load, dereference, upgrade } from '@scalar/openapi-parser';
2
+ import { fetchUrls } from '@scalar/openapi-parser/plugins/fetch-urls';
3
+ import { readFiles } from '@scalar/openapi-parser/plugins/read-files';
4
+ const cache = new Map();
5
+ /**
6
+ * process & reference input document to a Fumadocs OpenAPI compatible format
7
+ */
8
+ export async function processDocument(document, disableCache = false) {
9
+ const cached = !disableCache && typeof document === 'string' ? cache.get(document) : null;
10
+ if (cached)
11
+ return cached;
12
+ const dereferenceMap = new Map();
13
+ const loaded = await load(document, {
14
+ plugins: [readFiles(), fetchUrls()],
15
+ });
16
+ // upgrade
17
+ loaded.specification = upgrade(loaded.specification).specification;
18
+ const { schema: dereferenced } = await dereference(loaded.filesystem, {
19
+ onDereference({ ref, schema }) {
20
+ dereferenceMap.set(schema, ref);
21
+ },
22
+ });
23
+ const processed = {
24
+ document: dereferenced,
25
+ dereferenceMap,
26
+ downloaded: loaded.specification,
27
+ };
28
+ if (!disableCache && typeof document === 'string') {
29
+ cache.set(document, processed);
30
+ }
31
+ return processed;
32
+ }
@@ -0,0 +1,9 @@
1
+ import type { ReferenceObject } from '../types.js';
2
+ import type { OpenAPIV3_1 } from 'openapi-types';
3
+ export type NoReference<T> = T extends (infer I)[] ? NoReference<I>[] : T extends ReferenceObject ? Exclude<T, ReferenceObject> : T extends object ? {
4
+ [K in keyof T]: NoReference<T[K]>;
5
+ } : T;
6
+ export type ParsedSchema = OpenAPIV3_1.SchemaObject;
7
+ export declare function getPreferredType<B extends Record<string, unknown>>(body: B): keyof B | undefined;
8
+ export declare function isNullable(schema: NoReference<ParsedSchema>, includeOneOf?: boolean): boolean;
9
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/utils/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAC9C,WAAW,CAAC,CAAC,CAAC,EAAE,GAChB,CAAC,SAAS,eAAe,GACvB,OAAO,CAAC,CAAC,EAAE,eAAe,CAAC,GAC3B,CAAC,SAAS,MAAM,GACd;KACG,CAAC,IAAI,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAClC,GACD,CAAC,CAAC;AAEV,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC;AAEpD,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,IAAI,EAAE,CAAC,GACN,MAAM,CAAC,GAAG,SAAS,CAIrB;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,EACjC,YAAY,UAAO,GAClB,OAAO,CAQT"}
@@ -0,0 +1,16 @@
1
+ export function getPreferredType(body) {
2
+ if ('application/json' in body)
3
+ return 'application/json';
4
+ return Object.keys(body)[0];
5
+ }
6
+ export function isNullable(schema, includeOneOf = true) {
7
+ if (Array.isArray(schema.type) && schema.type.includes('null'))
8
+ return true;
9
+ if (includeOneOf && (schema.anyOf || schema.oneOf)) {
10
+ if (schema.anyOf?.some((item) => isNullable(item)))
11
+ return true;
12
+ if (schema.oneOf?.some((item) => isNullable(item)))
13
+ return true;
14
+ }
15
+ return false;
16
+ }
@@ -0,0 +1,2 @@
1
+ export declare function getUrl(url: string, variables: Record<string, string>): string;
2
+ //# sourceMappingURL=server-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-url.d.ts","sourceRoot":"","sources":["../../src/utils/server-url.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAQ7E"}
@@ -0,0 +1,7 @@
1
+ export function getUrl(url, variables) {
2
+ let out = url;
3
+ for (const [key, value] of Object.entries(variables)) {
4
+ out = out.replaceAll(`{${key}}`, value);
5
+ }
6
+ return out;
7
+ }
@@ -0,0 +1,6 @@
1
+ export declare function useQuery<I, T>(fn: (input: I) => Promise<T>): {
2
+ start: (input: I) => void;
3
+ data?: T;
4
+ isLoading: boolean;
5
+ };
6
+ //# sourceMappingURL=use-query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-query.d.ts","sourceRoot":"","sources":["../../src/utils/use-query.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAC3B,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAC3B;IACD,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;CACpB,CAyBA"}
@@ -0,0 +1,22 @@
1
+ import { useMemo, useState } from 'react';
2
+ export function useQuery(fn) {
3
+ const [loading, setLoading] = useState(false);
4
+ const [data, setData] = useState();
5
+ return useMemo(() => ({
6
+ isLoading: loading,
7
+ data,
8
+ start(input) {
9
+ setLoading(true);
10
+ void fn(input)
11
+ .then((res) => {
12
+ setData(res);
13
+ })
14
+ .catch(() => {
15
+ setData(undefined);
16
+ })
17
+ .finally(() => {
18
+ setLoading(false);
19
+ });
20
+ },
21
+ }), [data, fn, loading]);
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fumadocs-openapi",
3
- "version": "6.0.1",
3
+ "version": "6.0.3",
4
4
  "description": "Generate MDX docs for your OpenAPI spec",
5
5
  "keywords": [
6
6
  "NextJs",
@@ -45,6 +45,7 @@
45
45
  "github-slugger": "^2.0.0",
46
46
  "hast-util-to-jsx-runtime": "^2.3.2",
47
47
  "js-yaml": "^4.1.0",
48
+ "lucide-react": "^0.474.0",
48
49
  "next-themes": "^0.4.4",
49
50
  "openapi-sampler": "^1.6.1",
50
51
  "react-hook-form": "^7.54.2",
@@ -52,8 +53,8 @@
52
53
  "remark-rehype": "^11.1.1",
53
54
  "shiki": "^2.2.0",
54
55
  "xml-js": "^1.6.11",
55
- "fumadocs-core": "15.0.0",
56
- "fumadocs-ui": "15.0.0"
56
+ "fumadocs-core": "15.0.2",
57
+ "fumadocs-ui": "15.0.2"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@scalar/api-client-react": "^1.1.22",
@@ -61,11 +62,10 @@
61
62
  "@types/node": "22.13.0",
62
63
  "@types/openapi-sampler": "^1.0.3",
63
64
  "@types/react": "^19.0.8",
64
- "bunchee": "^6.3.2",
65
- "lucide-react": "^0.474.0",
66
65
  "next": "15.1.6",
67
66
  "openapi-types": "^12.1.3",
68
- "tailwindcss": "^4.0.2",
67
+ "tailwindcss": "^4.0.3",
68
+ "tsc-alias": "^1.8.10",
69
69
  "eslint-config-custom": "0.0.0",
70
70
  "tsconfig": "0.0.0"
71
71
  },
@@ -84,9 +84,9 @@
84
84
  "access": "public"
85
85
  },
86
86
  "scripts": {
87
- "build": "bunchee",
87
+ "build": "tsc --project tsconfig.build.json && tsc-alias -p tsconfig.build.json",
88
88
  "clean": "rimraf dist",
89
- "dev": "bunchee --watch",
89
+ "dev": "concurrently \"tsc -w --project tsconfig.build.json\" \"tsc-alias -w -p tsconfig.build.json\"",
90
90
  "lint": "eslint .",
91
91
  "types:check": "tsc --noEmit"
92
92
  }
@@ -1,93 +0,0 @@
1
- 'use client';
2
- import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { cn } from 'fumadocs-ui/components/api';
4
- import { buttonVariants } from 'fumadocs-ui/components/ui/button';
5
- import { ApiClientModalProvider, useApiClientModal } from '@scalar/api-client-react';
6
- import { cva } from 'class-variance-authority';
7
- import { useTheme } from 'next-themes';
8
- import { useState, useEffect } from 'react';
9
-
10
- const variants = cva('font-mono font-medium', {
11
- variants: {
12
- color: {
13
- green: 'text-green-600 dark:text-green-400',
14
- yellow: 'text-yellow-600 dark:text-yellow-400',
15
- red: 'text-red-600 dark:text-red-400',
16
- blue: 'text-blue-600 dark:text-blue-400',
17
- orange: 'text-orange-600 dark:text-orange-400'
18
- }
19
- }
20
- });
21
- function getBadgeColor(method) {
22
- switch(method.toUpperCase()){
23
- case 'PUT':
24
- return 'yellow';
25
- case 'PATCH':
26
- return 'orange';
27
- case 'POST':
28
- return 'blue';
29
- case 'DELETE':
30
- return 'red';
31
- default:
32
- return 'green';
33
- }
34
- }
35
- function MethodLabel({ children, ...props }) {
36
- return /*#__PURE__*/ jsx("span", {
37
- ...props,
38
- className: cn(variants({
39
- color: getBadgeColor(children)
40
- }), props.className),
41
- children: children.toUpperCase()
42
- });
43
- }
44
-
45
- function ScalarPlayground({ path, method, spec }) {
46
- const { resolvedTheme } = useTheme();
47
- const [mounted, setMounted] = useState(false);
48
- useEffect(()=>{
49
- setMounted(true);
50
- }, []);
51
- return /*#__PURE__*/ jsxs("div", {
52
- className: cn('flex flex-row items-center gap-2.5 p-3 rounded-xl border bg-fd-card text-fd-card-foreground not-prose', mounted ? `${resolvedTheme}-mode` : null),
53
- children: [
54
- /*#__PURE__*/ jsx(MethodLabel, {
55
- className: "text-xs",
56
- children: method
57
- }),
58
- /*#__PURE__*/ jsx("code", {
59
- className: "flex-1 overflow-auto text-nowrap text-[13px] text-fd-muted-foreground",
60
- children: path
61
- }),
62
- /*#__PURE__*/ jsx(ApiClientModalProvider, {
63
- configuration: {
64
- themeId: 'moon',
65
- spec: {
66
- content: spec
67
- }
68
- },
69
- children: /*#__PURE__*/ jsx(Trigger, {
70
- path: path,
71
- method: method
72
- })
73
- })
74
- ]
75
- });
76
- }
77
- function Trigger({ path, method }) {
78
- const client = useApiClientModal();
79
- return /*#__PURE__*/ jsx("button", {
80
- type: "submit",
81
- className: cn(buttonVariants({
82
- color: 'primary',
83
- size: 'sm'
84
- }), 'px-3 py-1.5'),
85
- onClick: ()=>client?.open({
86
- path,
87
- method: method
88
- }),
89
- children: "Test"
90
- });
91
- }
92
-
93
- export { ScalarPlayground as default };