@andesine/pages 0.0.0-stage → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/LICENSE +21 -0
  3. package/README.md +92 -2
  4. package/dist/answers.d.ts +6 -0
  5. package/dist/astro/content.astro +118 -0
  6. package/dist/astro/middleware.js +39 -0
  7. package/dist/astro/middleware.js.map +1 -0
  8. package/dist/astro/routes/answers.js +129 -0
  9. package/dist/astro/routes/answers.js.map +1 -0
  10. package/dist/astro/routes/entry-pages.js +22 -0
  11. package/dist/astro/routes/entry-pages.js.map +1 -0
  12. package/dist/astro/routes/llms-full.js +12 -0
  13. package/dist/astro/routes/llms-full.js.map +1 -0
  14. package/dist/astro/routes/llms.js +12 -0
  15. package/dist/astro/routes/llms.js.map +1 -0
  16. package/dist/astro/routes/markdown-alias.js +14 -0
  17. package/dist/astro/routes/markdown-alias.js.map +1 -0
  18. package/dist/astro/routes/markdown.js +12 -0
  19. package/dist/astro/routes/markdown.js.map +1 -0
  20. package/dist/astro/routes/not-found.astro +12 -0
  21. package/dist/astro/routes/robots.js +9 -0
  22. package/dist/astro/routes/robots.js.map +1 -0
  23. package/dist/astro/routes/search.js +42 -0
  24. package/dist/astro/routes/search.js.map +1 -0
  25. package/dist/astro/routes/sitemap.js +12 -0
  26. package/dist/astro/routes/sitemap.js.map +1 -0
  27. package/dist/astro/routes/skill.js +13 -0
  28. package/dist/astro/routes/skill.js.map +1 -0
  29. package/dist/astro/routes/skills.js +24 -0
  30. package/dist/astro/routes/skills.js.map +1 -0
  31. package/dist/astro/routes/social.js +91 -0
  32. package/dist/astro/routes/social.js.map +1 -0
  33. package/dist/astro/routes/static.astro +53 -0
  34. package/dist/astro/routes/well-known-llms.js +2 -0
  35. package/dist/astro.d.ts +34 -0
  36. package/dist/astro.js +60 -0
  37. package/dist/astro.js.map +1 -0
  38. package/dist/chunks/assets-D6WJmZ05.js +21 -0
  39. package/dist/chunks/assets-D6WJmZ05.js.map +1 -0
  40. package/dist/chunks/catalog-DU4BUrpw.js +28 -0
  41. package/dist/chunks/catalog-DU4BUrpw.js.map +1 -0
  42. package/dist/chunks/config-CuH5JSI4.js +184 -0
  43. package/dist/chunks/config-CuH5JSI4.js.map +1 -0
  44. package/dist/chunks/files-BxqiQzFj.js +62 -0
  45. package/dist/chunks/files-BxqiQzFj.js.map +1 -0
  46. package/dist/chunks/hash-D4piIIQ6.js +11 -0
  47. package/dist/chunks/hash-D4piIIQ6.js.map +1 -0
  48. package/dist/chunks/index-D8wL2B5s.d.ts +571 -0
  49. package/dist/chunks/index-vsu3hISM.d.ts +62 -0
  50. package/dist/chunks/limits-Ppc7BQPG.js +45 -0
  51. package/dist/chunks/limits-Ppc7BQPG.js.map +1 -0
  52. package/dist/chunks/markdown-DKJSQxR2.js +42 -0
  53. package/dist/chunks/markdown-DKJSQxR2.js.map +1 -0
  54. package/dist/chunks/mdx-components-CUUDTapN.d.ts +9 -0
  55. package/dist/chunks/normalize-DG5nxOLm.js +361 -0
  56. package/dist/chunks/normalize-DG5nxOLm.js.map +1 -0
  57. package/dist/chunks/paths-75QgA3Qs.js +16 -0
  58. package/dist/chunks/paths-75QgA3Qs.js.map +1 -0
  59. package/dist/chunks/prepare-lnuw_ycM.js +219 -0
  60. package/dist/chunks/prepare-lnuw_ycM.js.map +1 -0
  61. package/dist/chunks/read-DCv1lmcM.js +57 -0
  62. package/dist/chunks/read-DCv1lmcM.js.map +1 -0
  63. package/dist/chunks/request-DOuBHGQs.js +92 -0
  64. package/dist/chunks/request-DOuBHGQs.js.map +1 -0
  65. package/dist/chunks/response-CtzaKMWH.js +15 -0
  66. package/dist/chunks/response-CtzaKMWH.js.map +1 -0
  67. package/dist/chunks/site-DY-uZ0PP.js +419 -0
  68. package/dist/chunks/site-DY-uZ0PP.js.map +1 -0
  69. package/dist/chunks/skill-CBTGUHQH.js +85 -0
  70. package/dist/chunks/skill-CBTGUHQH.js.map +1 -0
  71. package/dist/chunks/sources-Cm6NdIen.js +236 -0
  72. package/dist/chunks/sources-Cm6NdIen.js.map +1 -0
  73. package/dist/chunks/stored-CabomV-C.js +354 -0
  74. package/dist/chunks/stored-CabomV-C.js.map +1 -0
  75. package/dist/chunks/stored-CcEfvCQH.js +475 -0
  76. package/dist/chunks/stored-CcEfvCQH.js.map +1 -0
  77. package/dist/chunks/types-DBzuXfSe.d.ts +53 -0
  78. package/dist/chunks/view-C-9ZM1zK.js +745 -0
  79. package/dist/chunks/view-C-9ZM1zK.js.map +1 -0
  80. package/dist/chunks/view-Dlf_VRI7.d.ts +151 -0
  81. package/dist/client.d.ts +73 -0
  82. package/dist/client.js +295 -0
  83. package/dist/client.js.map +1 -0
  84. package/dist/collections.d.ts +7 -0
  85. package/dist/collections.js +215 -0
  86. package/dist/collections.js.map +1 -0
  87. package/dist/entry-pages.d.ts +10 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.js +38 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/integration.d.ts +16 -0
  92. package/dist/integration.js +435 -0
  93. package/dist/integration.js.map +1 -0
  94. package/dist/llms-full.d.ts +5 -0
  95. package/dist/llms.d.ts +5 -0
  96. package/dist/markdown-alias.d.ts +7 -0
  97. package/dist/markdown.d.ts +7 -0
  98. package/dist/middleware.d.ts +8 -0
  99. package/dist/robots.d.ts +5 -0
  100. package/dist/runtime.d.ts +81 -0
  101. package/dist/runtime.js +56 -0
  102. package/dist/runtime.js.map +1 -0
  103. package/dist/scripts/restore-navigation.js +1 -0
  104. package/dist/search.d.ts +6 -0
  105. package/dist/sitemap.d.ts +5 -0
  106. package/dist/skill.d.ts +5 -0
  107. package/dist/skills.d.ts +10 -0
  108. package/dist/social.d.ts +7 -0
  109. package/dist/well-known-llms.d.ts +2 -0
  110. package/package.json +103 -3
@@ -0,0 +1,42 @@
1
+ //#region src/output/markdown.ts
2
+ const toLine = (value) => value.replace(/\s+/g, " ").trim();
3
+ /** Text for Markdown link labels, with brackets and backslashes escaped. */
4
+ const toLabel = (value) => toLine(value).replace(/[[\]\\]/g, "\\$&");
5
+ const toQuote = (text) => {
6
+ return text.split("\n").map((line) => line.trim() ? `> ${line}` : ">").join("\n");
7
+ };
8
+ const getLLMsURL = (config) => {
9
+ return new URL(`${config.base}llms.txt`, config.site).href;
10
+ };
11
+ /** Tells agents on a single page where the index is, with the site's agent instructions. */
12
+ const createAgentNote = (config) => {
13
+ const index = [
14
+ "## Documentation index",
15
+ "",
16
+ `Fetch the complete documentation index at: ${getLLMsURL(config)}`,
17
+ "Use it to find all pages before you explore further."
18
+ ];
19
+ const instructions = config.agents.instructions ? [
20
+ "",
21
+ "## Agent instructions",
22
+ "",
23
+ config.agents.instructions
24
+ ] : [];
25
+ return toQuote([...index, ...instructions].join("\n"));
26
+ };
27
+ /** A page's Markdown, with its title, description, and optional source URL. */
28
+ const createPageBody = (page, source) => {
29
+ return [
30
+ `# ${toLine(page.title)}`,
31
+ source && `Source: ${source}`,
32
+ page.description && `> ${toLine(page.description)}`,
33
+ page.markdown
34
+ ].filter(Boolean).join("\n\n");
35
+ };
36
+ const createMarkdownPage = (config, page) => {
37
+ return `${createAgentNote(config)}\n\n${createPageBody(page)}\n`;
38
+ };
39
+ //#endregion
40
+ export { toLine as i, createPageBody as n, toLabel as r, createMarkdownPage as t };
41
+
42
+ //# sourceMappingURL=markdown-DKJSQxR2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-DKJSQxR2.js","names":[],"sources":["../../src/output/markdown.ts"],"sourcesContent":["import type { PagesConfig } from \"../config\";\nimport type { SourcePage } from \"../sources\";\n\nconst toLine = (value: string): string => value.replace(/\\s+/g, \" \").trim();\n/** Text for Markdown link labels, with brackets and backslashes escaped. */\nconst toLabel = (value: string): string => toLine(value).replace(/[[\\]\\\\]/g, \"\\\\$&\");\nconst toQuote = (text: string): string => {\n return text\n .split(\"\\n\")\n .map((line) => (line.trim() ? `> ${line}` : \">\"))\n .join(\"\\n\");\n};\nconst getLLMsURL = (config: PagesConfig): string => {\n return new URL(`${config.base}llms.txt`, config.site).href;\n};\n/** Tells agents on a single page where the index is, with the site's agent instructions. */\nconst createAgentNote = (config: PagesConfig): string => {\n const index = [\n \"## Documentation index\",\n \"\",\n `Fetch the complete documentation index at: ${getLLMsURL(config)}`,\n \"Use it to find all pages before you explore further.\"\n ];\n const instructions = config.agents.instructions\n ? [\"\", \"## Agent instructions\", \"\", config.agents.instructions]\n : [];\n\n return toQuote([...index, ...instructions].join(\"\\n\"));\n};\n/** A page's Markdown, with its title, description, and optional source URL. */\nconst createPageBody = (page: SourcePage, source?: string): string => {\n const title = `# ${toLine(page.title)}`;\n const url = source && `Source: ${source}`;\n const description = page.description && `> ${toLine(page.description)}`;\n\n return [title, url, description, page.markdown].filter(Boolean).join(\"\\n\\n\");\n};\nconst createMarkdownPage = (config: PagesConfig, page: SourcePage): string => {\n return `${createAgentNote(config)}\\n\\n${createPageBody(page)}\\n`;\n};\n\nexport { toLine, toLabel, getLLMsURL, createAgentNote, createPageBody, createMarkdownPage };\n"],"mappings":";AAGA,MAAM,UAAU,UAA0B,MAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK;;AAE1E,MAAM,WAAW,UAA0B,OAAO,KAAK,CAAC,CAAC,QAAQ,YAAY,MAAM;AACnF,MAAM,WAAW,SAAyB;CACxC,OAAO,KACJ,MAAM,IAAI,CAAC,CACX,KAAK,SAAU,KAAK,KAAK,IAAI,KAAK,SAAS,GAAI,CAAC,CAChD,KAAK,IAAI;AACd;AACA,MAAM,cAAc,WAAgC;CAClD,OAAO,IAAI,IAAI,GAAG,OAAO,KAAK,WAAW,OAAO,IAAI,CAAC,CAAC;AACxD;;AAEA,MAAM,mBAAmB,WAAgC;CACvD,MAAM,QAAQ;EACZ;EACA;EACA,8CAA8C,WAAW,MAAM;EAC/D;CACF;CACA,MAAM,eAAe,OAAO,OAAO,eAC/B;EAAC;EAAI;EAAyB;EAAI,OAAO,OAAO;CAAY,IAC5D,CAAC;CAEL,OAAO,QAAQ,CAAC,GAAG,OAAO,GAAG,YAAY,CAAC,CAAC,KAAK,IAAI,CAAC;AACvD;;AAEA,MAAM,kBAAkB,MAAkB,WAA4B;CAKpE,OAAO;EAAC,KAJW,OAAO,KAAK,KAAK;EACxB,UAAU,WAAW;EACb,KAAK,eAAe,KAAK,OAAO,KAAK,WAAW;EAEnC,KAAK;CAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,MAAM;AAC7E;AACA,MAAM,sBAAsB,QAAqB,SAA6B;CAC5E,OAAO,GAAG,gBAAgB,MAAM,EAAE,MAAM,eAAe,IAAI,EAAE;AAC/D"}
@@ -0,0 +1,9 @@
1
+ //#region src/content/mdx-components.d.ts
2
+ interface FileTreeItem {
3
+ name: string;
4
+ type: "file" | "folder";
5
+ children: FileTreeItem[];
6
+ }
7
+ //#endregion
8
+ export { FileTreeItem as t };
9
+ //# sourceMappingURL=mdx-components-CUUDTapN.d.ts.map
@@ -0,0 +1,361 @@
1
+ //#region src/sources/openapi/normalize.ts
2
+ const reservedHeaders = [
3
+ "accept",
4
+ "content-type",
5
+ "authorization"
6
+ ];
7
+ const methods = [
8
+ "get",
9
+ "put",
10
+ "post",
11
+ "delete",
12
+ "options",
13
+ "head",
14
+ "patch",
15
+ "trace"
16
+ ];
17
+ const constraintKeys = [
18
+ "minimum",
19
+ "maximum",
20
+ "exclusiveMinimum",
21
+ "exclusiveMaximum",
22
+ "multipleOf",
23
+ "minLength",
24
+ "maxLength",
25
+ "pattern",
26
+ "minItems",
27
+ "maxItems",
28
+ "uniqueItems",
29
+ "minProperties",
30
+ "maxProperties"
31
+ ];
32
+ const exclusiveKeys = [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]];
33
+ const schemaPrefix = "#/components/schemas/";
34
+ const isObject = (value) => {
35
+ return typeof value === "object" && value !== null && !Array.isArray(value);
36
+ };
37
+ const toObject = (value) => isObject(value) ? value : {};
38
+ /** Makes a label from an identifier-like tag name, e.g. `schemaMigrations` or `type-metadata`. */
39
+ const toTagLabel = (name) => {
40
+ if (!/^[a-z][a-zA-Z\d]*(?:[-_][a-zA-Z\d]+)*$/.test(name)) return name;
41
+ const words = name.replace(/([a-z\d])([A-Z])/g, "$1 $2").split(/[-_\s]+/).join(" ").toLowerCase();
42
+ return `${words[0].toUpperCase()}${words.slice(1)}`;
43
+ };
44
+ const toText = (value) => {
45
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
46
+ };
47
+ /** Removes `undefined` fields, so the stored model stays small. */
48
+ const compact = (value) => {
49
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== void 0));
50
+ };
51
+ /** Decodes URI escapes; keys can contain a bare `%`, which is not an escape. */
52
+ const decodeSegment = (segment) => {
53
+ try {
54
+ return decodeURIComponent(segment);
55
+ } catch {
56
+ return segment;
57
+ }
58
+ };
59
+ const unescapeSegment = (segment) => {
60
+ return decodeSegment(segment).replaceAll("~1", "/").replaceAll("~0", "~");
61
+ };
62
+ /** Reads a local JSON pointer, such as `#/components/schemas/Pet`. */
63
+ const readPointer = (document, ref) => {
64
+ return ref.slice(2).split("/").map(unescapeSegment).reduce((value, key) => {
65
+ if (Array.isArray(value)) return /^(0|[1-9]\d*)$/.test(key) ? value[Number(key)] : void 0;
66
+ return isObject(value) ? value[key] : void 0;
67
+ }, document);
68
+ };
69
+ /** Schema examples: 3.1 `examples`, or the 3.0 `example`. */
70
+ const toSchemaExamples = (raw) => {
71
+ if (Array.isArray(raw.examples)) return raw.examples;
72
+ return raw.example === void 0 ? void 0 : [raw.example];
73
+ };
74
+ /** Normalizes a spec; `label` names its source in errors. */
75
+ const normalizeSpec = (document, label, baseURL = "https://api.example.com") => {
76
+ const info = toObject(document.info);
77
+ const components = toObject(document.components);
78
+ const schemas = {};
79
+ const schemaNames = /* @__PURE__ */ new Map();
80
+ const usedNames = /* @__PURE__ */ new Set();
81
+ const ignored = /* @__PURE__ */ new Set();
82
+ const supportsSchemaSiblings = String(document.openapi).startsWith("3.1.");
83
+ /** Follows references of parameters, responses, and other objects, which cannot recurse. */
84
+ const resolve = (value, depth = 0) => {
85
+ const ref = isObject(value) ? value.$ref : void 0;
86
+ if (typeof ref !== "string" || depth > 20) return toObject(value);
87
+ return resolve(readPointer(document, ref), depth + 1);
88
+ };
89
+ const toSchemaName = (ref) => {
90
+ const base = ref.startsWith(schemaPrefix) ? unescapeSegment(ref.slice(21)) : unescapeSegment(ref.split("/").at(-1) ?? "Schema");
91
+ let name = base;
92
+ for (let index = 2; usedNames.has(name); index++) name = `${base}${index}`;
93
+ usedNames.add(name);
94
+ return name;
95
+ };
96
+ const toSchemaList = (value) => {
97
+ return Array.isArray(value) ? value.map(toSchema) : void 0;
98
+ };
99
+ /** Named schemas become references, so recursive schemas stay finite. */
100
+ const toSchema = (value) => {
101
+ if (value === true) return {};
102
+ if (value === false) return { not: {} };
103
+ const raw = toObject(value);
104
+ if (typeof raw.$ref === "string") {
105
+ let name = schemaNames.get(raw.$ref);
106
+ if (!name) {
107
+ name = toSchemaName(raw.$ref);
108
+ schemaNames.set(raw.$ref, name);
109
+ schemas[name] = {};
110
+ schemas[name] = toSchema(readPointer(document, raw.$ref));
111
+ }
112
+ const reference = compact({
113
+ ref: name,
114
+ description: toText(raw.description),
115
+ default: raw.default,
116
+ examples: toSchemaExamples(raw),
117
+ deprecated: raw.deprecated === true || void 0,
118
+ readOnly: raw.readOnly === true || void 0,
119
+ writeOnly: raw.writeOnly === true || void 0
120
+ });
121
+ const { $ref: _ref, ...siblings } = raw;
122
+ const schema = supportsSchemaSiblings ? toSchema(siblings) : {};
123
+ if (Object.keys(schema).some((key) => !(key in reference))) return {
124
+ ...schema,
125
+ allOf: [{ ref: name }, ...schema.allOf ?? []]
126
+ };
127
+ return reference;
128
+ }
129
+ const types = raw.type === void 0 ? [] : [raw.type].flat().map(String);
130
+ const required = Array.isArray(raw.required) ? raw.required.map(String) : [];
131
+ const properties = isObject(raw.properties) ? Object.entries(raw.properties) : void 0;
132
+ const constraints = Object.fromEntries(constraintKeys.filter((key) => raw[key] !== void 0).map((key) => [key, raw[key]]));
133
+ const examples = toSchemaExamples(raw);
134
+ if (raw.nullable === true && types.length && !types.includes("null")) types.push("null");
135
+ for (const [exclusive, limit] of exclusiveKeys) {
136
+ if (typeof constraints[exclusive] !== "boolean") continue;
137
+ if (constraints[exclusive] && constraints[limit] !== void 0) {
138
+ constraints[exclusive] = constraints[limit];
139
+ delete constraints[limit];
140
+ } else delete constraints[exclusive];
141
+ }
142
+ return compact({
143
+ type: types.length ? types : void 0,
144
+ format: toText(raw.format),
145
+ contentMediaType: toText(raw.contentMediaType),
146
+ contentEncoding: toText(raw.contentEncoding),
147
+ title: toText(raw.title),
148
+ description: toText(raw.description),
149
+ enum: Array.isArray(raw.enum) ? raw.enum : void 0,
150
+ const: raw.const,
151
+ default: raw.default,
152
+ examples,
153
+ deprecated: raw.deprecated === true || void 0,
154
+ readOnly: raw.readOnly === true || void 0,
155
+ writeOnly: raw.writeOnly === true || void 0,
156
+ required: required.length ? required : void 0,
157
+ properties: properties?.map(([name, schema]) => {
158
+ return {
159
+ name,
160
+ required: required.includes(name),
161
+ schema: toSchema(schema)
162
+ };
163
+ }),
164
+ additionalProperties: typeof raw.additionalProperties === "boolean" ? raw.additionalProperties : raw.additionalProperties === void 0 ? void 0 : toSchema(raw.additionalProperties),
165
+ items: raw.items === void 0 ? void 0 : toSchema(raw.items),
166
+ allOf: toSchemaList(raw.allOf),
167
+ oneOf: toSchemaList(raw.oneOf),
168
+ anyOf: toSchemaList(raw.anyOf),
169
+ not: raw.not === void 0 ? void 0 : toSchema(raw.not),
170
+ discriminator: isObject(raw.discriminator) ? raw.discriminator : void 0,
171
+ constraints: Object.keys(constraints).length ? constraints : void 0
172
+ });
173
+ };
174
+ const toExamples = (raw) => {
175
+ if (isObject(raw.examples)) return Object.entries(raw.examples).map(([name, example]) => {
176
+ const resolved = resolve(example);
177
+ return compact({
178
+ name,
179
+ summary: toText(resolved.summary),
180
+ value: resolved.value
181
+ });
182
+ });
183
+ return raw.example === void 0 ? [] : [{ value: raw.example }];
184
+ };
185
+ const toMediaTypes = (content) => {
186
+ return Object.entries(toObject(content)).map(([type, media]) => {
187
+ const raw = resolve(media);
188
+ return compact({
189
+ type,
190
+ schema: raw.schema === void 0 ? void 0 : toSchema(raw.schema),
191
+ examples: toExamples(raw),
192
+ encoding: isObject(raw.encoding) ? Object.fromEntries(Object.entries(raw.encoding).map(([name, value]) => {
193
+ const encoding = toObject(value);
194
+ return [name, compact({
195
+ contentType: toText(encoding.contentType),
196
+ style: toText(encoding.style),
197
+ explode: typeof encoding.explode === "boolean" ? encoding.explode : void 0
198
+ })];
199
+ })) : void 0
200
+ });
201
+ });
202
+ };
203
+ const toParameter = (value) => {
204
+ const raw = resolve(value);
205
+ const [media] = toMediaTypes(raw.content);
206
+ const examples = toExamples(raw);
207
+ return compact({
208
+ name: String(raw.name),
209
+ in: raw.in,
210
+ required: raw.in === "path" || raw.required === true,
211
+ deprecated: raw.deprecated === true,
212
+ description: toText(raw.description),
213
+ schema: raw.schema === void 0 ? media?.schema : toSchema(raw.schema),
214
+ examples: examples.length ? examples : media?.examples ?? [],
215
+ mediaType: raw.schema === void 0 ? media?.type : void 0,
216
+ style: toText(raw.style),
217
+ explode: typeof raw.explode === "boolean" ? raw.explode : void 0
218
+ });
219
+ };
220
+ /** Response headers; OpenAPI ignores a `Content-Type` header, which the content sets. */
221
+ const toHeaders = (headers) => {
222
+ return Object.entries(toObject(headers)).filter(([name]) => {
223
+ return name.toLowerCase() !== "content-type";
224
+ }).map(([name, header]) => {
225
+ const raw = resolve(header);
226
+ return compact({
227
+ name,
228
+ required: raw.required === true,
229
+ description: toText(raw.description),
230
+ schema: raw.schema === void 0 ? void 0 : toSchema(raw.schema)
231
+ });
232
+ });
233
+ };
234
+ const toRequestBody = (value) => {
235
+ const raw = resolve(value);
236
+ return compact({
237
+ required: raw.required === true,
238
+ description: toText(raw.description),
239
+ contents: toMediaTypes(raw.content)
240
+ });
241
+ };
242
+ const toResponses = (responses) => {
243
+ return Object.entries(toObject(responses)).filter(([status]) => !status.startsWith("x-")).map(([status, response]) => {
244
+ const raw = resolve(response);
245
+ return compact({
246
+ status,
247
+ description: toText(raw.description),
248
+ headers: toHeaders(raw.headers),
249
+ contents: toMediaTypes(raw.content)
250
+ });
251
+ });
252
+ };
253
+ const toServers = (value) => {
254
+ return Array.isArray(value) ? value.map((server) => {
255
+ const raw = toObject(server);
256
+ const variables = toObject(raw.variables);
257
+ const url = String(raw.url).replace(/\{([^}]+)\}/g, (match, name) => {
258
+ const value = toObject(variables[name]).default;
259
+ return value === void 0 ? match : String(value);
260
+ });
261
+ return compact({
262
+ url: new URL(url, baseURL).href,
263
+ description: toText(raw.description)
264
+ });
265
+ }) : void 0;
266
+ };
267
+ const toCodeSamples = (raw) => {
268
+ const samples = raw["x-codeSamples"] ?? raw["x-code-samples"];
269
+ return (Array.isArray(samples) ? samples : []).filter(isObject).map((sample) => {
270
+ const lang = String(sample.lang);
271
+ return {
272
+ lang,
273
+ label: toText(sample.label) ?? lang,
274
+ source: String(sample.source)
275
+ };
276
+ });
277
+ };
278
+ const servers = toServers(document.servers) ?? [];
279
+ const operations = Object.entries(toObject(document.paths)).flatMap(([path, item]) => {
280
+ const pathItem = resolve(item);
281
+ const pathParameters = Array.isArray(pathItem.parameters) ? pathItem.parameters : [];
282
+ return methods.flatMap((method) => {
283
+ const raw = pathItem[method];
284
+ if (!isObject(raw)) return [];
285
+ if (raw.callbacks) ignored.add("callbacks");
286
+ const parameters = /* @__PURE__ */ new Map();
287
+ const operationParameters = Array.isArray(raw.parameters) ? raw.parameters : [];
288
+ [...pathParameters, ...operationParameters].map(toParameter).forEach((parameter) => {
289
+ const isHeader = parameter.in === "header";
290
+ const name = isHeader ? parameter.name.toLowerCase() : parameter.name;
291
+ if (isHeader && reservedHeaders.includes(name)) return;
292
+ parameters.set(`${parameter.in}:${name}`, parameter);
293
+ });
294
+ return [compact({
295
+ id: toText(raw.operationId) ?? `${method.toUpperCase()} ${path}`,
296
+ method,
297
+ path,
298
+ summary: toText(raw.summary),
299
+ description: toText(raw.description),
300
+ deprecated: raw.deprecated === true,
301
+ tags: Array.isArray(raw.tags) ? raw.tags.map(String) : [],
302
+ parameters: [...parameters.values()],
303
+ requestBody: raw.requestBody === void 0 ? void 0 : toRequestBody(raw.requestBody),
304
+ responses: toResponses(raw.responses),
305
+ security: Array.isArray(raw.security) ? raw.security : document.security ?? [],
306
+ servers: toServers(raw.servers) ?? toServers(pathItem.servers) ?? servers,
307
+ codeSamples: toCodeSamples(raw),
308
+ extensions: Object.fromEntries(Object.entries(raw).filter(([key]) => {
309
+ return key.startsWith("x-") && key !== "x-codeSamples" && key !== "x-code-samples";
310
+ }))
311
+ })];
312
+ });
313
+ });
314
+ const declaredTags = (Array.isArray(document.tags) ? document.tags : []).filter(isObject).map((tag) => {
315
+ const name = String(tag.name);
316
+ return compact({
317
+ name,
318
+ label: toText(tag["x-displayName"]) ?? toTagLabel(name),
319
+ description: toText(tag.description)
320
+ });
321
+ });
322
+ const operationIDs = /* @__PURE__ */ new Set();
323
+ const usedTags = new Set(operations.flatMap((operation) => operation.tags.slice(0, 1)));
324
+ const tags = [...declaredTags.filter((tag) => usedTags.has(tag.name)), ...[...usedTags].filter((name) => !declaredTags.some((tag) => tag.name === name)).map((name) => ({
325
+ name,
326
+ label: toTagLabel(name)
327
+ }))];
328
+ operations.forEach((operation) => {
329
+ if (operationIDs.has(operation.id)) throw new Error(`${label}: more than one operation uses the operation ID "${operation.id}".`);
330
+ operationIDs.add(operation.id);
331
+ });
332
+ if (document.webhooks) ignored.add("webhooks");
333
+ return {
334
+ model: compact({
335
+ title: toText(info.title) ?? "API",
336
+ version: String(info.version ?? ""),
337
+ description: toText(info.description),
338
+ servers,
339
+ securitySchemes: Object.entries(toObject(components.securitySchemes)).map(([id, scheme]) => {
340
+ const raw = resolve(scheme);
341
+ return compact({
342
+ id,
343
+ type: String(raw.type),
344
+ description: toText(raw.description),
345
+ scheme: toText(raw.scheme),
346
+ bearerFormat: toText(raw.bearerFormat),
347
+ name: toText(raw.name),
348
+ in: toText(raw.in)
349
+ });
350
+ }),
351
+ tags,
352
+ operations,
353
+ schemas
354
+ }),
355
+ ignored: [...ignored]
356
+ };
357
+ };
358
+ //#endregion
359
+ export { normalizeSpec as n, isObject as t };
360
+
361
+ //# sourceMappingURL=normalize-DG5nxOLm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-DG5nxOLm.js","names":[],"sources":["../../src/sources/openapi/normalize.ts"],"sourcesContent":["import type {\n ApiCodeSample,\n ApiExample,\n ApiHeader,\n ApiMediaType,\n ApiModel,\n ApiOperation,\n ApiParameter,\n ApiRequestBody,\n ApiResponse,\n ApiSchema,\n ApiServer,\n ApiTag\n} from \"./model\";\n\ninterface NormalizedSpec {\n model: ApiModel;\n /** Spec features that the reference leaves out, for build warnings. */\n ignored: string[];\n}\n\ntype RawObject = Record<string, unknown>;\n\n// OpenAPI ignores header parameters with these names; the spec sets them in other ways.\nconst reservedHeaders = [\"accept\", \"content-type\", \"authorization\"];\nconst methods = [\"get\", \"put\", \"post\", \"delete\", \"options\", \"head\", \"patch\", \"trace\"];\nconst constraintKeys = [\n \"minimum\",\n \"maximum\",\n \"exclusiveMinimum\",\n \"exclusiveMaximum\",\n \"multipleOf\",\n \"minLength\",\n \"maxLength\",\n \"pattern\",\n \"minItems\",\n \"maxItems\",\n \"uniqueItems\",\n \"minProperties\",\n \"maxProperties\"\n];\nconst exclusiveKeys = [\n [\"exclusiveMinimum\", \"minimum\"],\n [\"exclusiveMaximum\", \"maximum\"]\n] as const;\nconst schemaPrefix = \"#/components/schemas/\";\n\nconst isObject = (value: unknown): value is RawObject => {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\nconst toObject = (value: unknown): RawObject => (isObject(value) ? value : {});\n/** Makes a label from an identifier-like tag name, e.g. `schemaMigrations` or `type-metadata`. */\nconst toTagLabel = (name: string): string => {\n if (!/^[a-z][a-zA-Z\\d]*(?:[-_][a-zA-Z\\d]+)*$/.test(name)) return name;\n\n const words = name\n .replace(/([a-z\\d])([A-Z])/g, \"$1 $2\")\n .split(/[-_\\s]+/)\n .join(\" \")\n .toLowerCase();\n\n return `${words[0]!.toUpperCase()}${words.slice(1)}`;\n};\nconst toText = (value: unknown): string | undefined => {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n};\n/** Removes `undefined` fields, so the stored model stays small. */\nconst compact = <T extends object>(value: T): T => {\n return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined)) as T;\n};\n/** Decodes URI escapes; keys can contain a bare `%`, which is not an escape. */\nconst decodeSegment = (segment: string): string => {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n};\nconst unescapeSegment = (segment: string): string => {\n return decodeSegment(segment).replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\");\n};\n/** Reads a local JSON pointer, such as `#/components/schemas/Pet`. */\nconst readPointer = (document: RawObject, ref: string): unknown => {\n return ref\n .slice(2)\n .split(\"/\")\n .map(unescapeSegment)\n .reduce<unknown>((value, key) => {\n if (Array.isArray(value)) {\n return /^(0|[1-9]\\d*)$/.test(key) ? value[Number(key)] : undefined;\n }\n\n return isObject(value) ? value[key] : undefined;\n }, document);\n};\n/** Schema examples: 3.1 `examples`, or the 3.0 `example`. */\nconst toSchemaExamples = (raw: RawObject): unknown[] | undefined => {\n if (Array.isArray(raw.examples)) return raw.examples;\n\n return raw.example === undefined ? undefined : [raw.example];\n};\n/** Normalizes a spec; `label` names its source in errors. */\nconst normalizeSpec = (\n document: RawObject,\n label: string,\n baseURL = \"https://api.example.com\"\n): NormalizedSpec => {\n const info = toObject(document.info);\n const components = toObject(document.components);\n const schemas: Record<string, ApiSchema> = {};\n const schemaNames = new Map<string, string>();\n const usedNames = new Set<string>();\n const ignored = new Set<string>();\n const supportsSchemaSiblings = String(document.openapi).startsWith(\"3.1.\");\n /** Follows references of parameters, responses, and other objects, which cannot recurse. */\n const resolve = (value: unknown, depth = 0): RawObject => {\n const ref = isObject(value) ? value.$ref : undefined;\n\n if (typeof ref !== \"string\" || depth > 20) return toObject(value);\n\n return resolve(readPointer(document, ref), depth + 1);\n };\n const toSchemaName = (ref: string): string => {\n const base = ref.startsWith(schemaPrefix)\n ? unescapeSegment(ref.slice(schemaPrefix.length))\n : unescapeSegment(ref.split(\"/\").at(-1) ?? \"Schema\");\n\n let name = base;\n\n for (let index = 2; usedNames.has(name); index++) name = `${base}${index}`;\n\n usedNames.add(name);\n\n return name;\n };\n const toSchemaList = (value: unknown): ApiSchema[] | undefined => {\n return Array.isArray(value) ? value.map(toSchema) : undefined;\n };\n /** Named schemas become references, so recursive schemas stay finite. */\n const toSchema = (value: unknown): ApiSchema => {\n if (value === true) return {};\n if (value === false) return { not: {} };\n\n const raw = toObject(value);\n\n if (typeof raw.$ref === \"string\") {\n let name = schemaNames.get(raw.$ref);\n\n if (!name) {\n name = toSchemaName(raw.$ref);\n schemaNames.set(raw.$ref, name);\n schemas[name] = {};\n schemas[name] = toSchema(readPointer(document, raw.$ref));\n }\n\n const reference = compact({\n ref: name,\n description: toText(raw.description),\n default: raw.default,\n examples: toSchemaExamples(raw),\n deprecated: raw.deprecated === true || undefined,\n readOnly: raw.readOnly === true || undefined,\n writeOnly: raw.writeOnly === true || undefined\n });\n const { $ref: _ref, ...siblings } = raw;\n const schema = supportsSchemaSiblings ? toSchema(siblings) : {};\n const hasConstraints = Object.keys(schema).some((key) => !(key in reference));\n\n if (hasConstraints) {\n return { ...schema, allOf: [{ ref: name }, ...(schema.allOf ?? [])] };\n }\n\n return reference;\n }\n\n const types = raw.type === undefined ? [] : [raw.type].flat().map(String);\n const required = Array.isArray(raw.required) ? raw.required.map(String) : [];\n const properties = isObject(raw.properties) ? Object.entries(raw.properties) : undefined;\n const constraints = Object.fromEntries(\n constraintKeys.filter((key) => raw[key] !== undefined).map((key) => [key, raw[key]])\n );\n const examples = toSchemaExamples(raw);\n\n // OpenAPI 3.0 `nullable` has no effect without a `type`.\n if (raw.nullable === true && types.length && !types.includes(\"null\")) types.push(\"null\");\n\n // OpenAPI 3.0 makes `minimum` and `maximum` exclusive with booleans; 3.1 uses the limits.\n for (const [exclusive, limit] of exclusiveKeys) {\n if (typeof constraints[exclusive] !== \"boolean\") continue;\n\n if (constraints[exclusive] && constraints[limit] !== undefined) {\n constraints[exclusive] = constraints[limit];\n delete constraints[limit];\n } else {\n delete constraints[exclusive];\n }\n }\n\n return compact({\n type: types.length ? types : undefined,\n format: toText(raw.format),\n contentMediaType: toText(raw.contentMediaType),\n contentEncoding: toText(raw.contentEncoding),\n title: toText(raw.title),\n description: toText(raw.description),\n enum: Array.isArray(raw.enum) ? raw.enum : undefined,\n const: raw.const,\n default: raw.default,\n examples,\n deprecated: raw.deprecated === true || undefined,\n readOnly: raw.readOnly === true || undefined,\n writeOnly: raw.writeOnly === true || undefined,\n required: required.length ? required : undefined,\n properties: properties?.map(([name, schema]) => {\n return { name, required: required.includes(name), schema: toSchema(schema) };\n }),\n additionalProperties:\n typeof raw.additionalProperties === \"boolean\"\n ? raw.additionalProperties\n : raw.additionalProperties === undefined\n ? undefined\n : toSchema(raw.additionalProperties),\n items: raw.items === undefined ? undefined : toSchema(raw.items),\n allOf: toSchemaList(raw.allOf),\n oneOf: toSchemaList(raw.oneOf),\n anyOf: toSchemaList(raw.anyOf),\n not: raw.not === undefined ? undefined : toSchema(raw.not),\n discriminator: isObject(raw.discriminator)\n ? (raw.discriminator as ApiSchema[\"discriminator\"])\n : undefined,\n constraints: Object.keys(constraints).length ? constraints : undefined\n });\n };\n const toExamples = (raw: RawObject): ApiExample[] => {\n if (isObject(raw.examples)) {\n return Object.entries(raw.examples).map(([name, example]) => {\n const resolved = resolve(example);\n\n return compact({ name, summary: toText(resolved.summary), value: resolved.value });\n });\n }\n\n return raw.example === undefined ? [] : [{ value: raw.example }];\n };\n const toMediaTypes = (content: unknown): ApiMediaType[] => {\n return Object.entries(toObject(content)).map(([type, media]) => {\n const raw = resolve(media);\n\n return compact({\n type,\n schema: raw.schema === undefined ? undefined : toSchema(raw.schema),\n examples: toExamples(raw),\n encoding: isObject(raw.encoding)\n ? Object.fromEntries(\n Object.entries(raw.encoding).map(([name, value]) => {\n const encoding = toObject(value);\n\n return [\n name,\n compact({\n contentType: toText(encoding.contentType),\n style: toText(encoding.style),\n explode: typeof encoding.explode === \"boolean\" ? encoding.explode : undefined\n })\n ];\n })\n )\n : undefined\n });\n });\n };\n const toParameter = (value: unknown): ApiParameter => {\n const raw = resolve(value);\n const [media] = toMediaTypes(raw.content);\n const examples = toExamples(raw);\n\n return compact({\n name: String(raw.name),\n in: raw.in as ApiParameter[\"in\"],\n required: raw.in === \"path\" || raw.required === true,\n deprecated: raw.deprecated === true,\n description: toText(raw.description),\n schema: raw.schema === undefined ? media?.schema : toSchema(raw.schema),\n // A parameter with `content` can have its examples there.\n examples: examples.length ? examples : (media?.examples ?? []),\n mediaType: raw.schema === undefined ? media?.type : undefined,\n style: toText(raw.style),\n explode: typeof raw.explode === \"boolean\" ? raw.explode : undefined\n });\n };\n /** Response headers; OpenAPI ignores a `Content-Type` header, which the content sets. */\n const toHeaders = (headers: unknown): ApiHeader[] => {\n const entries = Object.entries(toObject(headers)).filter(([name]) => {\n return name.toLowerCase() !== \"content-type\";\n });\n\n return entries.map(([name, header]) => {\n const raw = resolve(header);\n\n return compact({\n name,\n required: raw.required === true,\n description: toText(raw.description),\n schema: raw.schema === undefined ? undefined : toSchema(raw.schema)\n });\n });\n };\n const toRequestBody = (value: unknown): ApiRequestBody => {\n const raw = resolve(value);\n\n return compact({\n required: raw.required === true,\n description: toText(raw.description),\n contents: toMediaTypes(raw.content)\n });\n };\n const toResponses = (responses: unknown): ApiResponse[] => {\n const entries = Object.entries(toObject(responses)).filter(\n ([status]) => !status.startsWith(\"x-\")\n );\n\n return entries.map(([status, response]) => {\n const raw = resolve(response);\n\n return compact({\n status,\n description: toText(raw.description),\n headers: toHeaders(raw.headers),\n contents: toMediaTypes(raw.content)\n });\n });\n };\n const toServers = (value: unknown): ApiServer[] | undefined => {\n return Array.isArray(value)\n ? value.map((server) => {\n const raw = toObject(server);\n const variables = toObject(raw.variables);\n // Variables, e.g. `{region}`, take their default values.\n const url = String(raw.url).replace(/\\{([^}]+)\\}/g, (match, name: string) => {\n const value = toObject(variables[name]).default;\n\n return value === undefined ? match : String(value);\n });\n\n return compact({ url: new URL(url, baseURL).href, description: toText(raw.description) });\n })\n : undefined;\n };\n const toCodeSamples = (raw: RawObject): ApiCodeSample[] => {\n const samples = raw[\"x-codeSamples\"] ?? raw[\"x-code-samples\"];\n\n return (Array.isArray(samples) ? samples : []).filter(isObject).map((sample) => {\n const lang = String(sample.lang);\n\n return { lang, label: toText(sample.label) ?? lang, source: String(sample.source) };\n });\n };\n const servers = toServers(document.servers) ?? [];\n const operations = Object.entries(toObject(document.paths)).flatMap(([path, item]) => {\n const pathItem = resolve(item);\n const pathParameters = Array.isArray(pathItem.parameters) ? pathItem.parameters : [];\n\n return methods.flatMap((method): ApiOperation[] => {\n const raw = pathItem[method];\n\n if (!isObject(raw)) return [];\n\n if (raw.callbacks) ignored.add(\"callbacks\");\n\n const parameters = new Map<string, ApiParameter>();\n const operationParameters = Array.isArray(raw.parameters) ? raw.parameters : [];\n\n // Operation parameters replace path parameters with the same name and place.\n [...pathParameters, ...operationParameters].map(toParameter).forEach((parameter) => {\n const isHeader = parameter.in === \"header\";\n const name = isHeader ? parameter.name.toLowerCase() : parameter.name;\n\n if (isHeader && reservedHeaders.includes(name)) return;\n\n parameters.set(`${parameter.in}:${name}`, parameter);\n });\n\n return [\n compact({\n id: toText(raw.operationId) ?? `${method.toUpperCase()} ${path}`,\n method,\n path,\n summary: toText(raw.summary),\n description: toText(raw.description),\n deprecated: raw.deprecated === true,\n tags: Array.isArray(raw.tags) ? raw.tags.map(String) : [],\n parameters: [...parameters.values()],\n requestBody: raw.requestBody === undefined ? undefined : toRequestBody(raw.requestBody),\n responses: toResponses(raw.responses),\n security: (Array.isArray(raw.security)\n ? raw.security\n : (document.security ?? [])) as Array<Record<string, string[]>>,\n servers: toServers(raw.servers) ?? toServers(pathItem.servers) ?? servers,\n codeSamples: toCodeSamples(raw),\n extensions: Object.fromEntries(\n Object.entries(raw).filter(([key]) => {\n return key.startsWith(\"x-\") && key !== \"x-codeSamples\" && key !== \"x-code-samples\";\n })\n )\n })\n ];\n });\n });\n const declaredTags = (Array.isArray(document.tags) ? document.tags : [])\n .filter(isObject)\n .map((tag): ApiTag => {\n const name = String(tag.name);\n\n return compact({\n name,\n label: toText(tag[\"x-displayName\"]) ?? toTagLabel(name),\n description: toText(tag.description)\n });\n });\n const operationIDs = new Set<string>();\n // Operations show in their first tag only, so other tags make no groups.\n const usedTags = new Set(operations.flatMap((operation) => operation.tags.slice(0, 1)));\n const tags = [\n ...declaredTags.filter((tag) => usedTags.has(tag.name)),\n ...[...usedTags]\n .filter((name) => !declaredTags.some((tag) => tag.name === name))\n .map((name) => ({ name, label: toTagLabel(name) }))\n ];\n\n operations.forEach((operation) => {\n if (operationIDs.has(operation.id)) {\n throw new Error(`${label}: more than one operation uses the operation ID \"${operation.id}\".`);\n }\n\n operationIDs.add(operation.id);\n });\n\n if (document.webhooks) ignored.add(\"webhooks\");\n\n return {\n model: compact({\n title: toText(info.title) ?? \"API\",\n version: String(info.version ?? \"\"),\n description: toText(info.description),\n servers,\n securitySchemes: Object.entries(toObject(components.securitySchemes)).map(([id, scheme]) => {\n const raw = resolve(scheme);\n\n return compact({\n id,\n type: String(raw.type),\n description: toText(raw.description),\n scheme: toText(raw.scheme),\n bearerFormat: toText(raw.bearerFormat),\n name: toText(raw.name),\n in: toText(raw.in)\n });\n }),\n tags,\n operations,\n schemas\n }),\n ignored: [...ignored]\n };\n};\n\nexport { normalizeSpec, isObject };\nexport type { NormalizedSpec };\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ //#region src/routing/paths.ts
2
+ /** Splits a decoded path, such as `/guides/intro/` or `guides/intro`, into segments. */
3
+ const toSegments = (path, label) => {
4
+ const segments = path.split("/").filter(Boolean);
5
+ if (segments.some((segment) => /^\.\.?$|[\\?#%]/.test(segment))) throw new Error(`${label}: "${path}" is not a valid path. Do not use ., .., \\, ?, #, or %.`);
6
+ return segments;
7
+ };
8
+ /** Joins decoded segments into an encoded URL path with a trailing slash. */
9
+ const toHref = (...segments) => {
10
+ const parts = segments.flat().map(encodeURIComponent);
11
+ return parts.length ? `/${parts.join("/")}/` : "/";
12
+ };
13
+ //#endregion
14
+ export { toSegments as n, toHref as t };
15
+
16
+ //# sourceMappingURL=paths-75QgA3Qs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths-75QgA3Qs.js","names":[],"sources":["../../src/routing/paths.ts"],"sourcesContent":["/** Splits a decoded path, such as `/guides/intro/` or `guides/intro`, into segments. */\nconst toSegments = (path: string, label: string): string[] => {\n const segments = path.split(\"/\").filter(Boolean);\n const invalid = segments.some((segment) => /^\\.\\.?$|[\\\\?#%]/.test(segment));\n\n if (invalid) {\n throw new Error(`${label}: \"${path}\" is not a valid path. Do not use ., .., \\\\, ?, #, or %.`);\n }\n\n return segments;\n};\n/** Joins decoded segments into an encoded URL path with a trailing slash. */\nconst toHref = (...segments: string[][]): string => {\n const parts = segments.flat().map(encodeURIComponent);\n\n return parts.length ? `/${parts.join(\"/\")}/` : \"/\";\n};\n\nexport { toSegments, toHref };\n"],"mappings":";;AACA,MAAM,cAAc,MAAc,UAA4B;CAC5D,MAAM,WAAW,KAAK,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;CAG/C,IAFgB,SAAS,MAAM,YAAY,kBAAkB,KAAK,OAAO,CAE/D,GACR,MAAM,IAAI,MAAM,GAAG,MAAM,KAAK,KAAK,yDAAyD;CAG9F,OAAO;AACT;;AAEA,MAAM,UAAU,GAAG,aAAiC;CAClD,MAAM,QAAQ,SAAS,KAAK,CAAC,CAAC,IAAI,kBAAkB;CAEpD,OAAO,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,EAAE,KAAK;AACjD"}