apitestcenter 0.9.0 → 0.10.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/dist/THIRD-PARTY-NOTICES-UI.txt +1 -1
- package/dist/THIRD-PARTY-NOTICES.txt +1 -1
- package/dist/cli.mjs +564 -170
- package/dist/ui/404/index.html +1 -1
- package/dist/ui/404.html +1 -1
- package/dist/ui/__next.__PAGE__.txt +15 -14
- package/dist/ui/__next._full.txt +13 -12
- package/dist/ui/__next._tree.txt +2 -2
- package/dist/ui/_next/static/chunks/{2od90u8fd_sla.js → 0f9cyrqzolhzx.js} +1 -1
- package/dist/ui/_next/static/chunks/0imlzn2evcfw6.css +3 -0
- package/dist/ui/_next/static/chunks/{13xdai3-mkg7c.js → 1-ogjtk9dipfq.js} +319 -134
- package/dist/ui/_next/static/chunks/{2idsynwg5lkk7.js → 115l_disvbdxa.js} +1 -1
- package/dist/ui/_next/static/chunks/{36lx6-56-udwb.js → 1b31b8g5_5h-y.js} +1 -1
- package/dist/ui/_next/static/chunks/2qchu_7euauai.js +1 -0
- package/dist/ui/_next/static/chunks/{3ad2zh-p8_xhv.js → 2sa_fr4vgkkrp.js} +2 -2
- package/dist/ui/_next/static/chunks/{02myfb0nlri-z.js → 3jywp_61ylz0z.js} +1 -1
- package/dist/ui/_next/static/media/icon.1oy4kb0w-k_2v.png +0 -0
- package/dist/ui/_not-found/__next._full.txt +12 -11
- package/dist/ui/_not-found/__next._not-found.__PAGE__.txt +17 -16
- package/dist/ui/_not-found/__next._tree.txt +2 -2
- package/dist/ui/_not-found/index.html +1 -1
- package/dist/ui/_not-found/index.txt +12 -11
- package/dist/ui/compare/__next._full.txt +13 -12
- package/dist/ui/compare/__next._tree.txt +2 -2
- package/dist/ui/compare/__next.compare.__PAGE__.txt +18 -17
- package/dist/ui/compare/index.html +1 -1
- package/dist/ui/compare/index.txt +13 -12
- package/dist/ui/history/__next._full.txt +14 -13
- package/dist/ui/history/__next._tree.txt +2 -2
- package/dist/ui/history/__next.history.__PAGE__.txt +19 -18
- package/dist/ui/history/index.html +1 -1
- package/dist/ui/history/index.txt +14 -13
- package/dist/ui/icon.png +0 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/index.txt +13 -12
- package/dist/ui/preview/__next._full.txt +14 -13
- package/dist/ui/preview/__next._tree.txt +2 -2
- package/dist/ui/preview/__next.preview.__PAGE__.txt +19 -18
- package/dist/ui/preview/index.html +1 -1
- package/dist/ui/preview/index.txt +14 -13
- package/dist/ui/suite/__next._full.txt +13 -12
- package/dist/ui/suite/__next._tree.txt +2 -2
- package/dist/ui/suite/__next.suite.__PAGE__.txt +18 -17
- package/dist/ui/suite/index.html +1 -1
- package/dist/ui/suite/index.txt +13 -12
- package/dist/ui/tests/__next._full.txt +12 -11
- package/dist/ui/tests/__next._tree.txt +2 -2
- package/dist/ui/tests/__next.tests.__PAGE__.txt +17 -16
- package/dist/ui/tests/index.html +1 -1
- package/dist/ui/tests/index.txt +12 -11
- package/package.json +1 -1
- package/dist/ui/_next/static/chunks/2i7s5kuurlkr6.css +0 -3
- package/dist/ui/_next/static/chunks/2nxnxp6p-40kg.js +0 -1
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_buildManifest.js +0 -0
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_clientMiddlewareManifest.js +0 -0
- /package/dist/ui/_next/static/{C6zMFzDkVqF8IXny_v7JK → 9enzqastnBYCi6FVPT4mz}/_ssgManifest.js +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -231,15 +231,15 @@ function normalizeView(raw) {
|
|
|
231
231
|
const v = raw;
|
|
232
232
|
if (typeof v.id !== "string" || !v.id || typeof v.name !== "string") return null;
|
|
233
233
|
const scope = v.scope === "compare" ? "compare" : "run";
|
|
234
|
-
const
|
|
234
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
235
235
|
const widgets = [];
|
|
236
236
|
for (const item of Array.isArray(v.widgets) ? v.widgets : []) {
|
|
237
237
|
const w = item;
|
|
238
238
|
const def = METRICS[w.metric];
|
|
239
239
|
if (!def || scope === "compare" && !def.compare) continue;
|
|
240
240
|
let id = typeof w.id === "string" && w.id ? w.id : `${def.id}-${widgets.length}`;
|
|
241
|
-
while (
|
|
242
|
-
|
|
241
|
+
while (seen2.has(id)) id = `${id}-x`;
|
|
242
|
+
seen2.add(id);
|
|
243
243
|
const kind = def.kinds.includes(w.kind) ? w.kind : def.kinds[0];
|
|
244
244
|
const width = clamp(w.w ?? def.size.w, def.min.w, GRID_COLUMNS);
|
|
245
245
|
widgets.push({
|
|
@@ -781,12 +781,12 @@ function variablesOf(env) {
|
|
|
781
781
|
}
|
|
782
782
|
function normalizeEnvironments(raw) {
|
|
783
783
|
if (!Array.isArray(raw)) return [];
|
|
784
|
-
const
|
|
784
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
785
785
|
const out = [];
|
|
786
786
|
for (const item of raw) {
|
|
787
787
|
const e = item;
|
|
788
|
-
if (typeof e?.id !== "string" || !e.id ||
|
|
789
|
-
|
|
788
|
+
if (typeof e?.id !== "string" || !e.id || seen2.has(e.id)) continue;
|
|
789
|
+
seen2.add(e.id);
|
|
790
790
|
const keys = /* @__PURE__ */ new Set();
|
|
791
791
|
const variables = [];
|
|
792
792
|
for (const v of Array.isArray(e.variables) ? e.variables : []) {
|
|
@@ -12334,14 +12334,14 @@ function initializeContext(params) {
|
|
|
12334
12334
|
function process2(schema, ctx, _params = { path: [], schemaPath: [] }) {
|
|
12335
12335
|
var _a3;
|
|
12336
12336
|
const def = schema._zod.def;
|
|
12337
|
-
const
|
|
12338
|
-
if (
|
|
12339
|
-
|
|
12337
|
+
const seen2 = ctx.seen.get(schema);
|
|
12338
|
+
if (seen2) {
|
|
12339
|
+
seen2.count++;
|
|
12340
12340
|
const isCycle = _params.schemaPath.includes(schema);
|
|
12341
12341
|
if (isCycle) {
|
|
12342
|
-
|
|
12342
|
+
seen2.cycle = _params.path;
|
|
12343
12343
|
}
|
|
12344
|
-
return
|
|
12344
|
+
return seen2.schema;
|
|
12345
12345
|
}
|
|
12346
12346
|
const result = { schema: {}, count: 1, cycle: void 0, path: _params.path };
|
|
12347
12347
|
ctx.seen.set(schema, result);
|
|
@@ -12424,12 +12424,12 @@ function extractDefs(ctx, schema) {
|
|
|
12424
12424
|
if (entry[1].schema.$ref) {
|
|
12425
12425
|
return;
|
|
12426
12426
|
}
|
|
12427
|
-
const
|
|
12427
|
+
const seen2 = entry[1];
|
|
12428
12428
|
const { ref, defId } = makeURI(entry);
|
|
12429
|
-
|
|
12429
|
+
seen2.def = { ...seen2.schema };
|
|
12430
12430
|
if (defId)
|
|
12431
|
-
|
|
12432
|
-
const schema2 =
|
|
12431
|
+
seen2.defId = defId;
|
|
12432
|
+
const schema2 = seen2.schema;
|
|
12433
12433
|
for (const key in schema2) {
|
|
12434
12434
|
delete schema2[key];
|
|
12435
12435
|
}
|
|
@@ -12437,16 +12437,16 @@ function extractDefs(ctx, schema) {
|
|
|
12437
12437
|
};
|
|
12438
12438
|
if (ctx.cycles === "throw") {
|
|
12439
12439
|
for (const entry of ctx.seen.entries()) {
|
|
12440
|
-
const
|
|
12441
|
-
if (
|
|
12442
|
-
throw new Error(`Cycle detected: #/${
|
|
12440
|
+
const seen2 = entry[1];
|
|
12441
|
+
if (seen2.cycle) {
|
|
12442
|
+
throw new Error(`Cycle detected: #/${seen2.cycle?.join("/")}/<root>
|
|
12443
12443
|
|
|
12444
12444
|
Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.`);
|
|
12445
12445
|
}
|
|
12446
12446
|
}
|
|
12447
12447
|
}
|
|
12448
12448
|
for (const entry of ctx.seen.entries()) {
|
|
12449
|
-
const
|
|
12449
|
+
const seen2 = entry[1];
|
|
12450
12450
|
if (schema === entry[0]) {
|
|
12451
12451
|
extractToDef(entry);
|
|
12452
12452
|
continue;
|
|
@@ -12463,11 +12463,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
12463
12463
|
extractToDef(entry);
|
|
12464
12464
|
continue;
|
|
12465
12465
|
}
|
|
12466
|
-
if (
|
|
12466
|
+
if (seen2.cycle) {
|
|
12467
12467
|
extractToDef(entry);
|
|
12468
12468
|
continue;
|
|
12469
12469
|
}
|
|
12470
|
-
if (
|
|
12470
|
+
if (seen2.count > 1) {
|
|
12471
12471
|
if (ctx.reused === "ref") {
|
|
12472
12472
|
extractToDef(entry);
|
|
12473
12473
|
continue;
|
|
@@ -12480,13 +12480,13 @@ function finalize(ctx, schema) {
|
|
|
12480
12480
|
if (!root2)
|
|
12481
12481
|
throw new Error("Unprocessed schema. This is a bug in Zod.");
|
|
12482
12482
|
const flattenRef = (zodSchema) => {
|
|
12483
|
-
const
|
|
12484
|
-
if (
|
|
12483
|
+
const seen2 = ctx.seen.get(zodSchema);
|
|
12484
|
+
if (seen2.ref === null)
|
|
12485
12485
|
return;
|
|
12486
|
-
const schema2 =
|
|
12486
|
+
const schema2 = seen2.def ?? seen2.schema;
|
|
12487
12487
|
const _cached = { ...schema2 };
|
|
12488
|
-
const ref =
|
|
12489
|
-
|
|
12488
|
+
const ref = seen2.ref;
|
|
12489
|
+
seen2.ref = null;
|
|
12490
12490
|
if (ref) {
|
|
12491
12491
|
flattenRef(ref);
|
|
12492
12492
|
const refSeen = ctx.seen.get(ref);
|
|
@@ -12538,7 +12538,7 @@ function finalize(ctx, schema) {
|
|
|
12538
12538
|
ctx.override({
|
|
12539
12539
|
zodSchema,
|
|
12540
12540
|
jsonSchema: schema2,
|
|
12541
|
-
path:
|
|
12541
|
+
path: seen2.path ?? []
|
|
12542
12542
|
});
|
|
12543
12543
|
};
|
|
12544
12544
|
for (const entry of [...ctx.seen.entries()].reverse()) {
|
|
@@ -12566,11 +12566,11 @@ function finalize(ctx, schema) {
|
|
|
12566
12566
|
delete result.id;
|
|
12567
12567
|
const defs = ctx.external?.defs ?? {};
|
|
12568
12568
|
for (const entry of ctx.seen.entries()) {
|
|
12569
|
-
const
|
|
12570
|
-
if (
|
|
12571
|
-
if (
|
|
12572
|
-
delete
|
|
12573
|
-
defs[
|
|
12569
|
+
const seen2 = entry[1];
|
|
12570
|
+
if (seen2.def && seen2.defId) {
|
|
12571
|
+
if (seen2.def.id === seen2.defId)
|
|
12572
|
+
delete seen2.def.id;
|
|
12573
|
+
defs[seen2.defId] = seen2.def;
|
|
12574
12574
|
}
|
|
12575
12575
|
}
|
|
12576
12576
|
if (ctx.external) {
|
|
@@ -13106,9 +13106,9 @@ var init_json_schema_processors = __esm({
|
|
|
13106
13106
|
nullableProcessor = (schema, ctx, json2, params) => {
|
|
13107
13107
|
const def = schema._zod.def;
|
|
13108
13108
|
const inner = process2(def.innerType, ctx, params);
|
|
13109
|
-
const
|
|
13109
|
+
const seen2 = ctx.seen.get(schema);
|
|
13110
13110
|
if (ctx.target === "openapi-3.0") {
|
|
13111
|
-
|
|
13111
|
+
seen2.ref = def.innerType;
|
|
13112
13112
|
json2.nullable = true;
|
|
13113
13113
|
} else {
|
|
13114
13114
|
json2.anyOf = [inner, { type: "null" }];
|
|
@@ -13117,29 +13117,29 @@ var init_json_schema_processors = __esm({
|
|
|
13117
13117
|
nonoptionalProcessor = (schema, ctx, _json, params) => {
|
|
13118
13118
|
const def = schema._zod.def;
|
|
13119
13119
|
process2(def.innerType, ctx, params);
|
|
13120
|
-
const
|
|
13121
|
-
|
|
13120
|
+
const seen2 = ctx.seen.get(schema);
|
|
13121
|
+
seen2.ref = def.innerType;
|
|
13122
13122
|
};
|
|
13123
13123
|
defaultProcessor = (schema, ctx, json2, params) => {
|
|
13124
13124
|
const def = schema._zod.def;
|
|
13125
13125
|
process2(def.innerType, ctx, params);
|
|
13126
|
-
const
|
|
13127
|
-
|
|
13126
|
+
const seen2 = ctx.seen.get(schema);
|
|
13127
|
+
seen2.ref = def.innerType;
|
|
13128
13128
|
json2.default = JSON.parse(JSON.stringify(def.defaultValue));
|
|
13129
13129
|
};
|
|
13130
13130
|
prefaultProcessor = (schema, ctx, json2, params) => {
|
|
13131
13131
|
const def = schema._zod.def;
|
|
13132
13132
|
process2(def.innerType, ctx, params);
|
|
13133
|
-
const
|
|
13134
|
-
|
|
13133
|
+
const seen2 = ctx.seen.get(schema);
|
|
13134
|
+
seen2.ref = def.innerType;
|
|
13135
13135
|
if (ctx.io === "input")
|
|
13136
13136
|
json2._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
|
13137
13137
|
};
|
|
13138
13138
|
catchProcessor = (schema, ctx, json2, params) => {
|
|
13139
13139
|
const def = schema._zod.def;
|
|
13140
13140
|
process2(def.innerType, ctx, params);
|
|
13141
|
-
const
|
|
13142
|
-
|
|
13141
|
+
const seen2 = ctx.seen.get(schema);
|
|
13142
|
+
seen2.ref = def.innerType;
|
|
13143
13143
|
let catchValue;
|
|
13144
13144
|
try {
|
|
13145
13145
|
catchValue = def.catchValue(void 0);
|
|
@@ -13153,33 +13153,33 @@ var init_json_schema_processors = __esm({
|
|
|
13153
13153
|
const inIsTransform = def.in._zod.traits.has("$ZodTransform");
|
|
13154
13154
|
const innerType = ctx.io === "input" ? inIsTransform ? def.out : def.in : def.out;
|
|
13155
13155
|
process2(innerType, ctx, params);
|
|
13156
|
-
const
|
|
13157
|
-
|
|
13156
|
+
const seen2 = ctx.seen.get(schema);
|
|
13157
|
+
seen2.ref = innerType;
|
|
13158
13158
|
};
|
|
13159
13159
|
readonlyProcessor = (schema, ctx, json2, params) => {
|
|
13160
13160
|
const def = schema._zod.def;
|
|
13161
13161
|
process2(def.innerType, ctx, params);
|
|
13162
|
-
const
|
|
13163
|
-
|
|
13162
|
+
const seen2 = ctx.seen.get(schema);
|
|
13163
|
+
seen2.ref = def.innerType;
|
|
13164
13164
|
json2.readOnly = true;
|
|
13165
13165
|
};
|
|
13166
13166
|
promiseProcessor = (schema, ctx, _json, params) => {
|
|
13167
13167
|
const def = schema._zod.def;
|
|
13168
13168
|
process2(def.innerType, ctx, params);
|
|
13169
|
-
const
|
|
13170
|
-
|
|
13169
|
+
const seen2 = ctx.seen.get(schema);
|
|
13170
|
+
seen2.ref = def.innerType;
|
|
13171
13171
|
};
|
|
13172
13172
|
optionalProcessor = (schema, ctx, _json, params) => {
|
|
13173
13173
|
const def = schema._zod.def;
|
|
13174
13174
|
process2(def.innerType, ctx, params);
|
|
13175
|
-
const
|
|
13176
|
-
|
|
13175
|
+
const seen2 = ctx.seen.get(schema);
|
|
13176
|
+
seen2.ref = def.innerType;
|
|
13177
13177
|
};
|
|
13178
13178
|
lazyProcessor = (schema, ctx, _json, params) => {
|
|
13179
13179
|
const innerType = schema._zod.innerType;
|
|
13180
13180
|
process2(innerType, ctx, params);
|
|
13181
|
-
const
|
|
13182
|
-
|
|
13181
|
+
const seen2 = ctx.seen.get(schema);
|
|
13182
|
+
seen2.ref = innerType;
|
|
13183
13183
|
};
|
|
13184
13184
|
allProcessors = {
|
|
13185
13185
|
string: stringProcessor,
|
|
@@ -16068,13 +16068,41 @@ function checkLabel(check2) {
|
|
|
16068
16068
|
case "status":
|
|
16069
16069
|
return `status is ${check2.expect.replace(/\s+/g, "")}`;
|
|
16070
16070
|
case "body":
|
|
16071
|
+
if (check2.op === "is_json") return "body is JSON";
|
|
16072
|
+
if (check2.op === "matches") return `body matches /${clip(check2.value)}/`;
|
|
16071
16073
|
return `body ${check2.op === "contains" ? "contains" : "does not contain"} "${clip(check2.value)}"`;
|
|
16072
|
-
case "json":
|
|
16073
|
-
|
|
16074
|
+
case "json": {
|
|
16075
|
+
const path = jsonPathLabel(check2.path);
|
|
16076
|
+
switch (check2.op) {
|
|
16077
|
+
case "exists":
|
|
16078
|
+
return `${path} exists`;
|
|
16079
|
+
case "not_exists":
|
|
16080
|
+
return `${path} does not exist`;
|
|
16081
|
+
case "greater":
|
|
16082
|
+
return `${path} > ${clip(check2.value)}`;
|
|
16083
|
+
case "less":
|
|
16084
|
+
return `${path} < ${clip(check2.value)}`;
|
|
16085
|
+
case "matches":
|
|
16086
|
+
return `${path} matches /${clip(check2.value)}/`;
|
|
16087
|
+
case "type":
|
|
16088
|
+
return `${path} is ${/^[aeiou]/.test(check2.value) ? "an" : "a"} ${check2.value || "?"}`;
|
|
16089
|
+
case "length":
|
|
16090
|
+
return `length of ${path} ${lengthRule(check2.value).label}`;
|
|
16091
|
+
default:
|
|
16092
|
+
return `${path} ${check2.op === "equals" ? "=" : check2.op === "not_equals" ? "\u2260" : "contains"} "${clip(check2.value)}"`;
|
|
16093
|
+
}
|
|
16094
|
+
}
|
|
16074
16095
|
case "header":
|
|
16075
|
-
|
|
16096
|
+
if (check2.op === "exists") return `header ${check2.name} exists`;
|
|
16097
|
+
if (check2.op === "not_exists") return `header ${check2.name} does not exist`;
|
|
16098
|
+
if (check2.op === "matches") return `header ${check2.name} matches /${clip(check2.value)}/`;
|
|
16099
|
+
return `header ${check2.name} ${check2.op === "equals" ? "=" : "contains"} "${clip(check2.value)}"`;
|
|
16076
16100
|
case "time":
|
|
16077
16101
|
return `responds within ${check2.maxMs} ms`;
|
|
16102
|
+
case "schema": {
|
|
16103
|
+
const title = schemaTitle(check2.schema);
|
|
16104
|
+
return title ? `body matches schema "${clip(title)}"` : "body matches the JSON schema";
|
|
16105
|
+
}
|
|
16078
16106
|
}
|
|
16079
16107
|
}
|
|
16080
16108
|
function clip(text) {
|
|
@@ -16082,26 +16110,86 @@ function clip(text) {
|
|
|
16082
16110
|
}
|
|
16083
16111
|
function jsonPathLabel(path) {
|
|
16084
16112
|
const trimmed = path.trim().replace(/^\$\.?/, "");
|
|
16085
|
-
return `$.${trimmed}
|
|
16113
|
+
return trimmed ? `$.${trimmed}` : "$";
|
|
16114
|
+
}
|
|
16115
|
+
function schemaTitle(schema) {
|
|
16116
|
+
try {
|
|
16117
|
+
const parsed = JSON.parse(schema);
|
|
16118
|
+
return typeof parsed?.title === "string" && parsed.title.trim() ? parsed.title.trim() : void 0;
|
|
16119
|
+
} catch {
|
|
16120
|
+
return void 0;
|
|
16121
|
+
}
|
|
16122
|
+
}
|
|
16123
|
+
function lengthRule(value) {
|
|
16124
|
+
const m = /^\s*(>=|<=|!=|>|<|=)?\s*(\d+)\s*$/.exec(value);
|
|
16125
|
+
if (!m) return { label: `is ${value.trim() || "?"}` };
|
|
16126
|
+
const op = m[1] ?? "=";
|
|
16127
|
+
return { label: `${op === "=" ? "=" : op === "!=" ? "\u2260" : op === ">=" ? "\u2265" : op === "<=" ? "\u2264" : op} ${m[2]}` };
|
|
16086
16128
|
}
|
|
16087
16129
|
function checksNeedBody(checks) {
|
|
16088
|
-
return checks.some((c) => c.type === "body" || c.type === "json");
|
|
16130
|
+
return checks.some((c) => c.type === "body" || c.type === "json" || c.type === "schema");
|
|
16089
16131
|
}
|
|
16090
16132
|
function evaluator() {
|
|
16091
16133
|
compiled ??= new Function(`${CHECK_EVALUATOR_JS}
|
|
16092
|
-
return __atcCheck;`)();
|
|
16134
|
+
return { check: __atcCheck, schemaError: __atcSchemaError, jsonGet: __atcJsonGet };`)();
|
|
16093
16135
|
return compiled;
|
|
16094
16136
|
}
|
|
16137
|
+
function explain(check2, res) {
|
|
16138
|
+
if (check2.type === "status") return `got ${res.status}`;
|
|
16139
|
+
if (check2.type === "time") return `took ${Math.round(res.durationMs)} ms`;
|
|
16140
|
+
if (check2.type === "header") {
|
|
16141
|
+
const h = res.headers[check2.name.toLowerCase()];
|
|
16142
|
+
return h === void 0 ? "no such header" : `is "${clip(h)}"`;
|
|
16143
|
+
}
|
|
16144
|
+
if (res.body === null) return "no body";
|
|
16145
|
+
if (check2.type === "body") return check2.op === "is_json" ? "not valid JSON" : void 0;
|
|
16146
|
+
let parsed;
|
|
16147
|
+
try {
|
|
16148
|
+
parsed = JSON.parse(res.body);
|
|
16149
|
+
} catch {
|
|
16150
|
+
return "the body is not JSON";
|
|
16151
|
+
}
|
|
16152
|
+
if (check2.type === "schema") {
|
|
16153
|
+
let schema;
|
|
16154
|
+
try {
|
|
16155
|
+
schema = JSON.parse(check2.schema);
|
|
16156
|
+
} catch {
|
|
16157
|
+
return "the schema is not valid JSON";
|
|
16158
|
+
}
|
|
16159
|
+
return evaluator().schemaError(schema, parsed, "", schema, 0) ?? void 0;
|
|
16160
|
+
}
|
|
16161
|
+
if (check2.type === "json") {
|
|
16162
|
+
const got = evaluator().jsonGet(parsed, check2.path);
|
|
16163
|
+
if (!got.found) return check2.op === "not_exists" ? void 0 : "not found";
|
|
16164
|
+
const v = got.value;
|
|
16165
|
+
if (check2.op === "type") return `is ${v === null ? "null" : Array.isArray(v) ? "an array" : typeof v === "object" ? "an object" : `a ${typeof v}`}`;
|
|
16166
|
+
if (check2.op === "length") {
|
|
16167
|
+
const n = typeof v === "string" || Array.isArray(v) ? v.length : v && typeof v === "object" ? Object.keys(v).length : void 0;
|
|
16168
|
+
return n === void 0 ? "has no length" : `length is ${n}`;
|
|
16169
|
+
}
|
|
16170
|
+
if (check2.op === "not_exists") return "it exists";
|
|
16171
|
+
const text = typeof v === "string" ? v : JSON.stringify(v);
|
|
16172
|
+
return `is ${clip(text ?? "")}`;
|
|
16173
|
+
}
|
|
16174
|
+
return void 0;
|
|
16175
|
+
}
|
|
16095
16176
|
function evaluateChecks(checks, res) {
|
|
16096
|
-
const run2 = evaluator();
|
|
16177
|
+
const run2 = evaluator().check;
|
|
16097
16178
|
return checks.map((check2) => {
|
|
16098
16179
|
let ok = false;
|
|
16099
16180
|
try {
|
|
16100
|
-
ok = Boolean(run2(check2, res));
|
|
16181
|
+
ok = Boolean(run2({ ...check2 }, res));
|
|
16101
16182
|
} catch {
|
|
16102
16183
|
ok = false;
|
|
16103
16184
|
}
|
|
16104
|
-
return { name: checkLabel(check2), ok };
|
|
16185
|
+
if (ok) return { name: checkLabel(check2), ok };
|
|
16186
|
+
let detail;
|
|
16187
|
+
try {
|
|
16188
|
+
detail = explain(check2, res);
|
|
16189
|
+
} catch {
|
|
16190
|
+
detail = void 0;
|
|
16191
|
+
}
|
|
16192
|
+
return detail ? { name: checkLabel(check2), ok, detail } : { name: checkLabel(check2), ok };
|
|
16105
16193
|
});
|
|
16106
16194
|
}
|
|
16107
16195
|
var responseCheckSchema, CHECK_EVALUATOR_JS, compiled;
|
|
@@ -16111,20 +16199,28 @@ var init_checks3 = __esm({
|
|
|
16111
16199
|
init_zod();
|
|
16112
16200
|
responseCheckSchema = external_exports.discriminatedUnion("type", [
|
|
16113
16201
|
external_exports.object({ type: external_exports.literal("status"), expect: external_exports.string().min(1).max(100) }).strict(),
|
|
16114
|
-
external_exports.object({
|
|
16202
|
+
external_exports.object({
|
|
16203
|
+
type: external_exports.literal("body"),
|
|
16204
|
+
op: external_exports.enum(["contains", "not_contains", "matches", "is_json"]),
|
|
16205
|
+
// Not used by is_json.
|
|
16206
|
+
value: external_exports.string().max(2e3).default("")
|
|
16207
|
+
}).strict(),
|
|
16115
16208
|
external_exports.object({
|
|
16116
16209
|
type: external_exports.literal("json"),
|
|
16117
16210
|
path: external_exports.string().min(1).max(300),
|
|
16118
|
-
op: external_exports.enum(["exists", "not_exists", "equals", "not_equals", "contains"]),
|
|
16211
|
+
op: external_exports.enum(["exists", "not_exists", "equals", "not_equals", "contains", "greater", "less", "matches", "type", "length"]),
|
|
16119
16212
|
value: external_exports.string().max(2e3).default("")
|
|
16120
16213
|
}).strict(),
|
|
16121
16214
|
external_exports.object({
|
|
16122
16215
|
type: external_exports.literal("header"),
|
|
16123
16216
|
name: external_exports.string().min(1).max(200),
|
|
16124
|
-
op: external_exports.enum(["exists", "equals", "contains"]),
|
|
16217
|
+
op: external_exports.enum(["exists", "not_exists", "equals", "contains", "matches"]),
|
|
16125
16218
|
value: external_exports.string().max(2e3).default("")
|
|
16126
16219
|
}).strict(),
|
|
16127
|
-
external_exports.object({ type: external_exports.literal("time"), maxMs: external_exports.number().positive().max(6e5) }).strict()
|
|
16220
|
+
external_exports.object({ type: external_exports.literal("time"), maxMs: external_exports.number().positive().max(6e5) }).strict(),
|
|
16221
|
+
// A JSON Schema (draft 7 subset) the whole body must match.
|
|
16222
|
+
// Kept while still empty (being written); only a JSON object is sent.
|
|
16223
|
+
external_exports.object({ type: external_exports.literal("schema"), schema: external_exports.string().max(2e5) }).strict()
|
|
16128
16224
|
]);
|
|
16129
16225
|
CHECK_EVALUATOR_JS = String.raw`
|
|
16130
16226
|
function __atcStatusOk(expect, status) {
|
|
@@ -16159,28 +16255,167 @@ function __atcAsText(value) {
|
|
|
16159
16255
|
if (value === undefined) return "";
|
|
16160
16256
|
return JSON.stringify(value);
|
|
16161
16257
|
}
|
|
16258
|
+
function __atcTypeOf(value) {
|
|
16259
|
+
if (value === null) return "null";
|
|
16260
|
+
if (Array.isArray(value)) return "array";
|
|
16261
|
+
return typeof value;
|
|
16262
|
+
}
|
|
16263
|
+
function __atcIsType(value, type) {
|
|
16264
|
+
if (type === "integer") return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
|
|
16265
|
+
if (type === "number") return typeof value === "number" && isFinite(value);
|
|
16266
|
+
return __atcTypeOf(value) === type;
|
|
16267
|
+
}
|
|
16268
|
+
function __atcMatches(pattern, text) {
|
|
16269
|
+
try { return new RegExp(pattern).test(text); } catch (e) { return false; }
|
|
16270
|
+
}
|
|
16271
|
+
function __atcLengthOk(rule, n) {
|
|
16272
|
+
var m = String(rule).match(/^\s*(>=|<=|!=|>|<|=)?\s*(\d+)\s*$/);
|
|
16273
|
+
if (!m) return false;
|
|
16274
|
+
var want = Number(m[2]);
|
|
16275
|
+
var op = m[1] || "=";
|
|
16276
|
+
if (op === ">") return n > want;
|
|
16277
|
+
if (op === "<") return n < want;
|
|
16278
|
+
if (op === ">=") return n >= want;
|
|
16279
|
+
if (op === "<=") return n <= want;
|
|
16280
|
+
if (op === "!=") return n !== want;
|
|
16281
|
+
return n === want;
|
|
16282
|
+
}
|
|
16283
|
+
function __atcPathText(path) { return path === "" ? "$" : "$" + path; }
|
|
16284
|
+
// JSON Schema, the parts APIs use: type (and nullable), enum, const, properties, required,
|
|
16285
|
+
// additionalProperties, items, min/max (Length, Items, imum), pattern, allOf/anyOf/oneOf,
|
|
16286
|
+
// local $ref. Returns the first problem as "$.items[0].id should be number", or null.
|
|
16287
|
+
function __atcSchemaError(schema, value, path, root, depth) {
|
|
16288
|
+
if (schema === true || schema === undefined || schema === null) return null;
|
|
16289
|
+
if (schema === false) return __atcPathText(path) + " should not be there";
|
|
16290
|
+
if (depth > 60) return null;
|
|
16291
|
+
if (typeof schema.$ref === "string") {
|
|
16292
|
+
var ref = schema.$ref.replace(/^#\/?/, "").split("/");
|
|
16293
|
+
var target = root;
|
|
16294
|
+
for (var r = 0; r < ref.length && target; r++) if (ref[r]) target = target[ref[r].replace(/~1/g, "/").replace(/~0/g, "~")];
|
|
16295
|
+
return target ? __atcSchemaError(target, value, path, root, depth + 1) : null;
|
|
16296
|
+
}
|
|
16297
|
+
var where = __atcPathText(path);
|
|
16298
|
+
if (schema.type !== undefined) {
|
|
16299
|
+
var types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
16300
|
+
if (schema.nullable === true) types = types.concat(["null"]);
|
|
16301
|
+
var okType = false;
|
|
16302
|
+
for (var t = 0; t < types.length; t++) if (__atcIsType(value, types[t])) okType = true;
|
|
16303
|
+
if (!okType) return where + " should be " + types.join(" or ") + " (it is " + __atcTypeOf(value) + ")";
|
|
16304
|
+
}
|
|
16305
|
+
if (schema.enum && Array.isArray(schema.enum)) {
|
|
16306
|
+
var inEnum = false;
|
|
16307
|
+
for (var e = 0; e < schema.enum.length; e++) if (JSON.stringify(schema.enum[e]) === JSON.stringify(value)) inEnum = true;
|
|
16308
|
+
if (!inEnum) return where + " should be one of " + JSON.stringify(schema.enum);
|
|
16309
|
+
}
|
|
16310
|
+
if (schema.const !== undefined && JSON.stringify(schema.const) !== JSON.stringify(value)) return where + " should be " + JSON.stringify(schema.const);
|
|
16311
|
+
if (typeof value === "string") {
|
|
16312
|
+
if (typeof schema.minLength === "number" && value.length < schema.minLength) return where + " should be at least " + schema.minLength + " characters";
|
|
16313
|
+
if (typeof schema.maxLength === "number" && value.length > schema.maxLength) return where + " should be at most " + schema.maxLength + " characters";
|
|
16314
|
+
if (typeof schema.pattern === "string" && !__atcMatches(schema.pattern, value)) return where + " should match /" + schema.pattern + "/";
|
|
16315
|
+
}
|
|
16316
|
+
if (typeof value === "number") {
|
|
16317
|
+
if (typeof schema.minimum === "number" && value < schema.minimum) return where + " should be at least " + schema.minimum;
|
|
16318
|
+
if (typeof schema.maximum === "number" && value > schema.maximum) return where + " should be at most " + schema.maximum;
|
|
16319
|
+
if (typeof schema.exclusiveMinimum === "number" && value <= schema.exclusiveMinimum) return where + " should be more than " + schema.exclusiveMinimum;
|
|
16320
|
+
if (typeof schema.exclusiveMaximum === "number" && value >= schema.exclusiveMaximum) return where + " should be less than " + schema.exclusiveMaximum;
|
|
16321
|
+
}
|
|
16322
|
+
if (Array.isArray(value)) {
|
|
16323
|
+
if (typeof schema.minItems === "number" && value.length < schema.minItems) return where + " should have at least " + schema.minItems + " items";
|
|
16324
|
+
if (typeof schema.maxItems === "number" && value.length > schema.maxItems) return where + " should have at most " + schema.maxItems + " items";
|
|
16325
|
+
if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
|
|
16326
|
+
for (var i = 0; i < value.length; i++) {
|
|
16327
|
+
var itemErr = __atcSchemaError(schema.items, value[i], path + "[" + i + "]", root, depth + 1);
|
|
16328
|
+
if (itemErr) return itemErr;
|
|
16329
|
+
}
|
|
16330
|
+
}
|
|
16331
|
+
}
|
|
16332
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
16333
|
+
var req = Array.isArray(schema.required) ? schema.required : [];
|
|
16334
|
+
for (var q = 0; q < req.length; q++) if (!Object.prototype.hasOwnProperty.call(value, req[q])) return where + " should have " + req[q];
|
|
16335
|
+
var props = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
|
|
16336
|
+
for (var key in value) {
|
|
16337
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
16338
|
+
var sub = path + (/^[A-Za-z_$][\w$]*$/.test(key) ? "." + key : "[" + JSON.stringify(key) + "]");
|
|
16339
|
+
if (Object.prototype.hasOwnProperty.call(props, key)) {
|
|
16340
|
+
var propErr = __atcSchemaError(props[key], value[key], sub, root, depth + 1);
|
|
16341
|
+
if (propErr) return propErr;
|
|
16342
|
+
} else if (schema.additionalProperties === false) {
|
|
16343
|
+
return __atcPathText(sub) + " is not expected";
|
|
16344
|
+
} else if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
|
|
16345
|
+
var addErr = __atcSchemaError(schema.additionalProperties, value[key], sub, root, depth + 1);
|
|
16346
|
+
if (addErr) return addErr;
|
|
16347
|
+
}
|
|
16348
|
+
}
|
|
16349
|
+
}
|
|
16350
|
+
if (Array.isArray(schema.allOf)) {
|
|
16351
|
+
for (var a = 0; a < schema.allOf.length; a++) {
|
|
16352
|
+
var allErr = __atcSchemaError(schema.allOf[a], value, path, root, depth + 1);
|
|
16353
|
+
if (allErr) return allErr;
|
|
16354
|
+
}
|
|
16355
|
+
}
|
|
16356
|
+
var some = schema.anyOf || schema.oneOf;
|
|
16357
|
+
if (Array.isArray(some) && some.length) {
|
|
16358
|
+
var first = null;
|
|
16359
|
+
var matched = 0;
|
|
16360
|
+
for (var s = 0; s < some.length; s++) {
|
|
16361
|
+
var someErr = __atcSchemaError(some[s], value, path, root, depth + 1);
|
|
16362
|
+
if (!someErr) matched++;
|
|
16363
|
+
else if (!first) first = someErr;
|
|
16364
|
+
}
|
|
16365
|
+
if (!matched) return first;
|
|
16366
|
+
if (schema.oneOf && matched > 1) return where + " matches more than one of oneOf";
|
|
16367
|
+
}
|
|
16368
|
+
return null;
|
|
16369
|
+
}
|
|
16370
|
+
function __atcParsedSchema(check) {
|
|
16371
|
+
if (check.__parsed === undefined) {
|
|
16372
|
+
try { check.__parsed = JSON.parse(check.schema); } catch (e) { check.__parsed = null; }
|
|
16373
|
+
}
|
|
16374
|
+
return check.__parsed;
|
|
16375
|
+
}
|
|
16162
16376
|
function __atcCheck(check, res) {
|
|
16163
16377
|
if (check.type === "status") return __atcStatusOk(check.expect, res.status);
|
|
16164
16378
|
if (check.type === "time") return res.durationMs <= check.maxMs;
|
|
16165
16379
|
if (check.type === "header") {
|
|
16166
16380
|
var h = res.headers[String(check.name).toLowerCase()];
|
|
16167
16381
|
if (check.op === "exists") return h !== undefined;
|
|
16382
|
+
if (check.op === "not_exists") return h === undefined;
|
|
16168
16383
|
if (h === undefined) return false;
|
|
16384
|
+
if (check.op === "matches") return __atcMatches(check.value, h);
|
|
16169
16385
|
return check.op === "equals" ? h === check.value : h.indexOf(check.value) >= 0;
|
|
16170
16386
|
}
|
|
16171
16387
|
if (res.body === null || res.body === undefined) return false;
|
|
16172
16388
|
if (check.type === "body") {
|
|
16389
|
+
if (check.op === "is_json") { try { JSON.parse(res.body); return true; } catch (e) { return false; } }
|
|
16390
|
+
if (check.op === "matches") return __atcMatches(check.value, res.body);
|
|
16173
16391
|
var has = res.body.indexOf(check.value) >= 0;
|
|
16174
16392
|
return check.op === "contains" ? has : !has;
|
|
16175
16393
|
}
|
|
16394
|
+
var parsed;
|
|
16395
|
+
try { parsed = JSON.parse(res.body); } catch (e) { return false; }
|
|
16396
|
+
if (check.type === "schema") {
|
|
16397
|
+
var schema = __atcParsedSchema(check);
|
|
16398
|
+
return schema !== null && __atcSchemaError(schema, parsed, "", schema, 0) === null;
|
|
16399
|
+
}
|
|
16176
16400
|
if (check.type === "json") {
|
|
16177
|
-
var parsed;
|
|
16178
|
-
try { parsed = JSON.parse(res.body); } catch (e) { return false; }
|
|
16179
16401
|
var got = __atcJsonGet(parsed, check.path);
|
|
16180
16402
|
if (check.op === "exists") return got.found;
|
|
16181
16403
|
if (check.op === "not_exists") return !got.found;
|
|
16182
16404
|
if (!got.found) return check.op === "not_equals";
|
|
16405
|
+
if (check.op === "type") return __atcIsType(got.value, String(check.value).trim().toLowerCase());
|
|
16406
|
+
if (check.op === "length") {
|
|
16407
|
+
var v = got.value;
|
|
16408
|
+
var n = typeof v === "string" || Array.isArray(v) ? v.length : v !== null && typeof v === "object" ? Object.keys(v).length : -1;
|
|
16409
|
+
return n >= 0 && __atcLengthOk(check.value, n);
|
|
16410
|
+
}
|
|
16411
|
+
if (check.op === "greater" || check.op === "less") {
|
|
16412
|
+
var num = Number(got.value);
|
|
16413
|
+
var lim = Number(check.value);
|
|
16414
|
+
if (got.value === null || got.value === "" || typeof got.value === "boolean" || !isFinite(num) || String(check.value).trim() === "" || !isFinite(lim)) return false;
|
|
16415
|
+
return check.op === "greater" ? num > lim : num < lim;
|
|
16416
|
+
}
|
|
16183
16417
|
var text = __atcAsText(got.value);
|
|
16418
|
+
if (check.op === "matches") return __atcMatches(check.value, text);
|
|
16184
16419
|
if (check.op === "equals") return text === check.value;
|
|
16185
16420
|
if (check.op === "not_equals") return text !== check.value;
|
|
16186
16421
|
return text.indexOf(check.value) >= 0;
|
|
@@ -16604,31 +16839,32 @@ var init_definition = __esm({
|
|
|
16604
16839
|
});
|
|
16605
16840
|
|
|
16606
16841
|
// ../shared/src/chain.ts
|
|
16607
|
-
function fillText(text, vars, mode = "raw") {
|
|
16842
|
+
function fillText(text, vars, mode = "raw", builtins = true) {
|
|
16608
16843
|
fillFn ??= new Function(`${FILL_JS}
|
|
16609
16844
|
return __atcFill;`)();
|
|
16610
|
-
return fillFn(text, vars, mode);
|
|
16845
|
+
return fillFn(text, vars, mode, builtins);
|
|
16611
16846
|
}
|
|
16612
|
-
function fillDeep(value, vars) {
|
|
16613
|
-
if (typeof value === "string") return fillText(value, vars, "raw");
|
|
16614
|
-
if (Array.isArray(value)) return value.map((v) => fillDeep(v, vars));
|
|
16847
|
+
function fillDeep(value, vars, builtins) {
|
|
16848
|
+
if (typeof value === "string") return fillText(value, vars, "raw", builtins);
|
|
16849
|
+
if (Array.isArray(value)) return value.map((v) => fillDeep(v, vars, builtins));
|
|
16615
16850
|
if (value && typeof value === "object") {
|
|
16616
|
-
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, fillDeep(v, vars)]));
|
|
16851
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, fillDeep(v, vars, builtins)]));
|
|
16617
16852
|
}
|
|
16618
16853
|
return value;
|
|
16619
16854
|
}
|
|
16620
|
-
function fillLab(lab, vars) {
|
|
16621
|
-
if (!Object.keys(vars).length) return lab;
|
|
16622
|
-
const raw = (s) => fillText(s, vars, "raw");
|
|
16855
|
+
function fillLab(lab, vars, { builtins = true } = {}) {
|
|
16856
|
+
if (!Object.keys(vars).length && !builtins) return lab;
|
|
16857
|
+
const raw = (s) => fillText(s, vars, "raw", builtins);
|
|
16858
|
+
const deep = (v) => fillDeep(v, vars, builtins);
|
|
16623
16859
|
const { request: request3, auth } = lab;
|
|
16624
16860
|
const body = request3.body;
|
|
16625
|
-
const filledBody = body.mode === "json" ? { ...body, json:
|
|
16861
|
+
const filledBody = body.mode === "json" ? { ...body, json: deep(body.json) } : body.mode === "text" ? { ...body, text: raw(body.text) } : body.mode === "form" ? { ...body, fields: body.fields.map((f) => ({ key: raw(f.key), value: raw(f.value) })) } : body.mode === "raw" ? { ...body, raw: raw(body.raw) } : body;
|
|
16626
16862
|
const filledAuth = auth.mode === "bearer" ? { ...auth, token: raw(auth.token) } : auth.mode === "basic" ? { ...auth, username: raw(auth.username), password: raw(auth.password) } : auth.mode === "api_key" ? { ...auth, name: raw(auth.name), value: raw(auth.value) } : auth;
|
|
16627
16863
|
return {
|
|
16628
16864
|
...lab,
|
|
16629
16865
|
request: {
|
|
16630
16866
|
...request3,
|
|
16631
|
-
url: fillText(request3.url, vars, "url"),
|
|
16867
|
+
url: fillText(request3.url, vars, "url", builtins),
|
|
16632
16868
|
query: request3.query.map((q) => ({ key: raw(q.key), value: raw(q.value) })),
|
|
16633
16869
|
headers: request3.headers.map((h) => ({ key: h.key, value: raw(h.value) })),
|
|
16634
16870
|
body: filledBody
|
|
@@ -16680,12 +16916,58 @@ var init_chain = __esm({
|
|
|
16680
16916
|
init_checks3();
|
|
16681
16917
|
init_definition();
|
|
16682
16918
|
FILL_JS = String.raw`
|
|
16683
|
-
|
|
16919
|
+
var __ATC_FIRST = ["Alex", "Maria", "Sam", "Priya", "Omar", "Lena", "Kofi", "Yuki", "Diego", "Emma", "Noah", "Aisha", "Ivan", "Sofia", "Liam", "Mei"];
|
|
16920
|
+
var __ATC_LAST = ["Smith", "Garcia", "Kim", "Patel", "Muller", "Silva", "Nguyen", "Okafor", "Rossi", "Cohen", "Tanaka", "Novak", "Brown", "Khan", "Lopez", "Berg"];
|
|
16921
|
+
function __atcRand(n) { return Math.floor(Math.random() * n); }
|
|
16922
|
+
function __atcRandText(len, chars) {
|
|
16923
|
+
var out = "";
|
|
16924
|
+
for (var i = 0; i < len; i++) out += chars.charAt(__atcRand(chars.length));
|
|
16925
|
+
return out;
|
|
16926
|
+
}
|
|
16927
|
+
function __atcBuiltin(name, arg) {
|
|
16928
|
+
var args = arg === undefined || String(arg).trim() === "" ? [] : String(arg).split(",");
|
|
16929
|
+
for (var i = 0; i < args.length; i++) args[i] = Number(String(args[i]).trim());
|
|
16930
|
+
switch (name.slice(1).toLowerCase()) {
|
|
16931
|
+
case "uuid": case "guid": case "randomuuid":
|
|
16932
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { var r = __atcRand(16); return (c === "x" ? r : (r & 3) | 8).toString(16); });
|
|
16933
|
+
case "timestamp": return String(Math.floor(Date.now() / 1000));
|
|
16934
|
+
case "timestampms": return String(Date.now());
|
|
16935
|
+
case "isotimestamp": return new Date().toISOString();
|
|
16936
|
+
case "isodate": return new Date().toISOString().slice(0, 10);
|
|
16937
|
+
case "randomint": {
|
|
16938
|
+
var lo = args.length > 1 ? args[0] : 0;
|
|
16939
|
+
var hi = args.length > 1 ? args[1] : args.length ? args[0] : 1000;
|
|
16940
|
+
if (!isFinite(lo) || !isFinite(hi)) return undefined;
|
|
16941
|
+
var min = Math.ceil(Math.min(lo, hi)), max = Math.floor(Math.max(lo, hi));
|
|
16942
|
+
return String(min + __atcRand(max - min + 1));
|
|
16943
|
+
}
|
|
16944
|
+
case "randomstring": {
|
|
16945
|
+
var len = args.length && isFinite(args[0]) ? Math.max(1, Math.min(1000, Math.floor(args[0]))) : 8;
|
|
16946
|
+
return __atcRandText(len, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
|
16947
|
+
}
|
|
16948
|
+
case "randomemail": return "user." + __atcRandText(8, "abcdefghijklmnopqrstuvwxyz0123456789") + "@example.com";
|
|
16949
|
+
case "randomfirstname": return __ATC_FIRST[__atcRand(__ATC_FIRST.length)];
|
|
16950
|
+
case "randomlastname": return __ATC_LAST[__atcRand(__ATC_LAST.length)];
|
|
16951
|
+
case "randomfullname": return __ATC_FIRST[__atcRand(__ATC_FIRST.length)] + " " + __ATC_LAST[__atcRand(__ATC_LAST.length)];
|
|
16952
|
+
case "randomboolean": return Math.random() < 0.5 ? "true" : "false";
|
|
16953
|
+
}
|
|
16954
|
+
return undefined;
|
|
16955
|
+
}
|
|
16956
|
+
function __atcFill(text, vars, mode, builtins) {
|
|
16684
16957
|
if (typeof text !== "string") return text;
|
|
16685
|
-
return text.replace(/\{\{\s*([A-Za-z_][\w.-]*)\s*\}\}|%7B%7B([A-Za-z_][\w.-]*)
|
|
16958
|
+
return text.replace(/\{\{\s*(\$?[A-Za-z_][\w.-]*)(?:\(([^(){}]*)\))?\s*\}\}|%7B%7B(\$?[A-Za-z_][\w.-]*)(?:\(([^(){}]*)\))?%7D%7D/gi, function (whole, a, aArg, b, bArg) {
|
|
16686
16959
|
var name = a || b;
|
|
16687
|
-
|
|
16688
|
-
var v
|
|
16960
|
+
var arg = a ? aArg : bArg;
|
|
16961
|
+
var v;
|
|
16962
|
+
if (name.charAt(0) === "$") {
|
|
16963
|
+
if (builtins === false) return whole;
|
|
16964
|
+
if (b && arg !== undefined) { try { arg = decodeURIComponent(arg); } catch (e) {} }
|
|
16965
|
+
v = __atcBuiltin(name, arg);
|
|
16966
|
+
if (v === undefined) return whole;
|
|
16967
|
+
} else {
|
|
16968
|
+
if (arg !== undefined || !Object.prototype.hasOwnProperty.call(vars, name)) return whole;
|
|
16969
|
+
v = String(vars[name]);
|
|
16970
|
+
}
|
|
16689
16971
|
if (mode === "url") return encodeURIComponent(v);
|
|
16690
16972
|
if (mode === "json") return JSON.stringify(v).slice(1, -1);
|
|
16691
16973
|
return v;
|
|
@@ -16697,6 +16979,32 @@ function __atcFill(text, vars, mode) {
|
|
|
16697
16979
|
}
|
|
16698
16980
|
});
|
|
16699
16981
|
|
|
16982
|
+
// ../shared/src/codegen.ts
|
|
16983
|
+
function parseSetCookie(header) {
|
|
16984
|
+
const [pair, ...attrs] = header.split(";");
|
|
16985
|
+
const eq = pair?.indexOf("=") ?? -1;
|
|
16986
|
+
if (!pair || eq <= 0) return null;
|
|
16987
|
+
const cookie = { name: pair.slice(0, eq).trim(), value: pair.slice(eq + 1).trim(), httpOnly: false, secure: false };
|
|
16988
|
+
for (const attr of attrs) {
|
|
16989
|
+
const i = attr.indexOf("=");
|
|
16990
|
+
const key = (i < 0 ? attr : attr.slice(0, i)).trim().toLowerCase();
|
|
16991
|
+
const value = i < 0 ? "" : attr.slice(i + 1).trim();
|
|
16992
|
+
if (key === "domain") cookie.domain = value;
|
|
16993
|
+
else if (key === "path") cookie.path = value;
|
|
16994
|
+
else if (key === "expires") cookie.expires = value;
|
|
16995
|
+
else if (key === "max-age" && /^-?\d+$/.test(value)) cookie.maxAge = Number(value);
|
|
16996
|
+
else if (key === "httponly") cookie.httpOnly = true;
|
|
16997
|
+
else if (key === "secure") cookie.secure = true;
|
|
16998
|
+
else if (key === "samesite") cookie.sameSite = value;
|
|
16999
|
+
}
|
|
17000
|
+
return cookie;
|
|
17001
|
+
}
|
|
17002
|
+
var init_codegen = __esm({
|
|
17003
|
+
"../shared/src/codegen.ts"() {
|
|
17004
|
+
"use strict";
|
|
17005
|
+
}
|
|
17006
|
+
});
|
|
17007
|
+
|
|
16700
17008
|
// ../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js
|
|
16701
17009
|
var require_identity = __commonJS({
|
|
16702
17010
|
"../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js"(exports) {
|
|
@@ -24120,7 +24428,9 @@ function defaultRequestDraft() {
|
|
|
24120
24428
|
maxRedirects: 5,
|
|
24121
24429
|
connectionReuse: true,
|
|
24122
24430
|
useCookies: true,
|
|
24123
|
-
|
|
24431
|
+
// On for new requests, so test servers with their own certificates just work. Saved requests
|
|
24432
|
+
// keep what they have; one saved without the setting checks certificates (as before).
|
|
24433
|
+
tlsSkip: true,
|
|
24124
24434
|
checks: [],
|
|
24125
24435
|
before: null,
|
|
24126
24436
|
testData: null,
|
|
@@ -24307,6 +24617,8 @@ function requestParts(draft) {
|
|
|
24307
24617
|
} catch (err) {
|
|
24308
24618
|
const bare = draftRuntimeNames(draft).find((n) => new RegExp(`(^|[^"])\\{\\{\\s*${n.replace(/[.-]/g, "\\$&")}\\s*\\}\\}(?!")`).test(draft.bodyText));
|
|
24309
24619
|
if (bare) throw new Error(`Put quotes around {{${bare}}} in the JSON body \u2014 values from test data and run-first steps are filled in as text`);
|
|
24620
|
+
const builtin = /(^|[^"])\{\{\s*(\$[A-Za-z]+)/.exec(draft.bodyText)?.[2];
|
|
24621
|
+
if (builtin) throw new Error(`Put quotes around {{${builtin}}} in the JSON body \u2014 built-in values are filled in as text`);
|
|
24310
24622
|
throw new Error(`Body is not valid JSON: ${err instanceof Error ? err.message : "parse error"}`);
|
|
24311
24623
|
}
|
|
24312
24624
|
} else if (hasBody(draft.method) && draft.bodyMode === "graphql") {
|
|
@@ -24348,12 +24660,21 @@ function requestParts(draft) {
|
|
|
24348
24660
|
}
|
|
24349
24661
|
};
|
|
24350
24662
|
}
|
|
24663
|
+
function isJsonObject(text) {
|
|
24664
|
+
try {
|
|
24665
|
+
const v = JSON.parse(text);
|
|
24666
|
+
return Boolean(v) && typeof v === "object" && !Array.isArray(v);
|
|
24667
|
+
} catch {
|
|
24668
|
+
return false;
|
|
24669
|
+
}
|
|
24670
|
+
}
|
|
24351
24671
|
function usableChecks(checks) {
|
|
24352
24672
|
return checks.filter((c) => {
|
|
24353
24673
|
if (c.type === "status") return c.expect.trim().length > 0;
|
|
24354
|
-
if (c.type === "body") return c.value.length > 0;
|
|
24674
|
+
if (c.type === "body") return c.op === "is_json" || c.value.length > 0;
|
|
24355
24675
|
if (c.type === "json") return c.path.trim().length > 0;
|
|
24356
24676
|
if (c.type === "header") return c.name.trim().length > 0;
|
|
24677
|
+
if (c.type === "schema") return isJsonObject(c.schema);
|
|
24357
24678
|
return c.maxMs > 0;
|
|
24358
24679
|
});
|
|
24359
24680
|
}
|
|
@@ -24630,10 +24951,10 @@ function sustainedFrom(buckets) {
|
|
|
24630
24951
|
function percentileFromHist(hist, p) {
|
|
24631
24952
|
const total = hist.reduce((a, n) => a + n, 0);
|
|
24632
24953
|
if (!total) return null;
|
|
24633
|
-
let
|
|
24954
|
+
let seen2 = 0;
|
|
24634
24955
|
for (let i = 0; i < hist.length; i++) {
|
|
24635
|
-
|
|
24636
|
-
if (
|
|
24956
|
+
seen2 += hist[i];
|
|
24957
|
+
if (seen2 / total >= p) {
|
|
24637
24958
|
const edge = LATENCY_BIN_EDGES_MS[i];
|
|
24638
24959
|
return Number.isFinite(edge) ? edge : LATENCY_BIN_EDGES_MS[LATENCY_BIN_EDGES_MS.length - 2];
|
|
24639
24960
|
}
|
|
@@ -25163,7 +25484,7 @@ function stepOutcome(r) {
|
|
|
25163
25484
|
if (!failed.length) return { state: "passed" };
|
|
25164
25485
|
return {
|
|
25165
25486
|
state: "failed",
|
|
25166
|
-
message: `${failed.length} of ${r.checks.length} check${r.checks.length === 1 ? "" : "s"} failed: ${failed.map((c) => c.name).join("; ")}`
|
|
25487
|
+
message: `${failed.length} of ${r.checks.length} check${r.checks.length === 1 ? "" : "s"} failed: ${failed.map((c) => c.detail ? `${c.name} (${c.detail})` : c.name).join("; ")}`
|
|
25167
25488
|
};
|
|
25168
25489
|
}
|
|
25169
25490
|
if (r.status >= 200 && r.status < 400) return { state: "passed" };
|
|
@@ -25186,16 +25507,16 @@ function suitePassed(run2) {
|
|
|
25186
25507
|
}
|
|
25187
25508
|
function orderSuite(items, plan) {
|
|
25188
25509
|
const byId = new Map(items.map((i) => [i.id, i]));
|
|
25189
|
-
const
|
|
25510
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
25190
25511
|
const out = [];
|
|
25191
25512
|
for (const id of plan?.order ?? []) {
|
|
25192
25513
|
const item = byId.get(id);
|
|
25193
|
-
if (item && !
|
|
25514
|
+
if (item && !seen2.has(id)) {
|
|
25194
25515
|
out.push(item);
|
|
25195
|
-
|
|
25516
|
+
seen2.add(id);
|
|
25196
25517
|
}
|
|
25197
25518
|
}
|
|
25198
|
-
for (const item of items) if (!
|
|
25519
|
+
for (const item of items) if (!seen2.has(item.id)) out.push(item);
|
|
25199
25520
|
const skip = new Set(plan?.skip ?? []);
|
|
25200
25521
|
return out.map((item) => ({ item, skipped: skip.has(item.id) }));
|
|
25201
25522
|
}
|
|
@@ -26660,6 +26981,7 @@ var init_src = __esm({
|
|
|
26660
26981
|
init_dashboard();
|
|
26661
26982
|
init_workspace();
|
|
26662
26983
|
init_chain();
|
|
26984
|
+
init_codegen();
|
|
26663
26985
|
init_import();
|
|
26664
26986
|
init_email_report();
|
|
26665
26987
|
init_junit();
|
|
@@ -26772,7 +27094,7 @@ token, password, or key.
|
|
|
26772
27094
|
async scan() {
|
|
26773
27095
|
await this.ensure();
|
|
26774
27096
|
let changed = false;
|
|
26775
|
-
const
|
|
27097
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
26776
27098
|
for (const folder of ["runs", "compares"]) {
|
|
26777
27099
|
let names = [];
|
|
26778
27100
|
try {
|
|
@@ -26782,7 +27104,7 @@ token, password, or key.
|
|
|
26782
27104
|
}
|
|
26783
27105
|
for (const name of names) {
|
|
26784
27106
|
const key = `${folder}/${name}`;
|
|
26785
|
-
|
|
27107
|
+
seen2.add(key);
|
|
26786
27108
|
let info;
|
|
26787
27109
|
try {
|
|
26788
27110
|
info = await stat(join(this.folder(folder), name));
|
|
@@ -26796,7 +27118,7 @@ token, password, or key.
|
|
|
26796
27118
|
}
|
|
26797
27119
|
}
|
|
26798
27120
|
for (const key of [...this.entries.keys()]) {
|
|
26799
|
-
if (!
|
|
27121
|
+
if (!seen2.has(key)) {
|
|
26800
27122
|
this.entries.delete(key);
|
|
26801
27123
|
changed = true;
|
|
26802
27124
|
}
|
|
@@ -27183,6 +27505,11 @@ function generateK6Script(run2, extra2 = {}) {
|
|
|
27183
27505
|
ATC_NAME: run2.name,
|
|
27184
27506
|
ATC_CHECKS: JSON.stringify(run2.request.checks.map((check2) => ({ label: checkLabel(check2), check: check2 })))
|
|
27185
27507
|
};
|
|
27508
|
+
if (run2.request.checks.some((c) => c.type === "schema")) {
|
|
27509
|
+
files["checks.json"] = env.ATC_CHECKS;
|
|
27510
|
+
env.ATC_CHECKS = "";
|
|
27511
|
+
env.ATC_CHECKS_FILE = "1";
|
|
27512
|
+
}
|
|
27186
27513
|
if (extra2.tlsAuth?.length) env.ATC_TLS_AUTH = JSON.stringify(extra2.tlsAuth);
|
|
27187
27514
|
if (extra2.jwt) {
|
|
27188
27515
|
const { tokens, ...rest } = extra2.jwt;
|
|
@@ -27213,15 +27540,14 @@ function generateK6Script(run2, extra2 = {}) {
|
|
|
27213
27540
|
env.ATC_AUTH_USER = run2.auth.mode === "ntlm" && run2.auth.domain ? `${run2.auth.domain}\\${run2.auth.username}` : run2.auth.username;
|
|
27214
27541
|
env.ATC_AUTH_PASS = run2.auth.password;
|
|
27215
27542
|
}
|
|
27543
|
+
const bodyMode = run2.request.body.mode;
|
|
27544
|
+
env.ATC_BODY_FILL = bodyMode === "json" ? "json" : bodyMode === "form" ? "url" : "raw";
|
|
27216
27545
|
if (data) {
|
|
27217
27546
|
files["data.json"] = JSON.stringify(data.rows);
|
|
27218
27547
|
env.ATC_DATA_COLUMNS = JSON.stringify(data.columns);
|
|
27219
27548
|
env.ATC_DATA_ORDER = data.order;
|
|
27220
|
-
const mode = run2.request.body.mode;
|
|
27221
|
-
env.ATC_BODY_FILL = mode === "json" ? "json" : mode === "form" ? "url" : "raw";
|
|
27222
27549
|
}
|
|
27223
27550
|
const dataBlock = data ? `
|
|
27224
|
-
${FILL_JS}
|
|
27225
27551
|
const ROWS = new SharedArray("rows", function () { return JSON.parse(open("./data.json")); });
|
|
27226
27552
|
const COLUMNS = JSON.parse(__ENV.ATC_DATA_COLUMNS);
|
|
27227
27553
|
function __atcRow() {
|
|
@@ -27245,12 +27571,12 @@ import { SharedArray } from "k6/data";
|
|
|
27245
27571
|
export const options = Object.assign(${optionsBlock(run2)}, __ENV.ATC_TLS_AUTH ? { tlsAuth: JSON.parse(__ENV.ATC_TLS_AUTH) } : {});
|
|
27246
27572
|
|
|
27247
27573
|
${CHECK_EVALUATOR_JS}
|
|
27248
|
-
${dataBlock}${run2.auth.mode === "aws_sigv4" ? `
|
|
27574
|
+
${FILL_JS}${dataBlock}${run2.auth.mode === "aws_sigv4" ? `
|
|
27249
27575
|
const AWS = JSON.parse(__ENV.ATC_AWS);
|
|
27250
27576
|
${SIGV4_JS}` : ""}${run2.auth.mode === "oauth1" ? `
|
|
27251
27577
|
const OAUTH1 = JSON.parse(__ENV.ATC_OAUTH1);
|
|
27252
27578
|
${OAUTH1_JS}` : ""}
|
|
27253
|
-
const CHECKS = JSON.parse(__ENV.ATC_CHECKS || "[]");
|
|
27579
|
+
const CHECKS = __ENV.ATC_CHECKS_FILE ? JSON.parse(open("./checks.json")) : JSON.parse(__ENV.ATC_CHECKS || "[]");
|
|
27254
27580
|
// JWT: tokens signed by the app for the whole run; each is used for its stretch of time.
|
|
27255
27581
|
const JWT = __ENV.ATC_JWT ? JSON.parse(__ENV.ATC_JWT) : null;
|
|
27256
27582
|
const JWTS = JWT ? JSON.parse(open("./jwt.json")) : [];
|
|
@@ -27278,7 +27604,9 @@ function __atcFreshToken() {
|
|
|
27278
27604
|
}
|
|
27279
27605
|
|
|
27280
27606
|
export default function () {
|
|
27281
|
-
|
|
27607
|
+
// Test-data values, and built-in values ({{$uuid}}, \u2026) made anew for every request.
|
|
27608
|
+
const vars = ${data ? "__atcRow()" : "{}"};
|
|
27609
|
+
const f = function (text, mode) { return __atcFill(text, vars, mode || "raw"); };
|
|
27282
27610
|
const headers = JSON.parse(__ENV.ATC_HEADERS || "{}");
|
|
27283
27611
|
for (const key in headers) headers[key] = f(headers[key]);
|
|
27284
27612
|
if (__ENV.ATC_COOKIE) headers.Cookie = __ENV.ATC_COOKIE;
|
|
@@ -45374,13 +45702,13 @@ function toPem(m) {
|
|
|
45374
45702
|
}
|
|
45375
45703
|
async function k6TlsAuth(urls) {
|
|
45376
45704
|
const out = [];
|
|
45377
|
-
const
|
|
45705
|
+
const seen2 = /* @__PURE__ */ new Set();
|
|
45378
45706
|
for (const target of urls) {
|
|
45379
45707
|
const m = await certificateFor(target);
|
|
45380
45708
|
if (!m) continue;
|
|
45381
45709
|
const domain2 = new URL(target).hostname;
|
|
45382
|
-
if (
|
|
45383
|
-
|
|
45710
|
+
if (seen2.has(domain2)) continue;
|
|
45711
|
+
seen2.add(domain2);
|
|
45384
45712
|
const pem = toPem(m);
|
|
45385
45713
|
out.push({ domains: [domain2], cert: pem.cert, key: pem.key, ...pem.password ? { password: pem.password } : {} });
|
|
45386
45714
|
}
|
|
@@ -45485,7 +45813,7 @@ function defaultPath(url2) {
|
|
|
45485
45813
|
if (!p.startsWith("/") || p.lastIndexOf("/") === 0) return "/";
|
|
45486
45814
|
return p.slice(0, p.lastIndexOf("/"));
|
|
45487
45815
|
}
|
|
45488
|
-
function
|
|
45816
|
+
function parseSetCookie2(header, url2, now = Date.now()) {
|
|
45489
45817
|
const [pair, ...attrs] = header.split(";");
|
|
45490
45818
|
const eq = pair.indexOf("=");
|
|
45491
45819
|
if (eq <= 0) return null;
|
|
@@ -45536,7 +45864,7 @@ async function storeCookies(target, setCookie) {
|
|
|
45536
45864
|
const now = Date.now();
|
|
45537
45865
|
let next = [...await load()];
|
|
45538
45866
|
for (const header of Array.isArray(setCookie) ? setCookie : [setCookie]) {
|
|
45539
|
-
const c =
|
|
45867
|
+
const c = parseSetCookie2(header, url2, now);
|
|
45540
45868
|
if (!c) continue;
|
|
45541
45869
|
next = next.filter((o) => !(o.name === c.name && o.domain === c.domain && o.path === c.path));
|
|
45542
45870
|
if (c.expires === null || c.expires > now) next.push(c);
|
|
@@ -69245,7 +69573,7 @@ var require_parse = __commonJS({
|
|
|
69245
69573
|
var { maxNameValuePairSize, maxAttributeValueSize } = require_constants4();
|
|
69246
69574
|
var { isCTLExcludingHtab } = require_util5();
|
|
69247
69575
|
var assert2 = __require("node:assert");
|
|
69248
|
-
function
|
|
69576
|
+
function parseSetCookie3(header) {
|
|
69249
69577
|
if (isCTLExcludingHtab(header)) {
|
|
69250
69578
|
return null;
|
|
69251
69579
|
}
|
|
@@ -69369,7 +69697,7 @@ var require_parse = __commonJS({
|
|
|
69369
69697
|
return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList);
|
|
69370
69698
|
}
|
|
69371
69699
|
module.exports = {
|
|
69372
|
-
parseSetCookie:
|
|
69700
|
+
parseSetCookie: parseSetCookie3,
|
|
69373
69701
|
parseUnparsedAttributes
|
|
69374
69702
|
};
|
|
69375
69703
|
}
|
|
@@ -69379,7 +69707,7 @@ var require_parse = __commonJS({
|
|
|
69379
69707
|
var require_cookies = __commonJS({
|
|
69380
69708
|
"../../node_modules/.pnpm/undici@8.10.0/node_modules/undici/lib/web/cookies/index.js"(exports, module) {
|
|
69381
69709
|
"use strict";
|
|
69382
|
-
var { parseSetCookie:
|
|
69710
|
+
var { parseSetCookie: parseSetCookie3 } = require_parse();
|
|
69383
69711
|
var { stringify } = require_util5();
|
|
69384
69712
|
var { webidl } = require_webidl();
|
|
69385
69713
|
var { Headers } = require_headers();
|
|
@@ -69418,11 +69746,11 @@ var require_cookies = __commonJS({
|
|
|
69418
69746
|
if (!cookies) {
|
|
69419
69747
|
return [];
|
|
69420
69748
|
}
|
|
69421
|
-
return cookies.map((pair) =>
|
|
69749
|
+
return cookies.map((pair) => parseSetCookie3(pair));
|
|
69422
69750
|
}
|
|
69423
69751
|
function parseCookie(cookie) {
|
|
69424
69752
|
cookie = webidl.converters.DOMString(cookie);
|
|
69425
|
-
return
|
|
69753
|
+
return parseSetCookie3(cookie);
|
|
69426
69754
|
}
|
|
69427
69755
|
function setCookie(headers, cookie) {
|
|
69428
69756
|
webidl.argumentLengthCheck(arguments, 2, "setCookie");
|
|
@@ -73150,7 +73478,7 @@ function parseLab(input) {
|
|
|
73150
73478
|
return labRequestSchema.parse(input);
|
|
73151
73479
|
}
|
|
73152
73480
|
async function runSetupStep(setup) {
|
|
73153
|
-
const sent = await sendOnce(setup);
|
|
73481
|
+
const sent = await sendOnce(fillLab(setup, {}));
|
|
73154
73482
|
const vars = {};
|
|
73155
73483
|
const values = [];
|
|
73156
73484
|
let problem = sent.result.error ? `could not reach it: ${sent.result.error}` : void 0;
|
|
@@ -73219,6 +73547,12 @@ function takeValues(rules, sent) {
|
|
|
73219
73547
|
});
|
|
73220
73548
|
}
|
|
73221
73549
|
async function sendOnce(lab) {
|
|
73550
|
+
const out = await sendOnceAuthed(lab);
|
|
73551
|
+
const note = AUTH_NOTES[lab.auth.mode];
|
|
73552
|
+
if (note && out.result.sent) out.result.sent.authNote = note;
|
|
73553
|
+
return out;
|
|
73554
|
+
}
|
|
73555
|
+
async function sendOnceAuthed(lab) {
|
|
73222
73556
|
if (lab.auth.mode === "digest" || lab.auth.mode === "ntlm") return sendChallenged(lab, lab.auth);
|
|
73223
73557
|
if (lab.auth.mode === "jwt") {
|
|
73224
73558
|
const { mode: _mode, ...config3 } = lab.auth;
|
|
@@ -73296,6 +73630,7 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73296
73630
|
headers[pair.key] = pair.value;
|
|
73297
73631
|
}
|
|
73298
73632
|
const secretNames = applyAuth(headers, url2, lab.auth);
|
|
73633
|
+
const secretQuery = lab.auth.mode === "api_key" && lab.auth.in === "query" ? [lab.auth.name] : [];
|
|
73299
73634
|
if (extra2.authorization) {
|
|
73300
73635
|
headers.authorization = extra2.authorization;
|
|
73301
73636
|
secretNames.push("authorization");
|
|
@@ -73312,7 +73647,10 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73312
73647
|
if (signed.authorization) {
|
|
73313
73648
|
headers.authorization = signed.authorization;
|
|
73314
73649
|
secretNames.push("authorization");
|
|
73315
|
-
} else
|
|
73650
|
+
} else {
|
|
73651
|
+
target = new URL(signed.url);
|
|
73652
|
+
secretQuery.push("oauth_signature", "oauth_token");
|
|
73653
|
+
}
|
|
73316
73654
|
}
|
|
73317
73655
|
if (lab.auth.mode === "aws_sigv4") {
|
|
73318
73656
|
const { mode: _mode, ...creds } = lab.auth;
|
|
@@ -73326,6 +73664,8 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73326
73664
|
const agent = extra2.dispatcher ?? new import_undici2.Agent({ connect: await tlsConnect(url2, options.tlsSkipVerify) });
|
|
73327
73665
|
const dispatcher = extra2.dispatcher ?? (useJar ? agent : agent.compose(import_undici2.interceptors.redirect({ maxRedirections: options.maxRedirects })));
|
|
73328
73666
|
const started = performance.now();
|
|
73667
|
+
let sent;
|
|
73668
|
+
const cookies = [];
|
|
73329
73669
|
try {
|
|
73330
73670
|
let current = target;
|
|
73331
73671
|
let method = lab.request.method;
|
|
@@ -73337,9 +73677,16 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73337
73677
|
const jar2 = await cookieHeader(current);
|
|
73338
73678
|
if (jar2) sendHeaders.cookie = jar2;
|
|
73339
73679
|
}
|
|
73680
|
+
if (!sent) sent = describeSent(method, current, sendHeaders, body, [...secretNames, ...ALWAYS_SECRET], secretQuery, options.tlsSkipVerify);
|
|
73681
|
+
else (sent.redirects ??= []).push(`${method} ${current.toString()}`);
|
|
73340
73682
|
response = await (0, import_undici2.request)(current, { method, headers: sendHeaders, body, headersTimeout: timeout, bodyTimeout: timeout, dispatcher });
|
|
73683
|
+
const setCookie = response.headers["set-cookie"];
|
|
73684
|
+
for (const line of typeof setCookie === "string" ? [setCookie] : setCookie ?? []) {
|
|
73685
|
+
const parsed = parseSetCookie(line);
|
|
73686
|
+
if (parsed) cookies.push(parsed);
|
|
73687
|
+
}
|
|
73341
73688
|
if (!useJar) break;
|
|
73342
|
-
await storeCookies(current,
|
|
73689
|
+
await storeCookies(current, setCookie);
|
|
73343
73690
|
const location = response.headers.location;
|
|
73344
73691
|
if (![301, 302, 303, 307, 308].includes(response.statusCode) || typeof location !== "string" || hops >= options.maxRedirects) break;
|
|
73345
73692
|
await response.body.dump();
|
|
@@ -73354,8 +73701,11 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73354
73701
|
}
|
|
73355
73702
|
current = next;
|
|
73356
73703
|
}
|
|
73357
|
-
const
|
|
73704
|
+
const bytes2 = Buffer.from(await response.body.arrayBuffer());
|
|
73705
|
+
const raw = bytes2.toString("utf8");
|
|
73358
73706
|
const durationMs = Math.round((performance.now() - started) * 10) / 10;
|
|
73707
|
+
const responseType = String(response.headers["content-type"] ?? "").toLowerCase();
|
|
73708
|
+
const bodyBase64 = /^image\/(png|jpe?g|gif|webp|bmp|svg\+xml|x-icon|vnd\.microsoft\.icon|avif)/.test(responseType) && bytes2.length <= IMAGE_LIMIT ? bytes2.toString("base64") : void 0;
|
|
73359
73709
|
const truncated = raw.length > BODY_LIMIT;
|
|
73360
73710
|
const headerBag = {};
|
|
73361
73711
|
for (const [key, value] of Object.entries(response.headers)) {
|
|
@@ -73376,7 +73726,10 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73376
73726
|
truncated,
|
|
73377
73727
|
durationMs,
|
|
73378
73728
|
url: url2.toString(),
|
|
73379
|
-
checks
|
|
73729
|
+
checks,
|
|
73730
|
+
sent,
|
|
73731
|
+
...cookies.length ? { cookies } : {},
|
|
73732
|
+
...bodyBase64 ? { bodyBase64 } : {}
|
|
73380
73733
|
}
|
|
73381
73734
|
};
|
|
73382
73735
|
} catch (err) {
|
|
@@ -73393,14 +73746,29 @@ async function sendRaw(lab, extra2 = {}) {
|
|
|
73393
73746
|
truncated: false,
|
|
73394
73747
|
durationMs,
|
|
73395
73748
|
url: url2.toString(),
|
|
73396
|
-
error: err instanceof Error ? err.message : String(err)
|
|
73749
|
+
error: err instanceof Error ? err.message : String(err),
|
|
73750
|
+
sent
|
|
73397
73751
|
}
|
|
73398
73752
|
};
|
|
73399
73753
|
} finally {
|
|
73400
73754
|
if (!extra2.dispatcher) await dispatcher.close();
|
|
73401
73755
|
}
|
|
73402
73756
|
}
|
|
73403
|
-
|
|
73757
|
+
function describeSent(method, url2, headers, body, secretHeaders, secretQuery, insecure) {
|
|
73758
|
+
const list = [["host", url2.host], ...Object.entries(headers)];
|
|
73759
|
+
if (body !== void 0) list.push(["content-length", String(Buffer.byteLength(body))]);
|
|
73760
|
+
return {
|
|
73761
|
+
method,
|
|
73762
|
+
url: url2.toString(),
|
|
73763
|
+
headers: list,
|
|
73764
|
+
...body !== void 0 ? { body: body.length > BODY_LIMIT ? body.slice(0, BODY_LIMIT) : body, bodyTruncated: body.length > BODY_LIMIT || void 0 } : {},
|
|
73765
|
+
secretHeaders: [...new Set(secretHeaders.map((h) => h.toLowerCase()))],
|
|
73766
|
+
secretQuery,
|
|
73767
|
+
// Only https has a certificate to skip.
|
|
73768
|
+
insecure: insecure && url2.protocol === "https:" || void 0
|
|
73769
|
+
};
|
|
73770
|
+
}
|
|
73771
|
+
var import_undici2, BODY_LIMIT, IMAGE_LIMIT, ALWAYS_SECRET, AUTH_NOTES;
|
|
73404
73772
|
var init_probe = __esm({
|
|
73405
73773
|
"../../apps/engine/src/probe.ts"() {
|
|
73406
73774
|
"use strict";
|
|
@@ -73414,6 +73782,16 @@ var init_probe = __esm({
|
|
|
73414
73782
|
init_cookies();
|
|
73415
73783
|
init_oauth();
|
|
73416
73784
|
BODY_LIMIT = 64 * 1024;
|
|
73785
|
+
IMAGE_LIMIT = 5 * 1024 * 1024;
|
|
73786
|
+
ALWAYS_SECRET = ["authorization", "proxy-authorization", "cookie", "x-api-key", "api-key", "x-amz-security-token"];
|
|
73787
|
+
AUTH_NOTES = {
|
|
73788
|
+
oauth2: "OAuth 2.0 \u2014 the app got the token and sent it as a Bearer token",
|
|
73789
|
+
oauth1: "OAuth 1.0 \u2014 signed for this one request (nonce and timestamp)",
|
|
73790
|
+
aws_sigv4: "AWS Signature \u2014 signed for this one request",
|
|
73791
|
+
jwt: "JWT \u2014 signed by the app for this request",
|
|
73792
|
+
digest: "Digest \u2014 answers the server's 401 challenge; this is the second request",
|
|
73793
|
+
ntlm: "NTLM \u2014 signs in over one connection; this is the last of three requests"
|
|
73794
|
+
};
|
|
73417
73795
|
}
|
|
73418
73796
|
});
|
|
73419
73797
|
|
|
@@ -73454,10 +73832,10 @@ var init_latency_histogram = __esm({
|
|
|
73454
73832
|
percentile(p) {
|
|
73455
73833
|
if (this.count === 0) return 0;
|
|
73456
73834
|
const rank = Math.ceil(p / 100 * this.count);
|
|
73457
|
-
let
|
|
73835
|
+
let seen2 = 0;
|
|
73458
73836
|
for (const bin of [...this.bins.keys()].sort((a, b) => a - b)) {
|
|
73459
|
-
|
|
73460
|
-
if (
|
|
73837
|
+
seen2 += this.bins.get(bin);
|
|
73838
|
+
if (seen2 >= rank) {
|
|
73461
73839
|
const mid = FLOOR_MS * Math.exp((bin + 0.5) * GROWTH);
|
|
73462
73840
|
return Math.min(this.max, Math.max(this.min, mid));
|
|
73463
73841
|
}
|
|
@@ -73968,7 +74346,7 @@ async function startRun(lab, repoRoot2) {
|
|
|
73968
74346
|
err.statusCode = 422;
|
|
73969
74347
|
throw err;
|
|
73970
74348
|
}
|
|
73971
|
-
filled = fillLab(lab, step.vars);
|
|
74349
|
+
filled = fillLab(lab, step.vars, { builtins: false });
|
|
73972
74350
|
}
|
|
73973
74351
|
const id = crypto.randomUUID();
|
|
73974
74352
|
const dir2 = await mkdtemp(join5(tmpdir2(), "atc-run-"));
|
|
@@ -74318,7 +74696,7 @@ function explainMissing(message, index, savers, steps) {
|
|
|
74318
74696
|
});
|
|
74319
74697
|
return hints.length ? hints.join("; ") : message;
|
|
74320
74698
|
}
|
|
74321
|
-
async function runStep(step, workspace, vars, envName, setups,
|
|
74699
|
+
async function runStep(step, workspace, vars, envName, setups, explain2 = (m) => m) {
|
|
74322
74700
|
const saved = await workspace.getRequest(step.id);
|
|
74323
74701
|
if (!saved) throw new StepProblem("This request is no longer saved");
|
|
74324
74702
|
if (saved.secretsMissing?.length) {
|
|
@@ -74328,7 +74706,7 @@ async function runStep(step, workspace, vars, envName, setups, explain = (m) =>
|
|
|
74328
74706
|
try {
|
|
74329
74707
|
draft = await resolveSaved(workspace, saved, vars, envName);
|
|
74330
74708
|
} catch (err) {
|
|
74331
|
-
throw new StepProblem(
|
|
74709
|
+
throw new StepProblem(explain2(err instanceof Error ? err.message.replace(/ — pick one next to the URL$/, " \u2014 pick an environment for this run") : String(err)));
|
|
74332
74710
|
}
|
|
74333
74711
|
const payload = buildPayload(draft, toLoadConfig(DEFAULT_LOAD), saved.name);
|
|
74334
74712
|
let runtime = {};
|
|
@@ -74354,23 +74732,23 @@ async function runStep(step, workspace, vars, envName, setups, explain = (m) =>
|
|
|
74354
74732
|
runtime = done.vars;
|
|
74355
74733
|
}
|
|
74356
74734
|
if (payload.data) runtime = { ...runtime, ...firstRowVars(payload.data) };
|
|
74357
|
-
const
|
|
74358
|
-
const outcome = stepOutcome(
|
|
74735
|
+
const probe2 = await runProbe({ ...fillLab({ request: payload.request, auth: payload.auth, options: payload.options }, runtime), save: payload.save });
|
|
74736
|
+
const outcome = stepOutcome(probe2);
|
|
74359
74737
|
step.state = outcome.state;
|
|
74360
74738
|
step.message = outcome.message;
|
|
74361
|
-
if (
|
|
74362
|
-
step.saved =
|
|
74363
|
-
for (const v of
|
|
74364
|
-
const missing =
|
|
74739
|
+
if (probe2.saved?.length) {
|
|
74740
|
+
step.saved = probe2.saved.map((v) => ({ name: v.name, found: v.found, preview: v.preview }));
|
|
74741
|
+
for (const v of probe2.saved) if (v.found && v.value !== void 0) vars[v.name] = v.value;
|
|
74742
|
+
const missing = probe2.saved.filter((v) => !v.found);
|
|
74365
74743
|
if (missing.length && step.state === "passed") {
|
|
74366
74744
|
step.state = "failed";
|
|
74367
74745
|
step.message = missing.map((v) => `{{${v.name}}} was not found in the answer (looked for ${v.from})`).join("; ");
|
|
74368
74746
|
}
|
|
74369
74747
|
}
|
|
74370
|
-
step.status =
|
|
74371
|
-
step.durationMs =
|
|
74372
|
-
step.checks =
|
|
74373
|
-
if (outcome.state !== "passed" &&
|
|
74748
|
+
step.status = probe2.status || void 0;
|
|
74749
|
+
step.durationMs = probe2.durationMs;
|
|
74750
|
+
step.checks = probe2.checks;
|
|
74751
|
+
if (outcome.state !== "passed" && probe2.body) step.bodyPreview = probe2.body.slice(0, BODY_PREVIEW_CHARS);
|
|
74374
74752
|
}
|
|
74375
74753
|
function registerSuiteRoutes(api, workspace, plans, builtins) {
|
|
74376
74754
|
api.get("/suites/plan", async (request3) => {
|
|
@@ -81457,32 +81835,32 @@ var require_err_helpers = __commonJS({
|
|
|
81457
81835
|
return isErrorLike(cause) ? cause : void 0;
|
|
81458
81836
|
}
|
|
81459
81837
|
};
|
|
81460
|
-
var _stackWithCauses = (err,
|
|
81838
|
+
var _stackWithCauses = (err, seen2) => {
|
|
81461
81839
|
if (!isErrorLike(err)) return "";
|
|
81462
81840
|
const stack = err.stack || "";
|
|
81463
|
-
if (
|
|
81841
|
+
if (seen2.has(err)) {
|
|
81464
81842
|
return stack + "\ncauses have become circular...";
|
|
81465
81843
|
}
|
|
81466
81844
|
const cause = getErrorCause(err);
|
|
81467
81845
|
if (cause) {
|
|
81468
|
-
|
|
81469
|
-
return stack + "\ncaused by: " + _stackWithCauses(cause,
|
|
81846
|
+
seen2.add(err);
|
|
81847
|
+
return stack + "\ncaused by: " + _stackWithCauses(cause, seen2);
|
|
81470
81848
|
} else {
|
|
81471
81849
|
return stack;
|
|
81472
81850
|
}
|
|
81473
81851
|
};
|
|
81474
81852
|
var stackWithCauses = (err) => _stackWithCauses(err, /* @__PURE__ */ new Set());
|
|
81475
|
-
var _messageWithCauses = (err,
|
|
81853
|
+
var _messageWithCauses = (err, seen2, skip) => {
|
|
81476
81854
|
if (!isErrorLike(err)) return "";
|
|
81477
81855
|
const message = skip ? "" : err.message || "";
|
|
81478
|
-
if (
|
|
81856
|
+
if (seen2.has(err)) {
|
|
81479
81857
|
return message + ": ...";
|
|
81480
81858
|
}
|
|
81481
81859
|
const cause = getErrorCause(err);
|
|
81482
81860
|
if (cause) {
|
|
81483
|
-
|
|
81861
|
+
seen2.add(err);
|
|
81484
81862
|
const skipIfVErrorStyleCause = typeof err.cause === "function";
|
|
81485
|
-
return message + (skipIfVErrorStyleCause ? "" : ": ") + _messageWithCauses(cause,
|
|
81863
|
+
return message + (skipIfVErrorStyleCause ? "" : ": ") + _messageWithCauses(cause, seen2, skipIfVErrorStyleCause);
|
|
81486
81864
|
} else {
|
|
81487
81865
|
return message;
|
|
81488
81866
|
}
|
|
@@ -81501,7 +81879,7 @@ var require_err_helpers = __commonJS({
|
|
|
81501
81879
|
var require_err_proto = __commonJS({
|
|
81502
81880
|
"../../node_modules/.pnpm/pino-std-serializers@7.1.0/node_modules/pino-std-serializers/lib/err-proto.js"(exports, module) {
|
|
81503
81881
|
"use strict";
|
|
81504
|
-
var
|
|
81882
|
+
var seen2 = /* @__PURE__ */ Symbol("circular-ref-tag");
|
|
81505
81883
|
var rawSymbol = /* @__PURE__ */ Symbol("pino-raw-err-ref");
|
|
81506
81884
|
var pinoErrProto = Object.create({}, {
|
|
81507
81885
|
type: {
|
|
@@ -81541,7 +81919,7 @@ var require_err_proto = __commonJS({
|
|
|
81541
81919
|
module.exports = {
|
|
81542
81920
|
pinoErrProto,
|
|
81543
81921
|
pinoErrorSymbols: {
|
|
81544
|
-
seen,
|
|
81922
|
+
seen: seen2,
|
|
81545
81923
|
rawSymbol
|
|
81546
81924
|
}
|
|
81547
81925
|
};
|
|
@@ -81555,13 +81933,13 @@ var require_err = __commonJS({
|
|
|
81555
81933
|
module.exports = errSerializer;
|
|
81556
81934
|
var { messageWithCauses, stackWithCauses, isErrorLike } = require_err_helpers();
|
|
81557
81935
|
var { pinoErrProto, pinoErrorSymbols } = require_err_proto();
|
|
81558
|
-
var { seen } = pinoErrorSymbols;
|
|
81936
|
+
var { seen: seen2 } = pinoErrorSymbols;
|
|
81559
81937
|
var { toString } = Object.prototype;
|
|
81560
81938
|
function errSerializer(err) {
|
|
81561
81939
|
if (!isErrorLike(err)) {
|
|
81562
81940
|
return err;
|
|
81563
81941
|
}
|
|
81564
|
-
err[
|
|
81942
|
+
err[seen2] = void 0;
|
|
81565
81943
|
const _err = Object.create(pinoErrProto);
|
|
81566
81944
|
_err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name;
|
|
81567
81945
|
_err.message = messageWithCauses(err);
|
|
@@ -81573,7 +81951,7 @@ var require_err = __commonJS({
|
|
|
81573
81951
|
if (_err[key] === void 0) {
|
|
81574
81952
|
const val = err[key];
|
|
81575
81953
|
if (isErrorLike(val)) {
|
|
81576
|
-
if (key !== "cause" && !Object.prototype.hasOwnProperty.call(val,
|
|
81954
|
+
if (key !== "cause" && !Object.prototype.hasOwnProperty.call(val, seen2)) {
|
|
81577
81955
|
_err[key] = errSerializer(val);
|
|
81578
81956
|
}
|
|
81579
81957
|
} else {
|
|
@@ -81581,7 +81959,7 @@ var require_err = __commonJS({
|
|
|
81581
81959
|
}
|
|
81582
81960
|
}
|
|
81583
81961
|
}
|
|
81584
|
-
delete err[
|
|
81962
|
+
delete err[seen2];
|
|
81585
81963
|
_err.raw = err;
|
|
81586
81964
|
return _err;
|
|
81587
81965
|
}
|
|
@@ -81595,13 +81973,13 @@ var require_err_with_cause = __commonJS({
|
|
|
81595
81973
|
module.exports = errWithCauseSerializer;
|
|
81596
81974
|
var { isErrorLike } = require_err_helpers();
|
|
81597
81975
|
var { pinoErrProto, pinoErrorSymbols } = require_err_proto();
|
|
81598
|
-
var { seen } = pinoErrorSymbols;
|
|
81976
|
+
var { seen: seen2 } = pinoErrorSymbols;
|
|
81599
81977
|
var { toString } = Object.prototype;
|
|
81600
81978
|
function errWithCauseSerializer(err) {
|
|
81601
81979
|
if (!isErrorLike(err)) {
|
|
81602
81980
|
return err;
|
|
81603
81981
|
}
|
|
81604
|
-
err[
|
|
81982
|
+
err[seen2] = void 0;
|
|
81605
81983
|
const _err = Object.create(pinoErrProto);
|
|
81606
81984
|
_err.type = toString.call(err.constructor) === "[object Function]" ? err.constructor.name : err.name;
|
|
81607
81985
|
_err.message = err.message;
|
|
@@ -81609,14 +81987,14 @@ var require_err_with_cause = __commonJS({
|
|
|
81609
81987
|
if (Array.isArray(err.errors)) {
|
|
81610
81988
|
_err.aggregateErrors = err.errors.map((err2) => errWithCauseSerializer(err2));
|
|
81611
81989
|
}
|
|
81612
|
-
if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause,
|
|
81990
|
+
if (isErrorLike(err.cause) && !Object.prototype.hasOwnProperty.call(err.cause, seen2)) {
|
|
81613
81991
|
_err.cause = errWithCauseSerializer(err.cause);
|
|
81614
81992
|
}
|
|
81615
81993
|
for (const key in err) {
|
|
81616
81994
|
if (_err[key] === void 0) {
|
|
81617
81995
|
const val = err[key];
|
|
81618
81996
|
if (isErrorLike(val)) {
|
|
81619
|
-
if (!Object.prototype.hasOwnProperty.call(val,
|
|
81997
|
+
if (!Object.prototype.hasOwnProperty.call(val, seen2)) {
|
|
81620
81998
|
_err[key] = errWithCauseSerializer(val);
|
|
81621
81999
|
}
|
|
81622
82000
|
} else {
|
|
@@ -81624,7 +82002,7 @@ var require_err_with_cause = __commonJS({
|
|
|
81624
82002
|
}
|
|
81625
82003
|
}
|
|
81626
82004
|
}
|
|
81627
|
-
delete err[
|
|
82005
|
+
delete err[seen2];
|
|
81628
82006
|
_err.raw = err;
|
|
81629
82007
|
return _err;
|
|
81630
82008
|
}
|
|
@@ -108779,7 +109157,7 @@ var require_dist5 = __commonJS({
|
|
|
108779
109157
|
exports.stringifyCookie = stringifyCookie;
|
|
108780
109158
|
exports.stringifySetCookie = stringifySetCookie;
|
|
108781
109159
|
exports.serialize = stringifySetCookie;
|
|
108782
|
-
exports.parseSetCookie =
|
|
109160
|
+
exports.parseSetCookie = parseSetCookie3;
|
|
108783
109161
|
exports.stringifySetCookie = stringifySetCookie;
|
|
108784
109162
|
exports.serialize = stringifySetCookie;
|
|
108785
109163
|
var cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
|
|
@@ -108916,7 +109294,7 @@ var require_dist5 = __commonJS({
|
|
|
108916
109294
|
}
|
|
108917
109295
|
return str2;
|
|
108918
109296
|
}
|
|
108919
|
-
function
|
|
109297
|
+
function parseSetCookie3(str2, options) {
|
|
108920
109298
|
const dec = options?.decode || decode4;
|
|
108921
109299
|
const len = str2.length;
|
|
108922
109300
|
const endIdx = endIndex(str2, 0, len);
|
|
@@ -112029,7 +112407,7 @@ import http from "node:http";
|
|
|
112029
112407
|
import https from "node:https";
|
|
112030
112408
|
function run(cmd, args) {
|
|
112031
112409
|
return new Promise((resolve5) => {
|
|
112032
|
-
execFile2(cmd, args, { timeout:
|
|
112410
|
+
execFile2(cmd, args, { timeout: 2e4, windowsHide: true, maxBuffer: 8 * 1024 * 1024 }, (err, stdout) => resolve5(err && !stdout ? "" : String(stdout)));
|
|
112033
112411
|
});
|
|
112034
112412
|
}
|
|
112035
112413
|
function local(address) {
|
|
@@ -112098,11 +112476,10 @@ function parseSs(text) {
|
|
|
112098
112476
|
async function listPorts() {
|
|
112099
112477
|
if (process.platform === "win32") {
|
|
112100
112478
|
const tasks = run("tasklist", ["/FO", "CSV", "/NH"]);
|
|
112101
|
-
const
|
|
112102
|
-
const found2 = parseNetstat(v4);
|
|
112103
|
-
for (const [port2, l] of parseNetstat(v6)) if (!found2.has(port2)) found2.set(port2, l);
|
|
112479
|
+
const found2 = parseNetstat(await run("netstat", ["-ano"]));
|
|
112104
112480
|
const named = tasks.then((text) => {
|
|
112105
112481
|
const names = parseTasklist(text);
|
|
112482
|
+
if (!names.size) return;
|
|
112106
112483
|
for (const l of found2.values()) {
|
|
112107
112484
|
const t = names.get(l.pid);
|
|
112108
112485
|
l.name = t?.name;
|
|
@@ -112126,20 +112503,34 @@ function ask(scheme, host2, port2, verify, timeoutMs) {
|
|
|
112126
112503
|
resolve5("yes");
|
|
112127
112504
|
}
|
|
112128
112505
|
);
|
|
112129
|
-
req.on("timeout", () =>
|
|
112506
|
+
req.on("timeout", () => {
|
|
112507
|
+
resolve5("slow");
|
|
112508
|
+
req.destroy(new Error("timeout"));
|
|
112509
|
+
});
|
|
112130
112510
|
req.on("error", (err) => resolve5(scheme === "https" && verify && /CERT|SELF_SIGNED|UNABLE_TO|SIGNATURE|HOSTNAME|ALTNAME/i.test(err.code ?? err.message) ? "cert" : "no"));
|
|
112131
112511
|
req.end();
|
|
112132
112512
|
});
|
|
112133
112513
|
}
|
|
112134
112514
|
async function identify(l, timeoutMs) {
|
|
112515
|
+
const before = seen.get(l.port);
|
|
112516
|
+
const server = await probe(l, timeoutMs);
|
|
112517
|
+
if (server && server !== "slow") {
|
|
112518
|
+
seen.set(l.port, { pid: l.pid, server });
|
|
112519
|
+
return server;
|
|
112520
|
+
}
|
|
112521
|
+
if (server === "slow" && before && before.pid === l.pid) return before.server;
|
|
112522
|
+
seen.delete(l.port);
|
|
112523
|
+
return null;
|
|
112524
|
+
}
|
|
112525
|
+
async function probe(l, timeoutMs) {
|
|
112135
112526
|
const host2 = l.ipv4 ? "127.0.0.1" : "::1";
|
|
112136
112527
|
const [plain, tls] = await Promise.all([ask("http", host2, l.port, true, timeoutMs), ask("https", host2, l.port, true, timeoutMs)]);
|
|
112137
112528
|
if (plain === "yes") return { port: l.port, scheme: "http", name: l.name };
|
|
112138
112529
|
if (tls === "yes") return { port: l.port, scheme: "https", name: l.name };
|
|
112139
112530
|
if (tls === "cert" && await ask("https", host2, l.port, false, timeoutMs) === "yes") return { port: l.port, scheme: "https", name: l.name, selfSigned: true };
|
|
112140
|
-
return null;
|
|
112531
|
+
return plain === "slow" || tls === "slow" ? "slow" : null;
|
|
112141
112532
|
}
|
|
112142
|
-
async function findLocalServers(skip = [], timeoutMs =
|
|
112533
|
+
async function findLocalServers(skip = [], timeoutMs = 1500) {
|
|
112143
112534
|
const { ports, named } = await listPorts();
|
|
112144
112535
|
const [answers] = await Promise.all([
|
|
112145
112536
|
Promise.all(ports.filter((l) => !skip.includes(l.port) && !NOT_HTTP.has(l.port)).map(async (l) => ({ l, server: await identify(l, timeoutMs) }))),
|
|
@@ -112147,12 +112538,13 @@ async function findLocalServers(skip = [], timeoutMs = 600) {
|
|
|
112147
112538
|
]);
|
|
112148
112539
|
return answers.filter(({ l, server }) => server && !l.service && !SYSTEM.has((l.name ?? "").toLowerCase())).map(({ l, server }) => ({ ...server, name: l.name })).sort((a, b) => a.port - b.port);
|
|
112149
112540
|
}
|
|
112150
|
-
var SYSTEM, NOT_HTTP;
|
|
112541
|
+
var SYSTEM, NOT_HTTP, seen;
|
|
112151
112542
|
var init_local_servers = __esm({
|
|
112152
112543
|
"../../apps/engine/src/local-servers.ts"() {
|
|
112153
112544
|
"use strict";
|
|
112154
112545
|
SYSTEM = /* @__PURE__ */ new Set(["system", "svchost", "lsass", "wininit", "services", "spoolsv", "launchd", "systemd", "systemd-resolved", "cupsd", "sshd", "rpcbind"]);
|
|
112155
112546
|
NOT_HTTP = /* @__PURE__ */ new Set([22, 25, 53, 135, 139, 445, 1433, 1521, 3306, 3389, 5432, 5672, 6379, 9042, 11211, 27017]);
|
|
112547
|
+
seen = /* @__PURE__ */ new Map();
|
|
112156
112548
|
}
|
|
112157
112549
|
});
|
|
112158
112550
|
|
|
@@ -112255,9 +112647,11 @@ async function routes(api) {
|
|
|
112255
112647
|
}
|
|
112256
112648
|
const key = skip.join(",");
|
|
112257
112649
|
if (!localCache || localCache.key !== key || Date.now() - localCache.at > 2e3) {
|
|
112258
|
-
|
|
112650
|
+
const entry = { at: Number.POSITIVE_INFINITY, key, servers: findLocalServers(skip) };
|
|
112651
|
+
void entry.servers.finally(() => entry.at = Date.now());
|
|
112652
|
+
localCache = entry;
|
|
112259
112653
|
}
|
|
112260
|
-
return { servers: localCache.servers };
|
|
112654
|
+
return { servers: await localCache.servers };
|
|
112261
112655
|
});
|
|
112262
112656
|
registerSuiteRoutes(api, workspace, suitePlans, (port2) => ({ practiceApi: `http://127.0.0.1:${port2}${api.prefix}/demo-api` }));
|
|
112263
112657
|
onRunFinished(async (report, error51) => {
|
|
@@ -112448,7 +112842,7 @@ init_cookies();
|
|
|
112448
112842
|
init_workspace_store();
|
|
112449
112843
|
var repoRoot = resolve4(dirname3(fileURLToPath2(import.meta.url)), "../../..");
|
|
112450
112844
|
var EXIT = { passed: 0, failed: 1, error: 2 };
|
|
112451
|
-
var VERSION = "0.
|
|
112845
|
+
var VERSION = "0.10.0";
|
|
112452
112846
|
var HELP = `APITestCenter CLI ${VERSION} \u2014 https://apitestcenter.com/docs/cli-and-ci.html
|
|
112453
112847
|
|
|
112454
112848
|
Usage (apitestcenter, or the short name atc once installed)
|
|
@@ -112675,10 +113069,10 @@ Environments (${index.environments.length})`);
|
|
|
112675
113069
|
}
|
|
112676
113070
|
if (payload.data) log(`data ${payload.data.fileName} \xB7 ${payload.data.rows.length} rows \xB7 ${payload.data.order}`);
|
|
112677
113071
|
if (!values["no-check"]) {
|
|
112678
|
-
const
|
|
112679
|
-
const failedChecks =
|
|
112680
|
-
log(`check ${
|
|
112681
|
-
if (!
|
|
113072
|
+
const probe2 = await runProbe({ request: payload.request, auth: payload.auth, options: payload.options, setup: payload.setup, data: payload.data });
|
|
113073
|
+
const failedChecks = probe2.checks?.filter((c) => !c.ok) ?? [];
|
|
113074
|
+
log(`check ${probe2.status || "ERR"} in ${probe2.durationMs} ms${probe2.checks ? ` \xB7 checks ${probe2.checks.length - failedChecks.length}/${probe2.checks.length}` : ""}`);
|
|
113075
|
+
if (!probe2.ok || probe2.status < 200 || probe2.status >= 300) fail(`check request returned ${probe2.status || probe2.error}; load did not start (use --no-check to force)`);
|
|
112682
113076
|
}
|
|
112683
113077
|
const history2 = values.save ? new HistoryStore(dataDir) : null;
|
|
112684
113078
|
if (history2) onRunFinished(async (report2, error51) => void await history2.saveRun(report2, { source: "run", error: error51 }));
|