@redocly/cli 2.38.0 → 2.40.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/THIRD_PARTY_NOTICES +3 -2
- package/lib/chunks/{QUMOPKXU.js → 325TP2UK.js} +2 -2
- package/lib/chunks/{NPHT727D.js → 3E6EHT7M.js} +9 -6
- package/lib/chunks/{FL4Q7PMA.js → 4BR7G6JO.js} +1 -1
- package/lib/chunks/4GKD2B4N.js +175 -0
- package/lib/chunks/{PIMMKQJ7.js → 6DYZ77KC.js} +4 -4
- package/lib/chunks/{OPV3WWWU.js → 73MCRGNI.js} +4 -4
- package/lib/chunks/{G76UYYPW.js → BFQ3EROY.js} +4 -4
- package/lib/chunks/{MIPR6NCD.js → HT6ZGKQQ.js} +7038 -6060
- package/lib/chunks/{ICAVAH7N.js → ICPYP2LP.js} +96 -82
- package/lib/chunks/{EDHFTO4X.js → ILH7YVRM.js} +2 -2
- package/lib/chunks/{U2FUDUNT.js → JBIFNX5C.js} +8 -165
- package/lib/chunks/NRZEGU6G.js +1754 -0
- package/lib/chunks/OYO2D2IL.js +79 -0
- package/lib/chunks/{K5FO6VRS.js → PVILCIEK.js} +2 -2
- package/lib/chunks/{N2TQJ4KM.js → QCV6V37L.js} +3 -3
- package/lib/chunks/{M5T4PDSH.js → RD4BYLLT.js} +1 -1
- package/lib/chunks/TYUOO44G.js +492 -0
- package/lib/chunks/{AAQTUNZI.js → V2UTD4F3.js} +134 -518
- package/lib/index.js +125 -117
- package/package.json +1 -1
|
@@ -178,111 +178,125 @@ var require_index_umd = __commonJS({
|
|
|
178
178
|
|
|
179
179
|
// ../../node_modules/@redocly/cli-otel/lib/index.js
|
|
180
180
|
var import_ulid = __toESM(require_index_umd(), 1);
|
|
181
|
-
var
|
|
182
|
-
var
|
|
183
|
-
for (var
|
|
181
|
+
var K = Object.defineProperty;
|
|
182
|
+
var q = (e, t) => {
|
|
183
|
+
for (var n in t) K(e, n, { get: t[n], enumerable: true });
|
|
184
184
|
};
|
|
185
|
-
var
|
|
186
|
-
|
|
187
|
-
var
|
|
188
|
-
function
|
|
189
|
-
let { type:
|
|
190
|
-
if (
|
|
191
|
-
let
|
|
192
|
-
Object.assign(
|
|
185
|
+
var E = {};
|
|
186
|
+
q(E, { CLOUD_EVENT_STANDARD_KEYS: () => C, mapToCloudEvent: () => G });
|
|
187
|
+
var C = ["id", "specversion", "object", "datacontenttype", "type", "time", "origin", "env", "category", "signal", "source", "subject", "subjects", "data", "actor", "requestId", "clientIp", "organizationId", "organizationSlug", "projectId", "projectSlug", "osPlatform", "userAgent", "sessionId"];
|
|
188
|
+
function G(e) {
|
|
189
|
+
let { type: t, data: n, actor: o, requestId: s, clientIp: r, origin: i, env: c, source: u, organizationId: a, organizationSlug: g, projectId: d, projectSlug: I, category: N = "product", signal: $ = "log", osPlatform: B, userAgent: U, sessionId: W } = e, L = !!(n && Array.isArray(n)), m = o ? { id: o.id ?? `ann_${(0, import_ulid.ulid)()}`, object: o.object ?? "user", uri: o.uri ?? "" } : null, T = `evt_${(0, import_ulid.ulid)()}`.toLowerCase(), S = /* @__PURE__ */ new Date(), M = u ?? m?.uri ?? null, O = { ...a !== void 0 && { organizationId: a }, ...g !== void 0 && { organizationSlug: g }, ...d !== void 0 && { projectId: d }, ...I !== void 0 && { projectSlug: I } }, j = { specversion: "1.0", object: "event", datacontenttype: "application/json; charset=utf-8", origin: i, env: c, category: N, signal: $, osPlatform: B, userAgent: U, clientIp: r, sessionId: W };
|
|
190
|
+
if (L) {
|
|
191
|
+
let p = n, V = p.map((A) => ({ id: A.id ?? "", object: A.object ?? "", uri: A.uri ?? "" })), z = p[0]?.id ?? null;
|
|
192
|
+
Object.assign(j, { ...O, id: T, type: t, time: S, source: M, actor: m, subject: z, subjects: V, data: p, requestId: s ?? "" });
|
|
193
193
|
} else {
|
|
194
|
-
let
|
|
195
|
-
Object.assign(
|
|
194
|
+
let p = (Array.isArray(n) ? n[0] : n)?.id ?? null;
|
|
195
|
+
Object.assign(j, { ...O, id: T, type: t, time: S, source: M, actor: m, subject: p, requestId: s ?? "", data: n, ...u != null && { request: { source: u } } });
|
|
196
196
|
}
|
|
197
|
-
return
|
|
197
|
+
return j;
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
var d = [O];
|
|
201
|
-
function f(e) {
|
|
199
|
+
function l(e) {
|
|
202
200
|
return e.replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
203
201
|
}
|
|
204
|
-
function
|
|
205
|
-
|
|
206
|
-
for (let o of e) {
|
|
207
|
-
if (!o || typeof o != "object") continue;
|
|
208
|
-
let t = o.object;
|
|
209
|
-
if (typeof t != "string") continue;
|
|
210
|
-
let s = o, r = n.notUpdated.find((i) => i.object === t);
|
|
211
|
-
r ? (n.updated = [r, s], n.notUpdated = n.notUpdated.filter((i) => i.object !== t)) : n.updated.some((i) => i.object === t) || n.notUpdated.push(s);
|
|
212
|
-
}
|
|
213
|
-
return n;
|
|
214
|
-
}
|
|
215
|
-
function p(e, n, o) {
|
|
216
|
-
let t = o ? `${o}.` : "", s = n === "" ? "" : `${n}.`;
|
|
217
|
-
return `${e}.${t}${s}`;
|
|
202
|
+
function v(e) {
|
|
203
|
+
return e != null;
|
|
218
204
|
}
|
|
219
|
-
function
|
|
220
|
-
|
|
221
|
-
return o === "before" || o === "after" ? o : n === 0 ? "after" : "before";
|
|
205
|
+
function y(e) {
|
|
206
|
+
return typeof e == "string" || typeof e == "number" || typeof e == "boolean";
|
|
222
207
|
}
|
|
223
|
-
function
|
|
208
|
+
function x(e, t, n, o = true, s) {
|
|
224
209
|
let r = s?.length ? new Set(s) : null;
|
|
225
210
|
for (let [i, c] of Object.entries(e)) if (!r?.has(i) && c !== void 0) {
|
|
226
|
-
let
|
|
227
|
-
|
|
211
|
+
let u = o ? l(i) : i;
|
|
212
|
+
n[`${t}${u}`] = c;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function f(e, t, n, o) {
|
|
216
|
+
let s = o?.currentDepth ?? 0, r = o?.useSnakeCase ?? true, i = o?.maxNestingLevels ?? 3, c = t.endsWith(".") ? t.slice(0, -1) : t;
|
|
217
|
+
for (let [u, a] of Object.entries(e)) {
|
|
218
|
+
if (!v(a)) continue;
|
|
219
|
+
let g = r ? l(u) : u, d = `${c}.${g}`;
|
|
220
|
+
typeof a == "object" && !Array.isArray(a) ? s < i && f(a, d, n, { currentDepth: s + 1, useSnakeCase: r, maxNestingLevels: i }) : y(a) && (n[d] = a);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
var _ = "context";
|
|
224
|
+
var h = [_];
|
|
225
|
+
function w(e) {
|
|
226
|
+
let t = { updated: [], notUpdated: [] };
|
|
227
|
+
for (let n of e) {
|
|
228
|
+
if (!n || typeof n != "object") continue;
|
|
229
|
+
let o = n.object;
|
|
230
|
+
if (typeof o != "string") continue;
|
|
231
|
+
let s = n, r = t.notUpdated.find((i) => i.object === o);
|
|
232
|
+
r ? (t.updated = [r, s], t.notUpdated = t.notUpdated.filter((i) => i.object !== o)) : t.updated.some((i) => i.object === o) || t.notUpdated.push(s);
|
|
228
233
|
}
|
|
234
|
+
return t;
|
|
235
|
+
}
|
|
236
|
+
function b(e, t, n) {
|
|
237
|
+
let o = n ? `${n}.` : "", s = t === "" ? "" : `${l(t)}.`;
|
|
238
|
+
return `${e}.${o}${s}`;
|
|
239
|
+
}
|
|
240
|
+
function P(e, t) {
|
|
241
|
+
let n = e[_];
|
|
242
|
+
return n === "before" || n === "after" ? n : t === 0 ? "after" : "before";
|
|
229
243
|
}
|
|
230
|
-
function
|
|
231
|
-
|
|
244
|
+
function k(e) {
|
|
245
|
+
let { [_]: t, ...n } = e;
|
|
246
|
+
return n;
|
|
247
|
+
}
|
|
248
|
+
function D(e) {
|
|
249
|
+
return e.endsWith(".") ? e : `${e}.`;
|
|
232
250
|
}
|
|
233
|
-
function
|
|
234
|
-
let
|
|
235
|
-
return { "cloudevents.event_id": e.id, "cloudevents.event_type": e.type, "cloudevents.event_source": e.source ?? void 0, "cloudevents.event_spec_version": e.specversion, "cloudevents.event_data_content_type": e.datacontenttype ?? "application/json; charset=utf-8", "cloudevents.event_time":
|
|
251
|
+
function Y(e, t, n) {
|
|
252
|
+
let o = t instanceof Date ? t.toISOString() : new Date(t).toISOString();
|
|
253
|
+
return { "cloudevents.event_id": e.id, "cloudevents.event_type": e.type, "cloudevents.event_source": e.source ?? void 0, "cloudevents.event_spec_version": e.specversion, "cloudevents.event_data_content_type": e.datacontenttype ?? "application/json; charset=utf-8", "cloudevents.event_time": o, "cloudevents.event_subject": e.subject ?? "", "cloudevents.event_version": n?.version, "cloudevents.event_origin": e.origin ?? n?.serviceName, "cloudevents.event_env": e.env, "cloudevents.event_client_ip": e.clientIp, "cloudevents.event_object": e.object || "event", "cloudevents.event_category": e.category, "cloudevents.event_signal": e.signal, "cloudevents.event_actor.id": e.actor?.id ?? void 0, "cloudevents.event_actor.object": e.actor?.object ?? void 0, "cloudevents.event_actor.uri": e.actor?.uri ?? void 0, "cloudevents.event_organization_id": e.organizationId, "cloudevents.event_organization_slug": e.organizationSlug, "cloudevents.event_project_id": e.projectId, "cloudevents.event_project_slug": e.projectSlug, "cloudevents.event_request_id": e.requestId, "cloudevents.event_os_platform": e.osPlatform, "cloudevents.event_user_agent": e.userAgent, "cloudevents.event_session_id": e.sessionId };
|
|
236
254
|
}
|
|
237
|
-
function
|
|
238
|
-
let
|
|
239
|
-
return
|
|
255
|
+
function F(e, t, n) {
|
|
256
|
+
let o = e.data, s = { ...Y(e, t, n) };
|
|
257
|
+
return X(o, s), ee(e, s), te(e, s), s;
|
|
240
258
|
}
|
|
241
|
-
function
|
|
242
|
-
!e || typeof e != "object" || (Array.isArray(e) ?
|
|
259
|
+
function X(e, t) {
|
|
260
|
+
!e || typeof e != "object" || (Array.isArray(e) ? H(e, t) : Q(e, t));
|
|
243
261
|
}
|
|
244
|
-
function
|
|
245
|
-
e.some((
|
|
262
|
+
function H(e, t) {
|
|
263
|
+
e.some((o) => o && typeof o == "object" && typeof o.object == "string") ? Z(e, t) : J(e, t);
|
|
246
264
|
}
|
|
247
|
-
function
|
|
248
|
-
let
|
|
249
|
-
|
|
250
|
-
let r =
|
|
251
|
-
|
|
252
|
-
}),
|
|
253
|
-
let s =
|
|
254
|
-
|
|
265
|
+
function Z(e, t) {
|
|
266
|
+
let n = w(e);
|
|
267
|
+
n.updated.forEach((o, s) => {
|
|
268
|
+
let r = b("cloudevents.event_data", o.object, P(o, s));
|
|
269
|
+
f(k(o), D(r), t);
|
|
270
|
+
}), n.notUpdated.forEach((o) => {
|
|
271
|
+
let s = b("cloudevents.event_data", o.object, void 0);
|
|
272
|
+
f(k(o), D(s), t);
|
|
255
273
|
});
|
|
256
274
|
}
|
|
257
|
-
function
|
|
258
|
-
for (let
|
|
259
|
-
if (s === void 0) continue;
|
|
260
|
-
let r = f(t);
|
|
261
|
-
s !== null && typeof s == "object" && !Array.isArray(s) ? W(s, `cloudevents.event_data.${r}`, n) : n[`cloudevents.event_data.${r}`] = s;
|
|
262
|
-
}
|
|
275
|
+
function J(e, t) {
|
|
276
|
+
for (let n of e) !n || typeof n != "object" || f(n, "cloudevents.event_data.", t);
|
|
263
277
|
}
|
|
264
|
-
function
|
|
265
|
-
for (let [
|
|
266
|
-
if (
|
|
267
|
-
let s =
|
|
268
|
-
if (typeof
|
|
269
|
-
else (
|
|
278
|
+
function Q(e, t) {
|
|
279
|
+
for (let [n, o] of Object.entries(e)) {
|
|
280
|
+
if (!v(o)) continue;
|
|
281
|
+
let s = l(n);
|
|
282
|
+
if (typeof o == "object" && !Array.isArray(o)) for (let [r, i] of Object.entries(o)) v(i) && y(i) && (t[`cloudevents.event_data.${s}.${r}`] = i);
|
|
283
|
+
else y(o) && (t[`cloudevents.event_data.${s}`] = o);
|
|
270
284
|
}
|
|
271
285
|
}
|
|
272
|
-
function
|
|
286
|
+
function ee(e, t) {
|
|
273
287
|
if (!e.subjects || !Array.isArray(e.subjects)) return;
|
|
274
|
-
let
|
|
275
|
-
|
|
276
|
-
let r =
|
|
277
|
-
|
|
278
|
-
}),
|
|
279
|
-
let s =
|
|
280
|
-
|
|
288
|
+
let n = w(e.subjects);
|
|
289
|
+
n.updated.forEach((o, s) => {
|
|
290
|
+
let r = b("cloudevents.event_subjects", o.object, P(o, s));
|
|
291
|
+
x(o, r, t, false, h);
|
|
292
|
+
}), n.notUpdated.forEach((o) => {
|
|
293
|
+
let s = b("cloudevents.event_subjects", o.object, void 0);
|
|
294
|
+
x(o, s, t, false, h);
|
|
281
295
|
});
|
|
282
296
|
}
|
|
283
|
-
function
|
|
284
|
-
for (let [
|
|
285
|
-
else
|
|
297
|
+
function te(e, t) {
|
|
298
|
+
for (let [n, o] of Object.entries(e)) if (!(C.includes(n) || o === void 0)) if (o instanceof Object) for (let [s, r] of Object.entries(o)) r !== void 0 && (t[`cloudevents.${n}.${s}`] = r);
|
|
299
|
+
else t[`cloudevents.${n}`] = o;
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
// ../../node_modules/ulid/dist/node/index.js
|
|
@@ -381,7 +395,7 @@ function ulid(seedTime, prng) {
|
|
|
381
395
|
}
|
|
382
396
|
|
|
383
397
|
export {
|
|
384
|
-
|
|
385
|
-
|
|
398
|
+
E,
|
|
399
|
+
F,
|
|
386
400
|
ulid
|
|
387
401
|
};
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
maskSecrets,
|
|
9
9
|
parseRuntimeExpression,
|
|
10
10
|
run
|
|
11
|
-
} from "./
|
|
11
|
+
} from "./RD4BYLLT.js";
|
|
12
12
|
import "./VXIQEZPR.js";
|
|
13
13
|
import "./UUU33DK3.js";
|
|
14
|
-
import "./
|
|
14
|
+
import "./HT6ZGKQQ.js";
|
|
15
15
|
import "./Z2I5YXYN.js";
|
|
16
16
|
import "./5ILQMFXK.js";
|
|
17
17
|
export {
|
|
@@ -1,36 +1,19 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from 'node:module';
|
|
2
2
|
const require = __createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
|
-
ValidationSession,
|
|
5
4
|
coerceNumber,
|
|
6
5
|
coerceString,
|
|
7
6
|
createNormalizedExchange,
|
|
8
7
|
decodeBody,
|
|
9
8
|
iterateJsonArray,
|
|
10
|
-
listFilesRecursively,
|
|
11
|
-
loadOpenApiIndex,
|
|
12
9
|
normalizeContentType,
|
|
13
|
-
normalizeFsPath,
|
|
14
|
-
parseCsv,
|
|
15
10
|
pickHeaderContentType,
|
|
16
11
|
readProbe,
|
|
17
|
-
renderReport,
|
|
18
12
|
streamNdjsonObjects
|
|
19
|
-
} from "./
|
|
13
|
+
} from "./TYUOO44G.js";
|
|
20
14
|
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} from "./FL4Q7PMA.js";
|
|
24
|
-
import {
|
|
25
|
-
isPlainObject,
|
|
26
|
-
logger
|
|
27
|
-
} from "./MIPR6NCD.js";
|
|
28
|
-
import "./Z2I5YXYN.js";
|
|
29
|
-
import "./5ILQMFXK.js";
|
|
30
|
-
|
|
31
|
-
// src/commands/drift/index.ts
|
|
32
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
33
|
-
import path5 from "node:path";
|
|
15
|
+
isPlainObject
|
|
16
|
+
} from "./HT6ZGKQQ.js";
|
|
34
17
|
|
|
35
18
|
// src/commands/drift/log-formats/har.ts
|
|
36
19
|
import path from "node:path";
|
|
@@ -203,15 +186,15 @@ function buildUrl(record, request) {
|
|
|
203
186
|
return { url: directUrl };
|
|
204
187
|
}
|
|
205
188
|
const host = coerceString(request?.host ?? request?.headers?.host ?? record?.host);
|
|
206
|
-
const
|
|
189
|
+
const path5 = coerceString(request?.path ?? record?.path ?? request?.pathname);
|
|
207
190
|
const explicitScheme = coerceString(request?.scheme ?? record?.scheme);
|
|
208
|
-
if (host &&
|
|
191
|
+
if (host && path5) {
|
|
209
192
|
return {
|
|
210
|
-
url: `${explicitScheme ?? "http"}://${host}${
|
|
193
|
+
url: `${explicitScheme ?? "http"}://${host}${path5}`,
|
|
211
194
|
schemeKnown: Boolean(explicitScheme)
|
|
212
195
|
};
|
|
213
196
|
}
|
|
214
|
-
return { url:
|
|
197
|
+
return { url: path5, schemeKnown: Boolean(explicitScheme) };
|
|
215
198
|
}
|
|
216
199
|
function normalizeGenericRecord(record, index, source) {
|
|
217
200
|
const request = getRequestCandidate(record);
|
|
@@ -426,146 +409,6 @@ async function selectTrafficParser(filePath, format) {
|
|
|
426
409
|
return PARSERS.find((candidate) => candidate.canParse(filePath, probe));
|
|
427
410
|
}
|
|
428
411
|
|
|
429
|
-
// src/commands/drift/engine/runner.ts
|
|
430
|
-
async function runTrafficValidation(options) {
|
|
431
|
-
const trafficFiles = await listFilesRecursively(options.trafficPath);
|
|
432
|
-
if (trafficFiles.length === 0) {
|
|
433
|
-
throw new Error("No traffic files found in the provided traffic path.");
|
|
434
|
-
}
|
|
435
|
-
const session = ValidationSession.create({
|
|
436
|
-
openApiIndex: options.openApiIndex,
|
|
437
|
-
matchMode: options.matchMode,
|
|
438
|
-
ignoreCookies: options.ignoreCookies,
|
|
439
|
-
previewFindingsLimit: options.previewFindingsLimit,
|
|
440
|
-
activeRules: options.activeRules,
|
|
441
|
-
server: options.server,
|
|
442
|
-
minSeverity: options.minSeverity
|
|
443
|
-
});
|
|
444
|
-
let supportedTrafficFileCount = 0;
|
|
445
|
-
let exchangeIndex = 0;
|
|
446
|
-
for (const trafficFile of trafficFiles) {
|
|
447
|
-
const parser = await selectTrafficParser(trafficFile, options.format);
|
|
448
|
-
if (!parser) {
|
|
449
|
-
logger.warn(`Skipping traffic file with unrecognized format: ${trafficFile}
|
|
450
|
-
`);
|
|
451
|
-
continue;
|
|
452
|
-
}
|
|
453
|
-
supportedTrafficFileCount += 1;
|
|
454
|
-
for await (const exchange of parser.parse(trafficFile)) {
|
|
455
|
-
await session.process({ ...exchange, index: exchangeIndex });
|
|
456
|
-
exchangeIndex += 1;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
if (supportedTrafficFileCount === 0) {
|
|
460
|
-
throw new Error(
|
|
461
|
-
"No supported traffic files found. In auto mode, files must match built-in traffic parser signatures."
|
|
462
|
-
);
|
|
463
|
-
}
|
|
464
|
-
if (exchangeIndex === 0) {
|
|
465
|
-
throw new Error("No HTTP exchanges were parsed from the provided traffic files.");
|
|
466
|
-
}
|
|
467
|
-
return session.finalize();
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// src/commands/drift/index.ts
|
|
471
|
-
var USE_COLOR = Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0;
|
|
472
|
-
function collectSpecServerUrls(openApiIndex) {
|
|
473
|
-
const urls = /* @__PURE__ */ new Set();
|
|
474
|
-
for (const operations of openApiIndex.operationsByMethod.values()) {
|
|
475
|
-
for (const operation of operations) {
|
|
476
|
-
for (const server of operation.servers) {
|
|
477
|
-
urls.add(server.rawUrl);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return Array.from(urls).sort();
|
|
482
|
-
}
|
|
483
|
-
function warnWhenNothingMatched(summary, openApiIndex, server) {
|
|
484
|
-
const validatedExchanges = summary.totalExchanges - summary.skippedExchanges;
|
|
485
|
-
if (validatedExchanges === 0 && summary.skippedExchanges > 0) {
|
|
486
|
-
logger.warn(
|
|
487
|
-
`All ${summary.skippedExchanges} exchange(s) were outside the --server "${server}" and were skipped. Check that the server matches the traffic URLs.
|
|
488
|
-
`
|
|
489
|
-
);
|
|
490
|
-
return;
|
|
491
|
-
}
|
|
492
|
-
if (summary.documentedExchanges > 0 || validatedExchanges === 0) {
|
|
493
|
-
return;
|
|
494
|
-
}
|
|
495
|
-
const serverUrls = collectSpecServerUrls(openApiIndex);
|
|
496
|
-
const hint = server ? `Check that the --server "${server}" matches the traffic URLs and that the description paths align with the remainder.` : summary.hostCompatibleExchanges === validatedExchanges ? `The traffic hosts are compatible with the description servers (${serverUrls.join(
|
|
497
|
-
", "
|
|
498
|
-
)}), so the endpoints are likely undocumented; if they should be documented, check that the description base paths and paths align with the traffic URLs, or use --server to declare the server the traffic was captured against.` : `Check that the traffic host and base path match the description servers (${serverUrls.join(
|
|
499
|
-
", "
|
|
500
|
-
)}), or use --server to declare the server the traffic was captured against.`;
|
|
501
|
-
logger.warn(
|
|
502
|
-
`None of the ${validatedExchanges} validated exchange(s) matched a documented operation. ${hint}
|
|
503
|
-
`
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
async function writeOutput(outputPath, content) {
|
|
507
|
-
const resolved = normalizeFsPath(outputPath);
|
|
508
|
-
await mkdir(path5.dirname(resolved), { recursive: true });
|
|
509
|
-
await writeFile(resolved, content, "utf8");
|
|
510
|
-
}
|
|
511
|
-
async function handleDrift({ argv, config }) {
|
|
512
|
-
const trafficPath = normalizeFsPath(argv.traffic);
|
|
513
|
-
const trafficFormat = argv["traffic-format"];
|
|
514
|
-
const activeRules = argv.rules ? parseCsv(argv.rules) : void 0;
|
|
515
|
-
const server = argv.server;
|
|
516
|
-
if (server && argv["match-mode"]) {
|
|
517
|
-
return exitWithError(
|
|
518
|
-
"The --server and --match-mode options are mutually exclusive: --match-mode controls how requests are located via the description servers, while --server replaces the description servers with the one the traffic was captured against."
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
|
-
const matchMode = argv["match-mode"] ?? "strict-host";
|
|
522
|
-
const specPath = normalizeFsPath(argv.api);
|
|
523
|
-
const openApiIndex = await loadOpenApiIndex(specPath, config);
|
|
524
|
-
if (openApiIndex.loadedOperations === 0) {
|
|
525
|
-
return exitWithError(`No OpenAPI operations were loaded from: ${specPath}`);
|
|
526
|
-
}
|
|
527
|
-
const { runId, summary, findings } = await runTrafficValidation({
|
|
528
|
-
trafficPath,
|
|
529
|
-
format: trafficFormat,
|
|
530
|
-
matchMode,
|
|
531
|
-
ignoreCookies: argv["ignore-cookies"],
|
|
532
|
-
previewFindingsLimit: argv["max-findings"],
|
|
533
|
-
activeRules,
|
|
534
|
-
openApiIndex,
|
|
535
|
-
server,
|
|
536
|
-
minSeverity: argv["min-severity"]
|
|
537
|
-
});
|
|
538
|
-
warnWhenNothingMatched(summary, openApiIndex, server);
|
|
539
|
-
const report = renderReport(
|
|
540
|
-
{
|
|
541
|
-
runId,
|
|
542
|
-
summary,
|
|
543
|
-
findings,
|
|
544
|
-
meta: {
|
|
545
|
-
specSource: specPath,
|
|
546
|
-
trafficPath,
|
|
547
|
-
format: trafficFormat,
|
|
548
|
-
matchMode,
|
|
549
|
-
server
|
|
550
|
-
}
|
|
551
|
-
},
|
|
552
|
-
{
|
|
553
|
-
format: argv["report-format"],
|
|
554
|
-
color: USE_COLOR && argv["report-format"] === "pretty" && !argv.output,
|
|
555
|
-
maxFindings: argv["max-findings"]
|
|
556
|
-
}
|
|
557
|
-
);
|
|
558
|
-
if (argv.output) {
|
|
559
|
-
await writeOutput(argv.output, report);
|
|
560
|
-
logger.info(`Drift report written to: ${normalizeFsPath(argv.output)}
|
|
561
|
-
`);
|
|
562
|
-
} else {
|
|
563
|
-
logger.output(report);
|
|
564
|
-
}
|
|
565
|
-
if (summary.findingsBySeverity.error > 0) {
|
|
566
|
-
throw new AbortFlowError("Drift detected.");
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
412
|
export {
|
|
570
|
-
|
|
413
|
+
selectTrafficParser
|
|
571
414
|
};
|