fumadocs-openapi 10.6.3 → 10.6.4
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 +8 -17
- package/dist/generate-file.d.ts +2 -2
- package/dist/generate-file.d.ts.map +1 -1
- package/dist/generate-file.js.map +1 -1
- package/dist/playground/client.d.ts +15 -19
- package/dist/playground/client.d.ts.map +1 -1
- package/dist/playground/client.js +30 -18
- package/dist/playground/client.js.map +1 -1
- package/dist/playground/schema.js +14 -35
- package/dist/playground/schema.js.map +1 -1
- package/dist/server/create.d.ts +1 -1
- package/dist/server/create.js +1 -1
- package/dist/server/create.js.map +1 -1
- package/dist/server/source-api.d.ts +2 -2
- package/dist/server/source-api.d.ts.map +1 -1
- package/dist/server/source-api.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/base.d.ts +10 -9
- package/dist/ui/base.d.ts.map +1 -1
- package/dist/ui/base.js +22 -0
- package/dist/ui/base.js.map +1 -1
- package/dist/ui/create-client.d.ts.map +1 -1
- package/dist/ui/create-client.js +18 -13
- package/dist/ui/create-client.js.map +1 -1
- package/dist/ui/operation/get-example-requests.js +2 -2
- package/dist/ui/operation/get-example-requests.js.map +1 -1
- package/dist/ui/operation/index.js +5 -6
- package/dist/ui/operation/index.js.map +1 -1
- package/dist/ui/operation/response-tabs.d.ts +1 -1
- package/dist/ui/schema/index.d.ts +1 -1
- package/dist/utils/deep-equal.js +8 -4
- package/dist/utils/deep-equal.js.map +1 -1
- package/dist/utils/document/dereference.d.ts +18 -0
- package/dist/utils/document/dereference.d.ts.map +1 -0
- package/dist/utils/document/dereference.js +21 -0
- package/dist/utils/document/dereference.js.map +1 -0
- package/dist/utils/document/process.d.ts +7 -0
- package/dist/utils/document/process.d.ts.map +1 -0
- package/dist/utils/{process-document.js → document/process.js} +5 -18
- package/dist/utils/document/process.js.map +1 -0
- package/dist/utils/is-plain-object.js +10 -0
- package/dist/utils/is-plain-object.js.map +1 -0
- package/dist/utils/pages/builder.d.ts +4 -4
- package/dist/utils/pages/builder.d.ts.map +1 -1
- package/dist/utils/pages/builder.js.map +1 -1
- package/dist/utils/pages/preset-auto.d.ts +2 -2
- package/dist/utils/pages/preset-auto.d.ts.map +1 -1
- package/dist/utils/pages/preset-auto.js.map +1 -1
- package/dist/utils/pages/to-text.js.map +1 -1
- package/dist/utils/remove-undefined.js +10 -8
- package/dist/utils/remove-undefined.js.map +1 -1
- package/dist/utils/schema/index.d.ts +7 -2
- package/dist/utils/schema/index.d.ts.map +1 -1
- package/dist/utils/schema/index.js +21 -2
- package/dist/utils/schema/index.js.map +1 -1
- package/dist/utils/schema/pick.js +46 -0
- package/dist/utils/schema/pick.js.map +1 -0
- package/dist/utils/schema/ref.js +37 -0
- package/dist/utils/schema/ref.js.map +1 -0
- package/dist/utils/schema/resolve-ref.js +4 -12
- package/dist/utils/schema/resolve-ref.js.map +1 -1
- package/dist/utils/schema/to-string.js.map +1 -1
- package/package.json +3 -4
- package/dist/playground/index.d.ts +0 -22
- package/dist/playground/index.d.ts.map +0 -1
- package/dist/playground/index.js +0 -118
- package/dist/playground/index.js.map +0 -1
- package/dist/utils/process-document.d.ts +0 -18
- package/dist/utils/process-document.d.ts.map +0 -1
- package/dist/utils/process-document.js.map +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mergeAllOf } from "../utils/merge-schema.js";
|
|
2
2
|
import { schemaToString } from "../utils/schema/to-string.js";
|
|
3
|
-
import { resolveRefSync } from "../utils/schema/resolve-ref.js";
|
|
4
3
|
import { createContext, use, useMemo } from "react";
|
|
5
4
|
import { jsx } from "react/jsx-runtime";
|
|
6
5
|
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
@@ -20,7 +19,7 @@ const anyFields = {
|
|
|
20
19
|
items: true,
|
|
21
20
|
additionalProperties: true
|
|
22
21
|
};
|
|
23
|
-
function SchemaProvider({
|
|
22
|
+
function SchemaProvider({ schema, readOnly, writeOnly, children }) {
|
|
24
23
|
const ajv = useMemo(() => new Ajv2020({
|
|
25
24
|
strict: false,
|
|
26
25
|
validateSchema: false,
|
|
@@ -28,12 +27,12 @@ function SchemaProvider({ references, readOnly, writeOnly, children }) {
|
|
|
28
27
|
}), []);
|
|
29
28
|
return /* @__PURE__ */ jsx(SchemaContext.Provider, {
|
|
30
29
|
value: useMemo(() => ({
|
|
31
|
-
|
|
30
|
+
schema,
|
|
32
31
|
ajv,
|
|
33
32
|
readOnly,
|
|
34
33
|
writeOnly
|
|
35
34
|
}), [
|
|
36
|
-
|
|
35
|
+
schema,
|
|
37
36
|
ajv,
|
|
38
37
|
readOnly,
|
|
39
38
|
writeOnly
|
|
@@ -52,7 +51,7 @@ function useSchemaScope() {
|
|
|
52
51
|
* @param depth - The depth to avoid duplicated field name with same schema (e.g. nested `oneOf`).
|
|
53
52
|
*/
|
|
54
53
|
function useFieldInfo(fieldName, schema, depth = 0) {
|
|
55
|
-
const { ajv
|
|
54
|
+
const { ajv } = use(SchemaContext);
|
|
56
55
|
const engine = useDataEngine();
|
|
57
56
|
const { generateDefault } = useSchemaUtils();
|
|
58
57
|
const [info, setInfo] = useFieldValue([], { stf: useNamespace({
|
|
@@ -63,10 +62,7 @@ function useFieldInfo(fieldName, schema, depth = 0) {
|
|
|
63
62
|
const union = getUnion(schema);
|
|
64
63
|
if (union) {
|
|
65
64
|
const [members, field] = union;
|
|
66
|
-
out.oneOf = members.findIndex((item) => ajv.validate(
|
|
67
|
-
...item,
|
|
68
|
-
...references
|
|
69
|
-
} : item, value));
|
|
65
|
+
out.oneOf = members.findIndex((item) => ajv.validate(item, value));
|
|
70
66
|
if (out.oneOf === -1) out.oneOf = 0;
|
|
71
67
|
out.unionField = field;
|
|
72
68
|
}
|
|
@@ -75,7 +71,6 @@ function useFieldInfo(fieldName, schema, depth = 0) {
|
|
|
75
71
|
out.selectedType = types.find((type) => {
|
|
76
72
|
return ajv.validate({
|
|
77
73
|
...schema,
|
|
78
|
-
...references,
|
|
79
74
|
type
|
|
80
75
|
}, value);
|
|
81
76
|
}) ?? types[0];
|
|
@@ -105,45 +100,29 @@ function useFieldInfo(fieldName, schema, depth = 0) {
|
|
|
105
100
|
};
|
|
106
101
|
}
|
|
107
102
|
function useSchemaUtils() {
|
|
108
|
-
const {
|
|
103
|
+
const { schema, readOnly } = use(SchemaContext);
|
|
109
104
|
return {
|
|
110
105
|
generateDefault(schema) {
|
|
111
106
|
return sample(schema, {
|
|
112
107
|
skipNonRequired: true,
|
|
113
|
-
skipReadOnly:
|
|
108
|
+
skipReadOnly: !readOnly,
|
|
114
109
|
quiet: true
|
|
115
|
-
}
|
|
110
|
+
});
|
|
116
111
|
},
|
|
117
112
|
schemaToString(value, flags) {
|
|
118
|
-
return schemaToString(value,
|
|
119
|
-
dereferenced: dereference(s, references),
|
|
120
|
-
raw: s
|
|
121
|
-
}), flags);
|
|
113
|
+
return schemaToString(value, schema, flags);
|
|
122
114
|
}
|
|
123
115
|
};
|
|
124
116
|
}
|
|
125
117
|
/**
|
|
126
|
-
*
|
|
118
|
+
* merge `allOf`.
|
|
127
119
|
*/
|
|
128
120
|
function useResolvedSchema(raw) {
|
|
129
|
-
const { references } = use(SchemaContext);
|
|
130
121
|
return useMemo(() => {
|
|
131
|
-
|
|
132
|
-
if (typeof
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
return dereference(schema, references);
|
|
136
|
-
} });
|
|
137
|
-
if (typeof merged === "boolean") return anyFields;
|
|
138
|
-
return merged;
|
|
139
|
-
}
|
|
140
|
-
return schema;
|
|
141
|
-
}, [raw, references]);
|
|
142
|
-
}
|
|
143
|
-
function dereference(schema, references) {
|
|
144
|
-
if (typeof schema === "boolean") return schema;
|
|
145
|
-
if (schema.$ref) return resolveRefSync(schema.$ref, references);
|
|
146
|
-
return schema;
|
|
122
|
+
let out = raw;
|
|
123
|
+
if (typeof out === "object" && out.allOf) out = mergeAllOf(out);
|
|
124
|
+
return typeof out === "boolean" ? anyFields : out;
|
|
125
|
+
}, [raw]);
|
|
147
126
|
}
|
|
148
127
|
function getUnion(schema) {
|
|
149
128
|
if (schema.anyOf) return [schema.anyOf, "anyOf"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../src/playground/schema.tsx"],"sourcesContent":["import { Ajv2020 } from 'ajv/dist/2020';\nimport { createContext, ReactNode, use, useMemo } from 'react';\nimport type { ParsedSchema, ResolvedSchema } from '@/utils/schema';\nimport { mergeAllOf } from '@/utils/merge-schema';\nimport { FieldKey, useDataEngine, useFieldValue, useNamespace } from '@fumari/stf';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { sample } from 'openapi-sampler';\nimport { FormatFlags, schemaToString } from '@/utils/schema/to-string';\nimport {
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../src/playground/schema.tsx"],"sourcesContent":["import { Ajv2020 } from 'ajv/dist/2020';\nimport { createContext, ReactNode, use, useMemo } from 'react';\nimport type { ParsedSchema, ResolvedSchema } from '@/utils/schema';\nimport { mergeAllOf } from '@/utils/merge-schema';\nimport { FieldKey, useDataEngine, useFieldValue, useNamespace } from '@fumari/stf';\nimport { stringifyFieldKey } from '@fumari/stf/lib/utils';\nimport { sample } from 'openapi-sampler';\nimport { FormatFlags, schemaToString } from '@/utils/schema/to-string';\nimport { DereferencedDocument } from '@/utils/document/dereference';\n\ninterface SchemaContextType extends SchemaScope {\n schema: DereferencedDocument;\n ajv: Ajv2020;\n}\n\nexport interface SchemaScope {\n /**\n * show write only fields\n */\n writeOnly: boolean;\n\n /**\n * show read only fields\n */\n readOnly: boolean;\n}\n\ntype UnionField = 'anyOf' | 'oneOf';\n\nexport interface FieldInfo {\n selectedType?: string;\n oneOf: number;\n\n /**\n * The actual field that represents union members.\n */\n unionField?: UnionField;\n}\n\nconst SchemaContext = createContext<SchemaContextType | undefined>(undefined);\nexport const anyFields = {\n type: ['string', 'number', 'boolean', 'array', 'object'],\n items: true,\n additionalProperties: true,\n} satisfies ParsedSchema;\n\nexport function SchemaProvider({\n schema,\n readOnly,\n writeOnly,\n children,\n}: Omit<SchemaContextType, 'ajv'> & { children: ReactNode }) {\n const ajv = useMemo(\n () =>\n new Ajv2020({\n strict: false,\n validateSchema: false,\n validateFormats: false,\n }),\n [],\n );\n\n return (\n <SchemaContext.Provider\n value={useMemo(\n () => ({ schema, ajv, readOnly, writeOnly }),\n [schema, ajv, readOnly, writeOnly],\n )}\n >\n {children}\n </SchemaContext.Provider>\n );\n}\n\nexport function useSchemaScope(): SchemaScope {\n return use(SchemaContext)!;\n}\n\n/**\n * A hook to store dynamic info of a field, such as selected schema of `oneOf`.\n *\n * @param fieldName - field name of form.\n * @param schema - The **resolved** JSON Schema to generate initial values.\n * @param depth - The depth to avoid duplicated field name with same schema (e.g. nested `oneOf`).\n */\nexport function useFieldInfo(\n fieldName: FieldKey,\n schema: Exclude<ParsedSchema, boolean>,\n depth = 0,\n): {\n info: FieldInfo;\n schema: Exclude<ParsedSchema, boolean>;\n updateInfo: (value: Partial<FieldInfo>) => void;\n} {\n const { ajv } = use(SchemaContext)!;\n const engine = useDataEngine();\n const { generateDefault } = useSchemaUtils();\n const fieldData = useNamespace({\n namespace: `field-info:${depth}:${stringifyFieldKey(fieldName)}`,\n initial(): FieldInfo {\n const value = engine.get(fieldName);\n const out: FieldInfo = {\n oneOf: -1,\n };\n const union = getUnion(schema);\n if (union) {\n const [members, field] = union;\n\n out.oneOf = members.findIndex((item) => ajv.validate(item, value));\n if (out.oneOf === -1) out.oneOf = 0;\n out.unionField = field;\n }\n\n if (Array.isArray(schema.type)) {\n const types = schema.type;\n\n out.selectedType =\n types.find((type) => {\n return ajv.validate({ ...schema, type }, value);\n }) ?? types[0];\n }\n\n return out;\n },\n });\n const [info, setInfo] = useFieldValue<FieldInfo>([], {\n stf: fieldData,\n });\n\n return {\n info,\n schema,\n updateInfo(value) {\n const updated = {\n ...info,\n ...value,\n };\n\n if (updated.oneOf === info.oneOf && updated.selectedType === info.selectedType) return;\n\n setInfo(updated);\n\n let valueSchema: ParsedSchema = schema;\n if (updated.unionField) {\n valueSchema = schema[updated.unionField]![updated.oneOf];\n } else if (updated.selectedType) {\n // must remove to `examples` to avoid invalid default values\n valueSchema = { ...schema, type: updated.selectedType, examples: undefined };\n }\n\n engine.update(fieldName, generateDefault(valueSchema));\n },\n };\n}\n\nexport function useSchemaUtils() {\n const { schema, readOnly } = use(SchemaContext)!;\n\n return {\n generateDefault(schema: ParsedSchema): unknown {\n return sample(schema as never, {\n skipNonRequired: true,\n skipReadOnly: !readOnly,\n quiet: true,\n });\n },\n schemaToString(value: ResolvedSchema, flags?: FormatFlags) {\n return schemaToString(value, schema, flags);\n },\n };\n}\n\n/**\n * merge `allOf`.\n */\nexport function useResolvedSchema(raw: ParsedSchema): Exclude<ParsedSchema, boolean> {\n return useMemo(() => {\n let out = raw;\n\n if (typeof out === 'object' && out.allOf) {\n out = mergeAllOf(out);\n }\n\n return typeof out === 'boolean' ? anyFields : out;\n }, [raw]);\n}\n\nfunction getUnion(\n schema: Exclude<ParsedSchema, boolean>,\n): [readonly ParsedSchema[], UnionField] | undefined {\n if (schema.anyOf) {\n return [schema.anyOf, 'anyOf'];\n }\n\n if (schema.oneOf) return [schema.oneOf, 'oneOf'];\n}\n"],"mappings":";;;;;;;;;AAuCA,MAAM,gBAAgB,cAA6C,KAAA,EAAU;AAC7E,MAAa,YAAY;CACvB,MAAM;EAAC;EAAU;EAAU;EAAW;EAAS;EAAS;CACxD,OAAO;CACP,sBAAsB;CACvB;AAED,SAAgB,eAAe,EAC7B,QACA,UACA,WACA,YAC2D;CAC3D,MAAM,MAAM,cAER,IAAI,QAAQ;EACV,QAAQ;EACR,gBAAgB;EAChB,iBAAiB;EAClB,CAAC,EACJ,EAAE,CACH;AAED,QACE,oBAAC,cAAc,UAAf;EACE,OAAO,eACE;GAAE;GAAQ;GAAK;GAAU;GAAW,GAC3C;GAAC;GAAQ;GAAK;GAAU;GAAU,CACnC;EAEA;EACsB,CAAA;;AAI7B,SAAgB,iBAA8B;AAC5C,QAAO,IAAI,cAAc;;;;;;;;;AAU3B,SAAgB,aACd,WACA,QACA,QAAQ,GAKR;CACA,MAAM,EAAE,QAAQ,IAAI,cAAc;CAClC,MAAM,SAAS,eAAe;CAC9B,MAAM,EAAE,oBAAoB,gBAAgB;CA6B5C,MAAM,CAAC,MAAM,WAAW,cAAyB,EAAE,EAAE,EACnD,KA7BgB,aAAa;EAC7B,WAAW,cAAc,MAAM,GAAG,kBAAkB,UAAU;EAC9D,UAAqB;GACnB,MAAM,QAAQ,OAAO,IAAI,UAAU;GACnC,MAAM,MAAiB,EACrB,OAAO,IACR;GACD,MAAM,QAAQ,SAAS,OAAO;AAC9B,OAAI,OAAO;IACT,MAAM,CAAC,SAAS,SAAS;AAEzB,QAAI,QAAQ,QAAQ,WAAW,SAAS,IAAI,SAAS,MAAM,MAAM,CAAC;AAClE,QAAI,IAAI,UAAU,GAAI,KAAI,QAAQ;AAClC,QAAI,aAAa;;AAGnB,OAAI,MAAM,QAAQ,OAAO,KAAK,EAAE;IAC9B,MAAM,QAAQ,OAAO;AAErB,QAAI,eACF,MAAM,MAAM,SAAS;AACnB,YAAO,IAAI,SAAS;MAAE,GAAG;MAAQ;MAAM,EAAE,MAAM;MAC/C,IAAI,MAAM;;AAGhB,UAAO;;EAEV,CAAC,EAGD,CAAC;AAEF,QAAO;EACL;EACA;EACA,WAAW,OAAO;GAChB,MAAM,UAAU;IACd,GAAG;IACH,GAAG;IACJ;AAED,OAAI,QAAQ,UAAU,KAAK,SAAS,QAAQ,iBAAiB,KAAK,aAAc;AAEhF,WAAQ,QAAQ;GAEhB,IAAI,cAA4B;AAChC,OAAI,QAAQ,WACV,eAAc,OAAO,QAAQ,YAAa,QAAQ;YACzC,QAAQ,aAEjB,eAAc;IAAE,GAAG;IAAQ,MAAM,QAAQ;IAAc,UAAU,KAAA;IAAW;AAG9E,UAAO,OAAO,WAAW,gBAAgB,YAAY,CAAC;;EAEzD;;AAGH,SAAgB,iBAAiB;CAC/B,MAAM,EAAE,QAAQ,aAAa,IAAI,cAAc;AAE/C,QAAO;EACL,gBAAgB,QAA+B;AAC7C,UAAO,OAAO,QAAiB;IAC7B,iBAAiB;IACjB,cAAc,CAAC;IACf,OAAO;IACR,CAAC;;EAEJ,eAAe,OAAuB,OAAqB;AACzD,UAAO,eAAe,OAAO,QAAQ,MAAM;;EAE9C;;;;;AAMH,SAAgB,kBAAkB,KAAmD;AACnF,QAAO,cAAc;EACnB,IAAI,MAAM;AAEV,MAAI,OAAO,QAAQ,YAAY,IAAI,MACjC,OAAM,WAAW,IAAI;AAGvB,SAAO,OAAO,QAAQ,YAAY,YAAY;IAC7C,CAAC,IAAI,CAAC;;AAGX,SAAS,SACP,QACmD;AACnD,KAAI,OAAO,MACT,QAAO,CAAC,OAAO,OAAO,QAAQ;AAGhC,KAAI,OAAO,MAAO,QAAO,CAAC,OAAO,OAAO,QAAQ"}
|
package/dist/server/create.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ProcessedDocument } from "../utils/document/process.js";
|
|
1
2
|
import { InlineCodeUsageGenerator } from "../requests/generators/index.js";
|
|
2
3
|
import { createProxy } from "./proxy.js";
|
|
3
4
|
import { Document } from "../types.js";
|
|
4
|
-
import { ProcessedDocument } from "../utils/process-document.js";
|
|
5
5
|
|
|
6
6
|
//#region src/server/create.d.ts
|
|
7
7
|
/**
|
package/dist/server/create.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createProxy } from "./proxy.js";
|
|
2
|
-
import { processDocument } from "../utils/process
|
|
2
|
+
import { processDocument } from "../utils/document/process.js";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
//#region src/server/create.ts
|
|
5
5
|
function createOpenAPI(options = {}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","names":[],"sources":["../../src/server/create.ts"],"sourcesContent":["import { createProxy } from '@/server/proxy';\nimport { processDocument, type ProcessedDocument } from '@/utils/process
|
|
1
|
+
{"version":3,"file":"create.js","names":[],"sources":["../../src/server/create.ts"],"sourcesContent":["import { createProxy } from '@/server/proxy';\nimport { processDocument, type ProcessedDocument } from '@/utils/document/process';\nimport type { Document } from '@/types';\nimport type { InlineCodeUsageGenerator } from '@/requests/generators';\nimport fs from 'node:fs';\n\n/**\n * schema id -> file path, URL, or downloaded schema object\n */\ntype SchemaMap = Record<string, string | Document>;\ntype ProcessedSchemaMap = Record<string, ProcessedDocument>;\n\nexport interface OpenAPIOptions {\n /**\n * Schema files, can be:\n * - URL\n * - file path\n * - a function returning records of downloaded schemas.\n */\n input?: string[] | (() => SchemaMap | Promise<SchemaMap>);\n\n disableCache?: boolean;\n\n /**\n * The url of proxy to avoid CORS issues\n */\n proxyUrl?: string;\n}\n\nexport interface OpenAPIServer {\n createProxy: typeof createProxy;\n getSchemas: () => Promise<ProcessedSchemaMap>;\n getSchema: (document: string) => Promise<ProcessedDocument>;\n /** @private internal API */\n _getWatchPaths: () => string[];\n readonly options: OpenAPIOptions;\n}\n\nexport function createOpenAPI(options: OpenAPIOptions = {}): OpenAPIServer {\n const { input = [], disableCache = false } = options;\n let schemas: Promise<ProcessedSchemaMap> | undefined;\n\n async function getSchemas(): Promise<ProcessedSchemaMap> {\n if (Array.isArray(input)) {\n const entries = await Promise.all(\n input.map(async (item) => [item, await processDocument(item)]),\n );\n return Object.fromEntries(entries);\n } else {\n const entries = await Promise.all(\n Object.entries(await input()).map(async ([k, v]) => [k, await processDocument(v)]),\n );\n return Object.fromEntries(entries);\n }\n }\n\n return {\n options,\n createProxy,\n _getWatchPaths() {\n const keys = Array.isArray(input) ? input : Object.keys(input);\n return keys.filter((key) => !URL.canParse(key) && fs.existsSync(key));\n },\n async getSchema(document) {\n const schemas = await this.getSchemas();\n if (document in schemas) return schemas[document];\n\n console.warn(\n `[Fumadocs OpenAPI] the document \"${document}\" is not listed in the input array, this may not be expected.`,\n );\n // do not cache unlisted documents\n return processDocument(document);\n },\n async getSchemas() {\n if (disableCache) return getSchemas();\n\n return (schemas ??= getSchemas());\n },\n };\n}\n\n/**\n * @deprecated\n */\nexport function createCodeSample<T>(\n options: InlineCodeUsageGenerator<T>,\n): InlineCodeUsageGenerator<T> {\n return options;\n}\n"],"mappings":";;;;AAsCA,SAAgB,cAAc,UAA0B,EAAE,EAAiB;CACzE,MAAM,EAAE,QAAQ,EAAE,EAAE,eAAe,UAAU;CAC7C,IAAI;CAEJ,eAAe,aAA0C;AACvD,MAAI,MAAM,QAAQ,MAAM,EAAE;GACxB,MAAM,UAAU,MAAM,QAAQ,IAC5B,MAAM,IAAI,OAAO,SAAS,CAAC,MAAM,MAAM,gBAAgB,KAAK,CAAC,CAAC,CAC/D;AACD,UAAO,OAAO,YAAY,QAAQ;SAC7B;GACL,MAAM,UAAU,MAAM,QAAQ,IAC5B,OAAO,QAAQ,MAAM,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,MAAM,gBAAgB,EAAE,CAAC,CAAC,CACnF;AACD,UAAO,OAAO,YAAY,QAAQ;;;AAItC,QAAO;EACL;EACA;EACA,iBAAiB;AAEf,WADa,MAAM,QAAQ,MAAM,GAAG,QAAQ,OAAO,KAAK,MAAM,EAClD,QAAQ,QAAQ,CAAC,IAAI,SAAS,IAAI,IAAI,GAAG,WAAW,IAAI,CAAC;;EAEvE,MAAM,UAAU,UAAU;GACxB,MAAM,UAAU,MAAM,KAAK,YAAY;AACvC,OAAI,YAAY,QAAS,QAAO,QAAQ;AAExC,WAAQ,KACN,oCAAoC,SAAS,+DAC9C;AAED,UAAO,gBAAgB,SAAS;;EAElC,MAAM,aAAa;AACjB,OAAI,aAAc,QAAO,YAAY;AAErC,UAAQ,YAAY,YAAY;;EAEnC;;;;;AAMH,SAAgB,iBACd,SAC6B;AAC7B,QAAO"}
|
|
@@ -2,7 +2,7 @@ import { OpenAPIServer } from "./create.js";
|
|
|
2
2
|
import { ApiPageProps } from "../ui/api-page.js";
|
|
3
3
|
import { SchemaToPagesOptions } from "../utils/pages/preset-auto.js";
|
|
4
4
|
import { ClientApiPageProps } from "../ui/create-client.js";
|
|
5
|
-
import {
|
|
5
|
+
import { DereferencedDocument } from "../utils/document/dereference.js";
|
|
6
6
|
import { LoaderPlugin, MetaData, PageData, PageTreeTransformer, Source } from "fumadocs-core/source";
|
|
7
7
|
import { StructuredData } from "fumadocs-core/mdx-plugins";
|
|
8
8
|
import { TOCItemType } from "fumadocs-core/toc";
|
|
@@ -28,7 +28,7 @@ interface OpenAPIPageData extends PageData {
|
|
|
28
28
|
getAPIPageProps: () => ApiPageProps;
|
|
29
29
|
getSchema: () => {
|
|
30
30
|
id: string;
|
|
31
|
-
} &
|
|
31
|
+
} & DereferencedDocument;
|
|
32
32
|
getClientAPIPageProps: () => Promise<ClientApiPageProps>;
|
|
33
33
|
structuredData: StructuredData;
|
|
34
34
|
toc: TOCItemType[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-api.d.ts","names":[],"sources":["../../src/server/source-api.tsx"],"mappings":";;;;;;;;;;;YA2BmB,QAAA;IAJ0C;;;IAQzD,QAAA,GAAW,mBAAA;EAAA;AAAA;AAAA,UAIE,mBAAA;EACf,MAAA;EACA,OAAA;AAAA;AAFF;;;AAAA,iBAQgB,aAAA,CAAA,GAAiB,YAAA;AAAA,UAuCvB,eAAA,SAAwB,QAAA;EAChC,eAAA,QAAuB,YAAA;EACvB,SAAA;IAAmB,EAAA;EAAA,IAAe,
|
|
1
|
+
{"version":3,"file":"source-api.d.ts","names":[],"sources":["../../src/server/source-api.tsx"],"mappings":";;;;;;;;;;;YA2BmB,QAAA;IAJ0C;;;IAQzD,QAAA,GAAW,mBAAA;EAAA;AAAA;AAAA,UAIE,mBAAA;EACf,MAAA;EACA,OAAA;AAAA;AAFF;;;AAAA,iBAQgB,aAAA,CAAA,GAAiB,YAAA;AAAA,UAuCvB,eAAA,SAAwB,QAAA;EAChC,eAAA,QAAuB,YAAA;EACvB,SAAA;IAAmB,EAAA;EAAA,IAAe,oBAAA;EAClC,qBAAA,QAA6B,OAAA,CAAQ,kBAAA;EACrC,cAAA,EAAgB,cAAA;EAChB,GAAA,EAAK,WAAA;AAAA;AAAA,UAGG,WAAA;EACR,WAAA;AAAA;;;;iBAMoB,aAAA,CACpB,MAAA,EAAQ,aAAA,EACR,OAAA,GAAS,oBAAA;EACP,OAAA,WAlBsC;EAoBtC,IAAA,aAAiB,WAAA;AAAA,IAElB,OAAA,CACD,MAAA;EACE,QAAA,EAAU,QAAA;EACV,QAAA,EAAU,eAAA;AAAA;;;;iBAqIE,kBAAA,CAAA,GAAsB,mBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-api.js","names":[],"sources":["../../src/server/source-api.tsx"],"sourcesContent":["import { MethodLabel } from '@/ui/components/method-label';\nimport {\n PathUtils,\n type LoaderPlugin,\n type MetaData,\n type PageData,\n type PageTreeTransformer,\n type Source,\n type VirtualFile,\n} from 'fumadocs-core/source';\nimport type { OpenAPIServer } from '@/server/create';\nimport type { SchemaToPagesOptions } from '@/utils/pages/preset-auto';\nimport type { ApiPageProps } from '@/ui/api-page';\nimport type { StructuredData } from 'fumadocs-core/mdx-plugins';\nimport type { TOCItemType } from 'fumadocs-core/toc';\nimport type {
|
|
1
|
+
{"version":3,"file":"source-api.js","names":[],"sources":["../../src/server/source-api.tsx"],"sourcesContent":["import { MethodLabel } from '@/ui/components/method-label';\nimport {\n PathUtils,\n type LoaderPlugin,\n type MetaData,\n type PageData,\n type PageTreeTransformer,\n type Source,\n type VirtualFile,\n} from 'fumadocs-core/source';\nimport type { OpenAPIServer } from '@/server/create';\nimport type { SchemaToPagesOptions } from '@/utils/pages/preset-auto';\nimport type { ApiPageProps } from '@/ui/api-page';\nimport type { StructuredData } from 'fumadocs-core/mdx-plugins';\nimport type { TOCItemType } from 'fumadocs-core/toc';\nimport type { DereferencedDocument } from '@/utils/document/dereference';\nimport type {\n OperationOutput,\n OutputEntry,\n PageOutput,\n WebhookOutput,\n} from '@/utils/pages/builder';\nimport path from 'node:path';\nimport type { ClientApiPageProps } from '@/ui/create-client';\nimport { toStaticData } from '@/utils/pages/to-static-data';\n\ndeclare module 'fumadocs-core/source' {\n export interface PageData {\n /**\n * Added by Fumadocs OpenAPI\n */\n _openapi?: InternalOpenAPIMeta;\n }\n}\n\nexport interface InternalOpenAPIMeta {\n method?: string;\n webhook?: boolean;\n}\n\n/**\n * Fumadocs Source API integration, pass this to `plugins` array in `loader()`.\n */\nexport function openapiPlugin(): LoaderPlugin {\n return {\n name: 'fumadocs:openapi',\n enforce: 'pre',\n transformPageTree: {\n file(node, filePath) {\n if (!filePath) return node;\n const file = this.storage.read(filePath);\n if (!file || file.format !== 'page') return node;\n\n const openApiData = file.data._openapi;\n if (!openApiData || typeof openApiData !== 'object') return node;\n\n if (openApiData.webhook) {\n node.name = (\n <>\n {node.name}{' '}\n <span className=\"ms-auto border border-current px-1 rounded-lg text-xs text-nowrap font-mono\">\n Webhook\n </span>\n </>\n );\n } else if (openApiData.method) {\n node.name = (\n <>\n {node.name}{' '}\n <MethodLabel className=\"ms-auto text-xs text-nowrap\">\n {openApiData.method}\n </MethodLabel>\n </>\n );\n }\n\n return node;\n },\n },\n };\n}\n\ninterface OpenAPIPageData extends PageData {\n getAPIPageProps: () => ApiPageProps;\n getSchema: () => { id: string } & DereferencedDocument;\n getClientAPIPageProps: () => Promise<ClientApiPageProps>;\n structuredData: StructuredData;\n toc: TOCItemType[];\n}\n\ninterface MetaOptions {\n folderStyle?: 'folder' | 'separator';\n}\n\n/**\n * Generate virtual pages for Fumadocs Source API\n */\nexport async function openapiSource(\n server: OpenAPIServer,\n options: SchemaToPagesOptions & {\n baseDir?: string;\n /** Generate `meta.json` files */\n meta?: boolean | MetaOptions;\n } = {},\n): Promise<\n Source<{\n metaData: MetaData;\n pageData: OpenAPIPageData;\n }>\n> {\n const { baseDir = '', meta = false } = options;\n const { createAutoPreset } = await import('@/utils/pages/preset-auto');\n const { fromServer } = await import('@/utils/pages/builder');\n const files: VirtualFile<{\n pageData: OpenAPIPageData;\n metaData: MetaData;\n }>[] = [];\n\n const entries = await fromServer(server, createAutoPreset(options));\n for (const [schemaId, list] of Object.entries(entries)) {\n const processed = await server.getSchema(schemaId);\n\n function onEntry(entry: PageOutput | OperationOutput | WebhookOutput) {\n const props = getProps(entry);\n\n files.push({\n type: 'page',\n path: `${baseDir}/${entry.path}`,\n data: {\n ...entry.info,\n getAPIPageProps() {\n return props;\n },\n async getClientAPIPageProps() {\n return {\n payload: {\n bundled: processed.bundled,\n proxyUrl: server.options.proxyUrl,\n },\n ...props,\n };\n },\n getSchema() {\n return {\n id: schemaId,\n ...processed,\n };\n },\n ...toStaticData(props, processed.dereferenced),\n _openapi: {\n method:\n entry.type === 'operation' || entry.type === 'webhook'\n ? entry.item.method\n : undefined,\n webhook: entry.type === 'webhook',\n },\n },\n });\n }\n\n function onEntries(entries: OutputEntry[], parent?: OutputEntry) {\n if (!meta) {\n for (const entry of entries) {\n if (entry.type === 'group') {\n onEntries(entry.entries, entry);\n } else {\n onEntry(entry);\n }\n }\n\n return;\n }\n\n const { folderStyle = 'folder' } = meta === true ? {} : meta;\n const pages: string[] = [];\n\n for (const entry of entries) {\n const relativePath = PathUtils.slash(\n parent ? path.relative(parent.path, entry.path) : entry.path,\n );\n\n if (entry.type === 'group') {\n onEntries(entry.entries, entry);\n if (folderStyle === 'folder') {\n pages.push(relativePath);\n } else {\n pages.push(`---${entry.info.title}---`, `...${relativePath}`);\n }\n } else {\n onEntry(entry);\n pages.push(relativePath.slice(0, -path.extname(entry.path).length));\n }\n }\n\n if (pages.length === 0) return;\n files.push({\n type: 'meta',\n path: path.join(baseDir, parent?.path ?? '', 'meta.json'),\n data: {\n title: parent?.info.title,\n description: parent?.info.description,\n pages,\n },\n });\n }\n\n onEntries(list);\n }\n\n return {\n files,\n };\n}\n\nfunction getProps(entry: PageOutput | OperationOutput | WebhookOutput): ApiPageProps {\n if (entry.type === 'operation')\n return {\n document: entry.schemaId,\n operations: [entry.item],\n showDescription: true,\n };\n if (entry.type === 'webhook')\n return {\n document: entry.schemaId,\n webhooks: [entry.item],\n showDescription: true,\n };\n\n return {\n showTitle: true,\n showDescription: true,\n document: entry.schemaId,\n operations: entry.operations,\n webhooks: entry.webhooks,\n };\n}\n\n/**\n * @deprecated use `openapiPlugin()`\n */\nexport function transformerOpenAPI(): PageTreeTransformer {\n return openapiPlugin().transformPageTree!;\n}\n"],"mappings":";;;;;;;;;AA2CA,SAAgB,gBAA8B;AAC5C,QAAO;EACL,MAAM;EACN,SAAS;EACT,mBAAmB,EACjB,KAAK,MAAM,UAAU;AACnB,OAAI,CAAC,SAAU,QAAO;GACtB,MAAM,OAAO,KAAK,QAAQ,KAAK,SAAS;AACxC,OAAI,CAAC,QAAQ,KAAK,WAAW,OAAQ,QAAO;GAE5C,MAAM,cAAc,KAAK,KAAK;AAC9B,OAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAE5D,OAAI,YAAY,QACd,MAAK,OACH,qBAAA,UAAA,EAAA,UAAA;IACG,KAAK;IAAM;IACZ,oBAAC,QAAD;KAAM,WAAU;eAA8E;KAEvF,CAAA;IACN,EAAA,CAAA;YAEI,YAAY,OACrB,MAAK,OACH,qBAAA,UAAA,EAAA,UAAA;IACG,KAAK;IAAM;IACZ,oBAAC,aAAD;KAAa,WAAU;eACpB,YAAY;KACD,CAAA;IACb,EAAA,CAAA;AAIP,UAAO;KAEV;EACF;;;;;AAkBH,eAAsB,cACpB,QACA,UAII,EAAE,EAMN;CACA,MAAM,EAAE,UAAU,IAAI,OAAO,UAAU;CACvC,MAAM,EAAE,qBAAqB,MAAM,OAAO;CAC1C,MAAM,EAAE,eAAe,MAAM,OAAO;CACpC,MAAM,QAGC,EAAE;CAET,MAAM,UAAU,MAAM,WAAW,QAAQ,iBAAiB,QAAQ,CAAC;AACnE,MAAK,MAAM,CAAC,UAAU,SAAS,OAAO,QAAQ,QAAQ,EAAE;EACtD,MAAM,YAAY,MAAM,OAAO,UAAU,SAAS;EAElD,SAAS,QAAQ,OAAqD;GACpE,MAAM,QAAQ,SAAS,MAAM;AAE7B,SAAM,KAAK;IACT,MAAM;IACN,MAAM,GAAG,QAAQ,GAAG,MAAM;IAC1B,MAAM;KACJ,GAAG,MAAM;KACT,kBAAkB;AAChB,aAAO;;KAET,MAAM,wBAAwB;AAC5B,aAAO;OACL,SAAS;QACP,SAAS,UAAU;QACnB,UAAU,OAAO,QAAQ;QAC1B;OACD,GAAG;OACJ;;KAEH,YAAY;AACV,aAAO;OACL,IAAI;OACJ,GAAG;OACJ;;KAEH,GAAG,aAAa,OAAO,UAAU,aAAa;KAC9C,UAAU;MACR,QACE,MAAM,SAAS,eAAe,MAAM,SAAS,YACzC,MAAM,KAAK,SACX,KAAA;MACN,SAAS,MAAM,SAAS;MACzB;KACF;IACF,CAAC;;EAGJ,SAAS,UAAU,SAAwB,QAAsB;AAC/D,OAAI,CAAC,MAAM;AACT,SAAK,MAAM,SAAS,QAClB,KAAI,MAAM,SAAS,QACjB,WAAU,MAAM,SAAS,MAAM;QAE/B,SAAQ,MAAM;AAIlB;;GAGF,MAAM,EAAE,cAAc,aAAa,SAAS,OAAO,EAAE,GAAG;GACxD,MAAM,QAAkB,EAAE;AAE1B,QAAK,MAAM,SAAS,SAAS;IAC3B,MAAM,eAAe,UAAU,MAC7B,SAAS,KAAK,SAAS,OAAO,MAAM,MAAM,KAAK,GAAG,MAAM,KACzD;AAED,QAAI,MAAM,SAAS,SAAS;AAC1B,eAAU,MAAM,SAAS,MAAM;AAC/B,SAAI,gBAAgB,SAClB,OAAM,KAAK,aAAa;SAExB,OAAM,KAAK,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,eAAe;WAE1D;AACL,aAAQ,MAAM;AACd,WAAM,KAAK,aAAa,MAAM,GAAG,CAAC,KAAK,QAAQ,MAAM,KAAK,CAAC,OAAO,CAAC;;;AAIvE,OAAI,MAAM,WAAW,EAAG;AACxB,SAAM,KAAK;IACT,MAAM;IACN,MAAM,KAAK,KAAK,SAAS,QAAQ,QAAQ,IAAI,YAAY;IACzD,MAAM;KACJ,OAAO,QAAQ,KAAK;KACpB,aAAa,QAAQ,KAAK;KAC1B;KACD;IACF,CAAC;;AAGJ,YAAU,KAAK;;AAGjB,QAAO,EACL,OACD;;AAGH,SAAS,SAAS,OAAmE;AACnF,KAAI,MAAM,SAAS,YACjB,QAAO;EACL,UAAU,MAAM;EAChB,YAAY,CAAC,MAAM,KAAK;EACxB,iBAAiB;EAClB;AACH,KAAI,MAAM,SAAS,UACjB,QAAO;EACL,UAAU,MAAM;EAChB,UAAU,CAAC,MAAM,KAAK;EACtB,iBAAiB;EAClB;AAEH,QAAO;EACL,WAAW;EACX,iBAAiB;EACjB,UAAU,MAAM;EAChB,YAAY,MAAM;EAClB,UAAU,MAAM;EACjB;;;;;AAMH,SAAgB,qBAA0C;AACxD,QAAO,eAAe,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { MediaAdapter } from "./requests/media/adapter.js";
|
|
2
|
-
import { NoReference } from "./utils/schema/index.js";
|
|
3
2
|
import { InlineCodeUsageGenerator } from "./requests/generators/index.js";
|
|
4
3
|
import { boundary_d_exports } from "./ui/client/boundary.js";
|
|
5
4
|
import { OpenAPIV3, OpenAPIV3_2 } from "./_openapi/types.js";
|
|
6
5
|
import { OpenAPIOptions } from "./server/create.js";
|
|
7
6
|
import { CreateAPIPageOptions } from "./ui/base.js";
|
|
8
|
-
import {
|
|
7
|
+
import { NoReference } from "./utils/schema/index.js";
|
|
8
|
+
import { DereferencedDocument } from "./utils/document/dereference.js";
|
|
9
9
|
import { HTMLAttributes, ReactNode } from "react";
|
|
10
10
|
|
|
11
11
|
//#region src/types.d.ts
|
|
@@ -26,7 +26,7 @@ type ExampleObject = OpenAPIV3_2.ExampleObject;
|
|
|
26
26
|
type MediaTypeObject = OpenAPIV3_2.MediaTypeObject;
|
|
27
27
|
type RequestBodyObject = OpenAPIV3_2.RequestBodyObject;
|
|
28
28
|
type MethodInformation = NoReference<OperationObject> & {
|
|
29
|
-
method:
|
|
29
|
+
method: HttpMethods;
|
|
30
30
|
'x-codeSamples'?: InlineCodeUsageGenerator[];
|
|
31
31
|
'x-selectedCodeSample'?: string;
|
|
32
32
|
'x-exclusiveCodeSample'?: string;
|
|
@@ -36,7 +36,7 @@ interface RenderContext extends Pick<OpenAPIOptions, 'proxyUrl'>, Omit<RequireKe
|
|
|
36
36
|
/**
|
|
37
37
|
* dereferenced schema
|
|
38
38
|
*/
|
|
39
|
-
schema:
|
|
39
|
+
schema: DereferencedDocument;
|
|
40
40
|
clientBoundary: typeof boundary_d_exports;
|
|
41
41
|
mediaAdapters: Record<string, MediaAdapter>;
|
|
42
42
|
renderHeading: (depth: number, text: string | ReactNode, props?: HTMLAttributes<HTMLHeadingElement> & {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;KASY,QAAA,GAAW,WAAA,CAAY,QAAA;AAAA,KACvB,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,oBAAA,GAAuB,WAAA,CAAY,oBAAA;AAAA,KACnC,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,SAAA,GAAY,WAAA,CAAY,SAAA;AAAA,KACxB,YAAA,GAAe,WAAA,CAAY,YAAA;AAAA,KAC3B,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,oBAAA,GAAuB,SAAA,CAAU,oBAAA;AAAA,KACjC,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,oBAAA,GAAuB,WAAA,CAAY,oBAAA;AAAA,KACnC,WAAA,GAAc,WAAA,CAAY,WAAA;AAAA,KAC1B,aAAA,GAAgB,WAAA,CAAY,aAAA;AAAA,KAC5B,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,iBAAA,GAAoB,WAAA,CAAY,iBAAA;AAAA,KAEhC,iBAAA,GAAoB,WAAA,CAAY,eAAA;EAC1C,MAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;;;;;;KASY,QAAA,GAAW,WAAA,CAAY,QAAA;AAAA,KACvB,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,oBAAA,GAAuB,WAAA,CAAY,oBAAA;AAAA,KACnC,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,SAAA,GAAY,WAAA,CAAY,SAAA;AAAA,KACxB,YAAA,GAAe,WAAA,CAAY,YAAA;AAAA,KAC3B,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,oBAAA,GAAuB,SAAA,CAAU,oBAAA;AAAA,KACjC,cAAA,GAAiB,WAAA,CAAY,cAAA;AAAA,KAC7B,oBAAA,GAAuB,WAAA,CAAY,oBAAA;AAAA,KACnC,WAAA,GAAc,WAAA,CAAY,WAAA;AAAA,KAC1B,aAAA,GAAgB,WAAA,CAAY,aAAA;AAAA,KAC5B,eAAA,GAAkB,WAAA,CAAY,eAAA;AAAA,KAC9B,iBAAA,GAAoB,WAAA,CAAY,iBAAA;AAAA,KAEhC,iBAAA,GAAoB,WAAA,CAAY,eAAA;EAC1C,MAAA,EAAQ,WAAA;EACR,eAAA,GAAkB,wBAAA;EAClB,sBAAA;EACA,uBAAA;AAAA;AAAA,KAGG,WAAA,oBAA+B,CAAA,IAAK,IAAA,CAAK,CAAA,EAAG,CAAA,IAAK,QAAA,CAAS,IAAA,CAAK,CAAA,EAAG,CAAA;AAAA,UAEtD,aAAA,SAEb,IAAA,CAAK,cAAA,eACL,IAAA,CACE,WAAA,CAAY,oBAAA;EA1BN;;;EAgCV,MAAA,EAAQ,oBAAA;EACR,cAAA,SAD4B,kBAAA;EAG5B,aAAA,EAAe,MAAA,SAAe,YAAA;EAE9B,aAAA,GACE,KAAA,UACA,IAAA,WAAe,SAAA,EACf,KAAA,GAAQ,cAAA,CAAe,kBAAA;IAAwB,EAAA;EAAA,MAC5C,SAAA;EACL,eAAA,GAAkB,IAAA,UAAc,IAAA,aAAiB,SAAA;AAAA;AAAA,KAGvC,gBAAA,cAA8B,WAAA,IAAe,CAAA,mBAAoB,IAAA,CAAK,CAAA,EAAG,CAAA;AAAA,KACzE,SAAA,MAAe,CAAA,GAAI,OAAA,CAAQ,CAAA"}
|
package/dist/ui/base.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { MediaAdapter } from "../requests/media/adapter.js";
|
|
2
|
-
import { NoReference } from "../utils/schema/index.js";
|
|
3
2
|
import { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from "../requests/generators/index.js";
|
|
4
3
|
import { ExampleRequestItem } from "./operation/get-example-requests.js";
|
|
5
4
|
import { APIPageClientOptions } from "./client/index.js";
|
|
@@ -9,7 +8,8 @@ import { ApiPageProps, OperationItem, WebhookItem } from "./api-page.js";
|
|
|
9
8
|
import { ResponseTab } from "./operation/response-tabs.js";
|
|
10
9
|
import { ClientCodeBlockProvider } from "./components/codeblock.js";
|
|
11
10
|
import { Awaitable, MethodInformation, RenderContext } from "../types.js";
|
|
12
|
-
import {
|
|
11
|
+
import { NoReference } from "../utils/schema/index.js";
|
|
12
|
+
import { DereferencedDocument } from "../utils/document/dereference.js";
|
|
13
13
|
import { FC, HTMLAttributes, ReactNode } from "react";
|
|
14
14
|
import { ShikiFactory } from "fumadocs-core/highlight/shiki";
|
|
15
15
|
import { JSONSchema } from "json-schema-typed";
|
|
@@ -26,6 +26,11 @@ interface GenerateTypeScriptDefinitionsContext extends RenderContext {
|
|
|
26
26
|
contentType: string;
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
+
interface APIPlaygroundProps {
|
|
30
|
+
path: string;
|
|
31
|
+
method: MethodInformation;
|
|
32
|
+
ctx: RenderContext;
|
|
33
|
+
}
|
|
29
34
|
interface CreateAPIPageOptions {
|
|
30
35
|
/**
|
|
31
36
|
* Generate TypeScript definitions from response schema.
|
|
@@ -140,11 +145,7 @@ interface CreateAPIPageOptions {
|
|
|
140
145
|
/**
|
|
141
146
|
* replace the server-side renderer
|
|
142
147
|
*/
|
|
143
|
-
render?: (props:
|
|
144
|
-
path: string;
|
|
145
|
-
method: MethodInformation;
|
|
146
|
-
ctx: RenderContext;
|
|
147
|
-
}) => Awaitable<ReactNode>;
|
|
148
|
+
render?: (props: APIPlaygroundProps) => ReactNode;
|
|
148
149
|
};
|
|
149
150
|
renderHeading?: (props: HTMLAttributes<HTMLHeadingElement>, depth: number) => ReactNode;
|
|
150
151
|
renderCodeBlock?: (props: {
|
|
@@ -154,9 +155,9 @@ interface CreateAPIPageOptions {
|
|
|
154
155
|
client?: APIPageClientOptions;
|
|
155
156
|
}
|
|
156
157
|
interface ServerApiPageProps extends Omit<ApiPageProps, 'document'> {
|
|
157
|
-
document: string |
|
|
158
|
+
document: string | DereferencedDocument;
|
|
158
159
|
}
|
|
159
160
|
declare function createAPIPage(server: OpenAPIServer, options: CreateAPIPageOptions): FC<ServerApiPageProps>;
|
|
160
161
|
//#endregion
|
|
161
|
-
export { ClientCodeBlockProvider, CreateAPIPageOptions, GenerateTypeScriptDefinitionsContext, ServerApiPageProps, createAPIPage };
|
|
162
|
+
export { APIPlaygroundProps, ClientCodeBlockProvider, CreateAPIPageOptions, GenerateTypeScriptDefinitionsContext, ServerApiPageProps, createAPIPage };
|
|
162
163
|
//# sourceMappingURL=base.d.ts.map
|
package/dist/ui/base.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","names":[],"sources":["../../src/ui/base.tsx"],"mappings":";;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"base.d.ts","names":[],"sources":["../../src/ui/base.tsx"],"mappings":"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"}
|
package/dist/ui/base.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { parseSecurities } from "../utils/schema/index.js";
|
|
1
2
|
import { defaultAdapters } from "../requests/media/adapter.js";
|
|
2
3
|
import { ClientCodeBlockProvider } from "./components/codeblock.js";
|
|
4
|
+
import { encodeInternalRef } from "../utils/schema/ref.js";
|
|
3
5
|
import { APIPage } from "./api-page.js";
|
|
6
|
+
import { pickSchema } from "../utils/schema/pick.js";
|
|
4
7
|
import Slugger from "github-slugger";
|
|
5
8
|
import * as JsxRuntime from "react/jsx-runtime";
|
|
6
9
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -35,6 +38,21 @@ function createAPIPage(server, options) {
|
|
|
35
38
|
...options.shikiOptions
|
|
36
39
|
}).use(rehypeReact);
|
|
37
40
|
}
|
|
41
|
+
function renderPlaygroundDefault({ path, method, ctx }) {
|
|
42
|
+
return /* @__PURE__ */ jsx(ctx.clientBoundary.PlaygroundClient, {
|
|
43
|
+
route: path,
|
|
44
|
+
securities: parseSecurities(method, ctx.schema.dereferenced),
|
|
45
|
+
method: method.method,
|
|
46
|
+
doc: { bundled: pickSchema(ctx.schema.bundled, encodeInternalRef([
|
|
47
|
+
"paths",
|
|
48
|
+
path,
|
|
49
|
+
method.method
|
|
50
|
+
])) },
|
|
51
|
+
proxyUrl: ctx.proxyUrl,
|
|
52
|
+
writeOnly: true,
|
|
53
|
+
readOnly: false
|
|
54
|
+
});
|
|
55
|
+
}
|
|
38
56
|
return async function APIPageWrapper({ document, ...props }) {
|
|
39
57
|
let processed;
|
|
40
58
|
if (typeof document === "string") processed = await server.getSchema(document);
|
|
@@ -57,6 +75,10 @@ function createAPIPage(server, options) {
|
|
|
57
75
|
...defaultAdapters,
|
|
58
76
|
...options.mediaAdapters
|
|
59
77
|
},
|
|
78
|
+
playground: {
|
|
79
|
+
...options.playground,
|
|
80
|
+
render: options.playground?.render ?? renderPlaygroundDefault
|
|
81
|
+
},
|
|
60
82
|
renderHeading(depth, text, props) {
|
|
61
83
|
const id = typeof text === "string" ? slugger.slug(text) : props?.id;
|
|
62
84
|
if (!id) throw new Error("missing 'id' for non-string children");
|
package/dist/ui/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","names":[],"sources":["../../src/ui/base.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport Slugger from 'github-slugger';\nimport type { Awaitable, MethodInformation, RenderContext } from '@/types';\nimport type { NoReference } from '@/utils/schema';\nimport type { ProcessedDocument } from '@/utils/process-document';\nimport { defaultAdapters, MediaAdapter } from '@/requests/media/adapter';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport type { OpenAPIServer } from '@/server';\nimport type { APIPageClientOptions } from './client';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { createRehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code.core';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';\nimport type { SchemaUIOptions } from './schema';\nimport type { ResponseTab } from './operation/response-tabs';\nimport { APIPage, type ApiPageProps, type OperationItem, type WebhookItem } from './api-page';\nimport type { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from '@/requests/generators';\nimport type { JSONSchema } from 'json-schema-typed';\nimport type { BundledTheme, CodeOptionsThemes, CodeToHastOptionsCommon } from 'shiki';\nimport { highlightHast, type ShikiFactory } from 'fumadocs-core/highlight/shiki';\nimport type { ExampleRequestItem } from './operation/get-example-requests';\nimport { compile } from '@fumari/json-schema-ts';\n\nexport interface GenerateTypeScriptDefinitionsContext extends RenderContext {\n operation: NoReference<MethodInformation>;\n readOnly: boolean;\n writeOnly: boolean;\n /** @deprecated */\n _internal_legacy?: {\n statusCode: string;\n contentType: string;\n };\n}\n\nexport interface CreateAPIPageOptions {\n /**\n * Generate TypeScript definitions from response schema.\n *\n * Pass `false` to disable it.\n *\n * @param method - the operation object\n * @param statusCode - status code\n * @deprecated use `generateTypeScriptDefinitions` instead.\n */\n generateTypeScriptSchema?:\n | ((\n method: NoReference<MethodInformation>,\n statusCode: string,\n contentType: string,\n ctx: RenderContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate TypeScript definitions from JSON schema.\n *\n * Pass `false` to disable it.\n */\n generateTypeScriptDefinitions?:\n | ((\n schema: JSONSchema,\n ctx: GenerateTypeScriptDefinitionsContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate example code usage for all endpoints.\n */\n codeUsages?: CodeUsageGeneratorRegistry;\n\n /**\n * Generate example code usage for each endpoint.\n */\n generateCodeSamples?: (method: MethodInformation) => InlineCodeUsageGenerator[];\n\n shiki: ShikiFactory;\n renderMarkdown?: (md: string) => ReactNode;\n shikiOptions: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;\n\n /**\n * Show full response schema instead of only example response & Typescript definitions.\n *\n * @default true\n */\n showResponseSchema?: boolean;\n\n /**\n * Support other media types (for server-side generation).\n */\n mediaAdapters?: Record<string, MediaAdapter>;\n\n /**\n * Customise page content\n */\n content?: {\n renderResponseTabs?: (tabs: ResponseTab[], ctx: RenderContext) => ReactNode;\n\n renderRequestTabs?: (\n items: ExampleRequestItem[],\n ctx: RenderContext & {\n route: string;\n operation: NoReference<MethodInformation>;\n },\n ) => ReactNode;\n\n renderAPIExampleLayout?: (\n slots: {\n selector: ReactNode;\n usageTabs: ReactNode;\n responseTabs: ReactNode;\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * @param generators - codegens for API example usages\n */\n renderAPIExampleUsageTabs?: (\n generators: CodeUsageGeneratorRegistry,\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * renderer of the entire page's layout (containing all operations & webhooks UI)\n */\n renderPageLayout?: (\n slots: {\n operations?: {\n item: OperationItem;\n children: ReactNode;\n }[];\n webhooks?: {\n item: WebhookItem;\n children: ReactNode;\n }[];\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n renderOperationLayout?: (\n slots: {\n header: ReactNode;\n description: ReactNode;\n apiExample: ReactNode;\n apiPlayground: ReactNode;\n\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n },\n ctx: RenderContext,\n method: NoReference<MethodInformation>,\n ) => ReactNode;\n\n renderWebhookLayout?: (slots: {\n header: ReactNode;\n description: ReactNode;\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n requests: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n }) => ReactNode;\n };\n\n /**\n * Info UI for JSON schemas\n */\n schemaUI?: {\n render?: (options: SchemaUIOptions, ctx: RenderContext) => ReactNode;\n\n /**\n * Show examples under the generated content of JSON schemas.\n *\n * @defaultValue false\n */\n showExample?: boolean;\n };\n\n /**\n * Customise API playground\n */\n playground?: {\n /**\n * @defaultValue true\n */\n enabled?: boolean;\n /**\n * replace the server-side renderer\n */\n render?: (props: {\n path: string;\n method: MethodInformation;\n ctx: RenderContext;\n }) => Awaitable<ReactNode>;\n };\n\n renderHeading?: (props: HTMLAttributes<HTMLHeadingElement>, depth: number) => ReactNode;\n renderCodeBlock?: (props: { lang: string; code: string }) => ReactNode;\n\n client?: APIPageClientOptions;\n}\n\nexport interface ServerApiPageProps extends Omit<ApiPageProps, 'document'> {\n document: string | ProcessedDocument;\n}\n\nexport function createAPIPage(\n server: OpenAPIServer,\n options: CreateAPIPageOptions,\n): FC<ServerApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: defaultMdxComponents,\n });\n };\n }\n\n return remark()\n .use(remarkGfm)\n .use(remarkRehype)\n .use(createRehypeCode(options.shiki), {\n langs: [],\n lazy: true,\n defaultColor: false,\n ...options.shikiOptions,\n })\n .use(rehypeReact);\n }\n\n return async function APIPageWrapper({ document, ...props }) {\n let processed: ProcessedDocument;\n if (typeof document === 'string') {\n processed = await server.getSchema(document);\n } else {\n processed = document;\n }\n\n const slugger = new Slugger();\n const { ApiProvider, PlaygroundClient, SchemaUI, ServerProvider, UsageTab, UsageTabsSelector } =\n await import('@/ui/client/boundary.lazy');\n\n const ctx: RenderContext = {\n schema: processed,\n proxyUrl: server.options.proxyUrl,\n clientBoundary: {\n ApiProvider,\n PlaygroundClient,\n SchemaUI,\n ServerProvider,\n UsageTab,\n UsageTabsSelector,\n },\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slugger.slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n generateTypeScriptDefinitions:\n options.generateTypeScriptDefinitions ??\n ((schema, ctx) => {\n if (options.generateTypeScriptSchema && ctx._internal_legacy) {\n const { statusCode, contentType } = ctx._internal_legacy;\n return options.generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);\n }\n\n if (typeof schema !== 'object') return;\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n }),\n async renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n const out = await processor.process({\n value: text,\n });\n\n return out.result as ReactNode;\n },\n async renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n const hast = await highlightHast(await options.shiki.getOrInit(), code, {\n lang,\n defaultColor: false,\n ...options.shikiOptions,\n });\n const rendered = toJsxRuntime(hast, {\n ...JsxRuntime,\n components: {\n pre: Pre,\n },\n });\n\n return <CodeBlock className=\"my-0\">{rendered}</CodeBlock>;\n },\n };\n\n return <APIPage {...props} ctx={ctx} />;\n };\n}\n\nexport { ClientCodeBlockProvider } from './components/codeblock';\n"],"mappings":";;;;;;;;;;;;;;;;;AAuNA,SAAgB,cACd,QACA,SACwB;CACxB,IAAI;CAEJ,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CACZ,IAAI,UAAU,CACd,IAAI,aAAa,CACjB,IAAI,iBAAiB,QAAQ,MAAM,EAAE;GACpC,OAAO,EAAE;GACT,MAAM;GACN,cAAc;GACd,GAAG,QAAQ;GACZ,CAAC,CACD,IAAI,YAAY;;AAGrB,QAAO,eAAe,eAAe,EAAE,UAAU,GAAG,SAAS;EAC3D,IAAI;AACJ,MAAI,OAAO,aAAa,SACtB,aAAY,MAAM,OAAO,UAAU,SAAS;MAE5C,aAAY;EAGd,MAAM,UAAU,IAAI,SAAS;EAC7B,MAAM,EAAE,aAAa,kBAAkB,UAAU,gBAAgB,UAAU,sBACzE,MAAM,OAAO;EAEf,MAAM,MAAqB;GACzB,QAAQ;GACR,UAAU,OAAO,QAAQ;GACzB,gBAAgB;IACd;IACA;IACA;IACA;IACA;IACA;IACD;GACD,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,QAAQ,KAAK,KAAK,GAAG,OAAO;AAClE,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,+BACE,QAAQ,mCACN,QAAQ,QAAQ;AAChB,QAAI,QAAQ,4BAA4B,IAAI,kBAAkB;KAC5D,MAAM,EAAE,YAAY,gBAAgB,IAAI;AACxC,YAAO,QAAQ,yBAAyB,IAAI,WAAW,YAAY,aAAa,IAAI;;AAGtF,QAAI,OAAO,WAAW,SAAU;AAChC,QAAI;AACF,YAAO,QAAQ,QAAQ;MACrB,MAAM;MACN,UAAU,IAAI;MACd,WAAW,IAAI;MACf,aAAa,IAAI,OAAO;MACzB,CAAC;aACK,GAAG;AACV,aAAQ,KAAK,yCAAyC,EAAE;;;GAG9D,MAAM,eAAe,MAAM;AACzB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAMvC,YAJY,MAAM,UAAU,QAAQ,EAClC,OAAO,MACR,CAAC,EAES;;GAEb,MAAM,gBAAgB,MAAM,MAAM;AAChC,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAehD,WAAO,oBAAC,WAAD;KAAW,WAAU;eAPX,aALJ,MAAM,cAAc,MAAM,QAAQ,MAAM,WAAW,EAAE,MAAM;MACtE;MACA,cAAc;MACd,GAAG,QAAQ;MACZ,CAAC,EACkC;MAClC,GAAG;MACH,YAAY,EACV,KAAK,KACN;MACF,CAAC;KAEuD,CAAA;;GAE5D;AAED,SAAO,oBAAC,SAAD;GAAS,GAAI;GAAY;GAAO,CAAA"}
|
|
1
|
+
{"version":3,"file":"base.js","names":[],"sources":["../../src/ui/base.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport Slugger from 'github-slugger';\nimport type { Awaitable, MethodInformation, RenderContext } from '@/types';\nimport { parseSecurities, type NoReference } from '@/utils/schema';\nimport type { DereferencedDocument } from '@/utils/document/dereference';\nimport { defaultAdapters, MediaAdapter } from '@/requests/media/adapter';\nimport type { FC, HTMLAttributes, ReactNode } from 'react';\nimport type { OpenAPIServer } from '@/server';\nimport type { APIPageClientOptions } from './client';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { createRehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code.core';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';\nimport type { SchemaUIOptions } from './schema';\nimport type { ResponseTab } from './operation/response-tabs';\nimport { APIPage, type ApiPageProps, type OperationItem, type WebhookItem } from './api-page';\nimport type { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from '@/requests/generators';\nimport type { JSONSchema } from 'json-schema-typed';\nimport type { BundledTheme, CodeOptionsThemes, CodeToHastOptionsCommon } from 'shiki';\nimport { highlightHast, type ShikiFactory } from 'fumadocs-core/highlight/shiki';\nimport type { ExampleRequestItem } from './operation/get-example-requests';\nimport { compile } from '@fumari/json-schema-ts';\nimport { pickSchema } from '@/utils/schema/pick';\nimport { encodeInternalRef } from '@/utils/schema/ref';\n\nexport interface GenerateTypeScriptDefinitionsContext extends RenderContext {\n operation: NoReference<MethodInformation>;\n readOnly: boolean;\n writeOnly: boolean;\n /** @deprecated */\n _internal_legacy?: {\n statusCode: string;\n contentType: string;\n };\n}\n\nexport interface APIPlaygroundProps {\n path: string;\n method: MethodInformation;\n ctx: RenderContext;\n}\n\nexport interface CreateAPIPageOptions {\n /**\n * Generate TypeScript definitions from response schema.\n *\n * Pass `false` to disable it.\n *\n * @param method - the operation object\n * @param statusCode - status code\n * @deprecated use `generateTypeScriptDefinitions` instead.\n */\n generateTypeScriptSchema?:\n | ((\n method: NoReference<MethodInformation>,\n statusCode: string,\n contentType: string,\n ctx: RenderContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate TypeScript definitions from JSON schema.\n *\n * Pass `false` to disable it.\n */\n generateTypeScriptDefinitions?:\n | ((\n schema: JSONSchema,\n ctx: GenerateTypeScriptDefinitionsContext,\n ) => Awaitable<string | undefined>)\n | false;\n\n /**\n * Generate example code usage for all endpoints.\n */\n codeUsages?: CodeUsageGeneratorRegistry;\n\n /**\n * Generate example code usage for each endpoint.\n */\n generateCodeSamples?: (method: MethodInformation) => InlineCodeUsageGenerator[];\n\n shiki: ShikiFactory;\n renderMarkdown?: (md: string) => ReactNode;\n shikiOptions: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;\n\n /**\n * Show full response schema instead of only example response & Typescript definitions.\n *\n * @default true\n */\n showResponseSchema?: boolean;\n\n /**\n * Support other media types (for server-side generation).\n */\n mediaAdapters?: Record<string, MediaAdapter>;\n\n /**\n * Customise page content\n */\n content?: {\n renderResponseTabs?: (tabs: ResponseTab[], ctx: RenderContext) => ReactNode;\n\n renderRequestTabs?: (\n items: ExampleRequestItem[],\n ctx: RenderContext & {\n route: string;\n operation: NoReference<MethodInformation>;\n },\n ) => ReactNode;\n\n renderAPIExampleLayout?: (\n slots: {\n selector: ReactNode;\n usageTabs: ReactNode;\n responseTabs: ReactNode;\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * @param generators - codegens for API example usages\n */\n renderAPIExampleUsageTabs?: (\n generators: CodeUsageGeneratorRegistry,\n ctx: RenderContext,\n ) => ReactNode;\n\n /**\n * renderer of the entire page's layout (containing all operations & webhooks UI)\n */\n renderPageLayout?: (\n slots: {\n operations?: {\n item: OperationItem;\n children: ReactNode;\n }[];\n webhooks?: {\n item: WebhookItem;\n children: ReactNode;\n }[];\n },\n ctx: RenderContext,\n ) => ReactNode;\n\n renderOperationLayout?: (\n slots: {\n header: ReactNode;\n description: ReactNode;\n apiExample: ReactNode;\n apiPlayground: ReactNode;\n\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n },\n ctx: RenderContext,\n method: NoReference<MethodInformation>,\n ) => ReactNode;\n\n renderWebhookLayout?: (slots: {\n header: ReactNode;\n description: ReactNode;\n authSchemes: ReactNode;\n parameters: ReactNode;\n body: ReactNode;\n requests: ReactNode;\n responses: ReactNode;\n callbacks: ReactNode;\n }) => ReactNode;\n };\n\n /**\n * Info UI for JSON schemas\n */\n schemaUI?: {\n render?: (options: SchemaUIOptions, ctx: RenderContext) => ReactNode;\n\n /**\n * Show examples under the generated content of JSON schemas.\n *\n * @defaultValue false\n */\n showExample?: boolean;\n };\n\n /**\n * Customise API playground\n */\n playground?: {\n /**\n * @defaultValue true\n */\n enabled?: boolean;\n /**\n * replace the server-side renderer\n */\n render?: (props: APIPlaygroundProps) => ReactNode;\n };\n\n renderHeading?: (props: HTMLAttributes<HTMLHeadingElement>, depth: number) => ReactNode;\n renderCodeBlock?: (props: { lang: string; code: string }) => ReactNode;\n\n client?: APIPageClientOptions;\n}\n\nexport interface ServerApiPageProps extends Omit<ApiPageProps, 'document'> {\n document: string | DereferencedDocument;\n}\n\nexport function createAPIPage(\n server: OpenAPIServer,\n options: CreateAPIPageOptions,\n): FC<ServerApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: defaultMdxComponents,\n });\n };\n }\n\n return remark()\n .use(remarkGfm)\n .use(remarkRehype)\n .use(createRehypeCode(options.shiki), {\n langs: [],\n lazy: true,\n defaultColor: false,\n ...options.shikiOptions,\n })\n .use(rehypeReact);\n }\n\n function renderPlaygroundDefault({ path, method, ctx }: APIPlaygroundProps) {\n return (\n <ctx.clientBoundary.PlaygroundClient\n route={path}\n securities={parseSecurities(method, ctx.schema.dereferenced)}\n method={method.method}\n doc={{\n bundled: pickSchema(\n ctx.schema.bundled,\n encodeInternalRef(['paths', path, method.method]),\n ),\n }}\n proxyUrl={ctx.proxyUrl}\n writeOnly\n readOnly={false}\n />\n );\n }\n\n return async function APIPageWrapper({ document, ...props }) {\n let processed: DereferencedDocument;\n if (typeof document === 'string') {\n processed = await server.getSchema(document);\n } else {\n processed = document;\n }\n\n const slugger = new Slugger();\n const { ApiProvider, PlaygroundClient, SchemaUI, ServerProvider, UsageTab, UsageTabsSelector } =\n await import('@/ui/client/boundary.lazy');\n\n const ctx: RenderContext = {\n schema: processed,\n proxyUrl: server.options.proxyUrl,\n clientBoundary: {\n ApiProvider,\n PlaygroundClient,\n SchemaUI,\n ServerProvider,\n UsageTab,\n UsageTabsSelector,\n },\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n playground: {\n ...options.playground,\n render: options.playground?.render ?? renderPlaygroundDefault,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slugger.slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n generateTypeScriptDefinitions:\n options.generateTypeScriptDefinitions ??\n ((schema, ctx) => {\n if (options.generateTypeScriptSchema && ctx._internal_legacy) {\n const { statusCode, contentType } = ctx._internal_legacy;\n return options.generateTypeScriptSchema(ctx.operation, statusCode, contentType, ctx);\n }\n\n if (typeof schema !== 'object') return;\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n }),\n async renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n const out = await processor.process({\n value: text,\n });\n\n return out.result as ReactNode;\n },\n async renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n const hast = await highlightHast(await options.shiki.getOrInit(), code, {\n lang,\n defaultColor: false,\n ...options.shikiOptions,\n });\n const rendered = toJsxRuntime(hast, {\n ...JsxRuntime,\n components: {\n pre: Pre,\n },\n });\n\n return <CodeBlock className=\"my-0\">{rendered}</CodeBlock>;\n },\n };\n\n return <APIPage {...props} ctx={ctx} />;\n };\n}\n\nexport { ClientCodeBlockProvider } from './components/codeblock';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA2NA,SAAgB,cACd,QACA,SACwB;CACxB,IAAI;CAEJ,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CACZ,IAAI,UAAU,CACd,IAAI,aAAa,CACjB,IAAI,iBAAiB,QAAQ,MAAM,EAAE;GACpC,OAAO,EAAE;GACT,MAAM;GACN,cAAc;GACd,GAAG,QAAQ;GACZ,CAAC,CACD,IAAI,YAAY;;CAGrB,SAAS,wBAAwB,EAAE,MAAM,QAAQ,OAA2B;AAC1E,SACE,oBAAC,IAAI,eAAe,kBAApB;GACE,OAAO;GACP,YAAY,gBAAgB,QAAQ,IAAI,OAAO,aAAa;GAC5D,QAAQ,OAAO;GACf,KAAK,EACH,SAAS,WACP,IAAI,OAAO,SACX,kBAAkB;IAAC;IAAS;IAAM,OAAO;IAAO,CAAC,CAClD,EACF;GACD,UAAU,IAAI;GACd,WAAA;GACA,UAAU;GACV,CAAA;;AAIN,QAAO,eAAe,eAAe,EAAE,UAAU,GAAG,SAAS;EAC3D,IAAI;AACJ,MAAI,OAAO,aAAa,SACtB,aAAY,MAAM,OAAO,UAAU,SAAS;MAE5C,aAAY;EAGd,MAAM,UAAU,IAAI,SAAS;EAC7B,MAAM,EAAE,aAAa,kBAAkB,UAAU,gBAAgB,UAAU,sBACzE,MAAM,OAAO;EAEf,MAAM,MAAqB;GACzB,QAAQ;GACR,UAAU,OAAO,QAAQ;GACzB,gBAAgB;IACd;IACA;IACA;IACA;IACA;IACA;IACD;GACD,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,YAAY;IACV,GAAG,QAAQ;IACX,QAAQ,QAAQ,YAAY,UAAU;IACvC;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,QAAQ,KAAK,KAAK,GAAG,OAAO;AAClE,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,+BACE,QAAQ,mCACN,QAAQ,QAAQ;AAChB,QAAI,QAAQ,4BAA4B,IAAI,kBAAkB;KAC5D,MAAM,EAAE,YAAY,gBAAgB,IAAI;AACxC,YAAO,QAAQ,yBAAyB,IAAI,WAAW,YAAY,aAAa,IAAI;;AAGtF,QAAI,OAAO,WAAW,SAAU;AAChC,QAAI;AACF,YAAO,QAAQ,QAAQ;MACrB,MAAM;MACN,UAAU,IAAI;MACd,WAAW,IAAI;MACf,aAAa,IAAI,OAAO;MACzB,CAAC;aACK,GAAG;AACV,aAAQ,KAAK,yCAAyC,EAAE;;;GAG9D,MAAM,eAAe,MAAM;AACzB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAMvC,YAJY,MAAM,UAAU,QAAQ,EAClC,OAAO,MACR,CAAC,EAES;;GAEb,MAAM,gBAAgB,MAAM,MAAM;AAChC,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAehD,WAAO,oBAAC,WAAD;KAAW,WAAU;eAPX,aALJ,MAAM,cAAc,MAAM,QAAQ,MAAM,WAAW,EAAE,MAAM;MACtE;MACA,cAAc;MACd,GAAG,QAAQ;MACZ,CAAC,EACkC;MAClC,GAAG;MACH,YAAY,EACV,KAAK,KACN;MACF,CAAC;KAEuD,CAAA;;GAE5D;AAED,SAAO,oBAAC,SAAD;GAAS,GAAI;GAAY;GAAO,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.d.ts","names":[],"sources":["../../src/ui/create-client.tsx"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"create-client.d.ts","names":[],"sources":["../../src/ui/create-client.tsx"],"mappings":";;;;;;UA4BiB,kBAAA,SAA2B,IAAA,CAAK,YAAA;EAC/C,OAAA,EAAS,oBAAA;AAAA;AAAA,UAGM,oBAAA;EACf,OAAA,EAAS,QAAA;EACT,QAAA;AAAA;AAAA,KAGU,0BAAA,GAA6B,IAAA,CACvC,OAAA,CAAQ,oBAAA;;;;iBAOM,mBAAA,CAAA;EACd,KAAA;EACA,YAAA;EACA,6BAAA;EAAA,GAcG;AAAA,IACF,0BAAA,GAAkC,EAAA,CAAG,kBAAA"}
|
package/dist/ui/create-client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { parseSecurities } from "../utils/schema/index.js";
|
|
1
2
|
import { defaultAdapters } from "../requests/media/adapter.js";
|
|
2
3
|
import { ClientCodeBlock, ClientCodeBlockProvider } from "./components/codeblock.js";
|
|
3
|
-
import {
|
|
4
|
+
import { dereferenceDocument } from "../utils/document/dereference.js";
|
|
4
5
|
import { APIPage } from "./api-page.js";
|
|
5
6
|
import { boundary_exports } from "./client/boundary.js";
|
|
6
7
|
import { slug } from "github-slugger";
|
|
@@ -54,19 +55,19 @@ function createClientAPIPage({ shiki = defaultShikiFactory, shikiOptions = { the
|
|
|
54
55
|
}
|
|
55
56
|
return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);
|
|
56
57
|
}
|
|
58
|
+
function renderPlaygroundDefault({ method, path, ctx }) {
|
|
59
|
+
return /* @__PURE__ */ jsx(ctx.clientBoundary.PlaygroundClient, {
|
|
60
|
+
route: path,
|
|
61
|
+
securities: parseSecurities(method, ctx.schema.dereferenced),
|
|
62
|
+
method: method.method,
|
|
63
|
+
doc: { processed: ctx.schema },
|
|
64
|
+
proxyUrl: ctx.proxyUrl,
|
|
65
|
+
writeOnly: true,
|
|
66
|
+
readOnly: false
|
|
67
|
+
});
|
|
68
|
+
}
|
|
57
69
|
return function ClientAPIPage({ payload, ...props }) {
|
|
58
|
-
const processed = useMemo(() =>
|
|
59
|
-
const dereferenceMap = /* @__PURE__ */ new Map();
|
|
60
|
-
return {
|
|
61
|
-
bundled: payload.bundled,
|
|
62
|
-
dereferenced: dereferenceSync(payload.bundled, (schema, ref) => {
|
|
63
|
-
dereferenceMap.set(schema, ref);
|
|
64
|
-
}),
|
|
65
|
-
getRawRef(obj) {
|
|
66
|
-
return dereferenceMap.get(obj);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
}, [payload.bundled]);
|
|
70
|
+
const processed = useMemo(() => dereferenceDocument(payload.bundled), [payload.bundled]);
|
|
70
71
|
const ctx = useMemo(() => ({
|
|
71
72
|
schema: processed,
|
|
72
73
|
proxyUrl: payload.proxyUrl,
|
|
@@ -79,6 +80,10 @@ function createClientAPIPage({ shiki = defaultShikiFactory, shikiOptions = { the
|
|
|
79
80
|
...defaultAdapters,
|
|
80
81
|
...options.mediaAdapters
|
|
81
82
|
},
|
|
83
|
+
playground: {
|
|
84
|
+
...options.playground,
|
|
85
|
+
render: options.playground?.render ?? renderPlaygroundDefault
|
|
86
|
+
},
|
|
82
87
|
renderHeading(depth, text, props) {
|
|
83
88
|
const id = typeof text === "string" ? slug(text) : props?.id;
|
|
84
89
|
if (!id) throw new Error("missing 'id' for non-string children");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-client.js","names":["ClientBoundary"],"sources":["../../src/ui/create-client.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport type { Document, RenderContext } from '@/types';\nimport
|
|
1
|
+
{"version":3,"file":"create-client.js","names":["ClientBoundary"],"sources":["../../src/ui/create-client.tsx"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */\nimport type { Document, RenderContext } from '@/types';\nimport { defaultAdapters } from '@/requests/media/adapter';\nimport {\n Children,\n type ComponentProps,\n type ReactElement,\n useMemo,\n type FC,\n type ReactNode,\n} from 'react';\nimport { Heading } from 'fumadocs-ui/components/heading';\nimport { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';\nimport defaultMdxComponents from 'fumadocs-ui/mdx';\nimport { remark } from 'remark';\nimport remarkRehype from 'remark-rehype';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport * as JsxRuntime from 'react/jsx-runtime';\nimport { APIPage, type ApiPageProps } from './api-page';\nimport type { APIPlaygroundProps, CreateAPIPageOptions } from './base';\nimport { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';\nimport { compile } from '@fumari/json-schema-ts';\nimport { ClientCodeBlock, ClientCodeBlockProvider } from './components/codeblock';\nimport { slug } from 'github-slugger';\nimport * as ClientBoundary from '@/ui/client/boundary';\nimport { dereferenceDocument } from '@/utils/document/dereference';\nimport { parseSecurities } from '@/utils/schema';\n\nexport interface ClientApiPageProps extends Omit<ApiPageProps, 'document'> {\n payload: ClientApiPagePayload;\n}\n\nexport interface ClientApiPagePayload {\n bundled: Document;\n proxyUrl?: string;\n}\n\nexport type CreateClientAPIPageOptions = Omit<\n Partial<CreateAPIPageOptions>,\n 'generateTypeScriptSchema'\n>;\n\n/**\n * Create `<APIPage />` for non-RSC environment, note that this may be unstable, and doesn't support the full set of features.\n */\nexport function createClientAPIPage({\n shiki = defaultShikiFactory,\n shikiOptions = { themes: { light: 'github-light', dark: 'github-dark' } },\n generateTypeScriptDefinitions = (schema, ctx) => {\n if (typeof schema !== 'object') return;\n\n try {\n return compile(schema, {\n name: 'Response',\n readOnly: ctx.readOnly,\n writeOnly: ctx.writeOnly,\n getSchemaId: ctx.schema.getRawRef,\n });\n } catch (e) {\n console.warn('Failed to generate typescript schema:', e);\n }\n },\n ...options\n}: CreateClientAPIPageOptions = {}): FC<ClientApiPageProps> {\n let processor: ReturnType<typeof createMarkdownProcessor>;\n const mdxComponents = {\n ...defaultMdxComponents,\n img: undefined,\n pre: MarkdownPre,\n };\n\n function createMarkdownProcessor() {\n function rehypeReact(this: any) {\n this.compiler = (tree: any, file: any) => {\n return toJsxRuntime(tree, {\n development: false,\n filePath: file.path,\n ...JsxRuntime,\n components: mdxComponents,\n });\n };\n }\n\n return remark().use(remarkGfm).use(remarkRehype).use(rehypeReact);\n }\n\n function renderPlaygroundDefault({ method, path, ctx }: APIPlaygroundProps) {\n return (\n <ctx.clientBoundary.PlaygroundClient\n route={path}\n securities={parseSecurities(method, ctx.schema.dereferenced)}\n method={method.method}\n doc={{ processed: ctx.schema }}\n proxyUrl={ctx.proxyUrl}\n writeOnly\n readOnly={false}\n />\n );\n }\n\n return function ClientAPIPage({ payload, ...props }) {\n const processed = useMemo(() => dereferenceDocument(payload.bundled), [payload.bundled]);\n\n const ctx: RenderContext = useMemo(\n () => ({\n schema: processed,\n proxyUrl: payload.proxyUrl,\n shiki,\n shikiOptions,\n generateTypeScriptDefinitions,\n clientBoundary: ClientBoundary,\n ...options,\n mediaAdapters: {\n ...defaultAdapters,\n ...options.mediaAdapters,\n },\n playground: {\n ...options.playground,\n render: options.playground?.render ?? renderPlaygroundDefault,\n },\n renderHeading(depth, text, props) {\n const id = typeof text === 'string' ? slug(text) : props?.id;\n if (!id) throw new Error(\"missing 'id' for non-string children\");\n\n if (options.renderHeading) {\n return options.renderHeading({ id, children: text, ...props }, depth);\n }\n\n return (\n <Heading id={id} key={id} as={`h${depth}` as `h1`} {...props}>\n {text}\n </Heading>\n );\n },\n renderMarkdown(text) {\n if (options.renderMarkdown) return options.renderMarkdown(text);\n processor ??= createMarkdownProcessor();\n\n return processor.processSync({\n value: text,\n }).result as ReactNode;\n },\n renderCodeBlock(lang, code) {\n if (options.renderCodeBlock) {\n return options.renderCodeBlock({ lang, code });\n }\n\n return <ClientCodeBlock lang={lang} code={code} />;\n },\n }),\n [payload.proxyUrl, processed],\n );\n\n return (\n <ClientCodeBlockProvider factory={shiki}>\n <APIPage {...props} ctx={ctx} />\n </ClientCodeBlockProvider>\n );\n };\n}\n\nfunction MarkdownPre(props: ComponentProps<'pre'>) {\n const code = Children.only(props.children) as ReactElement;\n const codeProps = code.props as ComponentProps<'code'>;\n const content = codeProps.children;\n if (typeof content !== 'string') return null;\n\n const lang =\n codeProps.className\n ?.split(' ')\n .find((v) => v.startsWith('language-'))\n ?.slice('language-'.length) ?? 'text';\n\n return <ClientCodeBlock lang={lang} code={content.trimEnd()} />;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,oBAAoB,EAClC,QAAQ,qBACR,eAAe,EAAE,QAAQ;CAAE,OAAO;CAAgB,MAAM;CAAe,EAAE,EACzE,iCAAiC,QAAQ,QAAQ;AAC/C,KAAI,OAAO,WAAW,SAAU;AAEhC,KAAI;AACF,SAAO,QAAQ,QAAQ;GACrB,MAAM;GACN,UAAU,IAAI;GACd,WAAW,IAAI;GACf,aAAa,IAAI,OAAO;GACzB,CAAC;UACK,GAAG;AACV,UAAQ,KAAK,yCAAyC,EAAE;;GAG5D,GAAG,YAC2B,EAAE,EAA0B;CAC1D,IAAI;CACJ,MAAM,gBAAgB;EACpB,GAAG;EACH,KAAK,KAAA;EACL,KAAK;EACN;CAED,SAAS,0BAA0B;EACjC,SAAS,cAAuB;AAC9B,QAAK,YAAY,MAAW,SAAc;AACxC,WAAO,aAAa,MAAM;KACxB,aAAa;KACb,UAAU,KAAK;KACf,GAAG;KACH,YAAY;KACb,CAAC;;;AAIN,SAAO,QAAQ,CAAC,IAAI,UAAU,CAAC,IAAI,aAAa,CAAC,IAAI,YAAY;;CAGnE,SAAS,wBAAwB,EAAE,QAAQ,MAAM,OAA2B;AAC1E,SACE,oBAAC,IAAI,eAAe,kBAApB;GACE,OAAO;GACP,YAAY,gBAAgB,QAAQ,IAAI,OAAO,aAAa;GAC5D,QAAQ,OAAO;GACf,KAAK,EAAE,WAAW,IAAI,QAAQ;GAC9B,UAAU,IAAI;GACd,WAAA;GACA,UAAU;GACV,CAAA;;AAIN,QAAO,SAAS,cAAc,EAAE,SAAS,GAAG,SAAS;EACnD,MAAM,YAAY,cAAc,oBAAoB,QAAQ,QAAQ,EAAE,CAAC,QAAQ,QAAQ,CAAC;EAExF,MAAM,MAAqB,eAClB;GACL,QAAQ;GACR,UAAU,QAAQ;GAClB;GACA;GACA;GACA,gBAAgBA;GAChB,GAAG;GACH,eAAe;IACb,GAAG;IACH,GAAG,QAAQ;IACZ;GACD,YAAY;IACV,GAAG,QAAQ;IACX,QAAQ,QAAQ,YAAY,UAAU;IACvC;GACD,cAAc,OAAO,MAAM,OAAO;IAChC,MAAM,KAAK,OAAO,SAAS,WAAW,KAAK,KAAK,GAAG,OAAO;AAC1D,QAAI,CAAC,GAAI,OAAM,IAAI,MAAM,uCAAuC;AAEhE,QAAI,QAAQ,cACV,QAAO,QAAQ,cAAc;KAAE;KAAI,UAAU;KAAM,GAAG;KAAO,EAAE,MAAM;AAGvE,WACE,oBAAC,SAAD;KAAa;KAAa,IAAI,IAAI;KAAiB,GAAI;eACpD;KACO,EAFY,GAEZ;;GAGd,eAAe,MAAM;AACnB,QAAI,QAAQ,eAAgB,QAAO,QAAQ,eAAe,KAAK;AAC/D,kBAAc,yBAAyB;AAEvC,WAAO,UAAU,YAAY,EAC3B,OAAO,MACR,CAAC,CAAC;;GAEL,gBAAgB,MAAM,MAAM;AAC1B,QAAI,QAAQ,gBACV,QAAO,QAAQ,gBAAgB;KAAE;KAAM;KAAM,CAAC;AAGhD,WAAO,oBAAC,iBAAD;KAAuB;KAAY;KAAQ,CAAA;;GAErD,GACD,CAAC,QAAQ,UAAU,UAAU,CAC9B;AAED,SACE,oBAAC,yBAAD;GAAyB,SAAS;aAChC,oBAAC,SAAD;IAAS,GAAI;IAAY;IAAO,CAAA;GACR,CAAA;;;AAKhC,SAAS,YAAY,OAA8B;CAEjD,MAAM,YADO,SAAS,KAAK,MAAM,SAAS,CACnB;CACvB,MAAM,UAAU,UAAU;AAC1B,KAAI,OAAO,YAAY,SAAU,QAAO;AAQxC,QAAO,oBAAC,iBAAD;EAAiB,MALtB,UAAU,WACN,MAAM,IAAI,CACX,MAAM,MAAM,EAAE,WAAW,YAAY,CAAC,EACrC,MAAM,EAAmB,IAAI;EAEC,MAAM,QAAQ,SAAS;EAAI,CAAA"}
|
|
@@ -70,8 +70,8 @@ function getRequestData(path, method, sampleKey, _ctx) {
|
|
|
70
70
|
if (bodyOfType.examples && sampleKey) result.body = bodyOfType.examples[sampleKey].value;
|
|
71
71
|
else if (bodyOfType.example) result.body = bodyOfType.example;
|
|
72
72
|
else result.body = sample(bodyOfType?.schema ?? {}, {
|
|
73
|
-
skipReadOnly: method.method !== "
|
|
74
|
-
skipWriteOnly: method.method === "
|
|
73
|
+
skipReadOnly: method.method !== "get",
|
|
74
|
+
skipWriteOnly: method.method === "get",
|
|
75
75
|
skipNonRequired: true
|
|
76
76
|
});
|
|
77
77
|
}
|