fumadocs-openapi 10.4.1 → 10.6.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/css/generated/shared.css +34 -22
- package/dist/generate-file.d.ts +21 -3
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js +74 -28
- package/dist/generate-file.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/playground/client.d.ts +27 -7
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +51 -44
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/components/inputs.js +1 -1
- package/dist/playground/components/inputs.js.map +1 -1
- package/dist/playground/components/server-select.js +3 -4
- package/dist/playground/components/server-select.js.map +1 -1
- package/dist/playground/index.d.ts +1 -1
- package/dist/playground/index.d.ts.map +1 -1
- package/dist/playground/index.js +2 -2
- package/dist/playground/index.js.map +1 -1
- package/dist/playground/schema.d.ts +0 -1
- package/dist/playground/schema.d.ts.map +1 -1
- package/dist/playground/schema.js +11 -13
- package/dist/playground/schema.js.map +1 -1
- package/dist/requests/generators/python.d.ts +2 -1
- package/dist/requests/generators/python.d.ts.map +1 -1
- package/dist/requests/generators/python.js +13 -2
- package/dist/requests/generators/python.js.map +1 -1
- package/dist/requests/media/adapter.js +1 -1
- package/dist/requests/string-utils.js +1 -1
- package/dist/scalar/index.d.ts +2 -1
- package/dist/scalar/index.d.ts.map +1 -1
- package/dist/server/create.d.ts +2 -0
- package/dist/server/create.d.ts.map +1 -1
- package/dist/server/create.js +11 -8
- package/dist/server/create.js.map +1 -1
- package/dist/server/source-api.d.ts +9 -3
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/server/source-api.js +65 -6
- package/dist/server/source-api.js.map +1 -1
- package/dist/types.d.ts +2 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/api-page.d.ts +2 -2
- package/dist/ui/api-page.d.ts.map +1 -1
- package/dist/ui/api-page.js +4 -6
- package/dist/ui/api-page.js.map +1 -1
- package/dist/ui/base.d.ts +20 -16
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +18 -9
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/{full.client.js → client/full.js} +3 -3
- package/dist/ui/client/full.js.map +1 -0
- package/dist/ui/client/index.d.ts +1 -1
- package/dist/ui/client/index.js.map +1 -1
- package/dist/ui/client/storage-key.js.map +1 -1
- package/dist/ui/components/server-tab.js +43 -0
- package/dist/ui/components/server-tab.js.map +1 -0
- package/dist/ui/contexts/api.js +18 -35
- package/dist/ui/contexts/api.js.map +1 -1
- package/dist/ui/create-client.d.ts +26 -0
- package/dist/ui/create-client.d.ts.map +1 -0
- package/dist/ui/create-client.js +132 -0
- package/dist/ui/create-client.js.map +1 -0
- package/dist/ui/index.d.ts +10 -2
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +21 -1
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/operation/client.js +44 -36
- package/dist/ui/operation/client.js.map +1 -1
- package/dist/ui/operation/{request-tabs.d.ts → get-example-requests.d.ts} +2 -3
- package/dist/ui/operation/get-example-requests.d.ts.map +1 -0
- package/dist/ui/operation/get-example-requests.js +83 -0
- package/dist/ui/operation/get-example-requests.js.map +1 -0
- package/dist/ui/operation/index.js +101 -63
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/request-tabs.js +3 -81
- package/dist/ui/operation/request-tabs.js.map +1 -1
- package/dist/ui/operation/response-tabs.d.ts +1 -1
- package/dist/ui/operation/response-tabs.js +57 -54
- package/dist/ui/operation/response-tabs.js.map +1 -1
- package/dist/ui/operation/usage-tabs/client.js +7 -48
- package/dist/ui/operation/usage-tabs/client.js.map +1 -1
- package/dist/ui/operation/usage-tabs/index.js +14 -10
- package/dist/ui/operation/usage-tabs/index.js.map +1 -1
- package/dist/ui/operation/usage-tabs/lazy.js +1 -2
- package/dist/ui/operation/usage-tabs/lazy.js.map +1 -1
- package/dist/ui/schema/client.d.ts +1 -0
- package/dist/ui/schema/client.d.ts.map +1 -1
- package/dist/ui/schema/index.d.ts +2 -1
- package/dist/ui/schema/index.d.ts.map +1 -1
- package/dist/ui/schema/index.js +4 -2
- package/dist/ui/schema/index.js.map +1 -1
- package/dist/utils/pages/builder.d.ts +10 -11
- package/dist/utils/pages/builder.d.ts.map +1 -1
- package/dist/utils/pages/builder.js +30 -31
- package/dist/utils/pages/builder.js.map +1 -1
- package/dist/utils/pages/preset-auto.d.ts +6 -5
- package/dist/utils/pages/preset-auto.d.ts.map +1 -1
- package/dist/utils/pages/preset-auto.js +97 -35
- package/dist/utils/pages/preset-auto.js.map +1 -1
- package/dist/utils/pages/to-text.d.ts.map +1 -1
- package/dist/utils/pages/to-text.js +4 -12
- package/dist/utils/pages/to-text.js.map +1 -1
- package/dist/utils/process-document.d.ts +1 -1
- package/dist/utils/process-document.js +1 -32
- package/dist/utils/process-document.js.map +1 -1
- package/dist/utils/schema/dereference.js +37 -0
- package/dist/utils/schema/dereference.js.map +1 -0
- package/dist/utils/{schema.d.ts → schema/index.d.ts} +3 -3
- package/dist/utils/schema/index.d.ts.map +1 -0
- package/dist/utils/{schema.js → schema/index.js} +3 -3
- package/dist/utils/schema/index.js.map +1 -0
- package/dist/utils/schema/resolve-ref.js +21 -0
- package/dist/utils/schema/resolve-ref.js.map +1 -0
- package/dist/utils/{schema-to-string.js → schema/to-string.js} +2 -2
- package/dist/utils/schema/to-string.js.map +1 -0
- package/package.json +10 -9
- package/dist/requests/to-python-object.js +0 -17
- package/dist/requests/to-python-object.js.map +0 -1
- package/dist/ui/full.client.js.map +0 -1
- package/dist/ui/full.d.ts +0 -11
- package/dist/ui/full.d.ts.map +0 -1
- package/dist/ui/full.js +0 -36
- package/dist/ui/full.js.map +0 -1
- package/dist/ui/operation/request-tabs.d.ts.map +0 -1
- package/dist/utils/pages/to-body.js +0 -22
- package/dist/utils/pages/to-body.js.map +0 -1
- package/dist/utils/schema-to-string.js.map +0 -1
- package/dist/utils/schema.d.ts.map +0 -1
- package/dist/utils/schema.js.map +0 -1
- /package/dist/utils/{schema-to-string.d.ts → schema/to-string.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { idToTitle } from "../id-to-title.js";
|
|
2
|
-
import { getTagDisplayName, methodKeys } from "../schema.js";
|
|
2
|
+
import { getTagDisplayName, methodKeys } from "../schema/index.js";
|
|
3
3
|
//#region src/utils/pages/builder.ts
|
|
4
4
|
async function fromServer(server, config) {
|
|
5
5
|
const schemas = await server.getSchemas();
|
|
@@ -19,7 +19,35 @@ function fromSchema(schemaId, processed, config) {
|
|
|
19
19
|
create(entry) {
|
|
20
20
|
files.push(entry);
|
|
21
21
|
},
|
|
22
|
-
extract
|
|
22
|
+
extract() {
|
|
23
|
+
const result = {
|
|
24
|
+
webhooks: [],
|
|
25
|
+
operations: []
|
|
26
|
+
};
|
|
27
|
+
for (const [path, pathItem] of Object.entries(dereferenced.paths ?? {})) {
|
|
28
|
+
if (!pathItem) continue;
|
|
29
|
+
for (const methodKey of methodKeys) {
|
|
30
|
+
if (!pathItem[methodKey]) continue;
|
|
31
|
+
result.operations.push({
|
|
32
|
+
method: methodKey,
|
|
33
|
+
path,
|
|
34
|
+
tags: pathItem[methodKey]?.tags
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const [name, pathItem] of Object.entries(dereferenced.webhooks ?? {})) {
|
|
39
|
+
if (!pathItem) continue;
|
|
40
|
+
for (const methodKey of methodKeys) {
|
|
41
|
+
if (!pathItem[methodKey]) continue;
|
|
42
|
+
result.webhooks.push({
|
|
43
|
+
method: methodKey,
|
|
44
|
+
name,
|
|
45
|
+
tags: pathItem[methodKey]?.tags
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
},
|
|
23
51
|
routePathToFilePath(path) {
|
|
24
52
|
return path.toLowerCase().replaceAll(".", "-").split("/").flatMap((v) => {
|
|
25
53
|
if (v.startsWith("{") && v.endsWith("}")) return v.slice(1, -1);
|
|
@@ -69,35 +97,6 @@ function fromSchema(schemaId, processed, config) {
|
|
|
69
97
|
});
|
|
70
98
|
return files;
|
|
71
99
|
}
|
|
72
|
-
function extractInfo(document) {
|
|
73
|
-
const result = {
|
|
74
|
-
webhooks: [],
|
|
75
|
-
operations: []
|
|
76
|
-
};
|
|
77
|
-
for (const [path, pathItem] of Object.entries(document.paths ?? {})) {
|
|
78
|
-
if (!pathItem) continue;
|
|
79
|
-
for (const methodKey of methodKeys) {
|
|
80
|
-
if (!pathItem[methodKey]) continue;
|
|
81
|
-
result.operations.push({
|
|
82
|
-
method: methodKey,
|
|
83
|
-
path,
|
|
84
|
-
tags: pathItem[methodKey]?.tags
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
for (const [name, pathItem] of Object.entries(document.webhooks ?? {})) {
|
|
89
|
-
if (!pathItem) continue;
|
|
90
|
-
for (const methodKey of methodKeys) {
|
|
91
|
-
if (!pathItem[methodKey]) continue;
|
|
92
|
-
result.webhooks.push({
|
|
93
|
-
method: methodKey,
|
|
94
|
-
name,
|
|
95
|
-
tags: pathItem[methodKey]?.tags
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return result;
|
|
100
|
-
}
|
|
101
100
|
//#endregion
|
|
102
101
|
export { fromSchema, fromServer };
|
|
103
102
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","names":[],"sources":["../../../src/utils/pages/builder.ts"],"sourcesContent":["import type { ProcessedDocument } from '@/utils/process-document';\nimport type { OpenAPIServer } from '@/server';\nimport type { OperationItem, WebhookItem } from '@/ui/api-page';\nimport type {
|
|
1
|
+
{"version":3,"file":"builder.js","names":[],"sources":["../../../src/utils/pages/builder.ts"],"sourcesContent":["import type { ProcessedDocument } from '@/utils/process-document';\nimport type { OpenAPIServer } from '@/server';\nimport type { OperationItem, WebhookItem } from '@/ui/api-page';\nimport type { OperationObject, PathItemObject, TagObject } from '@/types';\nimport { getTagDisplayName, methodKeys, type NoReference } from '@/utils/schema';\nimport { idToTitle } from '@/utils/id-to-title';\n\ninterface BaseEntry {\n path: string;\n schemaId: string;\n info: {\n title: string;\n description?: string;\n };\n}\n\nexport interface OperationOutput extends BaseEntry {\n type: 'operation';\n item: OperationItem;\n}\n\nexport interface WebhookOutput extends BaseEntry {\n type: 'webhook';\n item: WebhookItem;\n}\n\nexport interface PageOutput extends BaseEntry {\n type: 'page';\n operations: OperationItem[];\n webhooks: WebhookItem[];\n /** tag info if the page is generated from a tag. */\n tag?: TagObject;\n}\n\nexport interface OutputGroup extends BaseEntry {\n type: 'group';\n entries: OutputEntry[];\n /** tag info if the group is generated from a tag. */\n tag?: TagObject;\n}\n\nexport type OutputEntry = PageOutput | OperationOutput | WebhookOutput | OutputGroup;\n\nexport interface PagesBuilderConfig {\n toPages: (builder: PagesBuilder) => void;\n}\n\nexport interface PagesBuilder {\n /**\n * the input ID in OpenAPI server\n */\n id: string;\n document: ProcessedDocument;\n /**\n * add output entry.\n */\n create: (entry: OutputEntry) => void;\n\n /**\n * get file path from operation path, useful for generating output paths.\n */\n routePathToFilePath: (path: string) => string;\n\n /**\n * Extract useful info for rendering\n */\n extract: () => ExtractedInfo;\n fromExtractedWebhook: (item: WebhookItem) =>\n | {\n get displayName(): string;\n pathItem: NoReference<PathItemObject>;\n operation: NoReference<OperationObject>;\n }\n | undefined;\n fromExtractedOperation: (item: OperationItem) =>\n | {\n get displayName(): string;\n pathItem: NoReference<PathItemObject>;\n operation: NoReference<OperationObject>;\n }\n | undefined;\n fromTag: (tag: TagObject) => {\n get displayName(): string;\n };\n fromTagName: (tag: string) =>\n | {\n info: TagObject;\n get displayName(): string;\n }\n | undefined;\n}\n\ninterface ExtractedInfo {\n webhooks: (WebhookItem & { tags?: string[] })[];\n operations: (OperationItem & {\n tags?: string[];\n })[];\n}\n\nexport async function fromServer(\n server: OpenAPIServer,\n config: PagesBuilderConfig,\n): Promise<Record<string, OutputEntry[]>> {\n const schemas = await server.getSchemas();\n const generated: Record<string, OutputEntry[]> = {};\n\n const entries = Object.entries(schemas);\n if (entries.length === 0) {\n throw new Error('No input files found.');\n }\n\n for (const [id, schema] of entries) {\n generated[id] = fromSchema(id, schema, config);\n }\n\n return generated;\n}\n\nexport function fromSchema(\n schemaId: string,\n processed: ProcessedDocument,\n config: PagesBuilderConfig,\n): OutputEntry[] {\n const files: OutputEntry[] = [];\n const { toPages } = config;\n const { dereferenced } = processed;\n\n toPages({\n id: schemaId,\n document: processed,\n create(entry) {\n files.push(entry);\n },\n extract() {\n const result: ExtractedInfo = { webhooks: [], operations: [] };\n\n for (const [path, pathItem] of Object.entries(dereferenced.paths ?? {})) {\n if (!pathItem) continue;\n\n for (const methodKey of methodKeys) {\n if (!pathItem[methodKey]) continue;\n\n result.operations.push({\n method: methodKey,\n path,\n tags: pathItem[methodKey]?.tags,\n });\n }\n }\n\n for (const [name, pathItem] of Object.entries(dereferenced.webhooks ?? {})) {\n if (!pathItem) continue;\n\n for (const methodKey of methodKeys) {\n if (!pathItem[methodKey]) continue;\n\n result.webhooks.push({\n method: methodKey,\n name,\n tags: pathItem[methodKey]?.tags,\n });\n }\n }\n\n return result;\n },\n routePathToFilePath(path) {\n return path\n .toLowerCase()\n .replaceAll('.', '-')\n .split('/')\n .flatMap((v) => {\n if (v.startsWith('{') && v.endsWith('}')) return v.slice(1, -1);\n if (v.length === 0) return [];\n return v;\n })\n .join('/');\n },\n fromExtractedWebhook(item) {\n const pathItem = dereferenced.webhooks?.[item.name];\n if (!pathItem) return;\n const operation = pathItem?.[item.method];\n if (!operation) return;\n return {\n pathItem,\n operation,\n get displayName() {\n return operation.summary || pathItem.summary || idToTitle(item.name);\n },\n };\n },\n fromExtractedOperation(item) {\n const pathItem = dereferenced.paths?.[item.path];\n if (!pathItem) return;\n const operation = pathItem?.[item.method];\n if (!operation) return;\n return {\n pathItem,\n operation,\n get displayName() {\n return (\n operation.summary ||\n pathItem.summary ||\n (operation.operationId ? idToTitle(operation.operationId) : item.path)\n );\n },\n };\n },\n fromTag(tag) {\n return {\n get displayName() {\n return getTagDisplayName(tag);\n },\n };\n },\n fromTagName(name) {\n const tag = dereferenced.tags?.find((item) => item.name === name);\n if (!tag) return;\n\n return {\n info: tag,\n ...this.fromTag(tag),\n };\n },\n });\n\n return files;\n}\n"],"mappings":";;;AAmGA,eAAsB,WACpB,QACA,QACwC;CACxC,MAAM,UAAU,MAAM,OAAO,YAAY;CACzC,MAAM,YAA2C,EAAE;CAEnD,MAAM,UAAU,OAAO,QAAQ,QAAQ;AACvC,KAAI,QAAQ,WAAW,EACrB,OAAM,IAAI,MAAM,wBAAwB;AAG1C,MAAK,MAAM,CAAC,IAAI,WAAW,QACzB,WAAU,MAAM,WAAW,IAAI,QAAQ,OAAO;AAGhD,QAAO;;AAGT,SAAgB,WACd,UACA,WACA,QACe;CACf,MAAM,QAAuB,EAAE;CAC/B,MAAM,EAAE,YAAY;CACpB,MAAM,EAAE,iBAAiB;AAEzB,SAAQ;EACN,IAAI;EACJ,UAAU;EACV,OAAO,OAAO;AACZ,SAAM,KAAK,MAAM;;EAEnB,UAAU;GACR,MAAM,SAAwB;IAAE,UAAU,EAAE;IAAE,YAAY,EAAE;IAAE;AAE9D,QAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,aAAa,SAAS,EAAE,CAAC,EAAE;AACvE,QAAI,CAAC,SAAU;AAEf,SAAK,MAAM,aAAa,YAAY;AAClC,SAAI,CAAC,SAAS,WAAY;AAE1B,YAAO,WAAW,KAAK;MACrB,QAAQ;MACR;MACA,MAAM,SAAS,YAAY;MAC5B,CAAC;;;AAIN,QAAK,MAAM,CAAC,MAAM,aAAa,OAAO,QAAQ,aAAa,YAAY,EAAE,CAAC,EAAE;AAC1E,QAAI,CAAC,SAAU;AAEf,SAAK,MAAM,aAAa,YAAY;AAClC,SAAI,CAAC,SAAS,WAAY;AAE1B,YAAO,SAAS,KAAK;MACnB,QAAQ;MACR;MACA,MAAM,SAAS,YAAY;MAC5B,CAAC;;;AAIN,UAAO;;EAET,oBAAoB,MAAM;AACxB,UAAO,KACJ,aAAa,CACb,WAAW,KAAK,IAAI,CACpB,MAAM,IAAI,CACV,SAAS,MAAM;AACd,QAAI,EAAE,WAAW,IAAI,IAAI,EAAE,SAAS,IAAI,CAAE,QAAO,EAAE,MAAM,GAAG,GAAG;AAC/D,QAAI,EAAE,WAAW,EAAG,QAAO,EAAE;AAC7B,WAAO;KACP,CACD,KAAK,IAAI;;EAEd,qBAAqB,MAAM;GACzB,MAAM,WAAW,aAAa,WAAW,KAAK;AAC9C,OAAI,CAAC,SAAU;GACf,MAAM,YAAY,WAAW,KAAK;AAClC,OAAI,CAAC,UAAW;AAChB,UAAO;IACL;IACA;IACA,IAAI,cAAc;AAChB,YAAO,UAAU,WAAW,SAAS,WAAW,UAAU,KAAK,KAAK;;IAEvE;;EAEH,uBAAuB,MAAM;GAC3B,MAAM,WAAW,aAAa,QAAQ,KAAK;AAC3C,OAAI,CAAC,SAAU;GACf,MAAM,YAAY,WAAW,KAAK;AAClC,OAAI,CAAC,UAAW;AAChB,UAAO;IACL;IACA;IACA,IAAI,cAAc;AAChB,YACE,UAAU,WACV,SAAS,YACR,UAAU,cAAc,UAAU,UAAU,YAAY,GAAG,KAAK;;IAGtE;;EAEH,QAAQ,KAAK;AACX,UAAO,EACL,IAAI,cAAc;AAChB,WAAO,kBAAkB,IAAI;MAEhC;;EAEH,YAAY,MAAM;GAChB,MAAM,MAAM,aAAa,MAAM,MAAM,SAAS,KAAK,SAAS,KAAK;AACjE,OAAI,CAAC,IAAK;AAEV,UAAO;IACL,MAAM;IACN,GAAG,KAAK,QAAQ,IAAI;IACrB;;EAEJ,CAAC;AAEF,QAAO"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { OperationOutput,
|
|
1
|
+
import { OperationOutput, PageOutput, PagesBuilder, PagesBuilderConfig, WebhookOutput } from "./builder.js";
|
|
2
|
+
import { DistributiveOmit } from "../../types.js";
|
|
2
3
|
import { ProcessedDocument } from "../process-document.js";
|
|
3
4
|
|
|
4
5
|
//#region src/utils/pages/preset-auto.d.ts
|
|
@@ -16,7 +17,7 @@ interface OperationConfig extends BaseConfig {
|
|
|
16
17
|
*
|
|
17
18
|
* @defaultValue 'none'
|
|
18
19
|
*/
|
|
19
|
-
groupBy?: 'tag' | 'route' | 'none' | ((entry: OperationOutput | WebhookOutput) => string);
|
|
20
|
+
groupBy?: 'tag' | 'route' | 'none' | ((entry: DistributiveOmit<OperationOutput | WebhookOutput, 'path'>) => string);
|
|
20
21
|
/**
|
|
21
22
|
* Specify name for output file
|
|
22
23
|
*/
|
|
@@ -30,7 +31,7 @@ interface TagConfig extends BaseConfig {
|
|
|
30
31
|
/**
|
|
31
32
|
* Specify name for output file
|
|
32
33
|
*/
|
|
33
|
-
name?: NameFn<
|
|
34
|
+
name?: NameFn<PageOutput> | NameFnOptions;
|
|
34
35
|
}
|
|
35
36
|
interface SchemaConfig extends BaseConfig {
|
|
36
37
|
/**
|
|
@@ -40,12 +41,12 @@ interface SchemaConfig extends BaseConfig {
|
|
|
40
41
|
/**
|
|
41
42
|
* Specify name for output file
|
|
42
43
|
*/
|
|
43
|
-
name?: NameFn<
|
|
44
|
+
name?: NameFn<PageOutput> | NameFnOptions;
|
|
44
45
|
}
|
|
45
46
|
type SchemaToPagesOptions = SchemaConfig | TagConfig | OperationConfig | ({
|
|
46
47
|
per: 'custom';
|
|
47
48
|
} & PagesBuilderConfig);
|
|
48
|
-
type NameFn<Entry> = (this: PagesBuilder, output: Entry, document: ProcessedDocument['dereferenced']) => string;
|
|
49
|
+
type NameFn<Entry extends OperationOutput | WebhookOutput | PageOutput = OperationOutput | WebhookOutput | PageOutput> = (this: PagesBuilder, output: DistributiveOmit<Entry, 'path'>, document: ProcessedDocument['dereferenced']) => string;
|
|
49
50
|
interface NameFnOptions {
|
|
50
51
|
/**
|
|
51
52
|
* The version of algorithm used to generate file paths.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-auto.d.ts","names":[],"sources":["../../../src/utils/pages/preset-auto.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"preset-auto.d.ts","names":[],"sources":["../../../src/utils/pages/preset-auto.ts"],"mappings":";;;;;UAcU,eAAA,SAAwB,UAAA;;AAFc;;EAM9C,GAAA;EAe8B;;;;;;;;;EAJ9B,OAAA,gCAIM,KAAA,EAAO,gBAAA,CAAiB,eAAA,GAAkB,aAAA;EAnBhB;;;EAwBhC,IAAA,GAAO,MAAA,CAAO,eAAA,GAAkB,aAAA,IAAiB,aAAA;AAAA;AAAA,UAGzC,SAAA,SAAkB,UAAA;EARpB;;;EAYN,GAAA;EAPgC;;;EAYhC,IAAA,GAAO,MAAA,CAAO,UAAA,IAAc,aAAA;AAAA;AAAA,UAGpB,YAAA,SAAqB,UAAA;;;;EAI7B,GAAA;EAhB0B;;;EAqB1B,IAAA,GAAO,MAAA,CAAO,UAAA,IAAc,aAAA;AAAA;AAAA,KAGlB,oBAAA,GACR,YAAA,GACA,SAAA,GACA,eAAA;EAEE,GAAA;AAAA,IACE,kBAAA;AAAA,KAEH,MAAA,eACW,eAAA,GAAkB,aAAA,GAAgB,UAAA,GAC5C,eAAA,GACA,aAAA,GACA,UAAA,KAEJ,IAAA,EAAM,YAAA,EACN,MAAA,EAAQ,gBAAA,CAAiB,KAAA,WACzB,QAAA,EAAU,iBAAA;AAAA,UAGF,aAAA;EAlCiC;AAAA;;;;;;;EA2CzC,SAAA;AAAA;AAAA,UAGQ,UAAA;EAvCR;;;;;EA6CA,OAAA,IAAW,IAAA;AAAA;AAAA,iBAGG,gBAAA,CAAiB,OAAA,EAAS,oBAAA,GAAuB,kBAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isUrl } from "../url.js";
|
|
2
|
-
import * as path from "node:path";
|
|
2
|
+
import * as path$1 from "node:path";
|
|
3
3
|
//#region src/utils/pages/preset-auto.ts
|
|
4
4
|
function createAutoPreset(options) {
|
|
5
5
|
if (options.per === "custom") return options;
|
|
@@ -11,43 +11,114 @@ function createAutoPreset(options) {
|
|
|
11
11
|
else {
|
|
12
12
|
const { algorithm = "v2" } = options.name ?? {};
|
|
13
13
|
nameFn = function(result, document) {
|
|
14
|
-
if (result.type === "
|
|
15
|
-
|
|
14
|
+
if (result.type === "page") {
|
|
15
|
+
if (result.tag) return slugify(result.tag.name);
|
|
16
16
|
const schemaId = result.schemaId;
|
|
17
|
-
return isUrl(schemaId) ? "index" : path.basename(schemaId, path.extname(schemaId));
|
|
17
|
+
return isUrl(schemaId) ? "index" : path$1.basename(schemaId, path$1.extname(schemaId));
|
|
18
18
|
}
|
|
19
19
|
if (result.type === "operation") {
|
|
20
20
|
const operation = document.paths[result.item.path][result.item.method];
|
|
21
21
|
if (algorithm === "v2" && operation.operationId) return operation.operationId;
|
|
22
|
-
return path.join(this.routePathToFilePath(result.item.path), result.item.method.toLowerCase());
|
|
22
|
+
return path$1.join(this.routePathToFilePath(result.item.path), result.item.method.toLowerCase());
|
|
23
23
|
}
|
|
24
24
|
const hook = document.webhooks[result.item.name][result.item.method];
|
|
25
25
|
if (algorithm === "v2" && hook.operationId) return hook.operationId;
|
|
26
26
|
return slugify(result.item.name);
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
function
|
|
29
|
+
function group(builder, entries) {
|
|
30
|
+
const groups = /* @__PURE__ */ new Map();
|
|
31
|
+
const rest = [];
|
|
30
32
|
const { dereferenced } = builder.document;
|
|
31
33
|
const { groupBy = "none" } = options;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
for (const entry of entries) switch (groupBy) {
|
|
35
|
+
case "route": {
|
|
36
|
+
const groupName = builder.routePathToFilePath(entry.type === "operation" ? entry.item.path : entry.item.name);
|
|
37
|
+
let group = groups.get(groupName);
|
|
38
|
+
if (!group) {
|
|
39
|
+
group = {
|
|
40
|
+
type: "group",
|
|
41
|
+
info: { title: groupName },
|
|
42
|
+
entries: [],
|
|
43
|
+
schemaId: builder.id,
|
|
44
|
+
path: groupName
|
|
45
|
+
};
|
|
46
|
+
groups.set(groupName, group);
|
|
47
|
+
}
|
|
48
|
+
group.entries.push({
|
|
49
|
+
...entry,
|
|
50
|
+
path: path$1.join(groupName, `${entry.item.method.toLowerCase()}.mdx`)
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case "tag": {
|
|
55
|
+
let tags = entry.type === "operation" ? dereferenced.paths[entry.item.path][entry.item.method].tags : dereferenced.webhooks[entry.item.name][entry.item.method].tags;
|
|
56
|
+
if (!tags || tags.length === 0) {
|
|
57
|
+
console.warn("When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.");
|
|
58
|
+
tags = ["unknown"];
|
|
59
|
+
}
|
|
60
|
+
for (const tag of tags) {
|
|
61
|
+
const groupName = slugify(tag);
|
|
62
|
+
const { displayName, info } = builder.fromTagName(tag);
|
|
63
|
+
let group = groups.get(groupName);
|
|
64
|
+
if (!group) {
|
|
65
|
+
group = {
|
|
66
|
+
type: "group",
|
|
67
|
+
info: {
|
|
68
|
+
title: displayName,
|
|
69
|
+
description: info.description
|
|
70
|
+
},
|
|
71
|
+
tag: info,
|
|
72
|
+
entries: [],
|
|
73
|
+
schemaId: builder.id,
|
|
74
|
+
path: groupName
|
|
75
|
+
};
|
|
76
|
+
groups.set(groupName, group);
|
|
77
|
+
}
|
|
78
|
+
group.entries.push({
|
|
79
|
+
...entry,
|
|
80
|
+
path: path$1.join(groupName, `${nameFn.call(builder, entry, dereferenced)}.mdx`)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
default: {
|
|
86
|
+
const fileName = `${nameFn.call(builder, entry, dereferenced)}.mdx`;
|
|
87
|
+
if (typeof groupBy === "function") {
|
|
88
|
+
const groupDisplayName = groupBy(entry);
|
|
89
|
+
const groupName = slugify(groupDisplayName);
|
|
90
|
+
let group = groups.get(groupName);
|
|
91
|
+
if (!group) {
|
|
92
|
+
group = {
|
|
93
|
+
type: "group",
|
|
94
|
+
info: { title: groupDisplayName },
|
|
95
|
+
entries: [],
|
|
96
|
+
schemaId: builder.id,
|
|
97
|
+
path: groupName
|
|
98
|
+
};
|
|
99
|
+
groups.set(groupName, group);
|
|
100
|
+
}
|
|
101
|
+
group.entries.push({
|
|
102
|
+
...entry,
|
|
103
|
+
path: path$1.join(groupName, fileName)
|
|
104
|
+
});
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
rest.push({
|
|
108
|
+
...entry,
|
|
109
|
+
path: fileName
|
|
110
|
+
});
|
|
39
111
|
}
|
|
40
|
-
return tags.map((tag) => path.join(slugify(tag), `${file}.mdx`));
|
|
41
112
|
}
|
|
42
|
-
|
|
43
|
-
return
|
|
113
|
+
rest.push(...groups.values());
|
|
114
|
+
return rest;
|
|
44
115
|
}
|
|
45
116
|
return { toPages(builder) {
|
|
46
117
|
const { dereferenced } = builder.document;
|
|
47
118
|
const items = builder.extract();
|
|
48
119
|
if (options.per === "file") {
|
|
49
120
|
const entry = {
|
|
50
|
-
type: "
|
|
121
|
+
type: "page",
|
|
51
122
|
schemaId: builder.id,
|
|
52
123
|
path: "",
|
|
53
124
|
info: {
|
|
@@ -56,7 +127,7 @@ function createAutoPreset(options) {
|
|
|
56
127
|
},
|
|
57
128
|
...items
|
|
58
129
|
};
|
|
59
|
-
entry.path = nameFn.call(builder, entry, dereferenced)
|
|
130
|
+
entry.path = `${nameFn.call(builder, entry, dereferenced)}.mdx`;
|
|
60
131
|
builder.create(entry);
|
|
61
132
|
return;
|
|
62
133
|
}
|
|
@@ -65,7 +136,7 @@ function createAutoPreset(options) {
|
|
|
65
136
|
for (const tag of tags) {
|
|
66
137
|
const { displayName } = builder.fromTag(tag);
|
|
67
138
|
const entry = {
|
|
68
|
-
type: "
|
|
139
|
+
type: "page",
|
|
69
140
|
path: "",
|
|
70
141
|
schemaId: builder.id,
|
|
71
142
|
info: {
|
|
@@ -74,48 +145,39 @@ function createAutoPreset(options) {
|
|
|
74
145
|
},
|
|
75
146
|
webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name)),
|
|
76
147
|
operations: items.operations.filter((op) => op.tags?.includes(tag.name)),
|
|
77
|
-
tag
|
|
78
|
-
rawTag: tag
|
|
148
|
+
tag
|
|
79
149
|
};
|
|
80
|
-
entry.path = nameFn.call(builder, entry, dereferenced)
|
|
150
|
+
entry.path = `${nameFn.call(builder, entry, dereferenced)}.mdx`;
|
|
81
151
|
builder.create(entry);
|
|
82
152
|
}
|
|
83
153
|
return;
|
|
84
154
|
}
|
|
155
|
+
const entries = [];
|
|
85
156
|
for (const op of items.operations) {
|
|
86
157
|
const { pathItem, operation, displayName } = builder.fromExtractedOperation(op);
|
|
87
|
-
|
|
158
|
+
entries.push({
|
|
88
159
|
type: "operation",
|
|
89
160
|
schemaId: builder.id,
|
|
90
161
|
item: op,
|
|
91
|
-
path: "",
|
|
92
162
|
info: {
|
|
93
163
|
title: displayName,
|
|
94
164
|
description: operation.description ?? pathItem.description
|
|
95
165
|
}
|
|
96
|
-
};
|
|
97
|
-
for (const outputPath of groupOutput(builder, entry)) builder.create({
|
|
98
|
-
...entry,
|
|
99
|
-
path: outputPath
|
|
100
166
|
});
|
|
101
167
|
}
|
|
102
168
|
for (const webhook of items.webhooks) {
|
|
103
169
|
const { pathItem, operation, displayName } = builder.fromExtractedWebhook(webhook);
|
|
104
|
-
|
|
170
|
+
entries.push({
|
|
105
171
|
type: "webhook",
|
|
106
172
|
schemaId: builder.id,
|
|
107
173
|
info: {
|
|
108
174
|
title: displayName,
|
|
109
175
|
description: operation.description ?? pathItem.description
|
|
110
176
|
},
|
|
111
|
-
item: webhook
|
|
112
|
-
path: ""
|
|
113
|
-
};
|
|
114
|
-
for (const outputPath of groupOutput(builder, entry)) builder.create({
|
|
115
|
-
...entry,
|
|
116
|
-
path: outputPath
|
|
177
|
+
item: webhook
|
|
117
178
|
});
|
|
118
179
|
}
|
|
180
|
+
for (const entry of group(builder, entries)) builder.create(entry);
|
|
119
181
|
} };
|
|
120
182
|
}
|
|
121
183
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preset-auto.js","names":[],"sources":["../../../src/utils/pages/preset-auto.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type {\n OperationOutput,\n OutputEntry,\n OutputGroup,\n PagesBuilder,\n PagesBuilderConfig,\n TagOutput,\n WebhookOutput,\n} from '@/utils/pages/builder';\nimport { isUrl } from '@/utils/url';\n\ninterface OperationConfig extends BaseConfig {\n /**\n * Generate a page for each API endpoint/operation (default).\n */\n per?: 'operation';\n\n /**\n * Group output using folders (Only works on `operation` mode)\n * - tag: `{tag}/{file}`\n * - route: `{endpoint}/{method}` (it will ignore the `name` option)\n * - none: `{file}` (default)\n * - a function that aligns group name (folder path) to each entry\n *\n * @defaultValue 'none'\n */\n groupBy?: 'tag' | 'route' | 'none' | ((entry: OperationOutput | WebhookOutput) => string);\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OperationOutput | WebhookOutput> | NameFnOptions;\n}\n\ninterface TagConfig extends BaseConfig {\n /**\n * Generate a page for each tag.\n */\n per: 'tag';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<TagOutput> | NameFnOptions;\n}\n\ninterface SchemaConfig extends BaseConfig {\n /**\n * Generate a page for each schema file.\n */\n per: 'file';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OutputGroup> | NameFnOptions;\n}\n\nexport type SchemaToPagesOptions =\n | SchemaConfig\n | TagConfig\n | OperationConfig\n | ({\n per: 'custom';\n } & PagesBuilderConfig);\n\ntype NameFn<Entry> = (\n this: PagesBuilder,\n output: Entry,\n document: ProcessedDocument['dereferenced'],\n) => string;\n\ninterface NameFnOptions {\n /**\n * The version of algorithm used to generate file paths.\n *\n * v1: Fumadocs OpenAPI v8\n * v2: Fumadocs OpenAPI v9\n *\n * @defaultValue v2\n */\n algorithm?: 'v2' | 'v1';\n}\n\ninterface BaseConfig {\n /**\n * Custom function to convert names into file names.\n *\n * By default, it only escapes whitespaces and upper case (English) characters\n */\n slugify?: (name: string) => string;\n}\n\nexport function createAutoPreset(options: SchemaToPagesOptions): PagesBuilderConfig {\n if (options.per === 'custom') return options;\n const {\n slugify = (s) => {\n return s.replace(/\\s+/g, '-').toLowerCase();\n },\n } = options;\n let nameFn: NameFn<OutputEntry>;\n\n if (typeof options.name === 'function') {\n nameFn = options.name as NameFn<OutputEntry>;\n } else {\n const { algorithm = 'v2' } = options.name ?? {};\n\n nameFn = function (result, document) {\n if (result.type === 'tag') {\n return slugify(result.tag);\n }\n\n if (result.type === 'group') {\n const schemaId = result.schemaId;\n\n return isUrl(schemaId) ? 'index' : path.basename(schemaId, path.extname(schemaId));\n }\n\n if (result.type === 'operation') {\n const operation = document.paths![result.item.path]![result.item.method]!;\n\n if (algorithm === 'v2' && operation.operationId) {\n return operation.operationId;\n }\n\n return path.join(\n this.routePathToFilePath(result.item.path),\n result.item.method.toLowerCase(),\n );\n }\n\n const hook = document.webhooks![result.item.name][result.item.method]!;\n\n if (algorithm === 'v2' && hook.operationId) {\n return hook.operationId;\n }\n\n return slugify(result.item.name);\n };\n }\n\n function groupOutput(builder: PagesBuilder, entry: OperationOutput | WebhookOutput): string[] {\n const { dereferenced } = builder.document;\n const { groupBy = 'none' } = options as OperationConfig;\n\n if (groupBy === 'route') {\n return [\n path.join(\n builder.routePathToFilePath(\n entry.type === 'operation' ? entry.item.path : entry.item.name,\n ),\n `${entry.item.method.toLowerCase()}.mdx`,\n ),\n ];\n }\n\n const file = nameFn.call(builder, entry, dereferenced);\n if (groupBy === 'tag') {\n let tags =\n entry.type === 'operation'\n ? dereferenced.paths![entry.item.path]![entry.item.method]!.tags\n : dereferenced.webhooks![entry.item.name][entry.item.method]!.tags;\n\n if (!tags || tags.length === 0) {\n console.warn(\n 'When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.',\n );\n\n tags = ['unknown'];\n }\n\n return tags.map((tag) => path.join(slugify(tag), `${file}.mdx`));\n }\n\n if (typeof groupBy === 'function') {\n return [path.join(slugify(groupBy(entry)), `${file}.mdx`)];\n }\n\n return [`${file}.mdx`];\n }\n\n return {\n toPages(builder) {\n const { dereferenced } = builder.document;\n const items = builder.extract();\n\n if (options.per === 'file') {\n const entry: OutputGroup = {\n type: 'group',\n schemaId: builder.id,\n path: '',\n info: {\n title: dereferenced.info?.title ?? 'Unknown',\n description: dereferenced.info?.description,\n },\n ...items,\n };\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n return;\n }\n\n if (options.per === 'tag') {\n const tags = dereferenced.tags ?? [];\n for (const tag of tags) {\n const { displayName } = builder.fromTag(tag);\n const entry: TagOutput = {\n type: 'tag',\n path: '',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: tag.description,\n },\n webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name!)),\n operations: items.operations.filter((op) => op.tags?.includes(tag.name!)),\n tag: tag.name!,\n rawTag: tag,\n };\n\n entry.path = nameFn.call(builder, entry, dereferenced) + '.mdx';\n builder.create(entry);\n }\n\n return;\n }\n\n for (const op of items.operations) {\n const { pathItem, operation, displayName } = builder.fromExtractedOperation(op)!;\n\n const entry: OperationOutput = {\n type: 'operation',\n schemaId: builder.id,\n item: op,\n path: '',\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n\n for (const webhook of items.webhooks) {\n const { pathItem, operation, displayName } = builder.fromExtractedWebhook(webhook)!;\n\n const entry: WebhookOutput = {\n type: 'webhook',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n item: webhook,\n path: '',\n };\n\n for (const outputPath of groupOutput(builder, entry)) {\n builder.create({ ...entry, path: outputPath });\n }\n }\n },\n };\n}\n"],"mappings":";;;AA+FA,SAAgB,iBAAiB,SAAmD;AAClF,KAAI,QAAQ,QAAQ,SAAU,QAAO;CACrC,MAAM,EACJ,WAAW,MAAM;AACf,SAAO,EAAE,QAAQ,QAAQ,IAAI,CAAC,aAAa;OAE3C;CACJ,IAAI;AAEJ,KAAI,OAAO,QAAQ,SAAS,WAC1B,UAAS,QAAQ;MACZ;EACL,MAAM,EAAE,YAAY,SAAS,QAAQ,QAAQ,EAAE;AAE/C,WAAS,SAAU,QAAQ,UAAU;AACnC,OAAI,OAAO,SAAS,MAClB,QAAO,QAAQ,OAAO,IAAI;AAG5B,OAAI,OAAO,SAAS,SAAS;IAC3B,MAAM,WAAW,OAAO;AAExB,WAAO,MAAM,SAAS,GAAG,UAAU,KAAK,SAAS,UAAU,KAAK,QAAQ,SAAS,CAAC;;AAGpF,OAAI,OAAO,SAAS,aAAa;IAC/B,MAAM,YAAY,SAAS,MAAO,OAAO,KAAK,MAAO,OAAO,KAAK;AAEjE,QAAI,cAAc,QAAQ,UAAU,YAClC,QAAO,UAAU;AAGnB,WAAO,KAAK,KACV,KAAK,oBAAoB,OAAO,KAAK,KAAK,EAC1C,OAAO,KAAK,OAAO,aAAa,CACjC;;GAGH,MAAM,OAAO,SAAS,SAAU,OAAO,KAAK,MAAM,OAAO,KAAK;AAE9D,OAAI,cAAc,QAAQ,KAAK,YAC7B,QAAO,KAAK;AAGd,UAAO,QAAQ,OAAO,KAAK,KAAK;;;CAIpC,SAAS,YAAY,SAAuB,OAAkD;EAC5F,MAAM,EAAE,iBAAiB,QAAQ;EACjC,MAAM,EAAE,UAAU,WAAW;AAE7B,MAAI,YAAY,QACd,QAAO,CACL,KAAK,KACH,QAAQ,oBACN,MAAM,SAAS,cAAc,MAAM,KAAK,OAAO,MAAM,KAAK,KAC3D,EACD,GAAG,MAAM,KAAK,OAAO,aAAa,CAAC,MACpC,CACF;EAGH,MAAM,OAAO,OAAO,KAAK,SAAS,OAAO,aAAa;AACtD,MAAI,YAAY,OAAO;GACrB,IAAI,OACF,MAAM,SAAS,cACX,aAAa,MAAO,MAAM,KAAK,MAAO,MAAM,KAAK,QAAS,OAC1D,aAAa,SAAU,MAAM,KAAK,MAAM,MAAM,KAAK,QAAS;AAElE,OAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,YAAQ,KACN,4FACD;AAED,WAAO,CAAC,UAAU;;AAGpB,UAAO,KAAK,KAAK,QAAQ,KAAK,KAAK,QAAQ,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC;;AAGlE,MAAI,OAAO,YAAY,WACrB,QAAO,CAAC,KAAK,KAAK,QAAQ,QAAQ,MAAM,CAAC,EAAE,GAAG,KAAK,MAAM,CAAC;AAG5D,SAAO,CAAC,GAAG,KAAK,MAAM;;AAGxB,QAAO,EACL,QAAQ,SAAS;EACf,MAAM,EAAE,iBAAiB,QAAQ;EACjC,MAAM,QAAQ,QAAQ,SAAS;AAE/B,MAAI,QAAQ,QAAQ,QAAQ;GAC1B,MAAM,QAAqB;IACzB,MAAM;IACN,UAAU,QAAQ;IAClB,MAAM;IACN,MAAM;KACJ,OAAO,aAAa,MAAM,SAAS;KACnC,aAAa,aAAa,MAAM;KACjC;IACD,GAAG;IACJ;AACD,SAAM,OAAO,OAAO,KAAK,SAAS,OAAO,aAAa,GAAG;AACzD,WAAQ,OAAO,MAAM;AACrB;;AAGF,MAAI,QAAQ,QAAQ,OAAO;GACzB,MAAM,OAAO,aAAa,QAAQ,EAAE;AACpC,QAAK,MAAM,OAAO,MAAM;IACtB,MAAM,EAAE,gBAAgB,QAAQ,QAAQ,IAAI;IAC5C,MAAM,QAAmB;KACvB,MAAM;KACN,MAAM;KACN,UAAU,QAAQ;KAClB,MAAM;MACJ,OAAO;MACP,aAAa,IAAI;MAClB;KACD,UAAU,MAAM,SAAS,QAAQ,YAAY,QAAQ,MAAM,SAAS,IAAI,KAAM,CAAC;KAC/E,YAAY,MAAM,WAAW,QAAQ,OAAO,GAAG,MAAM,SAAS,IAAI,KAAM,CAAC;KACzE,KAAK,IAAI;KACT,QAAQ;KACT;AAED,UAAM,OAAO,OAAO,KAAK,SAAS,OAAO,aAAa,GAAG;AACzD,YAAQ,OAAO,MAAM;;AAGvB;;AAGF,OAAK,MAAM,MAAM,MAAM,YAAY;GACjC,MAAM,EAAE,UAAU,WAAW,gBAAgB,QAAQ,uBAAuB,GAAG;GAE/E,MAAM,QAAyB;IAC7B,MAAM;IACN,UAAU,QAAQ;IAClB,MAAM;IACN,MAAM;IACN,MAAM;KACJ,OAAO;KACP,aAAa,UAAU,eAAe,SAAS;KAChD;IACF;AAED,QAAK,MAAM,cAAc,YAAY,SAAS,MAAM,CAClD,SAAQ,OAAO;IAAE,GAAG;IAAO,MAAM;IAAY,CAAC;;AAIlD,OAAK,MAAM,WAAW,MAAM,UAAU;GACpC,MAAM,EAAE,UAAU,WAAW,gBAAgB,QAAQ,qBAAqB,QAAQ;GAElF,MAAM,QAAuB;IAC3B,MAAM;IACN,UAAU,QAAQ;IAClB,MAAM;KACJ,OAAO;KACP,aAAa,UAAU,eAAe,SAAS;KAChD;IACD,MAAM;IACN,MAAM;IACP;AAED,QAAK,MAAM,cAAc,YAAY,SAAS,MAAM,CAClD,SAAQ,OAAO;IAAE,GAAG;IAAO,MAAM;IAAY,CAAC;;IAIrD"}
|
|
1
|
+
{"version":3,"file":"preset-auto.js","names":["path"],"sources":["../../../src/utils/pages/preset-auto.ts"],"sourcesContent":["import * as path from 'node:path';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type {\n OperationOutput,\n OutputEntry,\n OutputGroup,\n PageOutput,\n PagesBuilder,\n PagesBuilderConfig,\n WebhookOutput,\n} from '@/utils/pages/builder';\nimport { isUrl } from '@/utils/url';\nimport type { DistributiveOmit } from '@/types';\n\ninterface OperationConfig extends BaseConfig {\n /**\n * Generate a page for each API endpoint/operation (default).\n */\n per?: 'operation';\n\n /**\n * Group output using folders (Only works on `operation` mode)\n * - tag: `{tag}/{file}`\n * - route: `{endpoint}/{method}` (it will ignore the `name` option)\n * - none: `{file}` (default)\n * - a function that aligns group name (folder path) to each entry\n *\n * @defaultValue 'none'\n */\n groupBy?:\n | 'tag'\n | 'route'\n | 'none'\n | ((entry: DistributiveOmit<OperationOutput | WebhookOutput, 'path'>) => string);\n\n /**\n * Specify name for output file\n */\n name?: NameFn<OperationOutput | WebhookOutput> | NameFnOptions;\n}\n\ninterface TagConfig extends BaseConfig {\n /**\n * Generate a page for each tag.\n */\n per: 'tag';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<PageOutput> | NameFnOptions;\n}\n\ninterface SchemaConfig extends BaseConfig {\n /**\n * Generate a page for each schema file.\n */\n per: 'file';\n\n /**\n * Specify name for output file\n */\n name?: NameFn<PageOutput> | NameFnOptions;\n}\n\nexport type SchemaToPagesOptions =\n | SchemaConfig\n | TagConfig\n | OperationConfig\n | ({\n per: 'custom';\n } & PagesBuilderConfig);\n\ntype NameFn<\n Entry extends OperationOutput | WebhookOutput | PageOutput =\n | OperationOutput\n | WebhookOutput\n | PageOutput,\n> = (\n this: PagesBuilder,\n output: DistributiveOmit<Entry, 'path'>,\n document: ProcessedDocument['dereferenced'],\n) => string;\n\ninterface NameFnOptions {\n /**\n * The version of algorithm used to generate file paths.\n *\n * v1: Fumadocs OpenAPI v8\n * v2: Fumadocs OpenAPI v9\n *\n * @defaultValue v2\n */\n algorithm?: 'v2' | 'v1';\n}\n\ninterface BaseConfig {\n /**\n * Custom function to convert names into file names.\n *\n * By default, it only escapes whitespaces and upper case (English) characters\n */\n slugify?: (name: string) => string;\n}\n\nexport function createAutoPreset(options: SchemaToPagesOptions): PagesBuilderConfig {\n if (options.per === 'custom') return options;\n const {\n slugify = (s) => {\n return s.replace(/\\s+/g, '-').toLowerCase();\n },\n } = options;\n let nameFn: NameFn;\n\n if (typeof options.name === 'function') {\n nameFn = options.name as NameFn;\n } else {\n const { algorithm = 'v2' } = options.name ?? {};\n\n nameFn = function (result, document) {\n if (result.type === 'page') {\n if (result.tag) return slugify(result.tag.name!);\n const schemaId = result.schemaId;\n\n return isUrl(schemaId) ? 'index' : path.basename(schemaId, path.extname(schemaId));\n }\n\n if (result.type === 'operation') {\n const operation = document.paths![result.item.path]![result.item.method]!;\n\n if (algorithm === 'v2' && operation.operationId) {\n return operation.operationId;\n }\n\n return path.join(\n this.routePathToFilePath(result.item.path),\n result.item.method.toLowerCase(),\n );\n }\n\n const hook = document.webhooks![result.item.name][result.item.method]!;\n\n if (algorithm === 'v2' && hook.operationId) {\n return hook.operationId;\n }\n\n return slugify(result.item.name);\n };\n }\n\n function group(\n builder: PagesBuilder,\n entries: DistributiveOmit<OperationOutput | WebhookOutput, 'path'>[],\n ): OutputEntry[] {\n const groups = new Map<string, OutputGroup>();\n const rest: OutputEntry[] = [];\n const { dereferenced } = builder.document;\n const { groupBy = 'none' } = options as OperationConfig;\n\n for (const entry of entries) {\n switch (groupBy) {\n case 'route': {\n const groupName = builder.routePathToFilePath(\n entry.type === 'operation' ? entry.item.path : entry.item.name,\n );\n\n let group = groups.get(groupName);\n if (!group) {\n group = {\n type: 'group',\n info: { title: groupName },\n entries: [],\n schemaId: builder.id,\n path: groupName,\n };\n groups.set(groupName, group);\n }\n\n group.entries.push({\n ...entry,\n path: path.join(groupName, `${entry.item.method.toLowerCase()}.mdx`),\n });\n break;\n }\n case 'tag': {\n let tags =\n entry.type === 'operation'\n ? dereferenced.paths![entry.item.path]![entry.item.method]!.tags\n : dereferenced.webhooks![entry.item.name][entry.item.method]!.tags;\n\n if (!tags || tags.length === 0) {\n console.warn(\n 'When `groupBy` is set to `tag`, make sure a `tags` is defined for every operation schema.',\n );\n\n tags = ['unknown'];\n }\n\n for (const tag of tags) {\n const groupName = slugify(tag);\n const { displayName, info } = builder.fromTagName(tag)!;\n let group = groups.get(groupName);\n if (!group) {\n group = {\n type: 'group',\n info: { title: displayName, description: info.description },\n tag: info,\n entries: [],\n schemaId: builder.id,\n path: groupName,\n };\n groups.set(groupName, group);\n }\n\n group.entries.push({\n ...entry,\n path: path.join(groupName, `${nameFn.call(builder, entry, dereferenced)}.mdx`),\n });\n }\n\n break;\n }\n default: {\n const fileName = `${nameFn.call(builder, entry, dereferenced)}.mdx`;\n\n if (typeof groupBy === 'function') {\n const groupDisplayName = groupBy(entry);\n const groupName = slugify(groupDisplayName);\n\n let group = groups.get(groupName);\n if (!group) {\n group = {\n type: 'group',\n info: { title: groupDisplayName },\n entries: [],\n schemaId: builder.id,\n path: groupName,\n };\n groups.set(groupName, group);\n }\n\n group.entries.push({\n ...entry,\n path: path.join(groupName, fileName),\n });\n break;\n }\n\n rest.push({\n ...entry,\n path: fileName,\n });\n }\n }\n }\n\n rest.push(...groups.values());\n return rest;\n }\n\n return {\n toPages(builder) {\n const { dereferenced } = builder.document;\n const items = builder.extract();\n\n if (options.per === 'file') {\n const entry: PageOutput = {\n type: 'page',\n schemaId: builder.id,\n path: '',\n info: {\n title: dereferenced.info?.title ?? 'Unknown',\n description: dereferenced.info?.description,\n },\n ...items,\n };\n entry.path = `${nameFn.call(builder, entry, dereferenced)}.mdx`;\n builder.create(entry);\n return;\n }\n\n if (options.per === 'tag') {\n const tags = dereferenced.tags ?? [];\n\n for (const tag of tags) {\n const { displayName } = builder.fromTag(tag);\n const entry: PageOutput = {\n type: 'page',\n path: '',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: tag.description,\n },\n webhooks: items.webhooks.filter((webhook) => webhook.tags?.includes(tag.name!)),\n operations: items.operations.filter((op) => op.tags?.includes(tag.name!)),\n tag,\n };\n\n entry.path = `${nameFn.call(builder, entry, dereferenced)}.mdx`;\n builder.create(entry);\n }\n\n return;\n }\n\n const entries: DistributiveOmit<OperationOutput | WebhookOutput, 'path'>[] = [];\n for (const op of items.operations) {\n const { pathItem, operation, displayName } = builder.fromExtractedOperation(op)!;\n\n entries.push({\n type: 'operation',\n schemaId: builder.id,\n item: op,\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n });\n }\n\n for (const webhook of items.webhooks) {\n const { pathItem, operation, displayName } = builder.fromExtractedWebhook(webhook)!;\n\n entries.push({\n type: 'webhook',\n schemaId: builder.id,\n info: {\n title: displayName,\n description: operation.description ?? pathItem.description,\n },\n item: webhook,\n });\n }\n\n for (const entry of group(builder, entries)) {\n builder.create(entry);\n }\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-text.d.ts","names":[],"sources":["../../../src/utils/pages/to-text.ts"],"mappings":";;UASiB,kBAAA;;AAAjB;;EAIE,OAAA;IACE,KAAA;IACA,IAAA;EAAA;EAAA;;;;;EAQF,WAAA,IACE,KAAA,UACA,WAAA,sBACA,OAAA,EAAS,eAAA,KACN,MAAA;EAAA;;;;;
|
|
1
|
+
{"version":3,"file":"to-text.d.ts","names":[],"sources":["../../../src/utils/pages/to-text.ts"],"mappings":";;UASiB,kBAAA;;AAAjB;;EAIE,OAAA;IACE,KAAA;IACA,IAAA;EAAA;EAAA;;;;;EAQF,WAAA,IACE,KAAA,UACA,WAAA,sBACA,OAAA,EAAS,eAAA,KACN,MAAA;EAAA;;;;;AAqHP;;EA5GE,kBAAA;EA+GkB;;;;;;;;EArGlB,mBAAA;AAAA;AAAA,KAkGU,eAAA;EAEN,IAAA;EACA,GAAA,EAAK,SAAA;AAAA;EAGL,IAAA;AAAA;EAGA,IAAA;AAAA"}
|
|
@@ -8,25 +8,17 @@ function toText(entry, processed, options = {}) {
|
|
|
8
8
|
...options,
|
|
9
9
|
...entry.info
|
|
10
10
|
}, { type: "operation" });
|
|
11
|
-
case "
|
|
11
|
+
case "page": return generatePage(entry.schemaId, processed, {
|
|
12
12
|
operations: entry.operations,
|
|
13
13
|
webhooks: entry.webhooks,
|
|
14
14
|
showTitle: true
|
|
15
15
|
}, {
|
|
16
16
|
...options,
|
|
17
17
|
...entry.info
|
|
18
|
-
},
|
|
19
|
-
case "tag": return generatePage(entry.schemaId, processed, {
|
|
20
|
-
operations: entry.operations,
|
|
21
|
-
webhooks: entry.webhooks,
|
|
22
|
-
showTitle: true
|
|
23
|
-
}, {
|
|
24
|
-
...options,
|
|
25
|
-
...entry.info
|
|
26
|
-
}, {
|
|
18
|
+
}, entry.tag ? {
|
|
27
19
|
type: "tag",
|
|
28
|
-
tag: entry.
|
|
29
|
-
});
|
|
20
|
+
tag: entry.tag
|
|
21
|
+
} : { type: "file" });
|
|
30
22
|
case "webhook": return generatePage(entry.schemaId, processed, { webhooks: [entry.item] }, {
|
|
31
23
|
...options,
|
|
32
24
|
...entry.info
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-text.js","names":[],"sources":["../../../src/utils/pages/to-text.ts"],"sourcesContent":["import type { ApiPageProps, OperationItem, WebhookItem } from '@/ui/api-page';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type { TagObject } from '@/types';\nimport { dump } from 'js-yaml';\nimport { removeUndefined } from '@/utils/remove-undefined';\nimport type {
|
|
1
|
+
{"version":3,"file":"to-text.js","names":[],"sources":["../../../src/utils/pages/to-text.ts"],"sourcesContent":["import type { ApiPageProps, OperationItem, WebhookItem } from '@/ui/api-page';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport type { TagObject } from '@/types';\nimport { dump } from 'js-yaml';\nimport { removeUndefined } from '@/utils/remove-undefined';\nimport type { OperationOutput, PageOutput, WebhookOutput } from '@/utils/pages/builder';\nimport type { InternalOpenAPIMeta } from '@/server/source-api';\nimport { toStaticData } from '@/utils/pages/to-static-data';\n\nexport interface PagesToTextOptions {\n /**\n * Additional imports of your MDX components.\n */\n imports?: {\n names: string[];\n from: string;\n }[];\n\n /**\n * Customise frontmatter.\n *\n * A `full: true` property will be added by default.\n */\n frontmatter?: (\n title: string,\n description: string | undefined,\n context: DocumentContext,\n ) => Record<string, unknown>;\n\n /**\n * Add description to document body.\n *\n * We recommend but don't enable it by default because some OpenAPI schemas have invalid description that breaks MDX syntax.\n *\n * @defaultValue false\n */\n includeDescription?: boolean;\n\n /**\n * Add a comment to the top of generated files indicating they are auto-generated.\n * - `true`: Adds a standardized comment\n * - `false`: No comment is added\n * - `string`: Adds the provided custom comment\n *\n * @defaultValue true\n */\n addGeneratedComment?: boolean | string;\n}\n\nexport function toText(\n entry: PageOutput | OperationOutput | WebhookOutput,\n processed: ProcessedDocument,\n options: PagesToTextOptions = {},\n) {\n switch (entry.type) {\n case 'operation':\n return generatePage(\n entry.schemaId,\n processed,\n {\n operations: [entry.item],\n },\n {\n ...options,\n ...entry.info,\n },\n {\n type: 'operation',\n },\n );\n case 'page':\n return generatePage(\n entry.schemaId,\n processed,\n {\n operations: entry.operations,\n webhooks: entry.webhooks,\n showTitle: true,\n },\n {\n ...options,\n ...entry.info,\n },\n entry.tag\n ? {\n type: 'tag',\n tag: entry.tag,\n }\n : {\n type: 'file',\n },\n );\n case 'webhook':\n return generatePage(\n entry.schemaId,\n processed,\n {\n webhooks: [entry.item],\n },\n {\n ...options,\n ...entry.info,\n },\n {\n type: 'operation',\n },\n );\n }\n}\n\nexport function generateDocument(\n frontmatter: unknown,\n content: string,\n options: PagesToTextOptions,\n): string {\n const { addGeneratedComment = true, imports } = options;\n const out: string[] = [];\n const banner = dump(removeUndefined(frontmatter as object)).trimEnd();\n if (banner.length > 0) out.push(`---\\n${banner}\\n---`);\n\n if (addGeneratedComment) {\n let commentContent =\n 'This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again.';\n\n if (typeof addGeneratedComment === 'string') {\n commentContent = addGeneratedComment;\n }\n\n commentContent = commentContent.replaceAll('/', '\\\\/');\n out.push(`{/* ${commentContent} */}`);\n }\n\n if (imports) {\n out.push(\n ...imports\n .map((item) => `import { ${item.names.join(', ')} } from ${JSON.stringify(item.from)};`)\n .join('\\n'),\n );\n }\n\n out.push(content);\n return out.join('\\n\\n');\n}\n\nexport type DocumentContext =\n | {\n type: 'tag';\n tag: TagObject | undefined;\n }\n | {\n type: 'operation';\n }\n | {\n type: 'file';\n };\n\nfunction generatePage(\n schemaId: string,\n processed: ProcessedDocument,\n pageProps: Omit<ApiPageProps, 'document'>,\n options: PagesToTextOptions & {\n title: string;\n description?: string;\n },\n context: DocumentContext,\n): string {\n const { frontmatter, includeDescription = false } = options;\n const extend = frontmatter?.(options.title, options.description, context);\n const page: ApiPageProps = {\n ...pageProps,\n document: schemaId,\n };\n\n let meta: InternalOpenAPIMeta | undefined;\n if (page.operations?.length === 1) {\n const operation = page.operations[0];\n\n meta = {\n method: operation.method.toUpperCase(),\n };\n } else if (page.webhooks?.length === 1) {\n const webhook = page.webhooks[0];\n\n meta = {\n method: webhook.method.toUpperCase(),\n webhook: true,\n };\n }\n\n const data = toStaticData(page, processed.dereferenced);\n const content: string[] = [];\n\n if (options.description && includeDescription) content.push(options.description);\n content.push(pageContent(page));\n\n return generateDocument(\n {\n title: options.title,\n description: !includeDescription ? options.description : undefined,\n full: true,\n ...extend,\n _openapi: {\n ...meta,\n ...data,\n ...(extend?._openapi as object | undefined),\n },\n },\n content.join('\\n\\n'),\n options,\n );\n}\n\nfunction pageContent({\n showTitle,\n showDescription,\n document,\n webhooks,\n operations,\n}: ApiPageProps): string {\n const propStrs: string[] = [`document={${JSON.stringify(document)}}`];\n\n // filter extra properties in props\n if (webhooks) {\n propStrs.push(\n `webhooks={${JSON.stringify(\n webhooks.map(\n (item) =>\n ({\n name: item.name,\n method: item.method,\n }) satisfies WebhookItem,\n ),\n )}}`,\n );\n }\n if (operations) {\n propStrs.push(\n `operations={${JSON.stringify(\n operations.map(\n (item) =>\n ({\n path: item.path,\n method: item.method,\n }) satisfies OperationItem,\n ),\n )}}`,\n );\n }\n if (showTitle) {\n propStrs.push(`showTitle={${JSON.stringify(showTitle)}}`);\n }\n if (showDescription) {\n propStrs.push(`showDescription={${JSON.stringify(showDescription)}}`);\n }\n\n return `<APIPage ${propStrs.join(' ')} />`;\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { dereferenceSync } from "./schema/dereference.js";
|
|
1
2
|
import { bundle } from "@scalar/json-magic/bundle";
|
|
2
3
|
import { upgrade } from "@scalar/openapi-upgrader";
|
|
3
4
|
import { fetchUrls, readFiles } from "@scalar/json-magic/bundle/plugins/node";
|
|
4
|
-
import dereference from "dereference-json-schema";
|
|
5
5
|
//#region src/utils/process-document.ts
|
|
6
6
|
/**
|
|
7
7
|
* process & reference input document to a Fumadocs OpenAPI compatible format
|
|
@@ -30,37 +30,6 @@ async function processDocument(input) {
|
|
|
30
30
|
bundled
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Resolves all $ref pointers in a schema and returns a new schema without any $ref pointers.
|
|
35
|
-
*/
|
|
36
|
-
function dereferenceSync(schema, setOriginalRef) {
|
|
37
|
-
if (typeof schema === "boolean") return schema;
|
|
38
|
-
const visitedNodes = /* @__PURE__ */ new Set();
|
|
39
|
-
const cloned = structuredClone(schema);
|
|
40
|
-
function resolve(current) {
|
|
41
|
-
if (typeof current === "object" && current !== null) {
|
|
42
|
-
if (visitedNodes.has(current)) return current;
|
|
43
|
-
visitedNodes.add(current);
|
|
44
|
-
if (Array.isArray(current)) {
|
|
45
|
-
for (let index = 0; index < current.length; index++) current[index] = resolve(current[index]);
|
|
46
|
-
return current;
|
|
47
|
-
}
|
|
48
|
-
const obj = current;
|
|
49
|
-
if ("$ref" in current && typeof current["$ref"] === "string") {
|
|
50
|
-
const ref = current["$ref"];
|
|
51
|
-
delete current["$ref"];
|
|
52
|
-
const resolved = resolve(dereference.resolveRefSync(cloned, ref));
|
|
53
|
-
setOriginalRef(resolved, ref);
|
|
54
|
-
setOriginalRef(current, ref);
|
|
55
|
-
if (typeof resolved === "boolean") throw new Error("invalid schema");
|
|
56
|
-
for (const k in resolved) if (!(k in current)) obj[k] = resolved[k];
|
|
57
|
-
}
|
|
58
|
-
for (const key in current) obj[key] = resolve(obj[key]);
|
|
59
|
-
}
|
|
60
|
-
return current;
|
|
61
|
-
}
|
|
62
|
-
return resolve(cloned);
|
|
63
|
-
}
|
|
64
33
|
//#endregion
|
|
65
34
|
export { processDocument };
|
|
66
35
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-document.js","names":[],"sources":["../../src/utils/process-document.ts"],"sourcesContent":["import type { Document } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport { bundle } from '@scalar/json-magic/bundle';\nimport { upgrade } from '@scalar/openapi-upgrader';\nimport { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport
|
|
1
|
+
{"version":3,"file":"process-document.js","names":[],"sources":["../../src/utils/process-document.ts"],"sourcesContent":["import type { Document } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport { bundle } from '@scalar/json-magic/bundle';\nimport { upgrade } from '@scalar/openapi-upgrader';\nimport { fetchUrls, readFiles } from '@scalar/json-magic/bundle/plugins/node';\nimport type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport { dereferenceSync } from './schema/dereference';\n\nexport interface ProcessedDocument {\n /**\n * dereferenced document\n */\n dereferenced: NoReference<Document>;\n\n /**\n * Get raw $ref from dereferenced object\n */\n getRawRef: (obj: object) => string | undefined;\n\n bundled: Document;\n}\n\n/**\n * process & reference input document to a Fumadocs OpenAPI compatible format\n */\nexport async function processDocument(input: string | Document): Promise<ProcessedDocument> {\n const bundled: Document = await bundle(input, {\n plugins: [fetchUrls(), readFiles()],\n treeShake: true,\n hooks: {\n onResolveError(node) {\n throw new Error(`Failed to resolve ${node.$ref}`);\n },\n },\n })\n .then((v) => upgrade(v as never, '3.2') as Document)\n .catch((e) => {\n throw new Error(`[OpenAPI] Failed to resolve input: ${input}`, {\n cause: e,\n });\n });\n\n /**\n * Dereferenced value and its original `$ref` value\n */\n const dereferenceMap = new Map<object, string>();\n\n return {\n dereferenced: dereferenceSync(bundled as JSONSchema, (schema, ref) => {\n dereferenceMap.set(schema as object, ref);\n }) as NoReference<Document>,\n getRawRef(obj) {\n return dereferenceMap.get(obj);\n },\n bundled,\n };\n}\n"],"mappings":";;;;;;;;AAyBA,eAAsB,gBAAgB,OAAsD;CAC1F,MAAM,UAAoB,MAAM,OAAO,OAAO;EAC5C,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;EACnC,WAAW;EACX,OAAO,EACL,eAAe,MAAM;AACnB,SAAM,IAAI,MAAM,qBAAqB,KAAK,OAAO;KAEpD;EACF,CAAC,CACC,MAAM,MAAM,QAAQ,GAAY,MAAM,CAAa,CACnD,OAAO,MAAM;AACZ,QAAM,IAAI,MAAM,sCAAsC,SAAS,EAC7D,OAAO,GACR,CAAC;GACF;;;;CAKJ,MAAM,iCAAiB,IAAI,KAAqB;AAEhD,QAAO;EACL,cAAc,gBAAgB,UAAwB,QAAQ,QAAQ;AACpE,kBAAe,IAAI,QAAkB,IAAI;IACzC;EACF,UAAU,KAAK;AACb,UAAO,eAAe,IAAI,IAAI;;EAEhC;EACD"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { resolveRefSync } from "./resolve-ref.js";
|
|
2
|
+
//#region src/utils/schema/dereference.ts
|
|
3
|
+
/**
|
|
4
|
+
* Resolves all $ref pointers in a schema and returns a new schema without any $ref pointers.
|
|
5
|
+
*/
|
|
6
|
+
function dereferenceSync(schema, setOriginalRef) {
|
|
7
|
+
if (typeof schema === "boolean") return schema;
|
|
8
|
+
const visitedNodes = /* @__PURE__ */ new Set();
|
|
9
|
+
const cloned = structuredClone(schema);
|
|
10
|
+
function resolve(current) {
|
|
11
|
+
if (typeof current === "object" && current !== null) {
|
|
12
|
+
if (visitedNodes.has(current)) return current;
|
|
13
|
+
visitedNodes.add(current);
|
|
14
|
+
if (Array.isArray(current)) {
|
|
15
|
+
for (let index = 0; index < current.length; index++) current[index] = resolve(current[index]);
|
|
16
|
+
return current;
|
|
17
|
+
}
|
|
18
|
+
const obj = current;
|
|
19
|
+
if ("$ref" in current && typeof current["$ref"] === "string") {
|
|
20
|
+
const ref = current["$ref"];
|
|
21
|
+
delete current["$ref"];
|
|
22
|
+
const resolved = resolve(resolveRefSync(ref, cloned));
|
|
23
|
+
setOriginalRef(resolved, ref);
|
|
24
|
+
setOriginalRef(current, ref);
|
|
25
|
+
if (typeof resolved === "boolean") throw new Error("invalid schema");
|
|
26
|
+
for (const k in resolved) if (!(k in current)) obj[k] = resolved[k];
|
|
27
|
+
}
|
|
28
|
+
for (const key in current) obj[key] = resolve(obj[key]);
|
|
29
|
+
}
|
|
30
|
+
return current;
|
|
31
|
+
}
|
|
32
|
+
return resolve(cloned);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { dereferenceSync };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=dereference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dereference.js","names":[],"sources":["../../../src/utils/schema/dereference.ts"],"sourcesContent":["import type { JSONSchema } from 'json-schema-typed/draft-2020-12';\nimport { resolveRefSync } from './resolve-ref';\n\n/**\n * Resolves all $ref pointers in a schema and returns a new schema without any $ref pointers.\n */\nexport function dereferenceSync(\n schema: JSONSchema,\n setOriginalRef: (schema: JSONSchema, ref: string) => void,\n): JSONSchema {\n if (typeof schema === 'boolean') return schema;\n const visitedNodes = new Set<unknown>();\n const cloned = structuredClone(schema);\n\n function resolve(current: unknown): JSONSchema {\n if (typeof current === 'object' && current !== null) {\n // make sure we don't visit the same node twice\n if (visitedNodes.has(current)) {\n return current;\n }\n visitedNodes.add(current);\n\n if (Array.isArray(current)) {\n // array\n for (let index = 0; index < current.length; index++) {\n current[index] = resolve(current[index]);\n }\n\n return current as JSONSchema;\n }\n\n const obj = current as Record<string, unknown>;\n\n // object\n if ('$ref' in current && typeof current['$ref'] === 'string') {\n const ref = current['$ref'];\n delete current['$ref'];\n const resolved = resolve(resolveRefSync(ref, cloned) as JSONSchema);\n setOriginalRef(resolved, ref);\n setOriginalRef(current as JSONSchema, ref);\n\n if (typeof resolved === 'boolean') throw new Error('invalid schema');\n for (const k in resolved) {\n if (!(k in current)) {\n obj[k] = resolved[k as never];\n }\n }\n }\n\n for (const key in current) {\n obj[key] = resolve(obj[key]);\n }\n }\n\n return current as JSONSchema;\n }\n\n return resolve(cloned);\n}\n"],"mappings":";;;;;AAMA,SAAgB,gBACd,QACA,gBACY;AACZ,KAAI,OAAO,WAAW,UAAW,QAAO;CACxC,MAAM,+BAAe,IAAI,KAAc;CACvC,MAAM,SAAS,gBAAgB,OAAO;CAEtC,SAAS,QAAQ,SAA8B;AAC7C,MAAI,OAAO,YAAY,YAAY,YAAY,MAAM;AAEnD,OAAI,aAAa,IAAI,QAAQ,CAC3B,QAAO;AAET,gBAAa,IAAI,QAAQ;AAEzB,OAAI,MAAM,QAAQ,QAAQ,EAAE;AAE1B,SAAK,IAAI,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,QAC1C,SAAQ,SAAS,QAAQ,QAAQ,OAAO;AAG1C,WAAO;;GAGT,MAAM,MAAM;AAGZ,OAAI,UAAU,WAAW,OAAO,QAAQ,YAAY,UAAU;IAC5D,MAAM,MAAM,QAAQ;AACpB,WAAO,QAAQ;IACf,MAAM,WAAW,QAAQ,eAAe,KAAK,OAAO,CAAe;AACnE,mBAAe,UAAU,IAAI;AAC7B,mBAAe,SAAuB,IAAI;AAE1C,QAAI,OAAO,aAAa,UAAW,OAAM,IAAI,MAAM,iBAAiB;AACpE,SAAK,MAAM,KAAK,SACd,KAAI,EAAE,KAAK,SACT,KAAI,KAAK,SAAS;;AAKxB,QAAK,MAAM,OAAO,QAChB,KAAI,OAAO,QAAQ,IAAI,KAAK;;AAIhC,SAAO;;AAGT,QAAO,QAAQ,OAAO"}
|