milieu-cli 0.1.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/LICENSE +200 -0
- package/README.md +153 -0
- package/dist/bridges/index.d.ts +5 -0
- package/dist/bridges/index.d.ts.map +1 -0
- package/dist/bridges/index.js +6 -0
- package/dist/bridges/index.js.map +1 -0
- package/dist/bridges/reachability/crawler-policy.d.ts +36 -0
- package/dist/bridges/reachability/crawler-policy.d.ts.map +1 -0
- package/dist/bridges/reachability/crawler-policy.js +110 -0
- package/dist/bridges/reachability/crawler-policy.js.map +1 -0
- package/dist/bridges/reachability/http-status.d.ts +7 -0
- package/dist/bridges/reachability/http-status.d.ts.map +1 -0
- package/dist/bridges/reachability/http-status.js +74 -0
- package/dist/bridges/reachability/http-status.js.map +1 -0
- package/dist/bridges/reachability/https-check.d.ts +14 -0
- package/dist/bridges/reachability/https-check.d.ts.map +1 -0
- package/dist/bridges/reachability/https-check.js +38 -0
- package/dist/bridges/reachability/https-check.js.map +1 -0
- package/dist/bridges/reachability/index.d.ts +13 -0
- package/dist/bridges/reachability/index.d.ts.map +1 -0
- package/dist/bridges/reachability/index.js +115 -0
- package/dist/bridges/reachability/index.js.map +1 -0
- package/dist/bridges/reachability/meta-robots.d.ts +16 -0
- package/dist/bridges/reachability/meta-robots.d.ts.map +1 -0
- package/dist/bridges/reachability/meta-robots.js +119 -0
- package/dist/bridges/reachability/meta-robots.js.map +1 -0
- package/dist/bridges/reachability/robots-parser.d.ts +26 -0
- package/dist/bridges/reachability/robots-parser.d.ts.map +1 -0
- package/dist/bridges/reachability/robots-parser.js +105 -0
- package/dist/bridges/reachability/robots-parser.js.map +1 -0
- package/dist/bridges/reachability/robots-txt.d.ts +14 -0
- package/dist/bridges/reachability/robots-txt.d.ts.map +1 -0
- package/dist/bridges/reachability/robots-txt.js +80 -0
- package/dist/bridges/reachability/robots-txt.js.map +1 -0
- package/dist/bridges/separation/api-presence.d.ts +14 -0
- package/dist/bridges/separation/api-presence.d.ts.map +1 -0
- package/dist/bridges/separation/api-presence.js +96 -0
- package/dist/bridges/separation/api-presence.js.map +1 -0
- package/dist/bridges/separation/developer-docs.d.ts +21 -0
- package/dist/bridges/separation/developer-docs.d.ts.map +1 -0
- package/dist/bridges/separation/developer-docs.js +81 -0
- package/dist/bridges/separation/developer-docs.js.map +1 -0
- package/dist/bridges/separation/index.d.ts +20 -0
- package/dist/bridges/separation/index.d.ts.map +1 -0
- package/dist/bridges/separation/index.js +63 -0
- package/dist/bridges/separation/index.js.map +1 -0
- package/dist/bridges/separation/sdk-references.d.ts +12 -0
- package/dist/bridges/separation/sdk-references.d.ts.map +1 -0
- package/dist/bridges/separation/sdk-references.js +93 -0
- package/dist/bridges/separation/sdk-references.js.map +1 -0
- package/dist/bridges/separation/webhook-support.d.ts +19 -0
- package/dist/bridges/separation/webhook-support.d.ts.map +1 -0
- package/dist/bridges/separation/webhook-support.js +94 -0
- package/dist/bridges/separation/webhook-support.js.map +1 -0
- package/dist/bridges/standards/index.d.ts +13 -0
- package/dist/bridges/standards/index.d.ts.map +1 -0
- package/dist/bridges/standards/index.js +79 -0
- package/dist/bridges/standards/index.js.map +1 -0
- package/dist/bridges/standards/json-ld.d.ts +16 -0
- package/dist/bridges/standards/json-ld.d.ts.map +1 -0
- package/dist/bridges/standards/json-ld.js +63 -0
- package/dist/bridges/standards/json-ld.js.map +1 -0
- package/dist/bridges/standards/llms-txt.d.ts +19 -0
- package/dist/bridges/standards/llms-txt.d.ts.map +1 -0
- package/dist/bridges/standards/llms-txt.js +64 -0
- package/dist/bridges/standards/llms-txt.js.map +1 -0
- package/dist/bridges/standards/mcp.d.ts +13 -0
- package/dist/bridges/standards/mcp.d.ts.map +1 -0
- package/dist/bridges/standards/mcp.js +72 -0
- package/dist/bridges/standards/mcp.js.map +1 -0
- package/dist/bridges/standards/openapi.d.ts +14 -0
- package/dist/bridges/standards/openapi.d.ts.map +1 -0
- package/dist/bridges/standards/openapi.js +424 -0
- package/dist/bridges/standards/openapi.js.map +1 -0
- package/dist/bridges/standards/schema-org.d.ts +12 -0
- package/dist/bridges/standards/schema-org.d.ts.map +1 -0
- package/dist/bridges/standards/schema-org.js +101 -0
- package/dist/bridges/standards/schema-org.js.map +1 -0
- package/dist/bridges/standards/well-known.d.ts +16 -0
- package/dist/bridges/standards/well-known.d.ts.map +1 -0
- package/dist/bridges/standards/well-known.js +77 -0
- package/dist/bridges/standards/well-known.js.map +1 -0
- package/dist/bridges/stubs.d.ts +4 -0
- package/dist/bridges/stubs.d.ts.map +1 -0
- package/dist/bridges/stubs.js +25 -0
- package/dist/bridges/stubs.js.map +1 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +83 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/explanations.d.ts +11 -0
- package/dist/core/explanations.d.ts.map +1 -0
- package/dist/core/explanations.js +128 -0
- package/dist/core/explanations.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +6 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/scan.d.ts +3 -0
- package/dist/core/scan.d.ts.map +1 -0
- package/dist/core/scan.js +89 -0
- package/dist/core/scan.js.map +1 -0
- package/dist/core/types.d.ts +119 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/version.d.ts +2 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +7 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/render/colors.d.ts +7 -0
- package/dist/render/colors.d.ts.map +1 -0
- package/dist/render/colors.js +28 -0
- package/dist/render/colors.js.map +1 -0
- package/dist/render/format-bridge.d.ts +3 -0
- package/dist/render/format-bridge.d.ts.map +1 -0
- package/dist/render/format-bridge.js +39 -0
- package/dist/render/format-bridge.js.map +1 -0
- package/dist/render/format-scan.d.ts +3 -0
- package/dist/render/format-scan.d.ts.map +1 -0
- package/dist/render/format-scan.js +44 -0
- package/dist/render/format-scan.js.map +1 -0
- package/dist/render/format-verbose.d.ts +3 -0
- package/dist/render/format-verbose.d.ts.map +1 -0
- package/dist/render/format-verbose.js +14 -0
- package/dist/render/format-verbose.js.map +1 -0
- package/dist/render/index.d.ts +7 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +8 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/progress-bar.d.ts +10 -0
- package/dist/render/progress-bar.d.ts.map +1 -0
- package/dist/render/progress-bar.js +21 -0
- package/dist/render/progress-bar.js.map +1 -0
- package/dist/render/symbols.d.ts +10 -0
- package/dist/render/symbols.d.ts.map +1 -0
- package/dist/render/symbols.js +21 -0
- package/dist/render/symbols.js.map +1 -0
- package/dist/utils/http-client.d.ts +25 -0
- package/dist/utils/http-client.d.ts.map +1 -0
- package/dist/utils/http-client.js +235 -0
- package/dist/utils/http-client.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/ssrf.d.ts +29 -0
- package/dist/utils/ssrf.d.ts.map +1 -0
- package/dist/utils/ssrf.js +134 -0
- package/dist/utils/ssrf.js.map +1 -0
- package/dist/utils/url.d.ts +53 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +64 -0
- package/dist/utils/url.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { httpGet } from "../../utils/http-client.js";
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Constants
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/** Spec paths -- expect raw JSON/YAML */
|
|
6
|
+
const SPEC_PATHS = [
|
|
7
|
+
"/openapi.json",
|
|
8
|
+
"/swagger.json",
|
|
9
|
+
"/api-docs",
|
|
10
|
+
"/v3/api-docs",
|
|
11
|
+
"/v2/api-docs",
|
|
12
|
+
"/swagger/v1/swagger.json",
|
|
13
|
+
"/api/openapi.json",
|
|
14
|
+
"/api/swagger.json",
|
|
15
|
+
"/.well-known/openapi.json",
|
|
16
|
+
"/openapi.yaml",
|
|
17
|
+
"/api/v1/openapi.json",
|
|
18
|
+
"/api/v1/swagger.json",
|
|
19
|
+
"/v3/api-docs.yaml",
|
|
20
|
+
"/v2/swagger.json",
|
|
21
|
+
"/api/v2/openapi.json",
|
|
22
|
+
"/api/v3/openapi.json",
|
|
23
|
+
"/spec.json",
|
|
24
|
+
];
|
|
25
|
+
/** Doc UI paths -- expect HTML with embedded spec URL */
|
|
26
|
+
const DOC_UI_PATHS = [
|
|
27
|
+
"/",
|
|
28
|
+
"/swagger-ui.html",
|
|
29
|
+
"/swagger-ui/",
|
|
30
|
+
"/docs",
|
|
31
|
+
"/redoc",
|
|
32
|
+
"/api/docs",
|
|
33
|
+
"/documentation",
|
|
34
|
+
];
|
|
35
|
+
/** All paths combined */
|
|
36
|
+
const ALL_PATHS = [...SPEC_PATHS, ...DOC_UI_PATHS];
|
|
37
|
+
const HTML_TYPES = new Set(["text/html", "application/xhtml+xml"]);
|
|
38
|
+
const JSON_TYPES = new Set([
|
|
39
|
+
"application/json",
|
|
40
|
+
"application/vnd.oai.openapi+json",
|
|
41
|
+
]);
|
|
42
|
+
const YAML_TYPES = new Set([
|
|
43
|
+
"application/yaml",
|
|
44
|
+
"text/yaml",
|
|
45
|
+
"application/x-yaml",
|
|
46
|
+
"application/vnd.oai.openapi",
|
|
47
|
+
]);
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Helpers
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/** Extract the media type portion of a Content-Type header (before ;) */
|
|
52
|
+
function mediaType(headers) {
|
|
53
|
+
return (headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate that an HTTP response contains a genuine OpenAPI / Swagger spec.
|
|
57
|
+
* Returns true only when the body is confirmed to contain spec content.
|
|
58
|
+
*/
|
|
59
|
+
function isOpenApiResponse(response) {
|
|
60
|
+
const ct = mediaType(response.headers);
|
|
61
|
+
// Reject HTML responses (Swagger UI pages)
|
|
62
|
+
if (HTML_TYPES.has(ct))
|
|
63
|
+
return false;
|
|
64
|
+
// JSON content types -- parse and check for top-level key
|
|
65
|
+
if (JSON_TYPES.has(ct)) {
|
|
66
|
+
return jsonHasSpecKey(response.body);
|
|
67
|
+
}
|
|
68
|
+
// YAML content types -- regex check
|
|
69
|
+
if (YAML_TYPES.has(ct)) {
|
|
70
|
+
return /^(openapi|swagger):/m.test(response.body);
|
|
71
|
+
}
|
|
72
|
+
// Unknown Content-Type -- try JSON.parse fallback if body looks like JSON
|
|
73
|
+
if (response.body.trimStart().startsWith("{")) {
|
|
74
|
+
return jsonHasSpecKey(response.body);
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
/** Parse JSON and check for top-level "openapi" or "swagger" key */
|
|
79
|
+
function jsonHasSpecKey(body) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(body);
|
|
82
|
+
return "openapi" in parsed || "swagger" in parsed;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** Determine whether the response is JSON (parseable) or YAML */
|
|
89
|
+
function isJsonParseable(body) {
|
|
90
|
+
try {
|
|
91
|
+
JSON.parse(body);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Extract version, spec type, and endpoint count from a JSON body */
|
|
99
|
+
function extractJsonInfo(body) {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(body);
|
|
102
|
+
const specType = "openapi" in parsed
|
|
103
|
+
? "openapi"
|
|
104
|
+
: "swagger" in parsed
|
|
105
|
+
? "swagger"
|
|
106
|
+
: null;
|
|
107
|
+
if (!specType)
|
|
108
|
+
return null;
|
|
109
|
+
const version = String(parsed[specType]);
|
|
110
|
+
const endpointCount = parsed.paths
|
|
111
|
+
? Object.keys(parsed.paths).length
|
|
112
|
+
: 0;
|
|
113
|
+
return { version, specType, endpointCount };
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Extract version, spec type, and endpoint count from YAML via regex */
|
|
120
|
+
function extractYamlInfo(body) {
|
|
121
|
+
const versionMatch = body.match(/^(openapi|swagger):\s*["']?(\d+\.\d+(?:\.\d+)?)/m);
|
|
122
|
+
if (!versionMatch)
|
|
123
|
+
return null;
|
|
124
|
+
// Count paths in YAML (lines that start with / at indent level 2)
|
|
125
|
+
const pathMatches = body.match(/^ {2}\/\S+:/gm);
|
|
126
|
+
return {
|
|
127
|
+
version: versionMatch[2],
|
|
128
|
+
specType: versionMatch[1],
|
|
129
|
+
endpointCount: pathMatches?.length ?? 0,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Patterns that extract spec URLs from HTML or JS content */
|
|
133
|
+
const SPEC_URL_PATTERNS = [
|
|
134
|
+
// 1. Swagger UI initializer: SwaggerUIBundle({ url: "/openapi.json" })
|
|
135
|
+
/SwaggerUI(?:Bundle|Standalone)?\s*\(\s*\{[^}]*url\s*:\s*["']([^"']+)["']/g,
|
|
136
|
+
// 2. Swagger UI configUrl: SwaggerUIBundle({ configUrl: "/swagger-config" })
|
|
137
|
+
/SwaggerUI(?:Bundle|Standalone)?\s*\(\s*\{[^}]*configUrl\s*:\s*["']([^"']+)["']/g,
|
|
138
|
+
// 3. Swagger UI swaggerUrl (older): swaggerUrl: "/api/swagger.json"
|
|
139
|
+
/swaggerUrl\s*:\s*["']([^"']+)["']/g,
|
|
140
|
+
// 4. ReDoc spec-url attribute: <redoc spec-url="/api/openapi.json">
|
|
141
|
+
/(?:spec-url|data-spec-url)\s*=\s*["']([^"']+)["']/g,
|
|
142
|
+
// 5. Generic spec path (relative): "/some-path/openapi.json"
|
|
143
|
+
/["'](\/[^"']*(?:openapi|swagger)\.(?:json|yaml))["']/g,
|
|
144
|
+
// 6. Generic spec URL (absolute): "https://host/path/openapi.json"
|
|
145
|
+
/["'](https?:\/\/[^"']*(?:openapi|swagger)\.(?:json|yaml))["']/g,
|
|
146
|
+
// 7. fetch() call to JSON/YAML (Flasgger pattern): fetch("/spec.json")
|
|
147
|
+
/fetch\(\s*["']([^"']+\.(?:json|yaml))["']\s*\)/g,
|
|
148
|
+
// 8. Unquoted spec URLs in JS (template literals, config strings)
|
|
149
|
+
/(https?:\/\/[^\s,`"'<>]+(?:openapi|swagger)\.(?:json|yaml))/g,
|
|
150
|
+
];
|
|
151
|
+
/**
|
|
152
|
+
* Extract spec URLs from text content (HTML or JS).
|
|
153
|
+
* Returns deduplicated, same-origin, absolute URLs.
|
|
154
|
+
*/
|
|
155
|
+
function extractSpecUrls(body, pageUrl) {
|
|
156
|
+
const origin = new URL(pageUrl).origin;
|
|
157
|
+
const seen = new Set();
|
|
158
|
+
const results = [];
|
|
159
|
+
for (const pattern of SPEC_URL_PATTERNS) {
|
|
160
|
+
pattern.lastIndex = 0;
|
|
161
|
+
let match;
|
|
162
|
+
while ((match = pattern.exec(body)) !== null) {
|
|
163
|
+
const raw = match[1];
|
|
164
|
+
if (!raw)
|
|
165
|
+
continue;
|
|
166
|
+
let absolute;
|
|
167
|
+
try {
|
|
168
|
+
absolute = new URL(raw, pageUrl).href;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
if (new URL(absolute).origin !== origin)
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (!seen.has(absolute)) {
|
|
181
|
+
seen.add(absolute);
|
|
182
|
+
results.push(absolute);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return results;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Extract Swagger UI config script URLs from HTML.
|
|
190
|
+
* Returns URLs of JS files that likely contain spec URL configuration.
|
|
191
|
+
*/
|
|
192
|
+
function extractSwaggerScriptUrls(html, pageUrl) {
|
|
193
|
+
const origin = new URL(pageUrl).origin;
|
|
194
|
+
// Match <script src="...swagger...js"> or <script src="...swagger...js">
|
|
195
|
+
const pattern = /<script[^>]+src=["']([^"']*swagger[^"']*\.js)["']/gi;
|
|
196
|
+
const results = [];
|
|
197
|
+
let match;
|
|
198
|
+
while ((match = pattern.exec(html)) !== null) {
|
|
199
|
+
const raw = match[1];
|
|
200
|
+
if (!raw)
|
|
201
|
+
continue;
|
|
202
|
+
try {
|
|
203
|
+
const absolute = new URL(raw, pageUrl).href;
|
|
204
|
+
if (new URL(absolute).origin !== origin)
|
|
205
|
+
continue;
|
|
206
|
+
results.push(absolute);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return results;
|
|
213
|
+
}
|
|
214
|
+
/** Returns true if response is a 401/403 HTTP error (not bot-protected) */
|
|
215
|
+
function isProtectedResponse(response) {
|
|
216
|
+
if (response.ok)
|
|
217
|
+
return false;
|
|
218
|
+
const { error } = response;
|
|
219
|
+
return (error.kind === "http_error" &&
|
|
220
|
+
error.statusCode !== undefined &&
|
|
221
|
+
(error.statusCode === 401 || error.statusCode === 403));
|
|
222
|
+
}
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// Public API
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
/**
|
|
227
|
+
* Probe 19 common OpenAPI / Swagger spec paths in parallel, then try
|
|
228
|
+
* extracting spec URLs from HTML doc pages, and finally detect protected specs.
|
|
229
|
+
*
|
|
230
|
+
* Returns a Check with id "openapi_spec" and a boolean indicating whether
|
|
231
|
+
* any valid spec was detected (for ctx.shared.openApiDetected).
|
|
232
|
+
*/
|
|
233
|
+
export async function checkOpenApi(baseUrl, timeout) {
|
|
234
|
+
const id = "openapi_spec";
|
|
235
|
+
const label = "OpenAPI Spec";
|
|
236
|
+
// Phase 1: Fire all 19 probes in parallel
|
|
237
|
+
const responses = await Promise.all([
|
|
238
|
+
...SPEC_PATHS.map((path) => httpGet(new URL(path, baseUrl).href, {
|
|
239
|
+
timeout,
|
|
240
|
+
headers: { Accept: "application/json, application/yaml, */*" },
|
|
241
|
+
})),
|
|
242
|
+
...DOC_UI_PATHS.map((path) => httpGet(new URL(path, baseUrl).href, {
|
|
243
|
+
timeout,
|
|
244
|
+
headers: { Accept: "text/html, */*" },
|
|
245
|
+
})),
|
|
246
|
+
]);
|
|
247
|
+
const specPathResponses = responses.slice(0, SPEC_PATHS.length);
|
|
248
|
+
const docUiResponses = responses.slice(SPEC_PATHS.length);
|
|
249
|
+
// Phase 2: Check spec-path responses for direct spec hits
|
|
250
|
+
for (let i = 0; i < specPathResponses.length; i++) {
|
|
251
|
+
const response = specPathResponses[i];
|
|
252
|
+
if (!response.ok)
|
|
253
|
+
continue;
|
|
254
|
+
if (!isOpenApiResponse(response))
|
|
255
|
+
continue;
|
|
256
|
+
const path = SPEC_PATHS[i];
|
|
257
|
+
if (isJsonParseable(response.body)) {
|
|
258
|
+
const info = extractJsonInfo(response.body);
|
|
259
|
+
if (info) {
|
|
260
|
+
return {
|
|
261
|
+
check: {
|
|
262
|
+
id,
|
|
263
|
+
label,
|
|
264
|
+
status: "pass",
|
|
265
|
+
detail: `OpenAPI ${info.version} found with ${info.endpointCount} endpoints`,
|
|
266
|
+
data: {
|
|
267
|
+
version: info.version,
|
|
268
|
+
specType: info.specType,
|
|
269
|
+
endpointCount: info.endpointCount,
|
|
270
|
+
path,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
detected: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const yamlInfo = extractYamlInfo(response.body);
|
|
278
|
+
if (yamlInfo) {
|
|
279
|
+
return {
|
|
280
|
+
check: {
|
|
281
|
+
id,
|
|
282
|
+
label,
|
|
283
|
+
status: "partial",
|
|
284
|
+
detail: `OpenAPI ${yamlInfo.version} found (YAML format)`,
|
|
285
|
+
data: {
|
|
286
|
+
version: yamlInfo.version,
|
|
287
|
+
specType: yamlInfo.specType,
|
|
288
|
+
endpointCount: yamlInfo.endpointCount,
|
|
289
|
+
path,
|
|
290
|
+
},
|
|
291
|
+
},
|
|
292
|
+
detected: true,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
// Phase 3: Check doc-UI-path responses for HTML with extractable spec URLs
|
|
297
|
+
const allProbedUrls = new Set(ALL_PATHS.map((p) => new URL(p, baseUrl).href));
|
|
298
|
+
const specCandidateUrls = [];
|
|
299
|
+
const scriptUrls = [];
|
|
300
|
+
for (let i = 0; i < docUiResponses.length; i++) {
|
|
301
|
+
const response = docUiResponses[i];
|
|
302
|
+
if (!response.ok)
|
|
303
|
+
continue;
|
|
304
|
+
const ct = mediaType(response.headers);
|
|
305
|
+
if (!HTML_TYPES.has(ct))
|
|
306
|
+
continue;
|
|
307
|
+
const pageUrl = new URL(DOC_UI_PATHS[i], baseUrl).href;
|
|
308
|
+
// Extract spec URLs directly from HTML
|
|
309
|
+
const extracted = extractSpecUrls(response.body, pageUrl);
|
|
310
|
+
for (const url of extracted) {
|
|
311
|
+
if (!allProbedUrls.has(url) && !specCandidateUrls.includes(url)) {
|
|
312
|
+
specCandidateUrls.push(url);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// Extract Swagger UI config script URLs for secondary fetching
|
|
316
|
+
if (specCandidateUrls.length === 0) {
|
|
317
|
+
const scripts = extractSwaggerScriptUrls(response.body, pageUrl);
|
|
318
|
+
for (const url of scripts) {
|
|
319
|
+
if (!scriptUrls.includes(url)) {
|
|
320
|
+
scriptUrls.push(url);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Phase 3a: Fetch external Swagger UI config scripts and extract spec URLs from them
|
|
326
|
+
if (specCandidateUrls.length === 0 && scriptUrls.length > 0) {
|
|
327
|
+
const scriptResponses = await Promise.all(scriptUrls.slice(0, 3).map((url) => httpGet(url, {
|
|
328
|
+
timeout,
|
|
329
|
+
headers: { Accept: "*/*" },
|
|
330
|
+
})));
|
|
331
|
+
for (let i = 0; i < scriptResponses.length; i++) {
|
|
332
|
+
const response = scriptResponses[i];
|
|
333
|
+
if (!response.ok)
|
|
334
|
+
continue;
|
|
335
|
+
const scriptUrl = scriptUrls[i];
|
|
336
|
+
const extracted = extractSpecUrls(response.body, scriptUrl);
|
|
337
|
+
for (const url of extracted) {
|
|
338
|
+
if (!allProbedUrls.has(url) && !specCandidateUrls.includes(url)) {
|
|
339
|
+
specCandidateUrls.push(url);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// Phase 3b: Fetch candidate spec URLs and validate
|
|
345
|
+
if (specCandidateUrls.length > 0) {
|
|
346
|
+
const secondaryResponses = await Promise.all(specCandidateUrls.slice(0, 3).map((url) => httpGet(url, {
|
|
347
|
+
timeout,
|
|
348
|
+
headers: { Accept: "application/json, application/yaml, */*" },
|
|
349
|
+
})));
|
|
350
|
+
for (let i = 0; i < secondaryResponses.length; i++) {
|
|
351
|
+
const response = secondaryResponses[i];
|
|
352
|
+
if (!response.ok)
|
|
353
|
+
continue;
|
|
354
|
+
if (!isOpenApiResponse(response))
|
|
355
|
+
continue;
|
|
356
|
+
const path = new URL(specCandidateUrls[i]).pathname;
|
|
357
|
+
if (isJsonParseable(response.body)) {
|
|
358
|
+
const info = extractJsonInfo(response.body);
|
|
359
|
+
if (info) {
|
|
360
|
+
return {
|
|
361
|
+
check: {
|
|
362
|
+
id,
|
|
363
|
+
label,
|
|
364
|
+
status: "pass",
|
|
365
|
+
detail: `OpenAPI ${info.version} found with ${info.endpointCount} endpoints`,
|
|
366
|
+
data: {
|
|
367
|
+
version: info.version,
|
|
368
|
+
specType: info.specType,
|
|
369
|
+
endpointCount: info.endpointCount,
|
|
370
|
+
path,
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
detected: true,
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const yamlInfo = extractYamlInfo(response.body);
|
|
378
|
+
if (yamlInfo) {
|
|
379
|
+
return {
|
|
380
|
+
check: {
|
|
381
|
+
id,
|
|
382
|
+
label,
|
|
383
|
+
status: "partial",
|
|
384
|
+
detail: `OpenAPI ${yamlInfo.version} found (YAML format)`,
|
|
385
|
+
data: {
|
|
386
|
+
version: yamlInfo.version,
|
|
387
|
+
specType: yamlInfo.specType,
|
|
388
|
+
endpointCount: yamlInfo.endpointCount,
|
|
389
|
+
path,
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
detected: true,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// Phase 4: Check spec-path responses for 401/403 (not bot_protected)
|
|
398
|
+
for (let i = 0; i < specPathResponses.length; i++) {
|
|
399
|
+
const response = specPathResponses[i];
|
|
400
|
+
if (isProtectedResponse(response)) {
|
|
401
|
+
return {
|
|
402
|
+
check: {
|
|
403
|
+
id,
|
|
404
|
+
label,
|
|
405
|
+
status: "partial",
|
|
406
|
+
detail: "OpenAPI spec appears to exist but requires authentication",
|
|
407
|
+
data: { protected: true, path: SPEC_PATHS[i] },
|
|
408
|
+
},
|
|
409
|
+
detected: true,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
// Phase 5: No valid spec found at any path
|
|
414
|
+
return {
|
|
415
|
+
check: {
|
|
416
|
+
id,
|
|
417
|
+
label,
|
|
418
|
+
status: "fail",
|
|
419
|
+
detail: "No OpenAPI spec found",
|
|
420
|
+
},
|
|
421
|
+
detected: false,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../../src/bridges/standards/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Check } from "../../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check for Schema.org markup via JSON-LD vocabulary and Microdata attributes.
|
|
4
|
+
*
|
|
5
|
+
* Takes the JSON-LD Check result (from checkJsonLd) to avoid re-parsing HTML
|
|
6
|
+
* for JSON-LD blocks. Also scans raw HTML for Microdata itemtype attributes
|
|
7
|
+
* containing schema.org URLs.
|
|
8
|
+
*
|
|
9
|
+
* Pure function -- no HTTP calls.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkSchemaOrg(html: string, jsonLdCheck: Check): Check;
|
|
12
|
+
//# sourceMappingURL=schema-org.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-org.d.ts","sourceRoot":"","sources":["../../../src/bridges/standards/schema-org.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,KAAK,GACjB,KAAK,CAmFP"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check for Schema.org markup via JSON-LD vocabulary and Microdata attributes.
|
|
3
|
+
*
|
|
4
|
+
* Takes the JSON-LD Check result (from checkJsonLd) to avoid re-parsing HTML
|
|
5
|
+
* for JSON-LD blocks. Also scans raw HTML for Microdata itemtype attributes
|
|
6
|
+
* containing schema.org URLs.
|
|
7
|
+
*
|
|
8
|
+
* Pure function -- no HTTP calls.
|
|
9
|
+
*/
|
|
10
|
+
export function checkSchemaOrg(html, jsonLdCheck) {
|
|
11
|
+
const id = "schema_org";
|
|
12
|
+
const label = "Schema.org Markup";
|
|
13
|
+
const types = [];
|
|
14
|
+
const sources = [];
|
|
15
|
+
// Check JSON-LD blocks for schema.org @context
|
|
16
|
+
if (jsonLdCheck.status === "pass" &&
|
|
17
|
+
jsonLdCheck.data &&
|
|
18
|
+
Array.isArray(jsonLdCheck.data.blocks)) {
|
|
19
|
+
const blocks = jsonLdCheck.data.blocks;
|
|
20
|
+
let foundSchemaOrg = false;
|
|
21
|
+
for (const block of blocks) {
|
|
22
|
+
if (isSchemaOrgContext(block.context)) {
|
|
23
|
+
foundSchemaOrg = true;
|
|
24
|
+
const typeNames = flattenType(block.type);
|
|
25
|
+
for (const t of typeNames) {
|
|
26
|
+
if (!types.includes(t)) {
|
|
27
|
+
types.push(t);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (foundSchemaOrg) {
|
|
33
|
+
sources.push("json-ld");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Check Microdata itemtype attributes for schema.org
|
|
37
|
+
const microdataRegex = /itemtype=["'](https?:\/\/schema\.org\/[^"']+)["']/gi;
|
|
38
|
+
let match;
|
|
39
|
+
const microdataTypes = [];
|
|
40
|
+
while ((match = microdataRegex.exec(html)) !== null) {
|
|
41
|
+
const typeUrl = match[1];
|
|
42
|
+
const typeName = typeUrl.split("/").pop();
|
|
43
|
+
if (typeName && !microdataTypes.includes(typeName)) {
|
|
44
|
+
microdataTypes.push(typeName);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (microdataTypes.length > 0) {
|
|
48
|
+
sources.push("microdata");
|
|
49
|
+
for (const t of microdataTypes) {
|
|
50
|
+
if (!types.includes(t)) {
|
|
51
|
+
types.push(t);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (types.length === 0) {
|
|
56
|
+
return {
|
|
57
|
+
id,
|
|
58
|
+
label,
|
|
59
|
+
status: "fail",
|
|
60
|
+
detail: "No Schema.org markup found",
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Build detail string based on sources
|
|
64
|
+
const typesStr = types.join(", ");
|
|
65
|
+
let detail;
|
|
66
|
+
if (sources.includes("json-ld") && sources.includes("microdata")) {
|
|
67
|
+
detail = `Schema.org types found via JSON-LD and Microdata: ${typesStr}`;
|
|
68
|
+
}
|
|
69
|
+
else if (sources.includes("json-ld")) {
|
|
70
|
+
detail = `Schema.org types found via JSON-LD: ${typesStr}`;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
detail = `Schema.org types found via Microdata: ${typesStr}`;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
label,
|
|
78
|
+
status: "pass",
|
|
79
|
+
detail,
|
|
80
|
+
data: { types, sources },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Check if a JSON-LD @context value references schema.org.
|
|
85
|
+
*/
|
|
86
|
+
function isSchemaOrgContext(context) {
|
|
87
|
+
if (typeof context === "string") {
|
|
88
|
+
return context.includes("schema.org");
|
|
89
|
+
}
|
|
90
|
+
if (Array.isArray(context)) {
|
|
91
|
+
return context.some((item) => typeof item === "string" && item.includes("schema.org"));
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Flatten a @type value to an array of type name strings.
|
|
97
|
+
*/
|
|
98
|
+
function flattenType(type) {
|
|
99
|
+
return Array.isArray(type) ? type : [type];
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=schema-org.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-org.js","sourceRoot":"","sources":["../../../src/bridges/standards/schema-org.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Check } from "../../core/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check for security.txt at /.well-known/security.txt.
|
|
4
|
+
*
|
|
5
|
+
* Per RFC 9116: must contain at least a Contact field.
|
|
6
|
+
* Returns pass if Contact present, partial if file exists but no Contact, fail if missing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function checkSecurityTxt(baseUrl: string, timeout?: number): Promise<Check>;
|
|
9
|
+
/**
|
|
10
|
+
* Check for ai-plugin.json at /.well-known/ai-plugin.json.
|
|
11
|
+
*
|
|
12
|
+
* Validates required fields: schema_version (string), name_for_human (string), api (object).
|
|
13
|
+
* Returns pass if all present, partial if JSON but missing fields, fail if missing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function checkAiPlugin(baseUrl: string, timeout?: number): Promise<Check>;
|
|
16
|
+
//# sourceMappingURL=well-known.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"well-known.d.ts","sourceRoot":"","sources":["../../../src/bridges/standards/well-known.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAGjD;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,CA2BhB;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,KAAK,CAAC,CA4ChB"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { httpGet } from "../../utils/http-client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check for security.txt at /.well-known/security.txt.
|
|
4
|
+
*
|
|
5
|
+
* Per RFC 9116: must contain at least a Contact field.
|
|
6
|
+
* Returns pass if Contact present, partial if file exists but no Contact, fail if missing.
|
|
7
|
+
*/
|
|
8
|
+
export async function checkSecurityTxt(baseUrl, timeout) {
|
|
9
|
+
const id = "security_txt";
|
|
10
|
+
const label = "security.txt";
|
|
11
|
+
const result = await httpGet(`${baseUrl}/.well-known/security.txt`, {
|
|
12
|
+
timeout,
|
|
13
|
+
});
|
|
14
|
+
if (!result.ok || result.body.trim().length === 0) {
|
|
15
|
+
return { id, label, status: "fail", detail: "No security.txt found" };
|
|
16
|
+
}
|
|
17
|
+
if (/^Contact:/mi.test(result.body)) {
|
|
18
|
+
return {
|
|
19
|
+
id,
|
|
20
|
+
label,
|
|
21
|
+
status: "pass",
|
|
22
|
+
detail: "security.txt found with Contact field",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
id,
|
|
27
|
+
label,
|
|
28
|
+
status: "partial",
|
|
29
|
+
detail: "security.txt found but missing Contact field",
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check for ai-plugin.json at /.well-known/ai-plugin.json.
|
|
34
|
+
*
|
|
35
|
+
* Validates required fields: schema_version (string), name_for_human (string), api (object).
|
|
36
|
+
* Returns pass if all present, partial if JSON but missing fields, fail if missing.
|
|
37
|
+
*/
|
|
38
|
+
export async function checkAiPlugin(baseUrl, timeout) {
|
|
39
|
+
const id = "ai_plugin";
|
|
40
|
+
const label = "ai-plugin.json";
|
|
41
|
+
const result = await httpGet(`${baseUrl}/.well-known/ai-plugin.json`, {
|
|
42
|
+
timeout,
|
|
43
|
+
headers: { Accept: "application/json" },
|
|
44
|
+
});
|
|
45
|
+
if (!result.ok) {
|
|
46
|
+
return { id, label, status: "fail", detail: "No ai-plugin.json found" };
|
|
47
|
+
}
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = JSON.parse(result.body);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return { id, label, status: "fail", detail: "No ai-plugin.json found" };
|
|
54
|
+
}
|
|
55
|
+
if (typeof parsed.schema_version === "string" &&
|
|
56
|
+
typeof parsed.name_for_human === "string" &&
|
|
57
|
+
typeof parsed.api === "object" &&
|
|
58
|
+
parsed.api !== null) {
|
|
59
|
+
return {
|
|
60
|
+
id,
|
|
61
|
+
label,
|
|
62
|
+
status: "pass",
|
|
63
|
+
detail: `ai-plugin.json found: ${parsed.name_for_human}`,
|
|
64
|
+
data: {
|
|
65
|
+
nameForHuman: parsed.name_for_human,
|
|
66
|
+
schemaVersion: parsed.schema_version,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
label,
|
|
73
|
+
status: "partial",
|
|
74
|
+
detail: "ai-plugin.json found but missing required fields",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=well-known.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"well-known.js","sourceRoot":"","sources":["../../../src/bridges/standards/well-known.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAErD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,OAAgB;IAEhB,MAAM,EAAE,GAAG,cAAc,CAAC;IAC1B,MAAM,KAAK,GAAG,cAAc,CAAC;IAE7B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,2BAA2B,EAAE;QAClE,OAAO;KACR,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IACxE,CAAC;IAED,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,EAAE;YACF,KAAK;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,uCAAuC;SAChD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE;QACF,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,8CAA8C;KACvD,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,OAAe,EACf,OAAgB;IAEhB,MAAM,EAAE,GAAG,WAAW,CAAC;IACvB,MAAM,KAAK,GAAG,gBAAgB,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,OAAO,6BAA6B,EAAE;QACpE,OAAO;QACP,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAC;IAEH,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC1E,CAAC;IAED,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAA4B,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IAC1E,CAAC;IAED,IACE,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;QACzC,OAAO,MAAM,CAAC,cAAc,KAAK,QAAQ;QACzC,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ;QAC9B,MAAM,CAAC,GAAG,KAAK,IAAI,EACnB,CAAC;QACD,OAAO;YACL,EAAE;YACF,KAAK;YACL,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,yBAAyB,MAAM,CAAC,cAAc,EAAE;YACxD,IAAI,EAAE;gBACJ,YAAY,EAAE,MAAM,CAAC,cAAc;gBACnC,aAAa,EAAE,MAAM,CAAC,cAAc;aACrC;SACF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE;QACF,KAAK;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,kDAAkD;KAC3D,CAAC;AACJ,CAAC"}
|