@andesine/pages 0.0.0-stage → 0.4.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/CHANGELOG.md +99 -0
- package/LICENSE +21 -0
- package/README.md +92 -2
- package/dist/answers.d.ts +6 -0
- package/dist/astro/content.astro +118 -0
- package/dist/astro/middleware.js +39 -0
- package/dist/astro/middleware.js.map +1 -0
- package/dist/astro/routes/answers.js +129 -0
- package/dist/astro/routes/answers.js.map +1 -0
- package/dist/astro/routes/entry-pages.js +22 -0
- package/dist/astro/routes/entry-pages.js.map +1 -0
- package/dist/astro/routes/llms-full.js +12 -0
- package/dist/astro/routes/llms-full.js.map +1 -0
- package/dist/astro/routes/llms.js +12 -0
- package/dist/astro/routes/llms.js.map +1 -0
- package/dist/astro/routes/markdown-alias.js +14 -0
- package/dist/astro/routes/markdown-alias.js.map +1 -0
- package/dist/astro/routes/markdown.js +12 -0
- package/dist/astro/routes/markdown.js.map +1 -0
- package/dist/astro/routes/not-found.astro +12 -0
- package/dist/astro/routes/robots.js +9 -0
- package/dist/astro/routes/robots.js.map +1 -0
- package/dist/astro/routes/search.js +42 -0
- package/dist/astro/routes/search.js.map +1 -0
- package/dist/astro/routes/sitemap.js +12 -0
- package/dist/astro/routes/sitemap.js.map +1 -0
- package/dist/astro/routes/skill.js +13 -0
- package/dist/astro/routes/skill.js.map +1 -0
- package/dist/astro/routes/skills.js +24 -0
- package/dist/astro/routes/skills.js.map +1 -0
- package/dist/astro/routes/social.js +91 -0
- package/dist/astro/routes/social.js.map +1 -0
- package/dist/astro/routes/static.astro +53 -0
- package/dist/astro/routes/well-known-llms.js +2 -0
- package/dist/astro.d.ts +34 -0
- package/dist/astro.js +60 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunks/assets-D6WJmZ05.js +21 -0
- package/dist/chunks/assets-D6WJmZ05.js.map +1 -0
- package/dist/chunks/catalog-DU4BUrpw.js +28 -0
- package/dist/chunks/catalog-DU4BUrpw.js.map +1 -0
- package/dist/chunks/config-CuH5JSI4.js +184 -0
- package/dist/chunks/config-CuH5JSI4.js.map +1 -0
- package/dist/chunks/files-BxqiQzFj.js +62 -0
- package/dist/chunks/files-BxqiQzFj.js.map +1 -0
- package/dist/chunks/hash-D4piIIQ6.js +11 -0
- package/dist/chunks/hash-D4piIIQ6.js.map +1 -0
- package/dist/chunks/index-D8wL2B5s.d.ts +571 -0
- package/dist/chunks/index-vsu3hISM.d.ts +62 -0
- package/dist/chunks/limits-Ppc7BQPG.js +45 -0
- package/dist/chunks/limits-Ppc7BQPG.js.map +1 -0
- package/dist/chunks/markdown-DKJSQxR2.js +42 -0
- package/dist/chunks/markdown-DKJSQxR2.js.map +1 -0
- package/dist/chunks/mdx-components-CUUDTapN.d.ts +9 -0
- package/dist/chunks/normalize-DG5nxOLm.js +361 -0
- package/dist/chunks/normalize-DG5nxOLm.js.map +1 -0
- package/dist/chunks/paths-75QgA3Qs.js +16 -0
- package/dist/chunks/paths-75QgA3Qs.js.map +1 -0
- package/dist/chunks/prepare-lnuw_ycM.js +219 -0
- package/dist/chunks/prepare-lnuw_ycM.js.map +1 -0
- package/dist/chunks/read-DCv1lmcM.js +57 -0
- package/dist/chunks/read-DCv1lmcM.js.map +1 -0
- package/dist/chunks/request-DOuBHGQs.js +92 -0
- package/dist/chunks/request-DOuBHGQs.js.map +1 -0
- package/dist/chunks/response-CtzaKMWH.js +15 -0
- package/dist/chunks/response-CtzaKMWH.js.map +1 -0
- package/dist/chunks/site-DY-uZ0PP.js +419 -0
- package/dist/chunks/site-DY-uZ0PP.js.map +1 -0
- package/dist/chunks/skill-CBTGUHQH.js +85 -0
- package/dist/chunks/skill-CBTGUHQH.js.map +1 -0
- package/dist/chunks/sources-Cm6NdIen.js +236 -0
- package/dist/chunks/sources-Cm6NdIen.js.map +1 -0
- package/dist/chunks/stored-CabomV-C.js +354 -0
- package/dist/chunks/stored-CabomV-C.js.map +1 -0
- package/dist/chunks/stored-CcEfvCQH.js +475 -0
- package/dist/chunks/stored-CcEfvCQH.js.map +1 -0
- package/dist/chunks/types-DBzuXfSe.d.ts +53 -0
- package/dist/chunks/view-C-9ZM1zK.js +745 -0
- package/dist/chunks/view-C-9ZM1zK.js.map +1 -0
- package/dist/chunks/view-Dlf_VRI7.d.ts +151 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.js +295 -0
- package/dist/client.js.map +1 -0
- package/dist/collections.d.ts +7 -0
- package/dist/collections.js +215 -0
- package/dist/collections.js.map +1 -0
- package/dist/entry-pages.d.ts +10 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.d.ts +16 -0
- package/dist/integration.js +435 -0
- package/dist/integration.js.map +1 -0
- package/dist/llms-full.d.ts +5 -0
- package/dist/llms.d.ts +5 -0
- package/dist/markdown-alias.d.ts +7 -0
- package/dist/markdown.d.ts +7 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/robots.d.ts +5 -0
- package/dist/runtime.d.ts +81 -0
- package/dist/runtime.js +56 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scripts/restore-navigation.js +1 -0
- package/dist/search.d.ts +6 -0
- package/dist/sitemap.d.ts +5 -0
- package/dist/skill.d.ts +5 -0
- package/dist/skills.d.ts +10 -0
- package/dist/social.d.ts +7 -0
- package/dist/well-known-llms.d.ts +2 -0
- package/package.json +103 -3
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
import { r as prepareMarkdown, t as highlightCode } from "./prepare-lnuw_ycM.js";
|
|
2
|
+
import { t as isObject } from "./normalize-DG5nxOLm.js";
|
|
3
|
+
import { c as resolveSchemaDetails, d as toSchemeLabel, f as toStatusLabel, l as toFacts, o as getRequiredNames, p as toTypeLabel, s as resolveSchema } from "./stored-CcEfvCQH.js";
|
|
4
|
+
import { toHtml } from "hast-util-to-html";
|
|
5
|
+
//#region src/sources/openapi/styles.ts
|
|
6
|
+
/** A value in the default `simple` style of path and header parameters, e.g. `a,b`. */
|
|
7
|
+
const toSimpleValue = (value, encode = String) => {
|
|
8
|
+
if (Array.isArray(value)) return value.map(encode).join(",");
|
|
9
|
+
if (isObject(value)) return Object.entries(value).flat().map(encode).join(",");
|
|
10
|
+
return encode(value);
|
|
11
|
+
};
|
|
12
|
+
/** A value in the `simple` style; `explode` writes object values as `key=value` pairs. */
|
|
13
|
+
const toSimpleStyleValue = (parameter, value) => {
|
|
14
|
+
if (!parameter.explode || !isObject(value)) return toSimpleValue(value);
|
|
15
|
+
return Object.entries(value).map(([key, item]) => `${key}=${String(item)}`).join(",");
|
|
16
|
+
};
|
|
17
|
+
/** A path value in the parameter's style: `simple` by default, `label` (`.a`), or `matrix` (`;id=a`). */
|
|
18
|
+
const toPathValue = (parameter, value) => {
|
|
19
|
+
const isObjectValue = isObject(value);
|
|
20
|
+
const encode = (item) => encodeURIComponent(String(item));
|
|
21
|
+
const items = isObjectValue ? Object.entries(value).flatMap(([key, item]) => {
|
|
22
|
+
return parameter.explode ? [`${encode(key)}=${encode(item)}`] : [encode(key), encode(item)];
|
|
23
|
+
}) : (Array.isArray(value) ? value : [value]).map(encode);
|
|
24
|
+
if (parameter.style === "label") return `.${items.join(parameter.explode ? "." : ",")}`;
|
|
25
|
+
if (parameter.style === "matrix") return parameter.explode ? items.map((item) => `;${isObjectValue ? "" : `${encode(parameter.name)}=`}${item}`).join("") : `;${encode(parameter.name)}=${items.join(",")}`;
|
|
26
|
+
return items.join(",");
|
|
27
|
+
};
|
|
28
|
+
/** Query entries in the parameter's style: by default `form`, which repeats the name for each array item. */
|
|
29
|
+
const toQueryEntries = (parameter, value, encode = String) => {
|
|
30
|
+
const { name, style = "form" } = parameter;
|
|
31
|
+
const explode = parameter.explode ?? style === "form";
|
|
32
|
+
const delimiter = {
|
|
33
|
+
spaceDelimited: " ",
|
|
34
|
+
pipeDelimited: "|"
|
|
35
|
+
}[style];
|
|
36
|
+
if (style === "deepObject" && isObject(value)) return Object.entries(value).map(([key, item]) => [`${name}[${key}]`, encode(item)]);
|
|
37
|
+
if (Array.isArray(value) && delimiter) return [[name, value.map(encode).join(style === "spaceDelimited" ? encode(delimiter) : delimiter)]];
|
|
38
|
+
if (!explode) return [[name, toSimpleValue(value, encode)]];
|
|
39
|
+
if (Array.isArray(value)) return value.map((item) => [name, encode(item)]);
|
|
40
|
+
if (isObject(value)) return Object.entries(value).map(([key, item]) => [key, encode(item)]);
|
|
41
|
+
return [[name, encode(value)]];
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/sources/openapi/samples.ts
|
|
45
|
+
const maxDepth$1 = 8;
|
|
46
|
+
const formatSamples = {
|
|
47
|
+
"date-time": "2026-01-01T00:00:00Z",
|
|
48
|
+
"date": "2026-01-01",
|
|
49
|
+
"time": "00:00:00Z",
|
|
50
|
+
"email": "user@example.com",
|
|
51
|
+
"uri": "https://example.com",
|
|
52
|
+
"url": "https://example.com",
|
|
53
|
+
"hostname": "example.com",
|
|
54
|
+
"uuid": "00000000-0000-0000-0000-000000000000",
|
|
55
|
+
"ipv4": "192.0.2.1",
|
|
56
|
+
"ipv6": "2001:db8::1",
|
|
57
|
+
"byte": "U3RyaW5n",
|
|
58
|
+
"binary": "<binary>"
|
|
59
|
+
};
|
|
60
|
+
const limitKeys = [
|
|
61
|
+
"minimum",
|
|
62
|
+
"exclusiveMinimum",
|
|
63
|
+
"maximum",
|
|
64
|
+
"exclusiveMaximum"
|
|
65
|
+
];
|
|
66
|
+
/**
|
|
67
|
+
* A number within the limits: the lower limit, or 0 without one, up to the upper limit.
|
|
68
|
+
* Integers round toward the inside of the limits.
|
|
69
|
+
*/
|
|
70
|
+
const toNumberSample = (constraints = {}, integer) => {
|
|
71
|
+
const [minimum, exclusiveMinimum, maximum, exclusiveMaximum] = limitKeys.map((key) => {
|
|
72
|
+
const value = constraints[key];
|
|
73
|
+
return typeof value === "number" ? value : void 0;
|
|
74
|
+
});
|
|
75
|
+
const lower = minimum ?? (exclusiveMinimum === void 0 ? void 0 : exclusiveMinimum + 1);
|
|
76
|
+
const upper = maximum ?? (exclusiveMaximum === void 0 ? void 0 : exclusiveMaximum - 1);
|
|
77
|
+
const isNarrow = lower !== void 0 && upper !== void 0 && lower > upper;
|
|
78
|
+
const usesUpper = upper !== void 0 && upper < (lower ?? 0);
|
|
79
|
+
if (isNarrow) {
|
|
80
|
+
const middle = ((minimum ?? exclusiveMinimum) + (maximum ?? exclusiveMaximum)) / 2;
|
|
81
|
+
return integer ? Math.ceil(middle) : middle;
|
|
82
|
+
}
|
|
83
|
+
if (usesUpper) return integer ? Math.floor(upper) : upper;
|
|
84
|
+
return integer ? Math.ceil(lower ?? 0) : lower ?? 0;
|
|
85
|
+
};
|
|
86
|
+
const toTypeSample = (schema) => {
|
|
87
|
+
const type = schema.type?.find((item) => item !== "null") ?? schema.type?.[0];
|
|
88
|
+
if (type === "string") return formatSamples[schema.format ?? ""] ?? "string";
|
|
89
|
+
if (type === "integer" || type === "number") return toNumberSample(schema.constraints, type === "integer");
|
|
90
|
+
if (type === "boolean") return true;
|
|
91
|
+
if (type === "null") return null;
|
|
92
|
+
};
|
|
93
|
+
const mergeSamples = (previous, next) => {
|
|
94
|
+
if (!isObject(previous) || !isObject(next)) return next === void 0 ? previous : next;
|
|
95
|
+
const names = /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(next)]);
|
|
96
|
+
return Object.fromEntries([...names].map((name) => [name, mergeSamples(previous[name], next[name])]));
|
|
97
|
+
};
|
|
98
|
+
/** Applies visibility to the combined sample, including nested fields from other branches. */
|
|
99
|
+
const filterSample = (value, schema, model, mode, seen = []) => {
|
|
100
|
+
const target = resolveSchema(schema, model);
|
|
101
|
+
const hidden = mode === "request" ? "readOnly" : "writeOnly";
|
|
102
|
+
const path = schema.ref ? [...seen, schema.ref] : seen;
|
|
103
|
+
if (target?.[hidden]) return void 0;
|
|
104
|
+
if (!target || schema.ref && seen.includes(schema.ref)) return value;
|
|
105
|
+
let filtered = value;
|
|
106
|
+
for (const part of target.allOf ?? []) filtered = filterSample(filtered, part, model, mode, path);
|
|
107
|
+
if (Array.isArray(filtered) && target.items) {
|
|
108
|
+
const items = target.items;
|
|
109
|
+
return filtered.map((item) => filterSample(item, items, model, mode, path));
|
|
110
|
+
}
|
|
111
|
+
if (!isObject(filtered)) return filtered;
|
|
112
|
+
return Object.fromEntries(Object.entries(filtered).flatMap(([name, item]) => {
|
|
113
|
+
const property = target.properties?.find((property) => property.name === name);
|
|
114
|
+
const sample = property ? filterSample(item, property.schema, model, mode, path) : item;
|
|
115
|
+
return sample === void 0 ? [] : [[name, sample]];
|
|
116
|
+
}));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Creates a sample value for a schema: its example, constant, default, or first enum value, or a
|
|
120
|
+
* value from its type. Recursive schemas stop at their first repetition.
|
|
121
|
+
*/
|
|
122
|
+
const createSample = (schema, model, mode, seen = []) => {
|
|
123
|
+
if (schema.ref) {
|
|
124
|
+
const target = resolveSchema(schema, model);
|
|
125
|
+
if (!target || seen.includes(schema.ref) || seen.length >= maxDepth$1) return void 0;
|
|
126
|
+
return createSample(target, model, mode, [...seen, schema.ref]);
|
|
127
|
+
}
|
|
128
|
+
const value = [
|
|
129
|
+
schema.examples?.[0],
|
|
130
|
+
schema.const,
|
|
131
|
+
schema.default,
|
|
132
|
+
schema.enum?.[0]
|
|
133
|
+
].find((item) => item !== void 0);
|
|
134
|
+
if (value !== void 0) return value;
|
|
135
|
+
if (schema.allOf) {
|
|
136
|
+
const { allOf, ...own } = schema;
|
|
137
|
+
const sample = [...allOf, own].reduce((merged, part) => {
|
|
138
|
+
const sample = createSample(part, model, mode, seen);
|
|
139
|
+
return mergeSamples(merged, sample);
|
|
140
|
+
}, void 0);
|
|
141
|
+
return filterSample(sample, schema, model, mode);
|
|
142
|
+
}
|
|
143
|
+
const option = schema.oneOf?.[0] ?? schema.anyOf?.[0];
|
|
144
|
+
if (option) {
|
|
145
|
+
const { oneOf: _oneOf, anyOf: _anyOf, ...own } = schema;
|
|
146
|
+
return createSample({ allOf: [own, option] }, model, mode, seen);
|
|
147
|
+
}
|
|
148
|
+
if (schema.type?.includes("array") || schema.items) {
|
|
149
|
+
const item = schema.items && createSample(schema.items, model, mode, seen);
|
|
150
|
+
return item === void 0 ? [] : [item];
|
|
151
|
+
}
|
|
152
|
+
if (schema.type?.includes("object") || schema.properties) {
|
|
153
|
+
const hidden = mode === "request" ? "readOnly" : "writeOnly";
|
|
154
|
+
const entries = (schema.properties ?? []).flatMap(({ name, schema: property }) => {
|
|
155
|
+
const sample = resolveSchema(property, model)?.[hidden] ? void 0 : createSample(property, model, mode, seen);
|
|
156
|
+
return sample === void 0 ? [] : [[name, sample]];
|
|
157
|
+
});
|
|
158
|
+
return Object.fromEntries(entries);
|
|
159
|
+
}
|
|
160
|
+
return toTypeSample(schema);
|
|
161
|
+
};
|
|
162
|
+
//#endregion
|
|
163
|
+
//#region src/sources/openapi/forms.ts
|
|
164
|
+
const isJSON = (mediaType) => /^application\/(.+\+)?json\b/.test(mediaType ?? "");
|
|
165
|
+
const isForm = (mediaType) => {
|
|
166
|
+
return mediaType === "application/x-www-form-urlencoded" || mediaType === "multipart/form-data";
|
|
167
|
+
};
|
|
168
|
+
const toFormEntries = (request) => {
|
|
169
|
+
const { body } = request;
|
|
170
|
+
return (typeof body === "object" && body !== null ? Object.entries(body) : []).flatMap(([name, value]) => {
|
|
171
|
+
const encoding = request.encoding?.[name];
|
|
172
|
+
if (request.mediaType === "application/x-www-form-urlencoded" || encoding?.style !== void 0 || encoding?.explode !== void 0) return toQueryEntries({
|
|
173
|
+
name,
|
|
174
|
+
...encoding
|
|
175
|
+
}, value).map(([name, value]) => ({
|
|
176
|
+
name,
|
|
177
|
+
value
|
|
178
|
+
}));
|
|
179
|
+
return (Array.isArray(value) ? value : [value]).map((item) => {
|
|
180
|
+
const contentType = encoding?.contentType ?? (typeof item === "object" && item !== null ? "application/json" : void 0);
|
|
181
|
+
return {
|
|
182
|
+
name,
|
|
183
|
+
value: typeof item === "string" && !isJSON(contentType) ? item : JSON.stringify(item),
|
|
184
|
+
contentType
|
|
185
|
+
};
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
};
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/sources/openapi/examples.ts
|
|
191
|
+
const placeholderURL = "https://api.example.com";
|
|
192
|
+
const placeholderFile = "path/to/file";
|
|
193
|
+
const fileSetup = "const file = new File([\"<file content>\"], \"file\");";
|
|
194
|
+
const aliases = {
|
|
195
|
+
shell: "curl",
|
|
196
|
+
bash: "curl",
|
|
197
|
+
sh: "curl",
|
|
198
|
+
js: "javascript",
|
|
199
|
+
node: "javascript",
|
|
200
|
+
py: "python"
|
|
201
|
+
};
|
|
202
|
+
const languages = {
|
|
203
|
+
"curl": "bash",
|
|
204
|
+
"javascript": "javascript",
|
|
205
|
+
"typescript": "typescript",
|
|
206
|
+
"ts": "typescript",
|
|
207
|
+
"python": "python",
|
|
208
|
+
"go": "go",
|
|
209
|
+
"golang": "go",
|
|
210
|
+
"ruby": "ruby",
|
|
211
|
+
"php": "php",
|
|
212
|
+
"java": "java",
|
|
213
|
+
"kotlin": "kotlin",
|
|
214
|
+
"csharp": "csharp",
|
|
215
|
+
"c#": "csharp",
|
|
216
|
+
"rust": "rust",
|
|
217
|
+
"swift": "swift"
|
|
218
|
+
};
|
|
219
|
+
const toJSON = (value) => JSON.stringify(value, null, 2);
|
|
220
|
+
const quoteShell = (value) => `'${value.replaceAll("'", "'\\''")}'`;
|
|
221
|
+
const quoteForm = (value) => `"${value.replace(/[\\"]/g, "\\$&")}"`;
|
|
222
|
+
const encodeQueryValue = (value) => encodeURIComponent(String(value));
|
|
223
|
+
/** A parameter with `content` is one value in its media type, e.g. JSON, without a style. */
|
|
224
|
+
const toContentValue = (parameter, value) => {
|
|
225
|
+
if (parameter.mediaType === void 0 || value === void 0) return void 0;
|
|
226
|
+
return isJSON(parameter.mediaType) ? JSON.stringify(value) : String(value);
|
|
227
|
+
};
|
|
228
|
+
/** Binary strings: `format: binary` in OpenAPI 3.0, or a media type without an encoding in 3.1. */
|
|
229
|
+
const isBinary = (schema) => {
|
|
230
|
+
return schema?.format === "binary" || Boolean(schema?.contentMediaType && !schema.contentEncoding);
|
|
231
|
+
};
|
|
232
|
+
const isFile = (schema, model) => {
|
|
233
|
+
const target = resolveSchema(schema, model);
|
|
234
|
+
return isBinary(target) || isBinary(target?.items && resolveSchema(target.items, model));
|
|
235
|
+
};
|
|
236
|
+
/** The properties of an object schema, with those of its `allOf` parts. */
|
|
237
|
+
const listProperties = (schema, model, seen = []) => {
|
|
238
|
+
const target = resolveSchema(schema, model);
|
|
239
|
+
const isRepeated = Boolean(schema.ref && seen.includes(schema.ref));
|
|
240
|
+
if (!target || isRepeated) return [];
|
|
241
|
+
const path = schema.ref ? [...seen, schema.ref] : seen;
|
|
242
|
+
return [...target.properties ?? [], ...(target.allOf ?? []).flatMap((part) => listProperties(part, model, path))];
|
|
243
|
+
};
|
|
244
|
+
/** Writes JSON values as Python literals. */
|
|
245
|
+
const toPython = (value, indent = "") => {
|
|
246
|
+
const inner = `${indent} `;
|
|
247
|
+
if (value === null || value === void 0) return "None";
|
|
248
|
+
if (value === true) return "True";
|
|
249
|
+
if (value === false) return "False";
|
|
250
|
+
if (typeof value !== "object") return JSON.stringify(value);
|
|
251
|
+
if (Array.isArray(value)) {
|
|
252
|
+
if (!value.length) return "[]";
|
|
253
|
+
return `[\n${value.map((item) => `${inner}${toPython(item, inner)}`).join(",\n")},\n${indent}]`;
|
|
254
|
+
}
|
|
255
|
+
const entries = Object.entries(value);
|
|
256
|
+
if (!entries.length) return "{}";
|
|
257
|
+
return `{\n${entries.map(([key, item]) => `${inner}${JSON.stringify(key)}: ${toPython(item, inner)}`).join(",\n")},\n${indent}}`;
|
|
258
|
+
};
|
|
259
|
+
const toBodyText = (request) => {
|
|
260
|
+
return !isJSON(request.mediaType) && typeof request.body === "string" ? request.body : toJSON(request.body);
|
|
261
|
+
};
|
|
262
|
+
const generators = {
|
|
263
|
+
curl: {
|
|
264
|
+
label: "cURL",
|
|
265
|
+
language: "bash",
|
|
266
|
+
generate: (request) => {
|
|
267
|
+
const lines = [`curl --request ${request.method.toUpperCase()}`, `--url ${quoteShell(request.url)}`];
|
|
268
|
+
request.headers.forEach(([name, value]) => {
|
|
269
|
+
lines.push(`--header ${quoteShell(`${name}: ${value}`)}`);
|
|
270
|
+
});
|
|
271
|
+
if (request.body !== void 0 && request.mediaType === "multipart/form-data") toFormEntries(request).forEach(({ name, value, contentType }) => {
|
|
272
|
+
const isFile = request.files.includes(name);
|
|
273
|
+
const part = isFile ? `@${placeholderFile}` : quoteForm(value);
|
|
274
|
+
const type = contentType ? `;type=${contentType}` : "";
|
|
275
|
+
lines.push(isFile || contentType ? `--form ${quoteShell(`${name}=${part}${type}`)}` : `--form-string ${quoteShell(`${name}=${value}`)}`);
|
|
276
|
+
});
|
|
277
|
+
else if (request.body !== void 0 && isForm(request.mediaType)) toFormEntries(request).forEach(({ name, value }) => {
|
|
278
|
+
lines.push(`--data-urlencode ${quoteShell(`${name}=${value}`)}`);
|
|
279
|
+
});
|
|
280
|
+
else if (request.isFileBody) lines.push(`--data-binary ${quoteShell(`@${placeholderFile}`)}`);
|
|
281
|
+
else if (request.body !== void 0) lines.push(`--data-raw ${quoteShell(toBodyText(request))}`);
|
|
282
|
+
return lines.join(" \\\n ");
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
javascript: {
|
|
286
|
+
label: "JavaScript",
|
|
287
|
+
language: "javascript",
|
|
288
|
+
generate: (request) => {
|
|
289
|
+
const headers = request.headers.filter(([name]) => {
|
|
290
|
+
return !(request.mediaType === "multipart/form-data" && name === "Content-Type");
|
|
291
|
+
});
|
|
292
|
+
const options = [` method: ${JSON.stringify(request.method.toUpperCase())}`];
|
|
293
|
+
const setup = [];
|
|
294
|
+
if (headers.length) {
|
|
295
|
+
const entries = headers.map(([name, value]) => ` ${JSON.stringify(name)}: ${JSON.stringify(value)}`);
|
|
296
|
+
options.push(` headers: {\n${entries.join(",\n")}\n }`);
|
|
297
|
+
}
|
|
298
|
+
if (request.body !== void 0 && isForm(request.mediaType)) {
|
|
299
|
+
const form = request.mediaType === "multipart/form-data" ? "FormData" : "URLSearchParams";
|
|
300
|
+
if (request.files.length) setup.push(fileSetup);
|
|
301
|
+
setup.push(`const body = new ${form}();`);
|
|
302
|
+
toFormEntries(request).forEach(({ name, value, contentType }) => {
|
|
303
|
+
const isFile = request.files.includes(name);
|
|
304
|
+
const item = isFile ? "file" : JSON.stringify(value);
|
|
305
|
+
const part = contentType ? `new Blob([${item}], { type: ${JSON.stringify(contentType)} })` : item;
|
|
306
|
+
const filename = contentType ? isFile ? ", file.name" : ", \"\"" : "";
|
|
307
|
+
setup.push(`body.append(${JSON.stringify(name)}, ${part}${filename});`);
|
|
308
|
+
});
|
|
309
|
+
options.push(" body");
|
|
310
|
+
} else if (request.isFileBody) {
|
|
311
|
+
setup.push(fileSetup);
|
|
312
|
+
options.push(" body: file");
|
|
313
|
+
} else if (request.body !== void 0) {
|
|
314
|
+
const body = isJSON(request.mediaType) ? `JSON.stringify(${toJSON(request.body).replaceAll("\n", "\n ")})` : JSON.stringify(toBodyText(request));
|
|
315
|
+
options.push(` body: ${body}`);
|
|
316
|
+
}
|
|
317
|
+
return [
|
|
318
|
+
...setup.length ? [setup.join("\n"), ""] : [],
|
|
319
|
+
`const response = await fetch(${JSON.stringify(request.url)}, {\n${options.join(",\n")}\n});`,
|
|
320
|
+
...request.response ? ["", `const data = await response.${request.response}();`] : []
|
|
321
|
+
].join("\n");
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
python: {
|
|
325
|
+
label: "Python",
|
|
326
|
+
language: "python",
|
|
327
|
+
generate: (request) => {
|
|
328
|
+
const headers = request.headers.filter(([name]) => {
|
|
329
|
+
return request.mediaType !== "multipart/form-data" || name !== "Content-Type";
|
|
330
|
+
});
|
|
331
|
+
const method = request.method.toLowerCase();
|
|
332
|
+
const isTrace = method === "trace";
|
|
333
|
+
const args = [...isTrace ? [" \"TRACE\""] : [], ` ${JSON.stringify(request.url)}`];
|
|
334
|
+
if (headers.length) args.push(` headers=${toPython(Object.fromEntries(headers), " ")}`);
|
|
335
|
+
if (request.body !== void 0 && isJSON(request.mediaType)) args.push(request.body === null ? " data=\"null\"" : ` json=${toPython(request.body, " ")}`);
|
|
336
|
+
else if (request.body !== void 0 && request.mediaType === "multipart/form-data") {
|
|
337
|
+
const files = toFormEntries(request).map(({ name, value, contentType }) => {
|
|
338
|
+
const isFile = request.files.includes(name);
|
|
339
|
+
const item = isFile ? `open(${JSON.stringify(placeholderFile)}, "rb")` : JSON.stringify(value);
|
|
340
|
+
const part = `(${isFile ? "\"file\"" : "None"}, ${item}${contentType ? `, ${JSON.stringify(contentType)}` : ""})`;
|
|
341
|
+
return ` (${JSON.stringify(name)}, ${part}),`;
|
|
342
|
+
});
|
|
343
|
+
if (files.length) args.push(` files=[\n${files.join("\n")}\n ]`);
|
|
344
|
+
} else if (request.isFileBody) args.push(` data=open(${JSON.stringify(placeholderFile)}, "rb")`);
|
|
345
|
+
else if (request.body !== void 0) {
|
|
346
|
+
const body = isForm(request.mediaType) ? toPython(toFormEntries(request).map(({ name, value }) => [name, value]), " ") : JSON.stringify(toBodyText(request));
|
|
347
|
+
args.push(` data=${body}`);
|
|
348
|
+
}
|
|
349
|
+
const output = {
|
|
350
|
+
json: "response.json()",
|
|
351
|
+
text: "response.text",
|
|
352
|
+
none: "response.status_code"
|
|
353
|
+
}[request.response ?? "none"];
|
|
354
|
+
return [
|
|
355
|
+
"import requests",
|
|
356
|
+
"",
|
|
357
|
+
`response = requests.${isTrace ? "request" : method}(\n${args.join(",\n")},\n)`,
|
|
358
|
+
"",
|
|
359
|
+
`print(${output})`
|
|
360
|
+
].join("\n");
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
/**
|
|
365
|
+
* Adds placeholders for the schemes of the first security requirement, which all apply. A request
|
|
366
|
+
* has one `Authorization` header, so only the first scheme that uses it adds it.
|
|
367
|
+
*/
|
|
368
|
+
const addCredentials = (operation, model, headers, query, cookies) => {
|
|
369
|
+
const setHeader = (name, value) => {
|
|
370
|
+
const index = headers.findIndex(([item]) => item.toLowerCase() === name.toLowerCase());
|
|
371
|
+
if (index === -1) headers.push([name, value]);
|
|
372
|
+
else headers[index] = [name, value];
|
|
373
|
+
};
|
|
374
|
+
const setAuthorization = (value) => {
|
|
375
|
+
if (!headers.some(([name]) => name === "Authorization")) headers.push(["Authorization", value]);
|
|
376
|
+
};
|
|
377
|
+
Object.keys(operation.security[0] ?? {}).forEach((id) => {
|
|
378
|
+
const scheme = model.securitySchemes.find((item) => item.id === id);
|
|
379
|
+
const httpScheme = scheme?.scheme?.toLowerCase();
|
|
380
|
+
const usesToken = scheme?.type === "oauth2" || scheme?.type === "openIdConnect";
|
|
381
|
+
if (scheme?.type === "http" && httpScheme === "basic") setAuthorization("Basic <credentials>");
|
|
382
|
+
else if (usesToken || scheme?.type === "http" && httpScheme === "bearer") setAuthorization("Bearer <token>");
|
|
383
|
+
else if (scheme?.type === "http" && scheme.scheme) {
|
|
384
|
+
const name = `${scheme.scheme[0].toUpperCase()}${scheme.scheme.slice(1)}`;
|
|
385
|
+
setAuthorization(`${name} <credentials>`);
|
|
386
|
+
} else if (scheme?.type === "apiKey" && scheme.name && scheme.in === "header") setHeader(scheme.name, "<api-key>");
|
|
387
|
+
else if (scheme?.type === "apiKey" && scheme.name && scheme.in === "query") query.set(scheme.name, [encodeQueryValue("<api-key>")]);
|
|
388
|
+
else if (scheme?.type === "apiKey" && scheme.name && scheme.in === "cookie") cookies.set(scheme.name, "<api-key>");
|
|
389
|
+
});
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* Creates the sample request of an operation: path values, required query, header, and cookie
|
|
393
|
+
* values, and parameters with examples, credential placeholders, and a body from examples or the
|
|
394
|
+
* schema.
|
|
395
|
+
*/
|
|
396
|
+
const createRequestSample = (operation, model) => {
|
|
397
|
+
const headers = [];
|
|
398
|
+
const query = /* @__PURE__ */ new Map();
|
|
399
|
+
const cookies = /* @__PURE__ */ new Map();
|
|
400
|
+
const media = operation.requestBody?.contents[0];
|
|
401
|
+
const isMultipart = media?.type === "multipart/form-data";
|
|
402
|
+
const isFileBody = Boolean(media?.schema && !isForm(media.type) && isFile(media.schema, model));
|
|
403
|
+
const files = (isMultipart && media.schema ? listProperties(media.schema, model) : []).filter((property) => isFile(property.schema, model)).map((property) => property.name);
|
|
404
|
+
const responseMedia = (operation.responses.find((response) => response.status.startsWith("2")) ?? operation.responses.find((response) => response.status === "default"))?.contents[0];
|
|
405
|
+
const server = (operation.servers[0]?.url ?? placeholderURL).replace(/\/$/, "");
|
|
406
|
+
const toValue = (parameter) => {
|
|
407
|
+
const example = parameter.examples[0]?.value;
|
|
408
|
+
return example === void 0 ? parameter.schema && createSample(parameter.schema, model, "request") : example;
|
|
409
|
+
};
|
|
410
|
+
let path = operation.path;
|
|
411
|
+
operation.parameters.forEach((parameter) => {
|
|
412
|
+
const value = toValue(parameter);
|
|
413
|
+
const isShown = parameter.required || parameter.examples.length > 0;
|
|
414
|
+
const content = toContentValue(parameter, value);
|
|
415
|
+
if (parameter.in === "path") {
|
|
416
|
+
const text = content === void 0 ? toPathValue(parameter, value === void 0 ? parameter.name : value) : encodeURIComponent(content);
|
|
417
|
+
path = path.replace(`{${parameter.name}}`, text);
|
|
418
|
+
} else if (parameter.in === "query" && isShown && value !== void 0) (content === void 0 ? toQueryEntries(parameter, value, encodeQueryValue) : [[parameter.name, encodeQueryValue(content)]]).forEach(([name, item]) => query.set(name, [...query.get(name) ?? [], item]));
|
|
419
|
+
else if (parameter.in === "header" && isShown && value !== void 0) headers.push([parameter.name, content ?? toSimpleStyleValue(parameter, value)]);
|
|
420
|
+
else if (parameter.in === "cookie" && isShown && value !== void 0) cookies.set(parameter.name, encodeURIComponent(content ?? toSimpleValue(value)));
|
|
421
|
+
});
|
|
422
|
+
addCredentials(operation, model, headers, query, cookies);
|
|
423
|
+
if (cookies.size) headers.push(["Cookie", [...cookies].map(([name, value]) => `${name}=${value}`).join("; ")]);
|
|
424
|
+
const example = media?.examples[0]?.value;
|
|
425
|
+
const body = example === void 0 ? media?.schema && createSample(media.schema, model, "request") : example;
|
|
426
|
+
const queryString = [...query].flatMap(([name, values]) => values.map((value) => `${encodeQueryValue(name)}=${value}`)).join("&");
|
|
427
|
+
const search = queryString ? `?${queryString}` : "";
|
|
428
|
+
if (media && body !== void 0) headers.push(["Content-Type", media.type]);
|
|
429
|
+
return {
|
|
430
|
+
method: operation.method,
|
|
431
|
+
url: `${server}${path}${search}`,
|
|
432
|
+
headers,
|
|
433
|
+
mediaType: media?.type,
|
|
434
|
+
encoding: media?.encoding,
|
|
435
|
+
body,
|
|
436
|
+
files,
|
|
437
|
+
isFileBody,
|
|
438
|
+
response: responseMedia && (isJSON(responseMedia.type) ? "json" : "text")
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
/**
|
|
442
|
+
* Lists the request examples of an operation: cURL, JavaScript, and Python, where a code sample
|
|
443
|
+
* from `x-codeSamples` with the same language replaces the generated one. Other samples follow.
|
|
444
|
+
*/
|
|
445
|
+
const createCodeExamples = (operation, model) => {
|
|
446
|
+
const request = createRequestSample(operation, model);
|
|
447
|
+
const samples = operation.codeSamples.map((sample) => {
|
|
448
|
+
const lang = sample.lang.toLowerCase();
|
|
449
|
+
const id = aliases[lang] ?? lang;
|
|
450
|
+
return {
|
|
451
|
+
id,
|
|
452
|
+
label: sample.label,
|
|
453
|
+
language: languages[id] ?? languages[lang] ?? "text",
|
|
454
|
+
code: sample.source
|
|
455
|
+
};
|
|
456
|
+
});
|
|
457
|
+
const generated = Object.entries(generators).map(([id, generator]) => {
|
|
458
|
+
return samples.find((sample) => sample.id === id) ?? {
|
|
459
|
+
id,
|
|
460
|
+
label: generator.label,
|
|
461
|
+
language: generator.language,
|
|
462
|
+
code: generator.generate(request)
|
|
463
|
+
};
|
|
464
|
+
});
|
|
465
|
+
const counts = /* @__PURE__ */ new Map();
|
|
466
|
+
return [...generated, ...samples.filter((sample) => !generated.includes(sample))].map((example) => {
|
|
467
|
+
const count = (counts.get(example.label) ?? 0) + 1;
|
|
468
|
+
counts.set(example.label, count);
|
|
469
|
+
return count > 1 ? {
|
|
470
|
+
...example,
|
|
471
|
+
label: `${example.label} ${count}`
|
|
472
|
+
} : example;
|
|
473
|
+
});
|
|
474
|
+
};
|
|
475
|
+
//#endregion
|
|
476
|
+
//#region src/sources/openapi/fields.ts
|
|
477
|
+
const maxDepth = 12;
|
|
478
|
+
const descriptions = /* @__PURE__ */ new Map();
|
|
479
|
+
const toID = (value) => value.replace(/[^\w-]+/g, "-");
|
|
480
|
+
/** Removes the IDs of headings, which could repeat the IDs of operation sections. */
|
|
481
|
+
const removeHeadingIDs = (node) => {
|
|
482
|
+
node.children.forEach((child) => {
|
|
483
|
+
if (child.type !== "element") return;
|
|
484
|
+
if (/^h[1-6]$/.test(child.tagName)) delete child.properties.id;
|
|
485
|
+
removeHeadingIDs(child);
|
|
486
|
+
});
|
|
487
|
+
return node;
|
|
488
|
+
};
|
|
489
|
+
const toHTML = (markdown, highlight) => {
|
|
490
|
+
if (!markdown) return void 0;
|
|
491
|
+
if (!descriptions.has(markdown)) descriptions.set(markdown, prepareMarkdown(markdown, highlight).then(({ nodes }) => toHtml(removeHeadingIDs(nodes))));
|
|
492
|
+
return descriptions.get(markdown);
|
|
493
|
+
};
|
|
494
|
+
/** Merges fields that `allOf` parts repeat, e.g. a part that makes a base field read-only. */
|
|
495
|
+
const mergeFields = (fields) => {
|
|
496
|
+
const merged = /* @__PURE__ */ new Map();
|
|
497
|
+
fields.forEach((field) => {
|
|
498
|
+
const previous = merged.get(field.name);
|
|
499
|
+
if (!previous) {
|
|
500
|
+
merged.set(field.name, field);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
merged.set(field.name, {
|
|
504
|
+
...previous,
|
|
505
|
+
type: field.type === "any" ? previous.type : field.type,
|
|
506
|
+
required: previous.required || field.required,
|
|
507
|
+
deprecated: previous.deprecated || field.deprecated,
|
|
508
|
+
readOnly: previous.readOnly || field.readOnly,
|
|
509
|
+
writeOnly: previous.writeOnly || field.writeOnly,
|
|
510
|
+
description: field.description ?? previous.description,
|
|
511
|
+
facts: [...new Map([...previous.facts, ...field.facts].map((fact) => [fact.label, fact])).values()],
|
|
512
|
+
fields: mergeFields([...previous.fields, ...field.fields]),
|
|
513
|
+
variants: [...previous.variants, ...field.variants],
|
|
514
|
+
recursive: previous.recursive ?? field.recursive
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
return [...merged.values()];
|
|
518
|
+
};
|
|
519
|
+
/** Builds field trees of schemas. A field that repeats a schema that contains it links to it. */
|
|
520
|
+
const createFieldBuilder = (model, highlight) => {
|
|
521
|
+
const expand = async (schema, id, ancestors, depth, required = /* @__PURE__ */ new Set()) => {
|
|
522
|
+
const ancestor = schema.ref && ancestors.find((item) => item.ref === schema.ref);
|
|
523
|
+
if (ancestor) return {
|
|
524
|
+
fields: [],
|
|
525
|
+
variants: [],
|
|
526
|
+
recursive: {
|
|
527
|
+
name: ancestor.ref,
|
|
528
|
+
href: `#${ancestor.id}`
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
const target = resolveSchema(schema, model);
|
|
532
|
+
const path = schema.ref ? [...ancestors, {
|
|
533
|
+
ref: schema.ref,
|
|
534
|
+
id
|
|
535
|
+
}] : ancestors;
|
|
536
|
+
const requiredNames = /* @__PURE__ */ new Set([...required, ...getRequiredNames(schema, model)]);
|
|
537
|
+
if (!target || depth > maxDepth) return {
|
|
538
|
+
fields: [],
|
|
539
|
+
variants: []
|
|
540
|
+
};
|
|
541
|
+
const fields = await Promise.all((target.properties ?? []).map((property) => {
|
|
542
|
+
return toField(property.name, property.required || requiredNames.has(property.name), property.schema, `${id}-${toID(property.name)}`, path, depth);
|
|
543
|
+
}));
|
|
544
|
+
const variants = [];
|
|
545
|
+
if (typeof target.additionalProperties === "object") fields.push(await toField("{key}", false, target.additionalProperties, `${id}-key`, path, depth));
|
|
546
|
+
let recursive;
|
|
547
|
+
if (target.items) {
|
|
548
|
+
const nested = await expand(target.items, id, path, depth);
|
|
549
|
+
fields.push(...nested.fields);
|
|
550
|
+
variants.push(...nested.variants);
|
|
551
|
+
recursive = nested.recursive;
|
|
552
|
+
}
|
|
553
|
+
for (const part of target.allOf ?? []) {
|
|
554
|
+
const nested = await expand(part, id, path, depth, requiredNames);
|
|
555
|
+
fields.push(...nested.fields);
|
|
556
|
+
variants.push(...nested.variants);
|
|
557
|
+
recursive ??= nested.recursive;
|
|
558
|
+
}
|
|
559
|
+
for (const kind of ["oneOf", "anyOf"]) {
|
|
560
|
+
const options = await Promise.all((target[kind] ?? []).map(async (option, index) => {
|
|
561
|
+
const optionID = `${id}-${kind}-${index + 1}`;
|
|
562
|
+
const nested = await expand(option, optionID, path, depth + 1, requiredNames);
|
|
563
|
+
const optionTarget = resolveSchemaDetails(option, model);
|
|
564
|
+
return {
|
|
565
|
+
id: optionID,
|
|
566
|
+
label: option.ref ?? option.title ?? `Option ${index + 1}`,
|
|
567
|
+
kind,
|
|
568
|
+
type: toTypeLabel(optionTarget ?? option),
|
|
569
|
+
description: await toHTML(optionTarget?.description, highlight),
|
|
570
|
+
facts: optionTarget ? toFacts(optionTarget) : [],
|
|
571
|
+
fields: nested.fields,
|
|
572
|
+
variants: nested.variants
|
|
573
|
+
};
|
|
574
|
+
}));
|
|
575
|
+
variants.push(...options);
|
|
576
|
+
}
|
|
577
|
+
return {
|
|
578
|
+
fields: mergeFields(fields),
|
|
579
|
+
variants,
|
|
580
|
+
recursive
|
|
581
|
+
};
|
|
582
|
+
};
|
|
583
|
+
const toField = async (name, required, schema, id, ancestors, depth) => {
|
|
584
|
+
const target = resolveSchemaDetails(schema, model);
|
|
585
|
+
const nested = await expand(schema, id, ancestors, depth + 1);
|
|
586
|
+
return {
|
|
587
|
+
id,
|
|
588
|
+
name,
|
|
589
|
+
type: toTypeLabel(schema.ref ? schema : target ?? schema),
|
|
590
|
+
required,
|
|
591
|
+
deprecated: Boolean(target?.deprecated),
|
|
592
|
+
readOnly: Boolean(target?.readOnly),
|
|
593
|
+
writeOnly: Boolean(target?.writeOnly),
|
|
594
|
+
description: await toHTML(target?.description, highlight),
|
|
595
|
+
facts: target ? toFacts(target) : [],
|
|
596
|
+
...nested
|
|
597
|
+
};
|
|
598
|
+
};
|
|
599
|
+
const toMedia = async (media, id) => {
|
|
600
|
+
const schema = media.schema ? await toField("Body", false, media.schema, `${id}-schema`, [], 0) : void 0;
|
|
601
|
+
if (schema && media.schema) schema.type = toTypeLabel(resolveSchemaDetails(media.schema, model) ?? media.schema);
|
|
602
|
+
return {
|
|
603
|
+
id,
|
|
604
|
+
type: media.type,
|
|
605
|
+
schema
|
|
606
|
+
};
|
|
607
|
+
};
|
|
608
|
+
return {
|
|
609
|
+
toField,
|
|
610
|
+
toMedia
|
|
611
|
+
};
|
|
612
|
+
};
|
|
613
|
+
//#endregion
|
|
614
|
+
//#region src/sources/openapi/view.ts
|
|
615
|
+
const locations = [
|
|
616
|
+
["path", "Path parameters"],
|
|
617
|
+
["query", "Query parameters"],
|
|
618
|
+
["header", "Headers"],
|
|
619
|
+
["cookie", "Cookies"]
|
|
620
|
+
];
|
|
621
|
+
const toPlainText = (value = "") => value.replace(/[^\p{L}\p{N}]+/gu, "").toLowerCase();
|
|
622
|
+
const toCodeView = async (label, language, code, highlight) => {
|
|
623
|
+
const pre = await highlightCode(code, language, highlight);
|
|
624
|
+
return {
|
|
625
|
+
label,
|
|
626
|
+
language,
|
|
627
|
+
code,
|
|
628
|
+
html: toHtml(pre.children)
|
|
629
|
+
};
|
|
630
|
+
};
|
|
631
|
+
const toResponseExample = async (media, label, model, highlight) => {
|
|
632
|
+
const example = media?.examples[0]?.value;
|
|
633
|
+
const value = example === void 0 ? media?.schema && createSample(media.schema, model, "response") : example;
|
|
634
|
+
if (value === void 0) return void 0;
|
|
635
|
+
const json = isJSON(media?.type) || typeof value !== "string";
|
|
636
|
+
return toCodeView(label, json ? "json" : "text", json ? JSON.stringify(value, null, 2) : String(value), highlight);
|
|
637
|
+
};
|
|
638
|
+
/**
|
|
639
|
+
* Resolves an operation for the template: HTML descriptions, field trees with anchors,
|
|
640
|
+
* highlighted request examples, and response examples.
|
|
641
|
+
*/
|
|
642
|
+
const createOperationView = async (operation, model, options) => {
|
|
643
|
+
const { highlight, anchor = "" } = options;
|
|
644
|
+
const builder = createFieldBuilder(model, highlight);
|
|
645
|
+
const show = (part) => {
|
|
646
|
+
return options.parts?.[part] ?? (part !== "examples" || options.anchor === void 0);
|
|
647
|
+
};
|
|
648
|
+
const body = show("requestBody") ? operation.requestBody : void 0;
|
|
649
|
+
const toParameter = async (parameter, id) => {
|
|
650
|
+
const field = await builder.toField(parameter.name, parameter.required, parameter.schema ?? {}, id, [], 0);
|
|
651
|
+
const description = await toHTML(parameter.description, highlight);
|
|
652
|
+
return {
|
|
653
|
+
...field,
|
|
654
|
+
deprecated: field.deprecated || parameter.deprecated,
|
|
655
|
+
description: description ?? field.description
|
|
656
|
+
};
|
|
657
|
+
};
|
|
658
|
+
const parameters = await Promise.all((show("parameters") ? locations : []).map(([location, label]) => {
|
|
659
|
+
return {
|
|
660
|
+
location,
|
|
661
|
+
label,
|
|
662
|
+
items: operation.parameters.filter((parameter) => parameter.in === location)
|
|
663
|
+
};
|
|
664
|
+
}).filter((group) => group.items.length).map(async ({ location, label, items }) => {
|
|
665
|
+
const id = `${anchor}${location}`;
|
|
666
|
+
return {
|
|
667
|
+
id,
|
|
668
|
+
label,
|
|
669
|
+
fields: await Promise.all(items.map((parameter) => toParameter(parameter, `${id}-${toID(parameter.name)}`)))
|
|
670
|
+
};
|
|
671
|
+
}));
|
|
672
|
+
const responses = await Promise.all((show("responses") ? operation.responses : []).map(async (response) => {
|
|
673
|
+
const id = `${anchor}response-${toID(response.status)}`;
|
|
674
|
+
const label = toStatusLabel(response.status);
|
|
675
|
+
const isRepeated = [response.status, label].some((text) => {
|
|
676
|
+
return toPlainText(text) === toPlainText(response.description);
|
|
677
|
+
});
|
|
678
|
+
return {
|
|
679
|
+
id,
|
|
680
|
+
status: response.status,
|
|
681
|
+
label,
|
|
682
|
+
description: isRepeated ? void 0 : await toHTML(response.description, highlight),
|
|
683
|
+
headers: await Promise.all(response.headers.map(async (header) => {
|
|
684
|
+
const field = await builder.toField(header.name, header.required, header.schema ?? {}, `${id}-header-${toID(header.name)}`, [], 0);
|
|
685
|
+
const description = await toHTML(header.description, highlight);
|
|
686
|
+
return {
|
|
687
|
+
...field,
|
|
688
|
+
description: description ?? field.description
|
|
689
|
+
};
|
|
690
|
+
})),
|
|
691
|
+
contents: await Promise.all(response.contents.map((media, index) => {
|
|
692
|
+
return builder.toMedia(media, index ? `${id}-${index + 1}` : `${id}-body`);
|
|
693
|
+
}))
|
|
694
|
+
};
|
|
695
|
+
}));
|
|
696
|
+
const examples = await Promise.all((show("examples") ? createCodeExamples(operation, model) : []).map((example) => {
|
|
697
|
+
return toCodeView(example.label, example.language, example.code, highlight);
|
|
698
|
+
}));
|
|
699
|
+
const responseExamples = await Promise.all((show("examples") ? operation.responses : []).map((response) => {
|
|
700
|
+
return toResponseExample(response.contents[0], response.status, model, highlight);
|
|
701
|
+
}));
|
|
702
|
+
return {
|
|
703
|
+
anchor,
|
|
704
|
+
embedded: options.anchor !== void 0,
|
|
705
|
+
title: options.title,
|
|
706
|
+
href: options.href,
|
|
707
|
+
method: operation.method,
|
|
708
|
+
path: operation.path,
|
|
709
|
+
deprecated: operation.deprecated,
|
|
710
|
+
description: show("description") ? await toHTML(operation.description, highlight) : void 0,
|
|
711
|
+
servers: await Promise.all(operation.servers.map(async (server) => {
|
|
712
|
+
return {
|
|
713
|
+
url: server.url,
|
|
714
|
+
description: await toHTML(server.description, highlight)
|
|
715
|
+
};
|
|
716
|
+
})),
|
|
717
|
+
security: await Promise.all((show("authentication") ? operation.security : []).map((requirement) => {
|
|
718
|
+
return Promise.all(Object.entries(requirement).map(async ([id, scopes]) => {
|
|
719
|
+
const scheme = model.securitySchemes.find((item) => item.id === id);
|
|
720
|
+
return {
|
|
721
|
+
id,
|
|
722
|
+
label: scheme ? toSchemeLabel(scheme) : id,
|
|
723
|
+
description: await toHTML(scheme?.description, highlight),
|
|
724
|
+
scopes
|
|
725
|
+
};
|
|
726
|
+
}));
|
|
727
|
+
})),
|
|
728
|
+
parameters,
|
|
729
|
+
requestBody: body && {
|
|
730
|
+
id: `${anchor}request-body`,
|
|
731
|
+
required: body.required,
|
|
732
|
+
description: await toHTML(body.description, highlight),
|
|
733
|
+
contents: await Promise.all(body.contents.map((media, index) => {
|
|
734
|
+
return builder.toMedia(media, index ? `${anchor}body-${index + 1}` : `${anchor}body`);
|
|
735
|
+
}))
|
|
736
|
+
},
|
|
737
|
+
responses,
|
|
738
|
+
examples,
|
|
739
|
+
responseExamples: responseExamples.filter((example) => Boolean(example))
|
|
740
|
+
};
|
|
741
|
+
};
|
|
742
|
+
//#endregion
|
|
743
|
+
export { toID as n, createOperationView as t };
|
|
744
|
+
|
|
745
|
+
//# sourceMappingURL=view-C-9ZM1zK.js.map
|