@schwabyio/gta 0.9.0 → 0.11.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/README.md +8 -1
- package/dist/SPEC.md +241 -31
- package/dist/chunks/{chunk-VRAFYQNE.js → chunk-OM3ZR56O.js} +1191 -566
- package/dist/gta.js +110 -41
- package/dist/worker.js +1 -1
- package/package.json +1 -1
|
@@ -118,17 +118,17 @@ var require_visit = __commonJS({
|
|
|
118
118
|
visit2.BREAK = BREAK;
|
|
119
119
|
visit2.SKIP = SKIP;
|
|
120
120
|
visit2.REMOVE = REMOVE;
|
|
121
|
-
function visit_(key, node2, visitor,
|
|
122
|
-
const ctrl = callVisitor(key, node2, visitor,
|
|
121
|
+
function visit_(key, node2, visitor, path11) {
|
|
122
|
+
const ctrl = callVisitor(key, node2, visitor, path11);
|
|
123
123
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
124
|
-
replaceNode(key,
|
|
125
|
-
return visit_(key, ctrl, visitor,
|
|
124
|
+
replaceNode(key, path11, ctrl);
|
|
125
|
+
return visit_(key, ctrl, visitor, path11);
|
|
126
126
|
}
|
|
127
127
|
if (typeof ctrl !== "symbol") {
|
|
128
128
|
if (identity.isCollection(node2)) {
|
|
129
|
-
|
|
129
|
+
path11 = Object.freeze(path11.concat(node2));
|
|
130
130
|
for (let i = 0; i < node2.items.length; ++i) {
|
|
131
|
-
const ci = visit_(i, node2.items[i], visitor,
|
|
131
|
+
const ci = visit_(i, node2.items[i], visitor, path11);
|
|
132
132
|
if (typeof ci === "number")
|
|
133
133
|
i = ci - 1;
|
|
134
134
|
else if (ci === BREAK)
|
|
@@ -139,13 +139,13 @@ var require_visit = __commonJS({
|
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
} else if (identity.isPair(node2)) {
|
|
142
|
-
|
|
143
|
-
const ck = visit_("key", node2.key, visitor,
|
|
142
|
+
path11 = Object.freeze(path11.concat(node2));
|
|
143
|
+
const ck = visit_("key", node2.key, visitor, path11);
|
|
144
144
|
if (ck === BREAK)
|
|
145
145
|
return BREAK;
|
|
146
146
|
else if (ck === REMOVE)
|
|
147
147
|
node2.key = null;
|
|
148
|
-
const cv = visit_("value", node2.value, visitor,
|
|
148
|
+
const cv = visit_("value", node2.value, visitor, path11);
|
|
149
149
|
if (cv === BREAK)
|
|
150
150
|
return BREAK;
|
|
151
151
|
else if (cv === REMOVE)
|
|
@@ -166,17 +166,17 @@ var require_visit = __commonJS({
|
|
|
166
166
|
visitAsync.BREAK = BREAK;
|
|
167
167
|
visitAsync.SKIP = SKIP;
|
|
168
168
|
visitAsync.REMOVE = REMOVE;
|
|
169
|
-
async function visitAsync_(key, node2, visitor,
|
|
170
|
-
const ctrl = await callVisitor(key, node2, visitor,
|
|
169
|
+
async function visitAsync_(key, node2, visitor, path11) {
|
|
170
|
+
const ctrl = await callVisitor(key, node2, visitor, path11);
|
|
171
171
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
172
|
-
replaceNode(key,
|
|
173
|
-
return visitAsync_(key, ctrl, visitor,
|
|
172
|
+
replaceNode(key, path11, ctrl);
|
|
173
|
+
return visitAsync_(key, ctrl, visitor, path11);
|
|
174
174
|
}
|
|
175
175
|
if (typeof ctrl !== "symbol") {
|
|
176
176
|
if (identity.isCollection(node2)) {
|
|
177
|
-
|
|
177
|
+
path11 = Object.freeze(path11.concat(node2));
|
|
178
178
|
for (let i = 0; i < node2.items.length; ++i) {
|
|
179
|
-
const ci = await visitAsync_(i, node2.items[i], visitor,
|
|
179
|
+
const ci = await visitAsync_(i, node2.items[i], visitor, path11);
|
|
180
180
|
if (typeof ci === "number")
|
|
181
181
|
i = ci - 1;
|
|
182
182
|
else if (ci === BREAK)
|
|
@@ -187,13 +187,13 @@ var require_visit = __commonJS({
|
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
} else if (identity.isPair(node2)) {
|
|
190
|
-
|
|
191
|
-
const ck = await visitAsync_("key", node2.key, visitor,
|
|
190
|
+
path11 = Object.freeze(path11.concat(node2));
|
|
191
|
+
const ck = await visitAsync_("key", node2.key, visitor, path11);
|
|
192
192
|
if (ck === BREAK)
|
|
193
193
|
return BREAK;
|
|
194
194
|
else if (ck === REMOVE)
|
|
195
195
|
node2.key = null;
|
|
196
|
-
const cv = await visitAsync_("value", node2.value, visitor,
|
|
196
|
+
const cv = await visitAsync_("value", node2.value, visitor, path11);
|
|
197
197
|
if (cv === BREAK)
|
|
198
198
|
return BREAK;
|
|
199
199
|
else if (cv === REMOVE)
|
|
@@ -220,23 +220,23 @@ var require_visit = __commonJS({
|
|
|
220
220
|
}
|
|
221
221
|
return visitor;
|
|
222
222
|
}
|
|
223
|
-
function callVisitor(key, node2, visitor,
|
|
223
|
+
function callVisitor(key, node2, visitor, path11) {
|
|
224
224
|
if (typeof visitor === "function")
|
|
225
|
-
return visitor(key, node2,
|
|
225
|
+
return visitor(key, node2, path11);
|
|
226
226
|
if (identity.isMap(node2))
|
|
227
|
-
return visitor.Map?.(key, node2,
|
|
227
|
+
return visitor.Map?.(key, node2, path11);
|
|
228
228
|
if (identity.isSeq(node2))
|
|
229
|
-
return visitor.Seq?.(key, node2,
|
|
229
|
+
return visitor.Seq?.(key, node2, path11);
|
|
230
230
|
if (identity.isPair(node2))
|
|
231
|
-
return visitor.Pair?.(key, node2,
|
|
231
|
+
return visitor.Pair?.(key, node2, path11);
|
|
232
232
|
if (identity.isScalar(node2))
|
|
233
|
-
return visitor.Scalar?.(key, node2,
|
|
233
|
+
return visitor.Scalar?.(key, node2, path11);
|
|
234
234
|
if (identity.isAlias(node2))
|
|
235
|
-
return visitor.Alias?.(key, node2,
|
|
235
|
+
return visitor.Alias?.(key, node2, path11);
|
|
236
236
|
return void 0;
|
|
237
237
|
}
|
|
238
|
-
function replaceNode(key,
|
|
239
|
-
const parent =
|
|
238
|
+
function replaceNode(key, path11, node2) {
|
|
239
|
+
const parent = path11[path11.length - 1];
|
|
240
240
|
if (identity.isCollection(parent)) {
|
|
241
241
|
parent.items[key] = node2;
|
|
242
242
|
} else if (identity.isPair(parent)) {
|
|
@@ -848,10 +848,10 @@ var require_Collection = __commonJS({
|
|
|
848
848
|
var createNode = require_createNode();
|
|
849
849
|
var identity = require_identity();
|
|
850
850
|
var Node = require_Node();
|
|
851
|
-
function collectionFromPath(schema,
|
|
851
|
+
function collectionFromPath(schema, path11, value) {
|
|
852
852
|
let v = value;
|
|
853
|
-
for (let i =
|
|
854
|
-
const k =
|
|
853
|
+
for (let i = path11.length - 1; i >= 0; --i) {
|
|
854
|
+
const k = path11[i];
|
|
855
855
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
856
856
|
const a = [];
|
|
857
857
|
a[k] = v;
|
|
@@ -870,7 +870,7 @@ var require_Collection = __commonJS({
|
|
|
870
870
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
871
871
|
});
|
|
872
872
|
}
|
|
873
|
-
var isEmptyPath = (
|
|
873
|
+
var isEmptyPath = (path11) => path11 == null || typeof path11 === "object" && !!path11[Symbol.iterator]().next().done;
|
|
874
874
|
var Collection = class extends Node.NodeBase {
|
|
875
875
|
constructor(type, schema) {
|
|
876
876
|
super(type);
|
|
@@ -900,11 +900,11 @@ var require_Collection = __commonJS({
|
|
|
900
900
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
901
901
|
* that already exists in the map.
|
|
902
902
|
*/
|
|
903
|
-
addIn(
|
|
904
|
-
if (isEmptyPath(
|
|
903
|
+
addIn(path11, value) {
|
|
904
|
+
if (isEmptyPath(path11))
|
|
905
905
|
this.add(value);
|
|
906
906
|
else {
|
|
907
|
-
const [key, ...rest] =
|
|
907
|
+
const [key, ...rest] = path11;
|
|
908
908
|
const node2 = this.get(key, true);
|
|
909
909
|
if (identity.isCollection(node2))
|
|
910
910
|
node2.addIn(rest, value);
|
|
@@ -918,8 +918,8 @@ var require_Collection = __commonJS({
|
|
|
918
918
|
* Removes a value from the collection.
|
|
919
919
|
* @returns `true` if the item was found and removed.
|
|
920
920
|
*/
|
|
921
|
-
deleteIn(
|
|
922
|
-
const [key, ...rest] =
|
|
921
|
+
deleteIn(path11) {
|
|
922
|
+
const [key, ...rest] = path11;
|
|
923
923
|
if (rest.length === 0)
|
|
924
924
|
return this.delete(key);
|
|
925
925
|
const node2 = this.get(key, true);
|
|
@@ -933,8 +933,8 @@ var require_Collection = __commonJS({
|
|
|
933
933
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
934
934
|
* `true` (collections are always returned intact).
|
|
935
935
|
*/
|
|
936
|
-
getIn(
|
|
937
|
-
const [key, ...rest] =
|
|
936
|
+
getIn(path11, keepScalar) {
|
|
937
|
+
const [key, ...rest] = path11;
|
|
938
938
|
const node2 = this.get(key, true);
|
|
939
939
|
if (rest.length === 0)
|
|
940
940
|
return !keepScalar && identity.isScalar(node2) ? node2.value : node2;
|
|
@@ -952,8 +952,8 @@ var require_Collection = __commonJS({
|
|
|
952
952
|
/**
|
|
953
953
|
* Checks if the collection includes a value with the key `key`.
|
|
954
954
|
*/
|
|
955
|
-
hasIn(
|
|
956
|
-
const [key, ...rest] =
|
|
955
|
+
hasIn(path11) {
|
|
956
|
+
const [key, ...rest] = path11;
|
|
957
957
|
if (rest.length === 0)
|
|
958
958
|
return this.has(key);
|
|
959
959
|
const node2 = this.get(key, true);
|
|
@@ -963,8 +963,8 @@ var require_Collection = __commonJS({
|
|
|
963
963
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
964
964
|
* boolean to add/remove the item from the set.
|
|
965
965
|
*/
|
|
966
|
-
setIn(
|
|
967
|
-
const [key, ...rest] =
|
|
966
|
+
setIn(path11, value) {
|
|
967
|
+
const [key, ...rest] = path11;
|
|
968
968
|
if (rest.length === 0) {
|
|
969
969
|
this.set(key, value);
|
|
970
970
|
} else {
|
|
@@ -3479,9 +3479,9 @@ var require_Document = __commonJS({
|
|
|
3479
3479
|
this.contents.add(value);
|
|
3480
3480
|
}
|
|
3481
3481
|
/** Adds a value to the document. */
|
|
3482
|
-
addIn(
|
|
3482
|
+
addIn(path11, value) {
|
|
3483
3483
|
if (assertCollection(this.contents))
|
|
3484
|
-
this.contents.addIn(
|
|
3484
|
+
this.contents.addIn(path11, value);
|
|
3485
3485
|
}
|
|
3486
3486
|
/**
|
|
3487
3487
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -3556,14 +3556,14 @@ var require_Document = __commonJS({
|
|
|
3556
3556
|
* Removes a value from the document.
|
|
3557
3557
|
* @returns `true` if the item was found and removed.
|
|
3558
3558
|
*/
|
|
3559
|
-
deleteIn(
|
|
3560
|
-
if (Collection.isEmptyPath(
|
|
3559
|
+
deleteIn(path11) {
|
|
3560
|
+
if (Collection.isEmptyPath(path11)) {
|
|
3561
3561
|
if (this.contents == null)
|
|
3562
3562
|
return false;
|
|
3563
3563
|
this.contents = null;
|
|
3564
3564
|
return true;
|
|
3565
3565
|
}
|
|
3566
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3566
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path11) : false;
|
|
3567
3567
|
}
|
|
3568
3568
|
/**
|
|
3569
3569
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -3578,10 +3578,10 @@ var require_Document = __commonJS({
|
|
|
3578
3578
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
3579
3579
|
* `true` (collections are always returned intact).
|
|
3580
3580
|
*/
|
|
3581
|
-
getIn(
|
|
3582
|
-
if (Collection.isEmptyPath(
|
|
3581
|
+
getIn(path11, keepScalar) {
|
|
3582
|
+
if (Collection.isEmptyPath(path11))
|
|
3583
3583
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3584
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3584
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path11, keepScalar) : void 0;
|
|
3585
3585
|
}
|
|
3586
3586
|
/**
|
|
3587
3587
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -3592,10 +3592,10 @@ var require_Document = __commonJS({
|
|
|
3592
3592
|
/**
|
|
3593
3593
|
* Checks if the document includes a value at `path`.
|
|
3594
3594
|
*/
|
|
3595
|
-
hasIn(
|
|
3596
|
-
if (Collection.isEmptyPath(
|
|
3595
|
+
hasIn(path11) {
|
|
3596
|
+
if (Collection.isEmptyPath(path11))
|
|
3597
3597
|
return this.contents !== void 0;
|
|
3598
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3598
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path11) : false;
|
|
3599
3599
|
}
|
|
3600
3600
|
/**
|
|
3601
3601
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -3612,13 +3612,13 @@ var require_Document = __commonJS({
|
|
|
3612
3612
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
3613
3613
|
* boolean to add/remove the item from the set.
|
|
3614
3614
|
*/
|
|
3615
|
-
setIn(
|
|
3616
|
-
if (Collection.isEmptyPath(
|
|
3615
|
+
setIn(path11, value) {
|
|
3616
|
+
if (Collection.isEmptyPath(path11)) {
|
|
3617
3617
|
this.contents = value;
|
|
3618
3618
|
} else if (this.contents == null) {
|
|
3619
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3619
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path11), value);
|
|
3620
3620
|
} else if (assertCollection(this.contents)) {
|
|
3621
|
-
this.contents.setIn(
|
|
3621
|
+
this.contents.setIn(path11, value);
|
|
3622
3622
|
}
|
|
3623
3623
|
}
|
|
3624
3624
|
/**
|
|
@@ -5579,9 +5579,9 @@ var require_cst_visit = __commonJS({
|
|
|
5579
5579
|
visit2.BREAK = BREAK;
|
|
5580
5580
|
visit2.SKIP = SKIP;
|
|
5581
5581
|
visit2.REMOVE = REMOVE;
|
|
5582
|
-
visit2.itemAtPath = (cst,
|
|
5582
|
+
visit2.itemAtPath = (cst, path11) => {
|
|
5583
5583
|
let item = cst;
|
|
5584
|
-
for (const [field, index] of
|
|
5584
|
+
for (const [field, index] of path11) {
|
|
5585
5585
|
const tok = item?.[field];
|
|
5586
5586
|
if (tok && "items" in tok) {
|
|
5587
5587
|
item = tok.items[index];
|
|
@@ -5590,23 +5590,23 @@ var require_cst_visit = __commonJS({
|
|
|
5590
5590
|
}
|
|
5591
5591
|
return item;
|
|
5592
5592
|
};
|
|
5593
|
-
visit2.parentCollection = (cst,
|
|
5594
|
-
const parent = visit2.itemAtPath(cst,
|
|
5595
|
-
const field =
|
|
5593
|
+
visit2.parentCollection = (cst, path11) => {
|
|
5594
|
+
const parent = visit2.itemAtPath(cst, path11.slice(0, -1));
|
|
5595
|
+
const field = path11[path11.length - 1][0];
|
|
5596
5596
|
const coll = parent?.[field];
|
|
5597
5597
|
if (coll && "items" in coll)
|
|
5598
5598
|
return coll;
|
|
5599
5599
|
throw new Error("Parent collection not found");
|
|
5600
5600
|
};
|
|
5601
|
-
function _visit(
|
|
5602
|
-
let ctrl = visitor(item,
|
|
5601
|
+
function _visit(path11, item, visitor) {
|
|
5602
|
+
let ctrl = visitor(item, path11);
|
|
5603
5603
|
if (typeof ctrl === "symbol")
|
|
5604
5604
|
return ctrl;
|
|
5605
5605
|
for (const field of ["key", "value"]) {
|
|
5606
5606
|
const token = item[field];
|
|
5607
5607
|
if (token && "items" in token) {
|
|
5608
5608
|
for (let i = 0; i < token.items.length; ++i) {
|
|
5609
|
-
const ci = _visit(Object.freeze(
|
|
5609
|
+
const ci = _visit(Object.freeze(path11.concat([[field, i]])), token.items[i], visitor);
|
|
5610
5610
|
if (typeof ci === "number")
|
|
5611
5611
|
i = ci - 1;
|
|
5612
5612
|
else if (ci === BREAK)
|
|
@@ -5617,10 +5617,10 @@ var require_cst_visit = __commonJS({
|
|
|
5617
5617
|
}
|
|
5618
5618
|
}
|
|
5619
5619
|
if (typeof ctrl === "function" && field === "key")
|
|
5620
|
-
ctrl = ctrl(item,
|
|
5620
|
+
ctrl = ctrl(item, path11);
|
|
5621
5621
|
}
|
|
5622
5622
|
}
|
|
5623
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5623
|
+
return typeof ctrl === "function" ? ctrl(item, path11) : ctrl;
|
|
5624
5624
|
}
|
|
5625
5625
|
exports.visit = visit2;
|
|
5626
5626
|
}
|
|
@@ -8480,14 +8480,14 @@ var require_util = __commonJS({
|
|
|
8480
8480
|
}
|
|
8481
8481
|
const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
|
|
8482
8482
|
let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
|
|
8483
|
-
let
|
|
8483
|
+
let path11 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
|
|
8484
8484
|
if (origin[origin.length - 1] === "/") {
|
|
8485
8485
|
origin = origin.slice(0, origin.length - 1);
|
|
8486
8486
|
}
|
|
8487
|
-
if (
|
|
8488
|
-
|
|
8487
|
+
if (path11 && path11[0] !== "/") {
|
|
8488
|
+
path11 = `/${path11}`;
|
|
8489
8489
|
}
|
|
8490
|
-
return new URL(`${origin}${
|
|
8490
|
+
return new URL(`${origin}${path11}`);
|
|
8491
8491
|
}
|
|
8492
8492
|
if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
|
|
8493
8493
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -9358,9 +9358,9 @@ var require_diagnostics = __commonJS({
|
|
|
9358
9358
|
"undici:client:sendHeaders",
|
|
9359
9359
|
(evt) => {
|
|
9360
9360
|
const {
|
|
9361
|
-
request: { method, path:
|
|
9361
|
+
request: { method, path: path11, origin }
|
|
9362
9362
|
} = evt;
|
|
9363
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
9363
|
+
debugLog("sending request to %s %s%s", method, origin, path11);
|
|
9364
9364
|
}
|
|
9365
9365
|
);
|
|
9366
9366
|
}
|
|
@@ -9378,14 +9378,14 @@ var require_diagnostics = __commonJS({
|
|
|
9378
9378
|
"undici:request:headers",
|
|
9379
9379
|
(evt) => {
|
|
9380
9380
|
const {
|
|
9381
|
-
request: { method, path:
|
|
9381
|
+
request: { method, path: path11, origin },
|
|
9382
9382
|
response: { statusCode }
|
|
9383
9383
|
} = evt;
|
|
9384
9384
|
debugLog(
|
|
9385
9385
|
"received response to %s %s%s - HTTP %d",
|
|
9386
9386
|
method,
|
|
9387
9387
|
origin,
|
|
9388
|
-
|
|
9388
|
+
path11,
|
|
9389
9389
|
statusCode
|
|
9390
9390
|
);
|
|
9391
9391
|
}
|
|
@@ -9394,23 +9394,23 @@ var require_diagnostics = __commonJS({
|
|
|
9394
9394
|
"undici:request:trailers",
|
|
9395
9395
|
(evt) => {
|
|
9396
9396
|
const {
|
|
9397
|
-
request: { method, path:
|
|
9397
|
+
request: { method, path: path11, origin }
|
|
9398
9398
|
} = evt;
|
|
9399
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
9399
|
+
debugLog("trailers received from %s %s%s", method, origin, path11);
|
|
9400
9400
|
}
|
|
9401
9401
|
);
|
|
9402
9402
|
diagnosticsChannel.subscribe(
|
|
9403
9403
|
"undici:request:error",
|
|
9404
9404
|
(evt) => {
|
|
9405
9405
|
const {
|
|
9406
|
-
request: { method, path:
|
|
9406
|
+
request: { method, path: path11, origin },
|
|
9407
9407
|
error: error62
|
|
9408
9408
|
} = evt;
|
|
9409
9409
|
debugLog(
|
|
9410
9410
|
"request to %s %s%s errored - %s",
|
|
9411
9411
|
method,
|
|
9412
9412
|
origin,
|
|
9413
|
-
|
|
9413
|
+
path11,
|
|
9414
9414
|
error62.message
|
|
9415
9415
|
);
|
|
9416
9416
|
}
|
|
@@ -9565,7 +9565,7 @@ var require_request = __commonJS({
|
|
|
9565
9565
|
};
|
|
9566
9566
|
var Request = class {
|
|
9567
9567
|
constructor(origin, {
|
|
9568
|
-
path:
|
|
9568
|
+
path: path11,
|
|
9569
9569
|
method,
|
|
9570
9570
|
body,
|
|
9571
9571
|
headers,
|
|
@@ -9582,11 +9582,11 @@ var require_request = __commonJS({
|
|
|
9582
9582
|
maxRedirections,
|
|
9583
9583
|
typeOfService
|
|
9584
9584
|
}, handler) {
|
|
9585
|
-
if (typeof
|
|
9585
|
+
if (typeof path11 !== "string") {
|
|
9586
9586
|
throw new InvalidArgumentError("path must be a string");
|
|
9587
|
-
} else if (
|
|
9587
|
+
} else if (path11[0] !== "/" && !(path11.startsWith("http://") || path11.startsWith("https://")) && method !== "CONNECT") {
|
|
9588
9588
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
9589
|
-
} else if (invalidPathRegex.test(
|
|
9589
|
+
} else if (invalidPathRegex.test(path11)) {
|
|
9590
9590
|
throw new InvalidArgumentError("invalid request path");
|
|
9591
9591
|
}
|
|
9592
9592
|
if (typeof method !== "string") {
|
|
@@ -9661,7 +9661,7 @@ var require_request = __commonJS({
|
|
|
9661
9661
|
this.completed = false;
|
|
9662
9662
|
this.aborted = false;
|
|
9663
9663
|
this.upgrade = upgrade || null;
|
|
9664
|
-
this.path = query ? serializePathWithQuery(
|
|
9664
|
+
this.path = query ? serializePathWithQuery(path11, query) : path11;
|
|
9665
9665
|
this.origin = origin;
|
|
9666
9666
|
this.protocol = getProtocolFromUrlString(origin);
|
|
9667
9667
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" || method === "QUERY" : idempotent;
|
|
@@ -14770,7 +14770,7 @@ var require_client_h1 = __commonJS({
|
|
|
14770
14770
|
}
|
|
14771
14771
|
}
|
|
14772
14772
|
function writeH1(client, request) {
|
|
14773
|
-
const { method, path:
|
|
14773
|
+
const { method, path: path11, host, upgrade, blocking, reset } = request;
|
|
14774
14774
|
let { body, headers, contentLength } = request;
|
|
14775
14775
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
14776
14776
|
if (util.isFormDataLike(body)) {
|
|
@@ -14846,7 +14846,7 @@ var require_client_h1 = __commonJS({
|
|
|
14846
14846
|
socket[kBlocking] = true;
|
|
14847
14847
|
}
|
|
14848
14848
|
setTypeOfService(socket, request);
|
|
14849
|
-
let header = `${method} ${
|
|
14849
|
+
let header = `${method} ${path11} HTTP/1.1\r
|
|
14850
14850
|
`;
|
|
14851
14851
|
if (typeof host === "string") {
|
|
14852
14852
|
header += `host: ${host}\r
|
|
@@ -15929,7 +15929,7 @@ var require_client_h2 = __commonJS({
|
|
|
15929
15929
|
const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout];
|
|
15930
15930
|
const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout];
|
|
15931
15931
|
const session = client[kHTTP2Session];
|
|
15932
|
-
const { method, path:
|
|
15932
|
+
const { method, path: path11, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request;
|
|
15933
15933
|
if (upgrade != null && upgrade !== "websocket") {
|
|
15934
15934
|
util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
15935
15935
|
return false;
|
|
@@ -15994,7 +15994,7 @@ var require_client_h2 = __commonJS({
|
|
|
15994
15994
|
}
|
|
15995
15995
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
15996
15996
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
15997
|
-
headers[HTTP2_HEADER_PATH] =
|
|
15997
|
+
headers[HTTP2_HEADER_PATH] = path11;
|
|
15998
15998
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
15999
15999
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
16000
16000
|
} else {
|
|
@@ -16016,7 +16016,7 @@ var require_client_h2 = __commonJS({
|
|
|
16016
16016
|
setupUpgradeStream(stream, state);
|
|
16017
16017
|
return true;
|
|
16018
16018
|
}
|
|
16019
|
-
headers[HTTP2_HEADER_PATH] =
|
|
16019
|
+
headers[HTTP2_HEADER_PATH] = path11;
|
|
16020
16020
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
16021
16021
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
16022
16022
|
let body = state.body;
|
|
@@ -18772,10 +18772,10 @@ var require_proxy_agent = __commonJS({
|
|
|
18772
18772
|
};
|
|
18773
18773
|
const {
|
|
18774
18774
|
origin,
|
|
18775
|
-
path:
|
|
18775
|
+
path: path11 = "/",
|
|
18776
18776
|
headers = {}
|
|
18777
18777
|
} = opts;
|
|
18778
|
-
opts.path = origin +
|
|
18778
|
+
opts.path = origin + path11;
|
|
18779
18779
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
18780
18780
|
const { host } = new URL(origin);
|
|
18781
18781
|
headers.host = host;
|
|
@@ -21128,20 +21128,20 @@ var require_mock_utils = __commonJS({
|
|
|
21128
21128
|
}
|
|
21129
21129
|
return normalizedQp;
|
|
21130
21130
|
}
|
|
21131
|
-
function safeUrl(
|
|
21132
|
-
if (typeof
|
|
21133
|
-
return
|
|
21131
|
+
function safeUrl(path11) {
|
|
21132
|
+
if (typeof path11 !== "string") {
|
|
21133
|
+
return path11;
|
|
21134
21134
|
}
|
|
21135
|
-
const pathSegments =
|
|
21135
|
+
const pathSegments = path11.split("?", 3);
|
|
21136
21136
|
if (pathSegments.length !== 2) {
|
|
21137
|
-
return
|
|
21137
|
+
return path11;
|
|
21138
21138
|
}
|
|
21139
21139
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
21140
21140
|
qp.sort();
|
|
21141
21141
|
return [...pathSegments, qp.toString()].join("?");
|
|
21142
21142
|
}
|
|
21143
|
-
function matchKey(mockDispatch2, { path:
|
|
21144
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
21143
|
+
function matchKey(mockDispatch2, { path: path11, method, body, headers }) {
|
|
21144
|
+
const pathMatch = matchValue(mockDispatch2.path, path11);
|
|
21145
21145
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
21146
21146
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
21147
21147
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -21168,8 +21168,8 @@ var require_mock_utils = __commonJS({
|
|
|
21168
21168
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
21169
21169
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
21170
21170
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
21171
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
21172
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
21171
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path11, ignoreTrailingSlash }) => {
|
|
21172
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path11)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path11), resolvedPath);
|
|
21173
21173
|
});
|
|
21174
21174
|
if (matchedMockDispatches.length === 0) {
|
|
21175
21175
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -21208,22 +21208,22 @@ var require_mock_utils = __commonJS({
|
|
|
21208
21208
|
mockDispatches.splice(index, 1);
|
|
21209
21209
|
}
|
|
21210
21210
|
}
|
|
21211
|
-
function removeTrailingSlash(
|
|
21212
|
-
if (typeof
|
|
21213
|
-
return
|
|
21211
|
+
function removeTrailingSlash(path11) {
|
|
21212
|
+
if (typeof path11 !== "string") {
|
|
21213
|
+
return path11;
|
|
21214
21214
|
}
|
|
21215
|
-
while (
|
|
21216
|
-
|
|
21215
|
+
while (path11.endsWith("/")) {
|
|
21216
|
+
path11 = path11.slice(0, -1);
|
|
21217
21217
|
}
|
|
21218
|
-
if (
|
|
21219
|
-
|
|
21218
|
+
if (path11.length === 0) {
|
|
21219
|
+
path11 = "/";
|
|
21220
21220
|
}
|
|
21221
|
-
return
|
|
21221
|
+
return path11;
|
|
21222
21222
|
}
|
|
21223
21223
|
function buildKey(opts) {
|
|
21224
|
-
const { path:
|
|
21224
|
+
const { path: path11, method, body, headers, query } = opts;
|
|
21225
21225
|
return {
|
|
21226
|
-
path:
|
|
21226
|
+
path: path11,
|
|
21227
21227
|
method,
|
|
21228
21228
|
body,
|
|
21229
21229
|
headers,
|
|
@@ -22092,10 +22092,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
22092
22092
|
}
|
|
22093
22093
|
format(pendingInterceptors) {
|
|
22094
22094
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
22095
|
-
({ method, path:
|
|
22095
|
+
({ method, path: path11, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
22096
22096
|
Method: method,
|
|
22097
22097
|
Origin: origin,
|
|
22098
|
-
Path:
|
|
22098
|
+
Path: path11,
|
|
22099
22099
|
"Status code": statusCode,
|
|
22100
22100
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
22101
22101
|
Invocations: timesInvoked,
|
|
@@ -22185,9 +22185,9 @@ var require_mock_agent = __commonJS({
|
|
|
22185
22185
|
}
|
|
22186
22186
|
}
|
|
22187
22187
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
22188
|
-
const [
|
|
22188
|
+
const [path11, searchParams] = dispatchOpts.path.split("?");
|
|
22189
22189
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
22190
|
-
dispatchOpts.path = `${
|
|
22190
|
+
dispatchOpts.path = `${path11}?${normalizedSearchParams}`;
|
|
22191
22191
|
}
|
|
22192
22192
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
22193
22193
|
}
|
|
@@ -22603,12 +22603,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
22603
22603
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
22604
22604
|
*/
|
|
22605
22605
|
async loadSnapshots(filePath) {
|
|
22606
|
-
const
|
|
22607
|
-
if (!
|
|
22606
|
+
const path11 = filePath || this.#snapshotPath;
|
|
22607
|
+
if (!path11) {
|
|
22608
22608
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
22609
22609
|
}
|
|
22610
22610
|
try {
|
|
22611
|
-
const data = await readFile(resolve(
|
|
22611
|
+
const data = await readFile(resolve(path11), "utf8");
|
|
22612
22612
|
const parsed = JSON.parse(data);
|
|
22613
22613
|
if (Array.isArray(parsed)) {
|
|
22614
22614
|
this.#snapshots.clear();
|
|
@@ -22622,7 +22622,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
22622
22622
|
if (error62.code === "ENOENT") {
|
|
22623
22623
|
this.#snapshots.clear();
|
|
22624
22624
|
} else {
|
|
22625
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
22625
|
+
throw new UndiciError(`Failed to load snapshots from ${path11}`, { cause: error62 });
|
|
22626
22626
|
}
|
|
22627
22627
|
}
|
|
22628
22628
|
}
|
|
@@ -22633,11 +22633,11 @@ var require_snapshot_recorder = __commonJS({
|
|
|
22633
22633
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
22634
22634
|
*/
|
|
22635
22635
|
async saveSnapshots(filePath) {
|
|
22636
|
-
const
|
|
22637
|
-
if (!
|
|
22636
|
+
const path11 = filePath || this.#snapshotPath;
|
|
22637
|
+
if (!path11) {
|
|
22638
22638
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
22639
22639
|
}
|
|
22640
|
-
const resolvedPath = resolve(
|
|
22640
|
+
const resolvedPath = resolve(path11);
|
|
22641
22641
|
await mkdir(dirname(resolvedPath), { recursive: true });
|
|
22642
22642
|
const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
22643
22643
|
hash: hash2,
|
|
@@ -23287,15 +23287,15 @@ var require_redirect_handler = __commonJS({
|
|
|
23287
23287
|
}
|
|
23288
23288
|
const baseUrl = requestOrigin ? new URL(this.opts.path, requestOrigin) : void 0;
|
|
23289
23289
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, baseUrl));
|
|
23290
|
-
const
|
|
23291
|
-
const redirectUrlString = `${origin}${
|
|
23290
|
+
const path11 = search ? `${pathname}${search}` : pathname;
|
|
23291
|
+
const redirectUrlString = `${origin}${path11}`;
|
|
23292
23292
|
for (const historyUrl of this.history) {
|
|
23293
23293
|
if (historyUrl.toString() === redirectUrlString) {
|
|
23294
23294
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
23295
23295
|
}
|
|
23296
23296
|
}
|
|
23297
23297
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, removeContentHeaders, requestOrigin !== origin, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect);
|
|
23298
|
-
this.opts.path =
|
|
23298
|
+
this.opts.path = path11;
|
|
23299
23299
|
this.opts.origin = origin;
|
|
23300
23300
|
this.opts[kRequestOrigin] = origin;
|
|
23301
23301
|
this.opts.query = null;
|
|
@@ -25146,10 +25146,10 @@ var require_cache_handler = __commonJS({
|
|
|
25146
25146
|
}
|
|
25147
25147
|
return locationUrl.pathname + locationUrl.search;
|
|
25148
25148
|
}
|
|
25149
|
-
function deleteCachedUri(store, cacheKey,
|
|
25149
|
+
function deleteCachedUri(store, cacheKey, path11) {
|
|
25150
25150
|
deleteCachedValue(store, {
|
|
25151
25151
|
...cacheKey,
|
|
25152
|
-
path:
|
|
25152
|
+
path: path11
|
|
25153
25153
|
});
|
|
25154
25154
|
for (let i = 0; i < util.safeHTTPMethods.length; i++) {
|
|
25155
25155
|
const method = util.safeHTTPMethods[i];
|
|
@@ -25157,7 +25157,7 @@ var require_cache_handler = __commonJS({
|
|
|
25157
25157
|
deleteCachedValue(store, {
|
|
25158
25158
|
...cacheKey,
|
|
25159
25159
|
method,
|
|
25160
|
-
path:
|
|
25160
|
+
path: path11
|
|
25161
25161
|
});
|
|
25162
25162
|
}
|
|
25163
25163
|
}
|
|
@@ -25168,9 +25168,9 @@ var require_cache_handler = __commonJS({
|
|
|
25168
25168
|
}
|
|
25169
25169
|
const values = Array.isArray(headerValue) ? headerValue : [headerValue];
|
|
25170
25170
|
for (let i = 0; i < values.length; i++) {
|
|
25171
|
-
const
|
|
25172
|
-
if (
|
|
25173
|
-
deleteCachedUri(store, cacheKey,
|
|
25171
|
+
const path11 = getSameOriginPath(cacheKey, values[i]);
|
|
25172
|
+
if (path11 !== void 0) {
|
|
25173
|
+
deleteCachedUri(store, cacheKey, path11);
|
|
25174
25174
|
}
|
|
25175
25175
|
}
|
|
25176
25176
|
}
|
|
@@ -30297,13 +30297,13 @@ var require_fetch = __commonJS({
|
|
|
30297
30297
|
function dispatch({ body }) {
|
|
30298
30298
|
const url2 = requestCurrentURL(request);
|
|
30299
30299
|
const agent = fetchParams.controller.dispatcher;
|
|
30300
|
-
const
|
|
30300
|
+
const path11 = url2.pathname + url2.search;
|
|
30301
30301
|
const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
|
|
30302
30302
|
return dispatchWithProtocolPreference(body);
|
|
30303
30303
|
function dispatchWithProtocolPreference(body2, allowH2) {
|
|
30304
30304
|
return new Promise((resolve, reject) => agent.dispatch(
|
|
30305
30305
|
{
|
|
30306
|
-
path: hasTrailingQuestionMark ? `${
|
|
30306
|
+
path: hasTrailingQuestionMark ? `${path11}?` : path11,
|
|
30307
30307
|
origin: url2.origin,
|
|
30308
30308
|
method: request.method,
|
|
30309
30309
|
body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body2,
|
|
@@ -31218,9 +31218,9 @@ var require_util4 = __commonJS({
|
|
|
31218
31218
|
}
|
|
31219
31219
|
}
|
|
31220
31220
|
}
|
|
31221
|
-
function validateCookiePath(
|
|
31222
|
-
for (let i = 0; i <
|
|
31223
|
-
const code =
|
|
31221
|
+
function validateCookiePath(path11) {
|
|
31222
|
+
for (let i = 0; i < path11.length; ++i) {
|
|
31223
|
+
const code = path11.charCodeAt(i);
|
|
31224
31224
|
if (code < 32 || // exclude CTLs (0-31)
|
|
31225
31225
|
code > 126 || // exclude non-ascii and DEL
|
|
31226
31226
|
code === 59) {
|
|
@@ -34628,11 +34628,11 @@ var require_undici = __commonJS({
|
|
|
34628
34628
|
if (typeof opts.path !== "string") {
|
|
34629
34629
|
throw new InvalidArgumentError("invalid opts.path");
|
|
34630
34630
|
}
|
|
34631
|
-
let
|
|
34631
|
+
let path11 = opts.path;
|
|
34632
34632
|
if (!opts.path.startsWith("/")) {
|
|
34633
|
-
|
|
34633
|
+
path11 = `/${path11}`;
|
|
34634
34634
|
}
|
|
34635
|
-
url2 = new URL(util.parseOrigin(url2).origin +
|
|
34635
|
+
url2 = new URL(util.parseOrigin(url2).origin + path11);
|
|
34636
34636
|
} else {
|
|
34637
34637
|
if (!opts) {
|
|
34638
34638
|
opts = typeof url2 === "object" ? url2 : {};
|
|
@@ -34744,7 +34744,7 @@ ${captureLines}` : capture2.stack;
|
|
|
34744
34744
|
// src/job.ts
|
|
34745
34745
|
var import_yaml7 = __toESM(require_dist(), 1);
|
|
34746
34746
|
import fs9 from "node:fs/promises";
|
|
34747
|
-
import
|
|
34747
|
+
import path10 from "node:path";
|
|
34748
34748
|
|
|
34749
34749
|
// ../../node_modules/zod/v4/classic/external.js
|
|
34750
34750
|
var external_exports = {};
|
|
@@ -35562,10 +35562,10 @@ function mergeDefs(...defs) {
|
|
|
35562
35562
|
function cloneDef(schema) {
|
|
35563
35563
|
return mergeDefs(schema._zod.def);
|
|
35564
35564
|
}
|
|
35565
|
-
function getElementAtPath(obj,
|
|
35566
|
-
if (!
|
|
35565
|
+
function getElementAtPath(obj, path11) {
|
|
35566
|
+
if (!path11)
|
|
35567
35567
|
return obj;
|
|
35568
|
-
return
|
|
35568
|
+
return path11.reduce((acc, key) => acc?.[key], obj);
|
|
35569
35569
|
}
|
|
35570
35570
|
function promiseAllObject(promisesObj) {
|
|
35571
35571
|
const keys = Object.keys(promisesObj);
|
|
@@ -35905,11 +35905,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
35905
35905
|
}
|
|
35906
35906
|
return false;
|
|
35907
35907
|
}
|
|
35908
|
-
function prefixIssues(
|
|
35908
|
+
function prefixIssues(path11, issues) {
|
|
35909
35909
|
return issues.map((iss) => {
|
|
35910
35910
|
var _a3;
|
|
35911
35911
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
35912
|
-
iss.path.unshift(
|
|
35912
|
+
iss.path.unshift(path11);
|
|
35913
35913
|
return iss;
|
|
35914
35914
|
});
|
|
35915
35915
|
}
|
|
@@ -36359,16 +36359,16 @@ function flattenError(error62, mapper = (issue2) => issue2.message) {
|
|
|
36359
36359
|
}
|
|
36360
36360
|
function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
36361
36361
|
const fieldErrors = { _errors: [] };
|
|
36362
|
-
const processError = (error63,
|
|
36362
|
+
const processError = (error63, path11 = []) => {
|
|
36363
36363
|
for (const issue2 of error63.issues) {
|
|
36364
36364
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
36365
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
36365
|
+
issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
|
|
36366
36366
|
} else if (issue2.code === "invalid_key") {
|
|
36367
|
-
processError({ issues: issue2.issues }, [...
|
|
36367
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
36368
36368
|
} else if (issue2.code === "invalid_element") {
|
|
36369
|
-
processError({ issues: issue2.issues }, [...
|
|
36369
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
36370
36370
|
} else {
|
|
36371
|
-
const fullpath = [...
|
|
36371
|
+
const fullpath = [...path11, ...issue2.path];
|
|
36372
36372
|
if (fullpath.length === 0) {
|
|
36373
36373
|
fieldErrors._errors.push(mapper(issue2));
|
|
36374
36374
|
} else {
|
|
@@ -36407,17 +36407,17 @@ function formatError(error62, mapper = (issue2) => issue2.message) {
|
|
|
36407
36407
|
}
|
|
36408
36408
|
function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
36409
36409
|
const result = { errors: [] };
|
|
36410
|
-
const processError = (error63,
|
|
36410
|
+
const processError = (error63, path11 = []) => {
|
|
36411
36411
|
var _a3;
|
|
36412
36412
|
for (const issue2 of error63.issues) {
|
|
36413
36413
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
36414
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
36414
|
+
issue2.errors.map((issues) => processError({ issues }, [...path11, ...issue2.path]));
|
|
36415
36415
|
} else if (issue2.code === "invalid_key") {
|
|
36416
|
-
processError({ issues: issue2.issues }, [...
|
|
36416
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
36417
36417
|
} else if (issue2.code === "invalid_element") {
|
|
36418
|
-
processError({ issues: issue2.issues }, [...
|
|
36418
|
+
processError({ issues: issue2.issues }, [...path11, ...issue2.path]);
|
|
36419
36419
|
} else {
|
|
36420
|
-
const fullpath = [...
|
|
36420
|
+
const fullpath = [...path11, ...issue2.path];
|
|
36421
36421
|
if (fullpath.length === 0) {
|
|
36422
36422
|
result.errors.push(mapper(issue2));
|
|
36423
36423
|
continue;
|
|
@@ -36456,8 +36456,8 @@ function treeifyError(error62, mapper = (issue2) => issue2.message) {
|
|
|
36456
36456
|
}
|
|
36457
36457
|
function toDotPath(_path) {
|
|
36458
36458
|
const segs = [];
|
|
36459
|
-
const
|
|
36460
|
-
for (const seg of
|
|
36459
|
+
const path11 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
36460
|
+
for (const seg of path11) {
|
|
36461
36461
|
if (typeof seg === "number")
|
|
36462
36462
|
segs.push(`[${seg}]`);
|
|
36463
36463
|
else if (typeof seg === "symbol")
|
|
@@ -53559,13 +53559,13 @@ function resolveRef(ref, ctx) {
|
|
|
53559
53559
|
if (!ref.startsWith("#")) {
|
|
53560
53560
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
53561
53561
|
}
|
|
53562
|
-
const
|
|
53563
|
-
if (
|
|
53562
|
+
const path11 = ref.slice(1).split("/").filter(Boolean);
|
|
53563
|
+
if (path11.length === 0) {
|
|
53564
53564
|
return ctx.rootSchema;
|
|
53565
53565
|
}
|
|
53566
53566
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
53567
|
-
if (
|
|
53568
|
-
const key =
|
|
53567
|
+
if (path11[0] === defsKey) {
|
|
53568
|
+
const key = path11[1] === void 0 ? void 0 : decodeJSONPointerSegment(path11[1]);
|
|
53569
53569
|
if (!key || !ctx.defs[key]) {
|
|
53570
53570
|
throw new Error(`Reference not found: ${ref}`);
|
|
53571
53571
|
}
|
|
@@ -54452,8 +54452,8 @@ var MultipartPartSchema = external_exports.union(
|
|
|
54452
54452
|
file: relativePath("a multipart file"),
|
|
54453
54453
|
/** Absent: from the file's extension, else application/octet-stream. */
|
|
54454
54454
|
contentType: external_exports.string().min(1).optional(),
|
|
54455
|
-
/** The name sent for it; absent, the file's own. */
|
|
54456
|
-
filename: external_exports.string().
|
|
54455
|
+
/** The name sent for it; absent, the file's own. `''`, as a browser sends no file chosen. */
|
|
54456
|
+
filename: external_exports.string().optional()
|
|
54457
54457
|
})
|
|
54458
54458
|
],
|
|
54459
54459
|
{
|
|
@@ -54539,6 +54539,16 @@ var StepSchema = external_exports.looseObject({
|
|
|
54539
54539
|
tags: TagsSchema.optional(),
|
|
54540
54540
|
/** Feature flags this step needs; unmet, it is skipped (SPEC.md §2.9). */
|
|
54541
54541
|
flags: FlagConditionsSchema.optional(),
|
|
54542
|
+
/**
|
|
54543
|
+
* Send the request once for each item of a list, read as `{{item}}` and
|
|
54544
|
+
* `item` in code: `'{{roots}}'`, a variable holding a JSON array (SPEC.md §2.1).
|
|
54545
|
+
*/
|
|
54546
|
+
forEach: external_exports.string().min(1).optional(),
|
|
54547
|
+
/**
|
|
54548
|
+
* In a request set: the use step's own `tests` check this step's response,
|
|
54549
|
+
* rather than the set's last (SPEC.md §2.5). At most one step has it.
|
|
54550
|
+
*/
|
|
54551
|
+
useTests: external_exports.literal(true).optional(),
|
|
54542
54552
|
docs: external_exports.string().optional(),
|
|
54543
54553
|
headers: HeadersSchema.optional(),
|
|
54544
54554
|
body: BodySchema.optional(),
|
|
@@ -54558,6 +54568,13 @@ var StepSchema = external_exports.looseObject({
|
|
|
54558
54568
|
}
|
|
54559
54569
|
const methods = HTTP_METHODS.filter((m) => m in step);
|
|
54560
54570
|
if ("use" in step) {
|
|
54571
|
+
if ("forEach" in step) {
|
|
54572
|
+
ctx.addIssue({
|
|
54573
|
+
code: "custom",
|
|
54574
|
+
path: ["forEach"],
|
|
54575
|
+
message: "forEach repeats one request, so a use: step cannot have it (SPEC.md \xA72.1)"
|
|
54576
|
+
});
|
|
54577
|
+
}
|
|
54561
54578
|
const own2 = [...methods, ...USE_FORBIDDEN.filter((key) => key in step)];
|
|
54562
54579
|
for (const key of own2) {
|
|
54563
54580
|
ctx.addIssue({
|
|
@@ -54606,6 +54623,8 @@ var STEP_KEYS = /* @__PURE__ */ new Set([
|
|
|
54606
54623
|
"tests",
|
|
54607
54624
|
"tags",
|
|
54608
54625
|
"flags",
|
|
54626
|
+
"forEach",
|
|
54627
|
+
"useTests",
|
|
54609
54628
|
"base",
|
|
54610
54629
|
"docs"
|
|
54611
54630
|
]);
|
|
@@ -54688,8 +54707,49 @@ var CollectionSchema = external_exports.strictObject({
|
|
|
54688
54707
|
* and as `params.name` in code.
|
|
54689
54708
|
*/
|
|
54690
54709
|
params: external_exports.record(external_exports.string(), ParamSpecSchema).optional(),
|
|
54691
|
-
|
|
54710
|
+
/**
|
|
54711
|
+
* Steps run once before `steps`, and before every row of a data file:
|
|
54712
|
+
* what they set lasts the whole run (SPEC.md §2.10).
|
|
54713
|
+
*/
|
|
54714
|
+
setup: external_exports.array(StepSchema).optional(),
|
|
54715
|
+
steps: external_exports.array(StepSchema).default([]),
|
|
54716
|
+
/** Steps run once after the rest, even when they failed (SPEC.md §2.10). */
|
|
54717
|
+
teardown: external_exports.array(StepSchema).optional()
|
|
54692
54718
|
}).superRefine((collection, ctx) => {
|
|
54719
|
+
for (const stage of STAGES) {
|
|
54720
|
+
if (!collection[stage]) continue;
|
|
54721
|
+
if (collection.params) {
|
|
54722
|
+
ctx.addIssue({
|
|
54723
|
+
code: "custom",
|
|
54724
|
+
path: [stage],
|
|
54725
|
+
message: `a request set runs inside another collection, so it has no ${stage} (SPEC.md \xA72.10)`
|
|
54726
|
+
});
|
|
54727
|
+
}
|
|
54728
|
+
collection[stage].forEach((step, index) => {
|
|
54729
|
+
if (step.tags) {
|
|
54730
|
+
ctx.addIssue({
|
|
54731
|
+
code: "custom",
|
|
54732
|
+
path: [stage, index, "tags"],
|
|
54733
|
+
message: `a ${stage} step runs whenever its collection does, so it has no tags (SPEC.md \xA72.10)`
|
|
54734
|
+
});
|
|
54735
|
+
}
|
|
54736
|
+
});
|
|
54737
|
+
}
|
|
54738
|
+
const marked = collection.steps.flatMap((step, index) => step.useTests ? [index] : []);
|
|
54739
|
+
if (marked.length > 0 && !collection.params) {
|
|
54740
|
+
ctx.addIssue({
|
|
54741
|
+
code: "custom",
|
|
54742
|
+
path: ["steps", marked[0], "useTests"],
|
|
54743
|
+
message: "useTests marks the request set step whose response a use step's tests check; this collection has no params, so it is not a request set (SPEC.md \xA72.5)"
|
|
54744
|
+
});
|
|
54745
|
+
}
|
|
54746
|
+
if (marked.length > 1) {
|
|
54747
|
+
ctx.addIssue({
|
|
54748
|
+
code: "custom",
|
|
54749
|
+
path: ["steps", marked[1], "useTests"],
|
|
54750
|
+
message: `only one step can have useTests; step ${marked[0] + 1} has it already (SPEC.md \xA72.5)`
|
|
54751
|
+
});
|
|
54752
|
+
}
|
|
54693
54753
|
if (collection.params) {
|
|
54694
54754
|
collection.steps.forEach((step, index) => {
|
|
54695
54755
|
if (isUseStep(step)) {
|
|
@@ -54719,6 +54779,8 @@ var CollectionSchema = external_exports.strictObject({
|
|
|
54719
54779
|
}
|
|
54720
54780
|
});
|
|
54721
54781
|
});
|
|
54782
|
+
var STAGES = ["setup", "teardown"];
|
|
54783
|
+
var STEP_LISTS = ["setup", "steps", "teardown"];
|
|
54722
54784
|
var EnvironmentVarSchema = external_exports.union([
|
|
54723
54785
|
VarValueSchema,
|
|
54724
54786
|
external_exports.strictObject({
|
|
@@ -54813,21 +54875,21 @@ async function canonical(target) {
|
|
|
54813
54875
|
return absolute;
|
|
54814
54876
|
}
|
|
54815
54877
|
}
|
|
54816
|
-
function isInside(parent, child,
|
|
54817
|
-
const relative =
|
|
54818
|
-
const leaves = relative === ".." || relative.startsWith(`..${
|
|
54819
|
-
return relative === "" || !leaves && !
|
|
54878
|
+
function isInside(parent, child, path11 = nodePath) {
|
|
54879
|
+
const relative = path11.relative(parent, child);
|
|
54880
|
+
const leaves = relative === ".." || relative.startsWith(`..${path11.sep}`);
|
|
54881
|
+
return relative === "" || !leaves && !path11.isAbsolute(relative);
|
|
54820
54882
|
}
|
|
54821
|
-
var samePath = (a, b,
|
|
54883
|
+
var samePath = (a, b, path11 = nodePath) => path11.relative(a, b) === "";
|
|
54822
54884
|
var toPosix = (relative) => relative.split(/[\\/]+/).join("/");
|
|
54823
54885
|
var isAbsoluteAnywhere = (target) => nodePath.posix.isAbsolute(target) || nodePath.win32.isAbsolute(target);
|
|
54824
|
-
function resolveRelative(root, relative,
|
|
54886
|
+
function resolveRelative(root, relative, path11 = nodePath) {
|
|
54825
54887
|
if (isAbsoluteAnywhere(relative)) {
|
|
54826
54888
|
throw new Error(`"${relative}" must be a relative path, so it works on every machine`);
|
|
54827
54889
|
}
|
|
54828
|
-
return
|
|
54890
|
+
return path11.resolve(root, ...relative.split(/[\\/]+/).filter(Boolean));
|
|
54829
54891
|
}
|
|
54830
|
-
var relativePosix = (from, to,
|
|
54892
|
+
var relativePosix = (from, to, path11 = nodePath) => toPosix(path11.relative(from, to)) || ".";
|
|
54831
54893
|
var RESERVED = /^(con|prn|aux|nul|conin\$|conout\$|com[0-9¹²³]|lpt[0-9¹²³])(\..*)?$/i;
|
|
54832
54894
|
var FORBIDDEN = /[<>:"/\\|?*\u0000-\u001f]/;
|
|
54833
54895
|
function nameProblem(name) {
|
|
@@ -54996,40 +55058,47 @@ function decodeEntities(text) {
|
|
|
54996
55058
|
}
|
|
54997
55059
|
|
|
54998
55060
|
// ../../packages/core/src/model/path.ts
|
|
54999
|
-
|
|
55061
|
+
var SEGMENT = (
|
|
55062
|
+
// eslint-disable-next-line no-control-regex
|
|
55063
|
+
/\[("(?:[^"\\\u0000-\u001f]|\\["\\/bfnrt]|\\u[0-9a-fA-F]{4})*")\]|([^.[\]]+)|\[(\d*)\]/g
|
|
55064
|
+
);
|
|
55065
|
+
function parsePath(path11) {
|
|
55000
55066
|
const segments = [];
|
|
55001
|
-
const
|
|
55002
|
-
|
|
55003
|
-
if (match[
|
|
55004
|
-
else if (match[
|
|
55005
|
-
else segments.push({ kind: "index", index: Number(match[
|
|
55067
|
+
for (const match of path11.matchAll(SEGMENT)) {
|
|
55068
|
+
if (match[1] !== void 0) segments.push({ kind: "key", key: JSON.parse(match[1]) });
|
|
55069
|
+
else if (match[2] !== void 0) segments.push({ kind: "key", key: match[2] });
|
|
55070
|
+
else if (match[3] === "") segments.push({ kind: "each" });
|
|
55071
|
+
else segments.push({ kind: "index", index: Number(match[3]) });
|
|
55006
55072
|
}
|
|
55007
55073
|
return segments;
|
|
55008
55074
|
}
|
|
55009
55075
|
function formatPath(segments) {
|
|
55010
55076
|
let out = "";
|
|
55011
55077
|
for (const segment of segments) {
|
|
55012
|
-
if (segment.kind === "key")
|
|
55013
|
-
|
|
55078
|
+
if (segment.kind === "key") {
|
|
55079
|
+
if (!plainKey(segment.key)) out += `[${JSON.stringify(segment.key)}]`;
|
|
55080
|
+
else out += out === "" ? segment.key : `.${segment.key}`;
|
|
55081
|
+
} else if (segment.kind === "index") out += `[${segment.index}]`;
|
|
55014
55082
|
else out += "[]";
|
|
55015
55083
|
}
|
|
55016
55084
|
return out;
|
|
55017
55085
|
}
|
|
55086
|
+
var plainKey = (key) => key !== "" && !/[.[\]]/.test(key);
|
|
55018
55087
|
var isIndexKey = (key) => /^\d+$/.test(key);
|
|
55019
55088
|
function resolvePath(root, pattern) {
|
|
55020
55089
|
let frontier = [{ path: [], value: root }];
|
|
55021
55090
|
for (const segment of pattern) {
|
|
55022
55091
|
const next = [];
|
|
55023
|
-
for (const { path:
|
|
55092
|
+
for (const { path: path11, value } of frontier) {
|
|
55024
55093
|
if (segment.kind === "each") {
|
|
55025
55094
|
if (!Array.isArray(value)) continue;
|
|
55026
55095
|
value.forEach(
|
|
55027
|
-
(item, index) => next.push({ path: [...
|
|
55096
|
+
(item, index) => next.push({ path: [...path11, { kind: "index", index }], value: item })
|
|
55028
55097
|
);
|
|
55029
55098
|
continue;
|
|
55030
55099
|
}
|
|
55031
55100
|
const step = childOf(value, segment);
|
|
55032
|
-
if (step) next.push({ path: [...
|
|
55101
|
+
if (step) next.push({ path: [...path11, step.segment], value: step.value });
|
|
55033
55102
|
}
|
|
55034
55103
|
frontier = next;
|
|
55035
55104
|
}
|
|
@@ -55047,17 +55116,17 @@ function childOf(value, segment) {
|
|
|
55047
55116
|
}
|
|
55048
55117
|
function sortArraysBy(value, properties) {
|
|
55049
55118
|
const paths = properties.map(parsePath);
|
|
55050
|
-
const sortValue = (item,
|
|
55119
|
+
const sortValue = (item, path11) => item !== null && typeof item === "object" && !Array.isArray(item) ? resolvePath(item, path11)[0]?.value : void 0;
|
|
55051
55120
|
const visit2 = (node2) => {
|
|
55052
55121
|
if (Array.isArray(node2)) {
|
|
55053
55122
|
const items = node2.map(visit2);
|
|
55054
55123
|
const sortable = paths.some(
|
|
55055
|
-
(
|
|
55124
|
+
(path11) => items.some((item) => sortValue(item, path11) !== void 0)
|
|
55056
55125
|
);
|
|
55057
55126
|
if (!sortable) return items;
|
|
55058
55127
|
return items.map((item, index) => ({ item, index })).sort((a, b) => {
|
|
55059
|
-
for (const
|
|
55060
|
-
const order = compareAlphanumerically(sortValue(a.item,
|
|
55128
|
+
for (const path11 of paths) {
|
|
55129
|
+
const order = compareAlphanumerically(sortValue(a.item, path11), sortValue(b.item, path11));
|
|
55061
55130
|
if (order !== 0) return order;
|
|
55062
55131
|
}
|
|
55063
55132
|
return a.index - b.index;
|
|
@@ -55156,7 +55225,7 @@ var RunErrorSchema = external_exports.object({
|
|
|
55156
55225
|
* Which stage failed, so the UI can say where without guessing. `body` is a
|
|
55157
55226
|
* file the body names that could not be read (SPEC.md §2.2).
|
|
55158
55227
|
*/
|
|
55159
|
-
phase: external_exports.enum(["use", "flags", "interpolate", "body", "pre-request", "http", "tests"]),
|
|
55228
|
+
phase: external_exports.enum(["use", "flags", "forEach", "interpolate", "body", "pre-request", "http", "tests"]),
|
|
55160
55229
|
message: external_exports.string(),
|
|
55161
55230
|
code: external_exports.string().optional(),
|
|
55162
55231
|
stack: external_exports.string().optional(),
|
|
@@ -55188,16 +55257,30 @@ var RunResultSchema = external_exports.object({
|
|
|
55188
55257
|
logs: external_exports.array(LogEntrySchema).optional(),
|
|
55189
55258
|
error: RunErrorSchema.nullable(),
|
|
55190
55259
|
status: RunStatusSchema,
|
|
55191
|
-
/**
|
|
55260
|
+
/**
|
|
55261
|
+
* Why a `skipped` step did not run: a feature flag it needs (SPEC.md §2.9),
|
|
55262
|
+
* `gta.skip` or `gta.skipRest` (§5), or an empty `forEach` list.
|
|
55263
|
+
*/
|
|
55192
55264
|
skipped: external_exports.object({ reason: external_exports.string() }).optional(),
|
|
55193
55265
|
/** Wall-clock milliseconds for the whole item, scripts included. */
|
|
55194
55266
|
durationMs: external_exports.number(),
|
|
55195
55267
|
/**
|
|
55196
|
-
* For a request run by a use step:
|
|
55197
|
-
*
|
|
55268
|
+
* For a request run by a use step: the set as `use:` names it, the use
|
|
55269
|
+
* step's own `name` when it has one, and which step of the set it was
|
|
55270
|
+
* (0-based) of how many. Absent for a collection's own request.
|
|
55198
55271
|
*/
|
|
55199
|
-
use: external_exports.object({ set: external_exports.string(), child: external_exports.number(), of: external_exports.number() }).optional()
|
|
55200
|
-
|
|
55272
|
+
use: external_exports.object({ set: external_exports.string(), name: external_exports.string().optional(), child: external_exports.number(), of: external_exports.number() }).optional(),
|
|
55273
|
+
/** For a `setup` or `teardown` step: which list it is in (SPEC.md §2.10). Absent for `steps`. */
|
|
55274
|
+
stage: external_exports.enum(["setup", "teardown"]).optional(),
|
|
55275
|
+
/** For a step with `forEach`: which item this request was for, from 0, of how many. */
|
|
55276
|
+
forEach: external_exports.object({ index: external_exports.number(), of: external_exports.number(), item: external_exports.string() }).optional()
|
|
55277
|
+
});
|
|
55278
|
+
function resultName(result) {
|
|
55279
|
+
const use = result.use;
|
|
55280
|
+
const name = !use?.name ? result.item.name : use.of === 1 ? use.name : `${use.name} \u203A ${result.item.name}`;
|
|
55281
|
+
const each = result.forEach ? ` (item ${result.forEach.index + 1} of ${result.forEach.of})` : "";
|
|
55282
|
+
return `${result.stage ? `${result.stage} \u203A ` : ""}${name}${each}`;
|
|
55283
|
+
}
|
|
55201
55284
|
var CollectionRunSummarySchema = external_exports.object({
|
|
55202
55285
|
total: external_exports.number(),
|
|
55203
55286
|
passed: external_exports.number(),
|
|
@@ -55544,8 +55627,8 @@ var FormatError = class extends Error {
|
|
|
55544
55627
|
};
|
|
55545
55628
|
function describeValidation(error62) {
|
|
55546
55629
|
return error62.issues.map((issue2) => {
|
|
55547
|
-
const
|
|
55548
|
-
return
|
|
55630
|
+
const path11 = issue2.path.join(".");
|
|
55631
|
+
return path11 ? `${path11}: ${issue2.message}` : issue2.message;
|
|
55549
55632
|
}).join("; ");
|
|
55550
55633
|
}
|
|
55551
55634
|
|
|
@@ -55578,8 +55661,10 @@ var STEP_KEY_ORDER = [
|
|
|
55578
55661
|
"use",
|
|
55579
55662
|
"with",
|
|
55580
55663
|
...HTTP_METHODS,
|
|
55664
|
+
"forEach",
|
|
55581
55665
|
"tags",
|
|
55582
55666
|
"flags",
|
|
55667
|
+
"useTests",
|
|
55583
55668
|
"base",
|
|
55584
55669
|
"docs",
|
|
55585
55670
|
"headers",
|
|
@@ -55631,116 +55716,36 @@ var runtime = defaultRuntime();
|
|
|
55631
55716
|
// ../../packages/core/src/git/diff.ts
|
|
55632
55717
|
var MAX_DIFF_BYTES = 2 * 1024 * 1024;
|
|
55633
55718
|
|
|
55634
|
-
// ../../packages/core/src/workspace/collection.ts
|
|
55635
|
-
import fs4 from "node:fs/promises";
|
|
55636
|
-
import path4 from "node:path";
|
|
55637
|
-
|
|
55638
|
-
// ../../packages/core/src/workspace/ids.ts
|
|
55639
|
-
import path from "node:path";
|
|
55640
|
-
var ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
55641
|
-
var idOfFile = (file2) => path.basename(file2, DOC_EXTENSION);
|
|
55642
|
-
function idProblem(doc, file2) {
|
|
55643
|
-
const expected = idOfFile(file2);
|
|
55644
|
-
if (!ID_PATTERN.test(expected)) {
|
|
55645
|
-
return `${expected}${DOC_EXTENSION}: a collection's file name is its id, and an id is letters, digits and - _ . (SPEC.md \xA72)`;
|
|
55646
|
-
}
|
|
55647
|
-
const unusable = nameProblem(path.basename(file2));
|
|
55648
|
-
if (unusable) return `${path.basename(file2)}: ${unusable} (SPEC.md \xA71.2)`;
|
|
55649
|
-
if (doc.id === void 0) {
|
|
55650
|
-
return `id: missing \u2014 a collection file says its id, its file name: id: ${expected} (SPEC.md \xA72)`;
|
|
55651
|
-
}
|
|
55652
|
-
if (doc.id !== expected) {
|
|
55653
|
-
return `id: ${doc.id} does not match the file name, ${expected}${DOC_EXTENSION} \u2014 they must be the same (SPEC.md \xA72)`;
|
|
55654
|
-
}
|
|
55655
|
-
return null;
|
|
55656
|
-
}
|
|
55657
|
-
function duplicateIds(files, home) {
|
|
55658
|
-
const byId = /* @__PURE__ */ new Map();
|
|
55659
|
-
for (const file2 of files) {
|
|
55660
|
-
const key = idOfFile(file2).toLowerCase();
|
|
55661
|
-
byId.set(key, [...byId.get(key) ?? [], file2]);
|
|
55662
|
-
}
|
|
55663
|
-
const problems = /* @__PURE__ */ new Map();
|
|
55664
|
-
for (const group of byId.values()) {
|
|
55665
|
-
if (group.length < 2) continue;
|
|
55666
|
-
for (const file2 of group) {
|
|
55667
|
-
const others = group.filter((other) => other !== file2).map((other) => `${path.basename(home)}/${relativePosix(home, other)}`);
|
|
55668
|
-
problems.set(
|
|
55669
|
-
file2,
|
|
55670
|
-
`id: ${idOfFile(file2)} is also the id of ${others.join(", ")} \u2014 an id is unique in ${path.basename(home)}/, ignoring case (SPEC.md \xA72)`
|
|
55671
|
-
);
|
|
55672
|
-
}
|
|
55673
|
-
}
|
|
55674
|
-
return problems;
|
|
55675
|
-
}
|
|
55676
|
-
|
|
55677
|
-
// ../../packages/core/src/workspace/dataFile.ts
|
|
55678
|
-
import fs2 from "node:fs/promises";
|
|
55679
|
-
import path2 from "node:path";
|
|
55680
|
-
var MAX_BYTES = 10 * 1024 * 1024;
|
|
55681
|
-
async function findDataFile(collectionFile) {
|
|
55682
|
-
const base2 = collectionFile.endsWith(DOC_EXTENSION) ? collectionFile.slice(0, -DOC_EXTENSION.length) : collectionFile;
|
|
55683
|
-
for (const extension of [".csv", ".json"]) {
|
|
55684
|
-
try {
|
|
55685
|
-
const candidate = `${base2}${extension}`;
|
|
55686
|
-
const names = await fs2.readdir(path2.dirname(candidate));
|
|
55687
|
-
if (names.includes(path2.basename(candidate))) return candidate;
|
|
55688
|
-
} catch {
|
|
55689
|
-
return null;
|
|
55690
|
-
}
|
|
55691
|
-
}
|
|
55692
|
-
return null;
|
|
55693
|
-
}
|
|
55694
|
-
async function readDataTable(file2) {
|
|
55695
|
-
const stat = await fs2.stat(file2);
|
|
55696
|
-
if (stat.size > MAX_BYTES) {
|
|
55697
|
-
throw new DataFileError(`${path2.basename(file2)}: larger than ${MAX_BYTES / 1024 / 1024} MB`);
|
|
55698
|
-
}
|
|
55699
|
-
const source = await fs2.readFile(file2, "utf8");
|
|
55700
|
-
return { source, table: parseDataTable(source, path2.basename(file2), dataKindOf(file2)) };
|
|
55701
|
-
}
|
|
55702
|
-
var rowsOf = (table) => table.rows.map((values) => ({ values, label: rowLabel(values) }));
|
|
55703
|
-
async function readDataFile(file2) {
|
|
55704
|
-
const { table } = await readDataTable(file2);
|
|
55705
|
-
const problem = dataTableProblems(table)[0];
|
|
55706
|
-
if (problem) throw new DataFileError(`${path2.basename(file2)}: ${problem}`);
|
|
55707
|
-
return { path: file2, rows: rowsOf(table) };
|
|
55708
|
-
}
|
|
55709
|
-
async function loadDataFile(collectionFile) {
|
|
55710
|
-
const file2 = await findDataFile(collectionFile);
|
|
55711
|
-
return file2 ? readDataFile(file2) : null;
|
|
55712
|
-
}
|
|
55713
|
-
|
|
55714
55719
|
// ../../packages/core/src/workspace/project.ts
|
|
55715
|
-
import
|
|
55716
|
-
import
|
|
55720
|
+
import fs2 from "node:fs/promises";
|
|
55721
|
+
import path from "node:path";
|
|
55717
55722
|
var HOMES = /* @__PURE__ */ new Set([COLLECTIONS_DIR, REQUESTS_DIR, ENDPOINTS_DIR, BASES_DIR]);
|
|
55718
55723
|
function projectRootOf(collectionFile) {
|
|
55719
|
-
const directory =
|
|
55720
|
-
if (HOMES.has(
|
|
55721
|
-
const parent =
|
|
55722
|
-
if (HOMES.has(
|
|
55724
|
+
const directory = path.dirname(path.resolve(collectionFile));
|
|
55725
|
+
if (HOMES.has(path.basename(directory))) return path.dirname(directory);
|
|
55726
|
+
const parent = path.dirname(directory);
|
|
55727
|
+
if (HOMES.has(path.basename(parent))) return path.dirname(parent);
|
|
55723
55728
|
return null;
|
|
55724
55729
|
}
|
|
55725
55730
|
function directoryOf(collectionFile) {
|
|
55726
|
-
const directory =
|
|
55727
|
-
return HOMES.has(
|
|
55731
|
+
const directory = path.dirname(path.resolve(collectionFile));
|
|
55732
|
+
return HOMES.has(path.basename(directory)) ? null : path.basename(directory);
|
|
55728
55733
|
}
|
|
55729
55734
|
var isHidden = (name) => name.startsWith(".") || IGNORED_DIRECTORIES.has(name);
|
|
55730
55735
|
var isCollectionFile = (name) => name.endsWith(DOC_EXTENSION) && !name.startsWith(".");
|
|
55731
55736
|
async function discoverProject(root) {
|
|
55732
|
-
const collectionsDir =
|
|
55737
|
+
const collectionsDir = path.join(root, COLLECTIONS_DIR);
|
|
55733
55738
|
const layout = { root, collectionsDir, files: [], directories: [], problems: [] };
|
|
55734
55739
|
const entries2 = await readDir(collectionsDir);
|
|
55735
55740
|
for (const entry of entries2) {
|
|
55736
55741
|
if (entry.isFile() && isCollectionFile(entry.name)) {
|
|
55737
|
-
layout.files.push(
|
|
55742
|
+
layout.files.push(path.join(collectionsDir, entry.name));
|
|
55738
55743
|
} else if (entry.isDirectory() && !isHidden(entry.name)) {
|
|
55739
55744
|
layout.directories.push(entry.name);
|
|
55740
|
-
const directory =
|
|
55745
|
+
const directory = path.join(collectionsDir, entry.name);
|
|
55741
55746
|
for (const inner of await readDir(directory)) {
|
|
55742
55747
|
if (inner.isFile() && isCollectionFile(inner.name)) {
|
|
55743
|
-
layout.files.push(
|
|
55748
|
+
layout.files.push(path.join(directory, inner.name));
|
|
55744
55749
|
} else if (inner.isDirectory() && !isHidden(inner.name)) {
|
|
55745
55750
|
layout.problems.push({
|
|
55746
55751
|
path: `${entry.name}/${inner.name}`,
|
|
@@ -55780,14 +55785,14 @@ async function portabilityProblems(root) {
|
|
|
55780
55785
|
}
|
|
55781
55786
|
}
|
|
55782
55787
|
for (const home of [COLLECTIONS_DIR, REQUESTS_DIR, ENDPOINTS_DIR, BASES_DIR]) {
|
|
55783
|
-
const directories = (await readDir(
|
|
55788
|
+
const directories = (await readDir(path.join(root, home))).filter((entry) => entry.isDirectory() && !isHidden(entry.name)).map((entry) => entry.name);
|
|
55784
55789
|
problems.push(...portableNameProblems(home, directories));
|
|
55785
55790
|
}
|
|
55786
55791
|
for (const [home, extension] of [
|
|
55787
55792
|
[ENVIRONMENTS_DIR, DOC_EXTENSION],
|
|
55788
55793
|
[CHECKS_DIR, ".js"]
|
|
55789
55794
|
]) {
|
|
55790
|
-
const files = (await readDir(
|
|
55795
|
+
const files = (await readDir(path.join(root, home))).filter((entry) => entry.isFile() && entry.name.endsWith(extension)).map((entry) => entry.name);
|
|
55791
55796
|
problems.push(...portableNameProblems(home, files));
|
|
55792
55797
|
}
|
|
55793
55798
|
return problems;
|
|
@@ -55856,7 +55861,7 @@ async function readProject(root) {
|
|
|
55856
55861
|
async function readProjectFile(root) {
|
|
55857
55862
|
let source;
|
|
55858
55863
|
try {
|
|
55859
|
-
source = await
|
|
55864
|
+
source = await fs2.readFile(path.join(root, PROJECT_FILE), "utf8");
|
|
55860
55865
|
} catch {
|
|
55861
55866
|
return { doc: null, source: null, problem: null };
|
|
55862
55867
|
}
|
|
@@ -55874,18 +55879,18 @@ async function readProjectFile(root) {
|
|
|
55874
55879
|
}
|
|
55875
55880
|
}
|
|
55876
55881
|
async function projectEnvironments(root, global) {
|
|
55877
|
-
const own2 = await readEnvironments(
|
|
55878
|
-
const shared = global ? await readEnvironments(
|
|
55882
|
+
const own2 = await readEnvironments(path.join(root, ENVIRONMENTS_DIR), "project");
|
|
55883
|
+
const shared = global ? await readEnvironments(path.join(global.root, ENVIRONMENTS_DIR), "global") : [];
|
|
55879
55884
|
return [...own2, ...shared];
|
|
55880
55885
|
}
|
|
55881
55886
|
async function readEnvironments(directory, source = "project") {
|
|
55882
55887
|
const environments = [];
|
|
55883
55888
|
for (const entry of await readDir(directory)) {
|
|
55884
55889
|
if (!entry.isFile() || !entry.name.endsWith(DOC_EXTENSION)) continue;
|
|
55885
|
-
const file2 =
|
|
55886
|
-
let name =
|
|
55890
|
+
const file2 = path.join(directory, entry.name);
|
|
55891
|
+
let name = path.basename(entry.name, DOC_EXTENSION);
|
|
55887
55892
|
try {
|
|
55888
|
-
name = parseEnvironment(await
|
|
55893
|
+
name = parseEnvironment(await fs2.readFile(file2, "utf8"), file2).data.name ?? name;
|
|
55889
55894
|
} catch {
|
|
55890
55895
|
}
|
|
55891
55896
|
environments.push({ name, path: file2, source });
|
|
@@ -55894,12 +55899,92 @@ async function readEnvironments(directory, source = "project") {
|
|
|
55894
55899
|
}
|
|
55895
55900
|
async function readDir(directory) {
|
|
55896
55901
|
try {
|
|
55897
|
-
return await
|
|
55902
|
+
return await fs2.readdir(directory, { withFileTypes: true });
|
|
55898
55903
|
} catch {
|
|
55899
55904
|
return [];
|
|
55900
55905
|
}
|
|
55901
55906
|
}
|
|
55902
55907
|
|
|
55908
|
+
// ../../packages/core/src/workspace/collection.ts
|
|
55909
|
+
import fs4 from "node:fs/promises";
|
|
55910
|
+
import path4 from "node:path";
|
|
55911
|
+
|
|
55912
|
+
// ../../packages/core/src/workspace/ids.ts
|
|
55913
|
+
import path2 from "node:path";
|
|
55914
|
+
var ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
55915
|
+
var idOfFile = (file2) => path2.basename(file2, DOC_EXTENSION);
|
|
55916
|
+
function idProblem(doc, file2) {
|
|
55917
|
+
const expected = idOfFile(file2);
|
|
55918
|
+
if (!ID_PATTERN.test(expected)) {
|
|
55919
|
+
return `${expected}${DOC_EXTENSION}: a collection's file name is its id, and an id is letters, digits and - _ . (SPEC.md \xA72)`;
|
|
55920
|
+
}
|
|
55921
|
+
const unusable = nameProblem(path2.basename(file2));
|
|
55922
|
+
if (unusable) return `${path2.basename(file2)}: ${unusable} (SPEC.md \xA71.2)`;
|
|
55923
|
+
if (doc.id === void 0) {
|
|
55924
|
+
return `id: missing \u2014 a collection file says its id, its file name: id: ${expected} (SPEC.md \xA72)`;
|
|
55925
|
+
}
|
|
55926
|
+
if (doc.id !== expected) {
|
|
55927
|
+
return `id: ${doc.id} does not match the file name, ${expected}${DOC_EXTENSION} \u2014 they must be the same (SPEC.md \xA72)`;
|
|
55928
|
+
}
|
|
55929
|
+
return null;
|
|
55930
|
+
}
|
|
55931
|
+
function duplicateIds(files, home) {
|
|
55932
|
+
const byId = /* @__PURE__ */ new Map();
|
|
55933
|
+
for (const file2 of files) {
|
|
55934
|
+
const key = idOfFile(file2).toLowerCase();
|
|
55935
|
+
byId.set(key, [...byId.get(key) ?? [], file2]);
|
|
55936
|
+
}
|
|
55937
|
+
const problems = /* @__PURE__ */ new Map();
|
|
55938
|
+
for (const group of byId.values()) {
|
|
55939
|
+
if (group.length < 2) continue;
|
|
55940
|
+
for (const file2 of group) {
|
|
55941
|
+
const others = group.filter((other) => other !== file2).map((other) => `${path2.basename(home)}/${relativePosix(home, other)}`);
|
|
55942
|
+
problems.set(
|
|
55943
|
+
file2,
|
|
55944
|
+
`id: ${idOfFile(file2)} is also the id of ${others.join(", ")} \u2014 an id is unique in ${path2.basename(home)}/, ignoring case (SPEC.md \xA72)`
|
|
55945
|
+
);
|
|
55946
|
+
}
|
|
55947
|
+
}
|
|
55948
|
+
return problems;
|
|
55949
|
+
}
|
|
55950
|
+
|
|
55951
|
+
// ../../packages/core/src/workspace/dataFile.ts
|
|
55952
|
+
import fs3 from "node:fs/promises";
|
|
55953
|
+
import path3 from "node:path";
|
|
55954
|
+
var MAX_BYTES = 10 * 1024 * 1024;
|
|
55955
|
+
async function findDataFile(collectionFile) {
|
|
55956
|
+
const base2 = collectionFile.endsWith(DOC_EXTENSION) ? collectionFile.slice(0, -DOC_EXTENSION.length) : collectionFile;
|
|
55957
|
+
for (const extension of [".csv", ".json"]) {
|
|
55958
|
+
try {
|
|
55959
|
+
const candidate = `${base2}${extension}`;
|
|
55960
|
+
const names = await fs3.readdir(path3.dirname(candidate));
|
|
55961
|
+
if (names.includes(path3.basename(candidate))) return candidate;
|
|
55962
|
+
} catch {
|
|
55963
|
+
return null;
|
|
55964
|
+
}
|
|
55965
|
+
}
|
|
55966
|
+
return null;
|
|
55967
|
+
}
|
|
55968
|
+
async function readDataTable(file2) {
|
|
55969
|
+
const stat = await fs3.stat(file2);
|
|
55970
|
+
if (stat.size > MAX_BYTES) {
|
|
55971
|
+
throw new DataFileError(`${path3.basename(file2)}: larger than ${MAX_BYTES / 1024 / 1024} MB`);
|
|
55972
|
+
}
|
|
55973
|
+
const source = await fs3.readFile(file2, "utf8");
|
|
55974
|
+
return { source, table: parseDataTable(source, path3.basename(file2), dataKindOf(file2)) };
|
|
55975
|
+
}
|
|
55976
|
+
var rowsOf = (table) => table.rows.map((values) => ({ values, label: rowLabel(values) }));
|
|
55977
|
+
async function readDataFile(file2) {
|
|
55978
|
+
const { table } = await readDataTable(file2);
|
|
55979
|
+
const problem = dataTableProblems(table)[0];
|
|
55980
|
+
if (problem) throw new DataFileError(`${path3.basename(file2)}: ${problem}`);
|
|
55981
|
+
return { path: file2, rows: rowsOf(table) };
|
|
55982
|
+
}
|
|
55983
|
+
async function loadDataFile(collectionFile) {
|
|
55984
|
+
const file2 = await findDataFile(collectionFile);
|
|
55985
|
+
return file2 ? readDataFile(file2) : null;
|
|
55986
|
+
}
|
|
55987
|
+
|
|
55903
55988
|
// ../../packages/core/src/workspace/collection.ts
|
|
55904
55989
|
async function loadCollection(file2, root) {
|
|
55905
55990
|
const absolute = path4.resolve(file2);
|
|
@@ -56223,6 +56308,7 @@ async function loadEndpoints(root, global) {
|
|
|
56223
56308
|
}
|
|
56224
56309
|
function baseProblem(doc) {
|
|
56225
56310
|
if (doc.steps.length > 0) return "a base collection has no steps of its own";
|
|
56311
|
+
if (doc.setup || doc.teardown) return "a base collection has no setup or teardown";
|
|
56226
56312
|
if (doc.params) return "a base collection has no params";
|
|
56227
56313
|
if (doc.extends) return "a base collection cannot extend another (SPEC.md \xA72.7)";
|
|
56228
56314
|
return void 0;
|
|
@@ -56451,6 +56537,14 @@ var VariableScope = class {
|
|
|
56451
56537
|
* `gta.flag`; null when none are known, so any flag named is unknown.
|
|
56452
56538
|
*/
|
|
56453
56539
|
flags = null;
|
|
56540
|
+
/**
|
|
56541
|
+
* Values that last the whole collection run, across its data rows and into
|
|
56542
|
+
* teardown (SPEC.md §2.10): where `gta.set(…, { scope: 'run' })` writes.
|
|
56543
|
+
* Null outside a collection run, where there is nothing to outlast.
|
|
56544
|
+
*/
|
|
56545
|
+
runValues = null;
|
|
56546
|
+
/** In setup and teardown, every value set lasts the run. */
|
|
56547
|
+
runWide = false;
|
|
56454
56548
|
values = /* @__PURE__ */ new Map();
|
|
56455
56549
|
origins = /* @__PURE__ */ new Map();
|
|
56456
56550
|
secrets = /* @__PURE__ */ new Set();
|
|
@@ -56494,6 +56588,12 @@ var VariableScope = class {
|
|
|
56494
56588
|
set(name, value, source = "runtime") {
|
|
56495
56589
|
this.values.set(name, value);
|
|
56496
56590
|
this.origins.set(name, source);
|
|
56591
|
+
if (this.runWide) this.runValues?.set(name, value);
|
|
56592
|
+
}
|
|
56593
|
+
/** `set`, and keep the value for every row after this one and for teardown. */
|
|
56594
|
+
setForRun(name, value, source = "runtime") {
|
|
56595
|
+
this.set(name, value, source);
|
|
56596
|
+
this.runValues?.set(name, value);
|
|
56497
56597
|
}
|
|
56498
56598
|
names() {
|
|
56499
56599
|
return [...this.values.keys()].sort();
|
|
@@ -56503,35 +56603,49 @@ var VariableScope = class {
|
|
|
56503
56603
|
return Object.fromEntries(this.values);
|
|
56504
56604
|
}
|
|
56505
56605
|
};
|
|
56506
|
-
var
|
|
56507
|
-
constructor(run,
|
|
56606
|
+
var OverlayScope = class extends VariableScope {
|
|
56607
|
+
constructor(run, own2, origin) {
|
|
56508
56608
|
super();
|
|
56509
56609
|
this.run = run;
|
|
56510
|
-
this.
|
|
56610
|
+
this.own = own2;
|
|
56611
|
+
this.origin = origin;
|
|
56511
56612
|
this.flags = run.flags;
|
|
56512
56613
|
}
|
|
56513
56614
|
run;
|
|
56514
|
-
|
|
56615
|
+
own;
|
|
56616
|
+
origin;
|
|
56515
56617
|
has(name) {
|
|
56516
|
-
return this.
|
|
56618
|
+
return this.own.has(name) || this.run.has(name);
|
|
56517
56619
|
}
|
|
56518
56620
|
get(name) {
|
|
56519
|
-
return this.
|
|
56621
|
+
return this.own.has(name) ? this.own.get(name) : this.run.get(name);
|
|
56520
56622
|
}
|
|
56521
56623
|
isSecret(name) {
|
|
56522
|
-
return !this.
|
|
56624
|
+
return !this.own.has(name) && this.run.isSecret(name);
|
|
56523
56625
|
}
|
|
56524
56626
|
originOf(name) {
|
|
56525
|
-
return this.
|
|
56627
|
+
return this.own.has(name) ? this.origin : this.run.originOf(name);
|
|
56526
56628
|
}
|
|
56527
56629
|
set(name, value, source = "runtime") {
|
|
56528
56630
|
this.run.set(name, value, source);
|
|
56529
56631
|
}
|
|
56632
|
+
setForRun(name, value, source = "runtime") {
|
|
56633
|
+
this.run.setForRun(name, value, source);
|
|
56634
|
+
}
|
|
56530
56635
|
names() {
|
|
56531
|
-
return [.../* @__PURE__ */ new Set([...this.
|
|
56636
|
+
return [.../* @__PURE__ */ new Set([...this.own.keys(), ...this.run.names()])].sort();
|
|
56532
56637
|
}
|
|
56533
56638
|
all() {
|
|
56534
|
-
return { ...this.run.all(), ...Object.fromEntries(this.
|
|
56639
|
+
return { ...this.run.all(), ...Object.fromEntries(this.own) };
|
|
56640
|
+
}
|
|
56641
|
+
};
|
|
56642
|
+
var ParamsScope = class extends OverlayScope {
|
|
56643
|
+
constructor(run, params) {
|
|
56644
|
+
super(
|
|
56645
|
+
run,
|
|
56646
|
+
new Map(Object.entries(params).map(([name, value]) => [`params.${name}`, value])),
|
|
56647
|
+
"params"
|
|
56648
|
+
);
|
|
56535
56649
|
}
|
|
56536
56650
|
};
|
|
56537
56651
|
var BUILT_INS = {
|
|
@@ -56545,19 +56659,19 @@ var BUILT_INS = {
|
|
|
56545
56659
|
var REFERENCE = /\{\{\s*([^{}\s]+)\s*\}\}/g;
|
|
56546
56660
|
var SOLE_REFERENCE = /^\{\{\s*([^{}\s]+)\s*\}\}$/;
|
|
56547
56661
|
var MAX_DEPTH = 16;
|
|
56548
|
-
function interpolate(value, scope) {
|
|
56662
|
+
function interpolate(value, scope, options = {}) {
|
|
56549
56663
|
const sole = SOLE_REFERENCE.exec(value);
|
|
56550
56664
|
if (sole?.[1]) {
|
|
56551
56665
|
const resolved = resolveName(sole[1], scope, []);
|
|
56552
|
-
return typeof resolved === "string" ? resolveString(resolved, scope, [sole[1]]) : resolved;
|
|
56666
|
+
return typeof resolved === "string" ? resolveString(resolved, scope, [sole[1]], options) : resolved;
|
|
56553
56667
|
}
|
|
56554
|
-
return resolveString(value, scope, []);
|
|
56668
|
+
return resolveString(value, scope, [], options);
|
|
56555
56669
|
}
|
|
56556
|
-
function interpolateToString(value, scope) {
|
|
56557
|
-
const result = interpolate(value, scope);
|
|
56558
|
-
return result === null || result === void 0 ? "" : String(result);
|
|
56670
|
+
function interpolateToString(value, scope, options = {}) {
|
|
56671
|
+
const result = interpolate(value, scope, options);
|
|
56672
|
+
return result === null || result === void 0 ? options.nullAs ?? "" : String(result);
|
|
56559
56673
|
}
|
|
56560
|
-
function resolveString(text, scope, seen) {
|
|
56674
|
+
function resolveString(text, scope, seen, options) {
|
|
56561
56675
|
if (seen.length > MAX_DEPTH) {
|
|
56562
56676
|
throw new InterpolationError(
|
|
56563
56677
|
`Variable nesting is too deep (${seen.join(" -> ")}); this is probably a loop`
|
|
@@ -56571,11 +56685,12 @@ function resolveString(text, scope, seen) {
|
|
|
56571
56685
|
);
|
|
56572
56686
|
}
|
|
56573
56687
|
const resolved = resolveName(name, scope, seen);
|
|
56574
|
-
if (resolved === null || resolved === void 0) return "";
|
|
56575
|
-
return typeof resolved === "string" ? resolveString(resolved, scope, [...seen, name]) : String(resolved);
|
|
56688
|
+
if (resolved === null || resolved === void 0) return options.nullAs ?? "";
|
|
56689
|
+
return typeof resolved === "string" ? resolveString(resolved, scope, [...seen, name], options) : String(resolved);
|
|
56576
56690
|
});
|
|
56577
56691
|
}
|
|
56578
56692
|
function resolveName(name, scope, seen) {
|
|
56693
|
+
if (name.length > 1 && name.startsWith("@")) return resolveNamed(name, scope, seen);
|
|
56579
56694
|
const builtIn = BUILT_INS[name];
|
|
56580
56695
|
if (builtIn) return builtIn();
|
|
56581
56696
|
if (!scope.has(name)) {
|
|
@@ -56592,6 +56707,31 @@ function resolveName(name, scope, seen) {
|
|
|
56592
56707
|
}
|
|
56593
56708
|
return value;
|
|
56594
56709
|
}
|
|
56710
|
+
function resolveNamed(name, scope, seen) {
|
|
56711
|
+
const holder = name.slice(1);
|
|
56712
|
+
const through = [...seen, name];
|
|
56713
|
+
const held = resolveName(holder, scope, through);
|
|
56714
|
+
const target = typeof held === "string" ? resolveString(held, scope, [...through, holder], {}) : held;
|
|
56715
|
+
if (typeof target !== "string" || target.trim() === "") {
|
|
56716
|
+
throw new InterpolationError(
|
|
56717
|
+
`{{${name}}} reads the variable ${holder} names, but ${holder} is ${JSON.stringify(target)}, not a variable name`,
|
|
56718
|
+
holder
|
|
56719
|
+
);
|
|
56720
|
+
}
|
|
56721
|
+
if (through.includes(target)) {
|
|
56722
|
+
throw new InterpolationError(
|
|
56723
|
+
`Variable "${target}" refers to itself: ${[...through, target].join(" -> ")}`,
|
|
56724
|
+
target
|
|
56725
|
+
);
|
|
56726
|
+
}
|
|
56727
|
+
if (!BUILT_INS[target] && !target.startsWith("@") && !scope.has(target)) {
|
|
56728
|
+
throw new InterpolationError(
|
|
56729
|
+
`Variable "${target}", which {{${name}}} names, is not defined in this environment.`,
|
|
56730
|
+
target
|
|
56731
|
+
);
|
|
56732
|
+
}
|
|
56733
|
+
return resolveName(target, scope, through);
|
|
56734
|
+
}
|
|
56595
56735
|
|
|
56596
56736
|
// ../../packages/core/src/vars/resolve.ts
|
|
56597
56737
|
import fs7 from "node:fs/promises";
|
|
@@ -56623,9 +56763,14 @@ async function buildScope(context) {
|
|
|
56623
56763
|
if (context.environmentName) {
|
|
56624
56764
|
layers.push(...await environmentLayers(context, context.environmentName));
|
|
56625
56765
|
}
|
|
56766
|
+
if (context.run) layers.push({ source: "run", vars: Object.fromEntries(context.run.values) });
|
|
56626
56767
|
const row = context.dataRow !== void 0 ? context.dataRow : await firstRow(context.collectionPath);
|
|
56627
56768
|
if (row) layers.push(row);
|
|
56628
56769
|
const scope = new VariableScope(layers, context.env ?? process.env);
|
|
56770
|
+
if (context.run) {
|
|
56771
|
+
scope.runValues = context.run.values;
|
|
56772
|
+
scope.runWide = context.run.wide === true;
|
|
56773
|
+
}
|
|
56629
56774
|
scope.flags = context.flags !== void 0 ? context.flags : context.environmentName ? (await environmentFlags(root, context.environmentName, context.environments)).values : null;
|
|
56630
56775
|
return scope;
|
|
56631
56776
|
}
|
|
@@ -57074,7 +57219,8 @@ import fs8 from "node:fs/promises";
|
|
|
57074
57219
|
var BodyFileError = class extends Error {
|
|
57075
57220
|
name = "BodyFileError";
|
|
57076
57221
|
};
|
|
57077
|
-
|
|
57222
|
+
var GLOBAL_FILE = "global:";
|
|
57223
|
+
async function prepareRequest(written, body, scope, files) {
|
|
57078
57224
|
const resolve = (text) => interpolateToString(text, scope);
|
|
57079
57225
|
const headers = written.headers.map((header) => ({
|
|
57080
57226
|
name: resolve(header.name),
|
|
@@ -57095,14 +57241,14 @@ async function prepareRequest(written, body, scope, root) {
|
|
|
57095
57241
|
if (typeof part === "string") {
|
|
57096
57242
|
parts.push({ name, value: resolve(part) });
|
|
57097
57243
|
} else if ("file" in part) {
|
|
57098
|
-
const
|
|
57099
|
-
const bytes2 = await readBodyFile(
|
|
57244
|
+
const path11 = resolve(part.file);
|
|
57245
|
+
const { bytes: bytes2, shown } = await readBodyFile(files, path11, `multipart field ${name}`);
|
|
57100
57246
|
parts.push({
|
|
57101
57247
|
name,
|
|
57102
57248
|
value: bytes2,
|
|
57103
|
-
filename: part.filename !== void 0 ? resolve(part.filename) : baseName(
|
|
57104
|
-
contentType: part.contentType ? resolve(part.contentType) : contentTypeFor(
|
|
57105
|
-
shown: fileMarker(
|
|
57249
|
+
filename: part.filename !== void 0 ? resolve(part.filename) : baseName(path11),
|
|
57250
|
+
contentType: part.contentType ? resolve(part.contentType) : contentTypeFor(path11),
|
|
57251
|
+
shown: fileMarker(shown, bytes2.byteLength)
|
|
57106
57252
|
});
|
|
57107
57253
|
} else {
|
|
57108
57254
|
parts.push({
|
|
@@ -57117,52 +57263,112 @@ async function prepareRequest(written, body, scope, root) {
|
|
|
57117
57263
|
return { request: { ...request, headers: typed.headers, body: text }, payload: bytes };
|
|
57118
57264
|
}
|
|
57119
57265
|
if (body?.file !== void 0) {
|
|
57120
|
-
const
|
|
57121
|
-
const bytes = await readBodyFile(
|
|
57266
|
+
const path11 = resolve(body.file);
|
|
57267
|
+
const { bytes, shown } = await readBodyFile(files, path11, "body.file");
|
|
57122
57268
|
const declared = headers.some((header) => header.name.toLowerCase() === "content-type");
|
|
57123
57269
|
return {
|
|
57124
57270
|
request: {
|
|
57125
57271
|
...request,
|
|
57126
|
-
headers: declared ? headers : [...headers, { name: "Content-Type", value: contentTypeFor(
|
|
57127
|
-
body: fileMarker(
|
|
57272
|
+
headers: declared ? headers : [...headers, { name: "Content-Type", value: contentTypeFor(path11) }],
|
|
57273
|
+
body: fileMarker(shown, bytes.byteLength)
|
|
57128
57274
|
},
|
|
57129
57275
|
payload: bytes
|
|
57130
57276
|
};
|
|
57131
57277
|
}
|
|
57132
57278
|
return {
|
|
57133
|
-
request: {
|
|
57279
|
+
request: {
|
|
57280
|
+
...request,
|
|
57281
|
+
// In a JSON body a null is JSON's own, not a gap that leaves it malformed.
|
|
57282
|
+
body: written.body === null ? null : body?.json !== void 0 ? interpolateToString(written.body, scope, { nullAs: "null" }) : resolve(written.body)
|
|
57283
|
+
},
|
|
57134
57284
|
payload: null
|
|
57135
57285
|
};
|
|
57136
57286
|
}
|
|
57137
|
-
var baseName = (
|
|
57138
|
-
|
|
57139
|
-
|
|
57140
|
-
|
|
57141
|
-
|
|
57287
|
+
var baseName = (path11) => withoutGlobal(path11).split(/[\\/]/).pop() ?? path11;
|
|
57288
|
+
var withoutGlobal = (path11) => path11.startsWith(GLOBAL_FILE) ? path11.slice(GLOBAL_FILE.length) : path11;
|
|
57289
|
+
function bodyFiles(body) {
|
|
57290
|
+
if (body?.file !== void 0) return [{ what: "body.file", written: body.file }];
|
|
57291
|
+
if (body?.multipart === void 0) return [];
|
|
57292
|
+
return partsOf(body.multipart).flatMap(
|
|
57293
|
+
([field, part]) => typeof part !== "string" && "file" in part ? [{ what: `multipart field ${field}`, written: part.file }] : []
|
|
57294
|
+
);
|
|
57295
|
+
}
|
|
57296
|
+
async function readBodyFile(roots, written, what) {
|
|
57297
|
+
const { file: file2, shown } = await findBodyFile(roots, written, what);
|
|
57298
|
+
try {
|
|
57299
|
+
return { bytes: await fs8.readFile(file2), shown };
|
|
57300
|
+
} catch (cause) {
|
|
57301
|
+
throw new BodyFileError(`${what}: ${written} \u2014 ${cause.message}`);
|
|
57302
|
+
}
|
|
57303
|
+
}
|
|
57304
|
+
async function findBodyFile(roots, written, what) {
|
|
57305
|
+
const missing = (reason) => new BodyFileError(`${what}: ${written} \u2014 ${reason}`);
|
|
57306
|
+
if (roots === null) {
|
|
57307
|
+
throw missing(
|
|
57308
|
+
"files are read from the project folder, so save the collection in a project first"
|
|
57142
57309
|
);
|
|
57143
57310
|
}
|
|
57311
|
+
const relative = withoutGlobal(written);
|
|
57312
|
+
if (relative !== written) {
|
|
57313
|
+
if (!roots.global) throw missing("this project does not use a global project");
|
|
57314
|
+
const file3 = await fileIn(roots.global, relative, written, what);
|
|
57315
|
+
if (file3) return { file: file3, shown: written };
|
|
57316
|
+
throw missing("no such file in the global project folder");
|
|
57317
|
+
}
|
|
57318
|
+
const file2 = await fileIn(roots.project, relative, written, what);
|
|
57319
|
+
if (file2) return { file: file2, shown: written };
|
|
57320
|
+
const global = roots.global && !samePath(roots.global, roots.project) ? roots.global : null;
|
|
57321
|
+
if (!global || !isInside(roots.project, resolveRelative(roots.project, relative))) {
|
|
57322
|
+
throw missing("no such file in the project folder");
|
|
57323
|
+
}
|
|
57324
|
+
const shared = await fileIn(global, relative, written, what);
|
|
57325
|
+
if (shared) return { file: shared, shown: `${GLOBAL_FILE}${toPosix(relative)}` };
|
|
57326
|
+
throw missing(
|
|
57327
|
+
`no such file in the project folder, or in its global project's (${relativePosix(roots.project, global)})`
|
|
57328
|
+
);
|
|
57329
|
+
}
|
|
57330
|
+
async function fileIn(root, relative, written, what) {
|
|
57144
57331
|
let file2;
|
|
57145
57332
|
try {
|
|
57146
|
-
file2 = resolveRelative(root,
|
|
57333
|
+
file2 = resolveRelative(root, relative);
|
|
57147
57334
|
} catch (cause) {
|
|
57148
57335
|
throw new BodyFileError(`${what}: ${cause.message}`);
|
|
57149
57336
|
}
|
|
57150
|
-
|
|
57337
|
+
if (written.startsWith(GLOBAL_FILE) && !isInside(root, file2)) {
|
|
57338
|
+
throw new BodyFileError(
|
|
57339
|
+
`${what}: ${written} \u2014 a global: path stays in the global project folder`
|
|
57340
|
+
);
|
|
57341
|
+
}
|
|
57342
|
+
const misspelled = await spellingProblem(root, relative);
|
|
57151
57343
|
if (misspelled) throw new BodyFileError(`${what}: ${misspelled}`);
|
|
57344
|
+
let stat;
|
|
57152
57345
|
try {
|
|
57153
|
-
|
|
57346
|
+
stat = await fs8.stat(file2);
|
|
57154
57347
|
} catch (cause) {
|
|
57155
57348
|
const code = cause.code;
|
|
57156
|
-
|
|
57157
|
-
throw new BodyFileError(`${what}: ${
|
|
57349
|
+
if (code === "ENOENT" || code === "ENOTDIR") return null;
|
|
57350
|
+
throw new BodyFileError(`${what}: ${written} \u2014 ${cause.message}`);
|
|
57158
57351
|
}
|
|
57352
|
+
if (stat.isDirectory())
|
|
57353
|
+
throw new BodyFileError(`${what}: ${written} \u2014 is a directory, not a file`);
|
|
57354
|
+
return file2;
|
|
57159
57355
|
}
|
|
57160
57356
|
|
|
57161
57357
|
// ../../packages/core/src/run/runRequest.ts
|
|
57162
57358
|
import assert3 from "node:assert/strict";
|
|
57163
|
-
import path8 from "node:path";
|
|
57164
57359
|
|
|
57165
57360
|
// ../../packages/core/src/assert/evaluate.ts
|
|
57361
|
+
function locate(root, segments, nullAlong) {
|
|
57362
|
+
const located = resolvePath(root, segments);
|
|
57363
|
+
if (located.length > 0 || !nullAlong || segments.some((s) => s.kind === "each")) return located;
|
|
57364
|
+
for (let end = 1; end < segments.length; end++) {
|
|
57365
|
+
const [reached] = resolvePath(root, segments.slice(0, end));
|
|
57366
|
+
if (!reached) return [];
|
|
57367
|
+
if (reached.value === null) return [reached];
|
|
57368
|
+
}
|
|
57369
|
+
return [];
|
|
57370
|
+
}
|
|
57371
|
+
var isNullCheck = (wanted) => wanted.equals === null && Object.keys(wanted).length === 1;
|
|
57166
57372
|
function checkScalarTarget(target, label, wanted, found, context) {
|
|
57167
57373
|
const base2 = { target, expected: describe3(wanted) };
|
|
57168
57374
|
const name = `${label} ${describe3(wanted, { brief: true })}`;
|
|
@@ -57181,9 +57387,9 @@ function checkScalarTarget(target, label, wanted, found, context) {
|
|
|
57181
57387
|
capture(wanted, value, context.scope);
|
|
57182
57388
|
return failure2 ? { ...base2, ...actual, name, status: "fail", message: failure2 } : { ...base2, ...actual, name, status: "pass" };
|
|
57183
57389
|
}
|
|
57184
|
-
function checkBody(
|
|
57185
|
-
const base2 = { target: "body", path:
|
|
57186
|
-
const name = `${
|
|
57390
|
+
function checkBody(path11, segments, wanted, located, context) {
|
|
57391
|
+
const base2 = { target: "body", path: path11, expected: describe3(wanted) };
|
|
57392
|
+
const name = `${path11} ${describe3(wanted, { brief: true })}`;
|
|
57187
57393
|
const fanOut = segments.some((s) => s.kind === "each");
|
|
57188
57394
|
const actual = located.length === 0 ? {} : { actual: fanOut ? show(located.map((l) => l.value)) : show(located[0].value) };
|
|
57189
57395
|
if (wanted.absent) {
|
|
@@ -57207,7 +57413,7 @@ function checkBody(path12, segments, wanted, located, context) {
|
|
|
57207
57413
|
const covered = [];
|
|
57208
57414
|
let failure2 = null;
|
|
57209
57415
|
for (const { path: at, value } of located) {
|
|
57210
|
-
const check2 = checkBodyValue(wanted, value, context);
|
|
57416
|
+
const check2 = checkBodyValue(wanted, value, context, context.claimed?.(formatPath(at)));
|
|
57211
57417
|
covered.push(...check2.covered.map((c) => ({ ...c, pattern: [...at, ...c.pattern] })));
|
|
57212
57418
|
if (check2.failure && !failure2) {
|
|
57213
57419
|
failure2 = fanOut ? `At ${formatPath(at)}: ${check2.failure}` : check2.failure;
|
|
@@ -57219,7 +57425,7 @@ function checkBody(path12, segments, wanted, located, context) {
|
|
|
57219
57425
|
covered
|
|
57220
57426
|
};
|
|
57221
57427
|
}
|
|
57222
|
-
function checkBodyValue(wanted, value, context) {
|
|
57428
|
+
function checkBodyValue(wanted, value, context, claimed = /* @__PURE__ */ new Set()) {
|
|
57223
57429
|
const failures = [];
|
|
57224
57430
|
let whole = !(value !== null && typeof value === "object");
|
|
57225
57431
|
const covered = [];
|
|
@@ -57258,7 +57464,7 @@ function checkBodyValue(wanted, value, context) {
|
|
|
57258
57464
|
const used = /* @__PURE__ */ new Set();
|
|
57259
57465
|
for (const expected of wanted.unordered) {
|
|
57260
57466
|
const matches = value.map((item, index) => ({ index, match: matchItem(item, expected, context) })).filter((candidate) => candidate.match !== null);
|
|
57261
|
-
const chosen = matches.find((m) => !used.has(m.index)) ?? matches[0];
|
|
57467
|
+
const chosen = matches.find((m) => !used.has(m.index) && !claimed.has(m.index)) ?? matches.find((m) => !used.has(m.index)) ?? matches[0];
|
|
57262
57468
|
if (!chosen) {
|
|
57263
57469
|
missing.push(expected);
|
|
57264
57470
|
continue;
|
|
@@ -57269,6 +57475,7 @@ function checkBodyValue(wanted, value, context) {
|
|
|
57269
57475
|
covered.push({ pattern: [{ kind: "index", index: chosen.index }, ...c.pattern] });
|
|
57270
57476
|
}
|
|
57271
57477
|
}
|
|
57478
|
+
for (const index of used) claimed.add(index);
|
|
57272
57479
|
if (missing.length > 0)
|
|
57273
57480
|
failures.push(`Missing from the array: ${missing.map(show).join(", ")}`);
|
|
57274
57481
|
}
|
|
@@ -57382,7 +57589,11 @@ function matchItem(item, expected, context) {
|
|
|
57382
57589
|
const captures = [];
|
|
57383
57590
|
for (const [key, want] of entries2) {
|
|
57384
57591
|
const segments = parsePath(key);
|
|
57385
|
-
const located =
|
|
57592
|
+
const located = locate(
|
|
57593
|
+
item,
|
|
57594
|
+
segments,
|
|
57595
|
+
isMatcherObject(want) ? isNullCheck(want) : want === null
|
|
57596
|
+
);
|
|
57386
57597
|
if (isMatcherObject(want)) {
|
|
57387
57598
|
if (want.absent) {
|
|
57388
57599
|
if (located.length > 0) return null;
|
|
@@ -57478,19 +57689,19 @@ var REMOVED = /* @__PURE__ */ Symbol("removed");
|
|
|
57478
57689
|
function findUnasserted(body, covered) {
|
|
57479
57690
|
const root = { value: structuredClone(body) };
|
|
57480
57691
|
for (const coverage of covered) {
|
|
57481
|
-
for (const { path:
|
|
57692
|
+
for (const { path: path11 } of resolvePath(root.value, coverage.pattern)) remove(root, path11);
|
|
57482
57693
|
}
|
|
57483
57694
|
const leaves = [];
|
|
57484
57695
|
collectLeaves(prune(root.value), [], leaves);
|
|
57485
57696
|
return leaves;
|
|
57486
57697
|
}
|
|
57487
|
-
function remove(root,
|
|
57488
|
-
if (
|
|
57698
|
+
function remove(root, path11) {
|
|
57699
|
+
if (path11.length === 0) {
|
|
57489
57700
|
root.value = REMOVED;
|
|
57490
57701
|
return;
|
|
57491
57702
|
}
|
|
57492
|
-
const parent = resolvePath(root.value,
|
|
57493
|
-
const last =
|
|
57703
|
+
const parent = resolvePath(root.value, path11.slice(0, -1))[0]?.value;
|
|
57704
|
+
const last = path11[path11.length - 1];
|
|
57494
57705
|
if (Array.isArray(parent) && last.kind === "index") parent[last.index] = REMOVED;
|
|
57495
57706
|
else if (parent !== null && typeof parent === "object" && last.kind === "key") {
|
|
57496
57707
|
delete parent[last.key];
|
|
@@ -57509,16 +57720,16 @@ function prune(value) {
|
|
|
57509
57720
|
}
|
|
57510
57721
|
return value;
|
|
57511
57722
|
}
|
|
57512
|
-
function collectLeaves(value,
|
|
57723
|
+
function collectLeaves(value, path11, out) {
|
|
57513
57724
|
if (value === void 0) return;
|
|
57514
57725
|
if (Array.isArray(value)) {
|
|
57515
|
-
value.forEach((item, index) => collectLeaves(item, [...
|
|
57726
|
+
value.forEach((item, index) => collectLeaves(item, [...path11, { kind: "index", index }], out));
|
|
57516
57727
|
} else if (value !== null && typeof value === "object") {
|
|
57517
57728
|
for (const [key, child] of Object.entries(value)) {
|
|
57518
|
-
collectLeaves(child, [...
|
|
57729
|
+
collectLeaves(child, [...path11, { kind: "key", key }], out);
|
|
57519
57730
|
}
|
|
57520
57731
|
} else {
|
|
57521
|
-
out.push(formatPath(
|
|
57732
|
+
out.push(formatPath(path11));
|
|
57522
57733
|
}
|
|
57523
57734
|
}
|
|
57524
57735
|
|
|
@@ -57538,6 +57749,10 @@ var CheckSession = class {
|
|
|
57538
57749
|
/** While true, checks recorded are defaults: an endpoint base's (SPEC.md §2.6). */
|
|
57539
57750
|
recordingDefaults = false;
|
|
57540
57751
|
defaults = /* @__PURE__ */ new Set();
|
|
57752
|
+
/** Checks whose meaning waits on strict validation: what each would be with it on. */
|
|
57753
|
+
byStrictness = [];
|
|
57754
|
+
/** Items of each array unordered checks matched, by the array's path. */
|
|
57755
|
+
claims = /* @__PURE__ */ new Map();
|
|
57541
57756
|
/** Turn strict validation on or off. The last word wins. */
|
|
57542
57757
|
setStrict(strict) {
|
|
57543
57758
|
this.strict = strict;
|
|
@@ -57553,6 +57768,7 @@ var CheckSession = class {
|
|
|
57553
57768
|
if (properties.length === 0) return;
|
|
57554
57769
|
this.sortKeys = [...properties, ...this.sortKeys];
|
|
57555
57770
|
this.sorted = void 0;
|
|
57771
|
+
this.claims.clear();
|
|
57556
57772
|
}
|
|
57557
57773
|
status(matcher) {
|
|
57558
57774
|
return this.record(
|
|
@@ -57567,17 +57783,43 @@ var CheckSession = class {
|
|
|
57567
57783
|
path: name
|
|
57568
57784
|
});
|
|
57569
57785
|
}
|
|
57570
|
-
body(
|
|
57786
|
+
body(path11, matcher) {
|
|
57571
57787
|
const body = this.body_();
|
|
57572
57788
|
if (body === BODY_UNAVAILABLE) return null;
|
|
57573
|
-
const segments = parsePath(
|
|
57574
|
-
const
|
|
57789
|
+
const segments = parsePath(path11);
|
|
57790
|
+
const located = locate(body, segments, isNullCheck(matcher));
|
|
57791
|
+
const result = checkBody(path11, segments, matcher, located, {
|
|
57792
|
+
...this.context,
|
|
57793
|
+
claimed: (arrayPath) => this.claimsOn(arrayPath)
|
|
57794
|
+
});
|
|
57575
57795
|
this.covered.push(...result.covered);
|
|
57576
57796
|
return this.record(result.assertion);
|
|
57577
57797
|
}
|
|
57798
|
+
/**
|
|
57799
|
+
* A body check that means one thing under strict validation and another
|
|
57800
|
+
* without, as xtest's lone `notThisExpectedValue` entry did (SPEC.md §3).
|
|
57801
|
+
* Both are checked now, against the body as it is now, and `finish()` keeps
|
|
57802
|
+
* the one the step's last word on strict validation asks for.
|
|
57803
|
+
*/
|
|
57804
|
+
bodyByStrictness(path11, matchers) {
|
|
57805
|
+
const body = this.body_();
|
|
57806
|
+
if (body === BODY_UNAVAILABLE) return null;
|
|
57807
|
+
const segments = parsePath(path11);
|
|
57808
|
+
const located = locate(body, segments, false);
|
|
57809
|
+
const strict = checkBody(path11, segments, matchers.strict, located, this.context);
|
|
57810
|
+
const lenient = checkBody(path11, segments, matchers.lenient, located, this.context);
|
|
57811
|
+
const assertion = this.record(lenient.assertion);
|
|
57812
|
+
this.byStrictness.push({ assertion, strict });
|
|
57813
|
+
return assertion;
|
|
57814
|
+
}
|
|
57815
|
+
claimsOn(arrayPath) {
|
|
57816
|
+
let claimed = this.claims.get(arrayPath);
|
|
57817
|
+
if (!claimed) this.claims.set(arrayPath, claimed = /* @__PURE__ */ new Set());
|
|
57818
|
+
return claimed;
|
|
57819
|
+
}
|
|
57578
57820
|
/** Account for a path under strict validation without asserting anything. */
|
|
57579
|
-
ignore(
|
|
57580
|
-
this.covered.push({ pattern: parsePath(
|
|
57821
|
+
ignore(path11) {
|
|
57822
|
+
this.covered.push({ pattern: parsePath(path11) });
|
|
57581
57823
|
}
|
|
57582
57824
|
/** Add a result to the report — every check's, and a named check's from code. */
|
|
57583
57825
|
record(assertion) {
|
|
@@ -57614,9 +57856,17 @@ var CheckSession = class {
|
|
|
57614
57856
|
}
|
|
57615
57857
|
}
|
|
57616
57858
|
finish() {
|
|
57859
|
+
if (this.strict) {
|
|
57860
|
+
for (const { assertion, strict } of this.byStrictness) {
|
|
57861
|
+
for (const key of Object.keys(assertion)) delete assertion[key];
|
|
57862
|
+
Object.assign(assertion, strict.assertion);
|
|
57863
|
+
this.covered.push(...strict.covered);
|
|
57864
|
+
}
|
|
57865
|
+
}
|
|
57617
57866
|
this.replaceDefaults();
|
|
57618
57867
|
if (this.strict) {
|
|
57619
|
-
const
|
|
57868
|
+
const readable = !["binary", "html"].includes(this.context.response.bodyKind);
|
|
57869
|
+
const body = readable ? this.body_() : {};
|
|
57620
57870
|
if (body !== BODY_UNAVAILABLE) {
|
|
57621
57871
|
const unasserted = findUnasserted(body, this.covered);
|
|
57622
57872
|
this.assertions.push({
|
|
@@ -57781,26 +58031,53 @@ function variableName(value) {
|
|
|
57781
58031
|
}
|
|
57782
58032
|
return value;
|
|
57783
58033
|
}
|
|
58034
|
+
function pathOf2(path11, what) {
|
|
58035
|
+
if (typeof path11 === "string") return path11;
|
|
58036
|
+
if (!Array.isArray(path11)) {
|
|
58037
|
+
throw new GtaUsageError(
|
|
58038
|
+
`${what} is a string, such as "user.name", or a list of keys, such as ["user", "name"]; got ${show(path11)}`
|
|
58039
|
+
);
|
|
58040
|
+
}
|
|
58041
|
+
if (path11.length === 0) throw new GtaUsageError(`${what} is an empty list; it needs a key`);
|
|
58042
|
+
return formatPath(
|
|
58043
|
+
path11.map((key) => {
|
|
58044
|
+
if (typeof key === "string") return { kind: "key", key };
|
|
58045
|
+
if (typeof key === "number") return { kind: "key", key: String(key) };
|
|
58046
|
+
throw new GtaUsageError(`${what}'s keys are strings or numbers; got ${show(key)}`);
|
|
58047
|
+
})
|
|
58048
|
+
);
|
|
58049
|
+
}
|
|
57784
58050
|
var isValidationEntry = (value) => value !== null && typeof value === "object" && "pathToProperty" in value;
|
|
57785
58051
|
function itemFrom(list, valueKey) {
|
|
57786
58052
|
const item = {};
|
|
57787
58053
|
for (const entry of list) {
|
|
57788
|
-
const
|
|
58054
|
+
const path11 = pathOf2(entry.pathToProperty, "pathToProperty");
|
|
57789
58055
|
if (valueKey === "compareValue") {
|
|
57790
|
-
|
|
58056
|
+
const value = entry.compareValue;
|
|
58057
|
+
item[path11] = isRegExp(value) ? { matches: value } : value;
|
|
57791
58058
|
continue;
|
|
57792
58059
|
}
|
|
57793
58060
|
const matcher = xtestMatcher(valueKey in entry, entry[valueKey], entry.specialHandling);
|
|
57794
|
-
item[
|
|
58061
|
+
item[path11] = { ...item[path11], ...matcher };
|
|
57795
58062
|
}
|
|
57796
58063
|
return item;
|
|
57797
58064
|
}
|
|
58065
|
+
function loneNotThisValue(list) {
|
|
58066
|
+
const [entry] = list;
|
|
58067
|
+
if (list.length !== 1 || !isValidationEntry(entry)) return null;
|
|
58068
|
+
if (entry.specialHandling !== "notThisExpectedValue" || !("expectedValue" in entry)) return null;
|
|
58069
|
+
const value = entry.expectedValue;
|
|
58070
|
+
const path11 = pathOf2(entry.pathToProperty, "pathToProperty");
|
|
58071
|
+
return { unorderedNot: [{ [path11]: isRegExp(value) ? { matches: value } : value }] };
|
|
58072
|
+
}
|
|
57798
58073
|
function toList(validationList) {
|
|
57799
58074
|
if (!Array.isArray(validationList)) {
|
|
57800
58075
|
throw new GtaUsageError(`validationList must be an array, got ${show(validationList)}`);
|
|
57801
58076
|
}
|
|
57802
58077
|
return validationList;
|
|
57803
58078
|
}
|
|
58079
|
+
var newStepControl = () => ({ skip: null, rest: null });
|
|
58080
|
+
var reasonOf = (reason, fallback) => reason === void 0 || reason === null || String(reason).trim() === "" ? fallback : String(reason);
|
|
57804
58081
|
function guarded(session, label, fn) {
|
|
57805
58082
|
return (...args) => {
|
|
57806
58083
|
try {
|
|
@@ -57811,11 +58088,26 @@ function guarded(session, label, fn) {
|
|
|
57811
58088
|
}
|
|
57812
58089
|
};
|
|
57813
58090
|
}
|
|
57814
|
-
function testsGta({
|
|
57815
|
-
|
|
58091
|
+
function testsGta({
|
|
58092
|
+
session,
|
|
58093
|
+
scope,
|
|
58094
|
+
pending,
|
|
58095
|
+
warn = () => {
|
|
58096
|
+
},
|
|
58097
|
+
control = newStepControl()
|
|
58098
|
+
}) {
|
|
57816
58099
|
const shared = sharedGta(scope);
|
|
57817
58100
|
return {
|
|
57818
58101
|
...shared,
|
|
58102
|
+
skip() {
|
|
58103
|
+
throw new Error(
|
|
58104
|
+
"gta.skip() stops a request before it is sent, so it belongs in before.script; gta.skipRest() skips the steps after this one"
|
|
58105
|
+
);
|
|
58106
|
+
},
|
|
58107
|
+
/** Run none of the steps after this one in this row; the next row, and teardown, still run. */
|
|
58108
|
+
skipRest(reason) {
|
|
58109
|
+
control.rest ??= reasonOf(reason, "gta.skipRest() in an earlier step");
|
|
58110
|
+
},
|
|
57819
58111
|
expectResponseStatusCodeToBe: guarded(
|
|
57820
58112
|
session,
|
|
57821
58113
|
"expectResponseStatusCodeToBe",
|
|
@@ -57836,40 +58128,63 @@ function testsGta({ session, scope, pending, warn = () => {
|
|
|
57836
58128
|
session,
|
|
57837
58129
|
"expectResponseBodyToHaveProperty",
|
|
57838
58130
|
(...args) => {
|
|
57839
|
-
const [
|
|
57840
|
-
session.body(
|
|
58131
|
+
const [path11, value, specialHandling] = args;
|
|
58132
|
+
session.body(
|
|
58133
|
+
pathOf2(path11, "jsonPathToProperty"),
|
|
58134
|
+
xtestMatcher(args.length > 1, value, specialHandling)
|
|
58135
|
+
);
|
|
57841
58136
|
}
|
|
57842
58137
|
),
|
|
57843
58138
|
expectResponseBodyToHaveUnorderedArray: guarded(
|
|
57844
58139
|
session,
|
|
57845
58140
|
"expectResponseBodyToHaveUnorderedArray",
|
|
57846
58141
|
(jsonPathToArray, validationList) => {
|
|
58142
|
+
const path11 = pathOf2(jsonPathToArray, "jsonPathToArray");
|
|
57847
58143
|
const list = toList(validationList);
|
|
57848
58144
|
const unordered = list.every(isValidationEntry) ? [itemFrom(list, "expectedValue")] : list;
|
|
57849
|
-
|
|
58145
|
+
const lone = loneNotThisValue(list);
|
|
58146
|
+
if (lone) session.bodyByStrictness(path11, { strict: { unordered }, lenient: lone });
|
|
58147
|
+
else session.body(path11, { unordered });
|
|
57850
58148
|
}
|
|
57851
58149
|
),
|
|
57852
58150
|
expectResponseBodyToHaveUnorderedArrayNotThisItem: guarded(
|
|
57853
58151
|
session,
|
|
57854
58152
|
"expectResponseBodyToHaveUnorderedArrayNotThisItem",
|
|
57855
58153
|
(jsonPathToArray, validationList) => {
|
|
58154
|
+
const path11 = pathOf2(jsonPathToArray, "jsonPathToArray");
|
|
57856
58155
|
const list = toList(validationList);
|
|
57857
58156
|
const unorderedNot = list.every(isValidationEntry) ? [itemFrom(list, "compareValue")] : list;
|
|
57858
|
-
session.body(
|
|
58157
|
+
session.body(path11, { unorderedNot });
|
|
58158
|
+
}
|
|
58159
|
+
),
|
|
58160
|
+
ignoreResponseBodyProperty: guarded(
|
|
58161
|
+
session,
|
|
58162
|
+
"ignoreResponseBodyProperty",
|
|
58163
|
+
(jsonPathToProperty) => {
|
|
58164
|
+
session.ignore(pathOf2(jsonPathToProperty, "jsonPathToProperty"));
|
|
58165
|
+
}
|
|
58166
|
+
),
|
|
58167
|
+
ignoreResponseBodyArrayObjectProperty: guarded(
|
|
58168
|
+
session,
|
|
58169
|
+
"ignoreResponseBodyArrayObjectProperty",
|
|
58170
|
+
(jsonPathToArray, jsonPathOfObjectProperty) => {
|
|
58171
|
+
const array2 = parsePath(pathOf2(jsonPathToArray, "jsonPathToArray"));
|
|
58172
|
+
const property = parsePath(pathOf2(jsonPathOfObjectProperty, "jsonPathOfObjectProperty"));
|
|
58173
|
+
session.ignore(formatPath([...array2, { kind: "each" }, ...property]));
|
|
57859
58174
|
}
|
|
57860
58175
|
),
|
|
57861
|
-
ignoreResponseBodyProperty(jsonPathToProperty) {
|
|
57862
|
-
session.ignore(jsonPathToProperty);
|
|
57863
|
-
},
|
|
57864
|
-
ignoreResponseBodyArrayObjectProperty(jsonPathToArray, jsonPathOfObjectProperty) {
|
|
57865
|
-
session.ignore(`${jsonPathToArray}[].${jsonPathOfObjectProperty}`);
|
|
57866
|
-
},
|
|
57867
58176
|
sortResponseBodyArrays(propertyName) {
|
|
57868
|
-
|
|
58177
|
+
const named = typeof propertyName === "string" && propertyName !== "" || Array.isArray(propertyName) && propertyName.length > 0;
|
|
58178
|
+
if (!named) {
|
|
57869
58179
|
warn("gta.sortResponseBodyArrays() needs a property name to sort by; nothing was sorted");
|
|
57870
58180
|
return;
|
|
57871
58181
|
}
|
|
57872
|
-
|
|
58182
|
+
try {
|
|
58183
|
+
session.sortBy([pathOf2(propertyName, "propertyName")]);
|
|
58184
|
+
} catch (cause) {
|
|
58185
|
+
if (!(cause instanceof GtaUsageError)) throw cause;
|
|
58186
|
+
warn(`gta.sortResponseBodyArrays(): ${cause.message}; nothing was sorted`);
|
|
58187
|
+
}
|
|
57873
58188
|
},
|
|
57874
58189
|
/** Strict validation for this step. Replaces `startXTest`'s second argument. */
|
|
57875
58190
|
useStrictValidation(enabled = true) {
|
|
@@ -57908,12 +58223,25 @@ function testsGta({ session, scope, pending, warn = () => {
|
|
|
57908
58223
|
}
|
|
57909
58224
|
};
|
|
57910
58225
|
}
|
|
57911
|
-
function preRequestGta(scope) {
|
|
58226
|
+
function preRequestGta(scope, control = newStepControl()) {
|
|
57912
58227
|
const notHere = (name) => () => {
|
|
57913
58228
|
throw new Error(`gta.${name}() checks a response, so it belongs in tests, not before.script`);
|
|
57914
58229
|
};
|
|
57915
58230
|
return {
|
|
57916
58231
|
...sharedGta(scope),
|
|
58232
|
+
/**
|
|
58233
|
+
* Send nothing for this step, and report it skipped with the reason. The
|
|
58234
|
+
* script runs to its end; no later `before.script` does.
|
|
58235
|
+
*/
|
|
58236
|
+
skip(reason) {
|
|
58237
|
+
control.skip ??= reasonOf(reason, "gta.skip() in before.script");
|
|
58238
|
+
},
|
|
58239
|
+
/** `skip`, and run none of the steps after this one in this row either. */
|
|
58240
|
+
skipRest(reason) {
|
|
58241
|
+
const given = reasonOf(reason, "gta.skipRest() in before.script");
|
|
58242
|
+
control.skip ??= given;
|
|
58243
|
+
control.rest ??= given;
|
|
58244
|
+
},
|
|
57917
58245
|
expectResponseStatusCodeToBe: notHere("expectResponseStatusCodeToBe"),
|
|
57918
58246
|
expectResponseToHaveHeader: notHere("expectResponseToHaveHeader"),
|
|
57919
58247
|
expectResponseBodyToHaveProperty: notHere("expectResponseBodyToHaveProperty"),
|
|
@@ -57926,9 +58254,18 @@ function sharedGta(scope) {
|
|
|
57926
58254
|
get(name) {
|
|
57927
58255
|
return scope.get(name);
|
|
57928
58256
|
},
|
|
57929
|
-
/**
|
|
57930
|
-
|
|
57931
|
-
|
|
58257
|
+
/**
|
|
58258
|
+
* Set a variable for the rest of this run, like a capture. With
|
|
58259
|
+
* `{ scope: 'run' }` it lasts past this data row too, into every row after
|
|
58260
|
+
* it and teardown (SPEC.md §2.10).
|
|
58261
|
+
*/
|
|
58262
|
+
set(name, value, options) {
|
|
58263
|
+
const lasting = options?.scope;
|
|
58264
|
+
if (lasting !== void 0 && lasting !== "run") {
|
|
58265
|
+
throw new Error(`gta.set(): scope is 'run' or left out, got ${show(lasting)}`);
|
|
58266
|
+
}
|
|
58267
|
+
if (lasting === "run") scope.setForRun(String(name), toVarValue2(value), "script");
|
|
58268
|
+
else scope.set(String(name), toVarValue2(value), "script");
|
|
57932
58269
|
},
|
|
57933
58270
|
/**
|
|
57934
58271
|
* A feature flag's value in this run (SPEC.md §2.9) — to check something
|
|
@@ -57977,6 +58314,7 @@ function uuidv72(now = Date.now()) {
|
|
|
57977
58314
|
}
|
|
57978
58315
|
var isThenable = (value) => value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
57979
58316
|
function toVarValue2(value) {
|
|
58317
|
+
if (value === void 0) return null;
|
|
57980
58318
|
if (value === null || ["string", "number", "boolean"].includes(typeof value)) {
|
|
57981
58319
|
return value;
|
|
57982
58320
|
}
|
|
@@ -58165,7 +58503,151 @@ function captureConsole(logs, phase) {
|
|
|
58165
58503
|
return { log: write("log"), info: write("info"), warn: write("warn"), error: write("error") };
|
|
58166
58504
|
}
|
|
58167
58505
|
|
|
58506
|
+
// ../../packages/core/src/run/plan.ts
|
|
58507
|
+
import path8 from "node:path";
|
|
58508
|
+
async function planSteps(collection, collectionPath) {
|
|
58509
|
+
const planned = [];
|
|
58510
|
+
let project;
|
|
58511
|
+
for (const [index, step] of collection.steps.entries()) {
|
|
58512
|
+
if (!isUseStep(step)) {
|
|
58513
|
+
planned.push({ kind: "request", index, step });
|
|
58514
|
+
continue;
|
|
58515
|
+
}
|
|
58516
|
+
try {
|
|
58517
|
+
if (!collectionPath)
|
|
58518
|
+
throw new Error(`use: ${step.use} \u2014 save the collection in a project first`);
|
|
58519
|
+
project ??= await projectOf(collectionPath);
|
|
58520
|
+
const set2 = await resolveRequestSet(project.root, project.global, step.use);
|
|
58521
|
+
checkWith(step.use, set2.doc, step.with ?? {});
|
|
58522
|
+
if (set2.doc.steps.length === 0) throw new Error(`use: ${step.use} \u2014 the set has no steps`);
|
|
58523
|
+
const planSet = {
|
|
58524
|
+
name: step.use,
|
|
58525
|
+
useName: step.name?.trim() ? step.name : void 0,
|
|
58526
|
+
path: set2.path,
|
|
58527
|
+
doc: set2.doc,
|
|
58528
|
+
with: step.with ?? {},
|
|
58529
|
+
useTests: step.tests
|
|
58530
|
+
};
|
|
58531
|
+
set2.doc.steps.forEach((child, number4) => {
|
|
58532
|
+
planned.push({ kind: "request", index, step: child, set: planSet, child: number4 });
|
|
58533
|
+
});
|
|
58534
|
+
} catch (cause) {
|
|
58535
|
+
planned.push({
|
|
58536
|
+
kind: "broken",
|
|
58537
|
+
index,
|
|
58538
|
+
step,
|
|
58539
|
+
error: { phase: "use", message: cause instanceof Error ? cause.message : String(cause) }
|
|
58540
|
+
});
|
|
58541
|
+
}
|
|
58542
|
+
}
|
|
58543
|
+
return planned;
|
|
58544
|
+
}
|
|
58545
|
+
async function projectOf(collectionPath) {
|
|
58546
|
+
const root = projectRootOf(collectionPath) ?? path8.dirname(collectionPath);
|
|
58547
|
+
const { global } = await readProject(root);
|
|
58548
|
+
return { root, global };
|
|
58549
|
+
}
|
|
58550
|
+
async function fileRootsOf(file2, collectionPath) {
|
|
58551
|
+
const { global } = await projectOf(collectionPath);
|
|
58552
|
+
return { project: projectRootOf(file2) ?? path8.dirname(file2), global: global?.root ?? null };
|
|
58553
|
+
}
|
|
58554
|
+
function checkWith(name, set2, given) {
|
|
58555
|
+
const params = set2.params ?? {};
|
|
58556
|
+
const unknown2 = Object.keys(given).filter((key) => !(key in params));
|
|
58557
|
+
if (unknown2.length > 0) {
|
|
58558
|
+
const takes = Object.keys(params).join(", ") || "none";
|
|
58559
|
+
throw new Error(`use: ${name} \u2014 it takes no ${unknown2.join(", ")} (it takes: ${takes})`);
|
|
58560
|
+
}
|
|
58561
|
+
const missing = Object.entries(params).filter(([key, spec]) => readParam(spec).required && !(key in given)).map(([key]) => key);
|
|
58562
|
+
if (missing.length > 0) {
|
|
58563
|
+
throw new Error(`use: ${name} \u2014 needs ${missing.join(", ")} in with:`);
|
|
58564
|
+
}
|
|
58565
|
+
}
|
|
58566
|
+
function resolveParams(specs, given, scope) {
|
|
58567
|
+
const params = {};
|
|
58568
|
+
const defaults = /* @__PURE__ */ new Map();
|
|
58569
|
+
for (const [key, spec] of Object.entries(specs ?? {})) {
|
|
58570
|
+
const value = given[key];
|
|
58571
|
+
if (value !== void 0)
|
|
58572
|
+
params[key] = typeof value === "string" ? interpolate(value, scope) : value;
|
|
58573
|
+
else {
|
|
58574
|
+
const fallback = readParam(spec).default;
|
|
58575
|
+
if (fallback !== void 0) defaults.set(key, fallback);
|
|
58576
|
+
}
|
|
58577
|
+
}
|
|
58578
|
+
const resolving = [];
|
|
58579
|
+
const resolve = (key) => {
|
|
58580
|
+
const fallback = defaults.get(key);
|
|
58581
|
+
if (fallback === void 0 || Object.hasOwn(params, key)) return;
|
|
58582
|
+
if (resolving.includes(key)) {
|
|
58583
|
+
const chain = [...resolving, key].map((name) => `params.${name}`);
|
|
58584
|
+
throw new InterpolationError(
|
|
58585
|
+
`params.${key} refers to itself: ${chain.join(" -> ")}`,
|
|
58586
|
+
`params.${key}`
|
|
58587
|
+
);
|
|
58588
|
+
}
|
|
58589
|
+
if (typeof fallback !== "string") {
|
|
58590
|
+
params[key] = fallback;
|
|
58591
|
+
return;
|
|
58592
|
+
}
|
|
58593
|
+
resolving.push(key);
|
|
58594
|
+
for (const [, name] of fallback.matchAll(PARAM_REFERENCE)) resolve(name);
|
|
58595
|
+
resolving.pop();
|
|
58596
|
+
try {
|
|
58597
|
+
params[key] = interpolate(fallback, new ParamsScope(scope, params));
|
|
58598
|
+
} catch (cause) {
|
|
58599
|
+
if (!(cause instanceof InterpolationError)) throw cause;
|
|
58600
|
+
throw new InterpolationError(`params.${key}'s default: ${cause.message}`, cause.variable);
|
|
58601
|
+
}
|
|
58602
|
+
};
|
|
58603
|
+
for (const key of defaults.keys()) resolve(key);
|
|
58604
|
+
return params;
|
|
58605
|
+
}
|
|
58606
|
+
var PARAM_REFERENCE = /\{\{\s*params\.([^{}\s]+)\s*\}\}/g;
|
|
58607
|
+
async function referenceProblems(collection, collectionPath) {
|
|
58608
|
+
const problems = [];
|
|
58609
|
+
if (collection.extends) {
|
|
58610
|
+
try {
|
|
58611
|
+
const { root, global } = await projectOf(collectionPath);
|
|
58612
|
+
await resolveBase(root, global, collection.extends);
|
|
58613
|
+
} catch (cause) {
|
|
58614
|
+
problems.push({ step: null, message: cause.message });
|
|
58615
|
+
}
|
|
58616
|
+
}
|
|
58617
|
+
for (const list of STEP_LISTS) {
|
|
58618
|
+
const steps = collection[list];
|
|
58619
|
+
if (!steps) continue;
|
|
58620
|
+
const stage = list === "steps" ? {} : { stage: list };
|
|
58621
|
+
for (const planned of await planSteps({ ...collection, steps }, collectionPath)) {
|
|
58622
|
+
if (planned.kind === "broken") {
|
|
58623
|
+
problems.push({ step: planned.index, ...stage, message: planned.error.message });
|
|
58624
|
+
continue;
|
|
58625
|
+
}
|
|
58626
|
+
for (const message of await missingFiles(planned, collectionPath)) {
|
|
58627
|
+
problems.push({ step: planned.index, ...stage, message });
|
|
58628
|
+
}
|
|
58629
|
+
}
|
|
58630
|
+
}
|
|
58631
|
+
return problems;
|
|
58632
|
+
}
|
|
58633
|
+
async function missingFiles(planned, collectionPath) {
|
|
58634
|
+
const named = bodyFiles(planned.step.body).filter(({ written }) => !written.includes("{{"));
|
|
58635
|
+
if (named.length === 0) return [];
|
|
58636
|
+
const roots = await fileRootsOf(planned.set?.path ?? collectionPath, collectionPath);
|
|
58637
|
+
const messages = [];
|
|
58638
|
+
for (const { what, written } of named) {
|
|
58639
|
+
try {
|
|
58640
|
+
await findBodyFile(roots, written, what);
|
|
58641
|
+
} catch (cause) {
|
|
58642
|
+
if (!(cause instanceof BodyFileError)) throw cause;
|
|
58643
|
+
messages.push(planned.set ? `use: ${planned.set.name} \u2014 ${cause.message}` : cause.message);
|
|
58644
|
+
}
|
|
58645
|
+
}
|
|
58646
|
+
return messages;
|
|
58647
|
+
}
|
|
58648
|
+
|
|
58168
58649
|
// ../../packages/core/src/run/runRequest.ts
|
|
58650
|
+
var itemText = (value) => value === null || ["string", "number", "boolean"].includes(typeof value) ? value : JSON.stringify(value) ?? String(value);
|
|
58169
58651
|
function folded(layers, collection) {
|
|
58170
58652
|
let headers;
|
|
58171
58653
|
let settings = {};
|
|
@@ -58205,16 +58687,9 @@ function endpointValues(endpoint, step, scope) {
|
|
|
58205
58687
|
}
|
|
58206
58688
|
return values;
|
|
58207
58689
|
}
|
|
58208
|
-
function defaultsOf(params) {
|
|
58209
|
-
const defaults = {};
|
|
58210
|
-
for (const [key, spec] of Object.entries(params)) {
|
|
58211
|
-
const value = readParam(spec).default;
|
|
58212
|
-
if (value !== void 0) defaults[key] = value;
|
|
58213
|
-
}
|
|
58214
|
-
return defaults;
|
|
58215
|
-
}
|
|
58216
58690
|
async function runRequest(input2) {
|
|
58217
|
-
const { step, itemPath = null, signal, context, scope: provided, set: set2 } = input2;
|
|
58691
|
+
const { step, itemPath = null, signal, context, scope: provided, set: set2, item: each } = input2;
|
|
58692
|
+
const control = input2.control ?? newStepControl();
|
|
58218
58693
|
if (isUseStep(step)) {
|
|
58219
58694
|
return {
|
|
58220
58695
|
item: { path: itemPath, name: stepLabel(step), seq: null },
|
|
@@ -58226,7 +58701,6 @@ async function runRequest(input2) {
|
|
|
58226
58701
|
durationMs: 0
|
|
58227
58702
|
};
|
|
58228
58703
|
}
|
|
58229
|
-
const params = set2?.params ?? input2.params ?? (input2.collection?.params ? defaultsOf(input2.collection.params) : void 0);
|
|
58230
58704
|
const library = context && needsLibrary(input2) ? await loadLibrary(context.collectionPath) : null;
|
|
58231
58705
|
const checks = input2.checks ?? library?.checks;
|
|
58232
58706
|
const endpoints = input2.endpoints ?? library?.endpoints ?? [];
|
|
@@ -58264,9 +58738,18 @@ async function runRequest(input2) {
|
|
|
58264
58738
|
const logs = [];
|
|
58265
58739
|
const withLogs = () => ({
|
|
58266
58740
|
...logs.length > 0 ? { logs } : {},
|
|
58267
|
-
...
|
|
58741
|
+
...each ? { forEach: { index: each.index, of: each.of, item: String(itemText(each.value)) } } : {},
|
|
58742
|
+
...set2 ? {
|
|
58743
|
+
use: {
|
|
58744
|
+
set: set2.name,
|
|
58745
|
+
...set2.useName ? { name: set2.useName } : {},
|
|
58746
|
+
child: set2.child,
|
|
58747
|
+
of: set2.of
|
|
58748
|
+
}
|
|
58749
|
+
} : {}
|
|
58268
58750
|
});
|
|
58269
|
-
const
|
|
58751
|
+
const marked = set2 ? set2.doc.steps.findIndex((s) => s.useTests === true) : -1;
|
|
58752
|
+
const useChecksThis = set2 ? set2.child === (marked >= 0 ? marked : set2.of - 1) : false;
|
|
58270
58753
|
const layers = [];
|
|
58271
58754
|
if (endpoint) {
|
|
58272
58755
|
layers.push({
|
|
@@ -58286,51 +58769,93 @@ async function runRequest(input2) {
|
|
|
58286
58769
|
layers.push({ script: "collection", label: "collection", ...partsOf2(input2.collection) });
|
|
58287
58770
|
if (set2) layers.push({ script: "set", label: "set", ...partsOf2(set2.doc) });
|
|
58288
58771
|
layers.push({ script: "step", label: "", before: step.before, tests: step.tests });
|
|
58289
|
-
if (
|
|
58772
|
+
if (useChecksThis && set2?.useTests)
|
|
58773
|
+
layers.push({ script: "use", label: "use", tests: set2.useTests });
|
|
58290
58774
|
const collection = folded(layers, input2.collection);
|
|
58291
58775
|
const failed = (error62) => ({
|
|
58292
58776
|
...failedBeforeSending(step, collection, item, error62, startedHr, logs),
|
|
58293
58777
|
...withLogs()
|
|
58294
58778
|
});
|
|
58295
58779
|
let spec;
|
|
58296
|
-
let
|
|
58780
|
+
let run;
|
|
58781
|
+
let params;
|
|
58297
58782
|
try {
|
|
58298
|
-
|
|
58299
|
-
|
|
58783
|
+
run = provided ?? (context ? await buildScope(context) : new VariableScope());
|
|
58784
|
+
if (!set2)
|
|
58785
|
+
params = input2.params ?? (input2.collection?.params ? resolveParams(input2.collection.params, {}, run) : void 0);
|
|
58300
58786
|
} catch (cause) {
|
|
58301
58787
|
return failed(interpolateError(cause));
|
|
58302
58788
|
}
|
|
58303
|
-
const
|
|
58789
|
+
const scopeOf = (known) => {
|
|
58790
|
+
const own2 = known ? new ParamsScope(run, known) : run;
|
|
58791
|
+
return each ? new OverlayScope(own2, /* @__PURE__ */ new Map([["item", itemText(each.value)]]), "forEach") : own2;
|
|
58792
|
+
};
|
|
58793
|
+
let scope = scopeOf(params);
|
|
58794
|
+
const opens = set2 ? layers.findIndex((layer) => layer.script === "set") : 0;
|
|
58795
|
+
const shared = (adopt, index) => ({
|
|
58304
58796
|
assert: assert3,
|
|
58305
|
-
...params ? { params: adopt(params) } : {},
|
|
58797
|
+
...params && index >= opens ? { params: adopt(params) } : {},
|
|
58798
|
+
...each ? { item: adopt(each.value) } : {},
|
|
58306
58799
|
...endpoint ? { endpoint: adopt(endpointValues(endpoint, step, scope)) } : {}
|
|
58307
58800
|
});
|
|
58308
58801
|
const filenameOf = (layer, kind) => layer.label === "" ? kind : `${layer.label} ${kind}`;
|
|
58309
|
-
|
|
58802
|
+
let edited = null;
|
|
58803
|
+
for (const [index, layer] of layers.entries()) {
|
|
58804
|
+
if (set2 && index === opens) {
|
|
58805
|
+
try {
|
|
58806
|
+
params = set2.params();
|
|
58807
|
+
} catch (cause) {
|
|
58808
|
+
return failed({ phase: "use", message: cause.message });
|
|
58809
|
+
}
|
|
58810
|
+
scope = scopeOf(params);
|
|
58811
|
+
}
|
|
58310
58812
|
const before = layer.before;
|
|
58311
58813
|
const script = layer.script;
|
|
58312
58814
|
if (before?.script) {
|
|
58815
|
+
const shown = edited ?? toSentRequestSafely(step, collection);
|
|
58816
|
+
let view;
|
|
58313
58817
|
const error62 = await runScript(before.script, {
|
|
58314
58818
|
phase: "pre-request",
|
|
58315
58819
|
filename: filenameOf(layer, "before.script"),
|
|
58316
58820
|
logs,
|
|
58317
58821
|
...checks ? { checks } : {},
|
|
58318
|
-
globals: (adopt) =>
|
|
58319
|
-
|
|
58320
|
-
gta: preRequestGta(scope),
|
|
58321
|
-
|
|
58322
|
-
})
|
|
58822
|
+
globals: (adopt) => {
|
|
58823
|
+
view = requestView(shown, adopt);
|
|
58824
|
+
return { ...shared(adopt, index), gta: preRequestGta(scope, control), req: view };
|
|
58825
|
+
}
|
|
58323
58826
|
});
|
|
58324
58827
|
if (error62) return failed({ ...error62, script });
|
|
58828
|
+
try {
|
|
58829
|
+
edited = changedRequest(shown, view, step.body) ?? edited;
|
|
58830
|
+
} catch (cause) {
|
|
58831
|
+
return failed({ phase: "pre-request", message: cause.message, script });
|
|
58832
|
+
}
|
|
58833
|
+
if (control.skip !== null) {
|
|
58834
|
+
return {
|
|
58835
|
+
item,
|
|
58836
|
+
request: edited ?? toSentRequestSafely(step, collection),
|
|
58837
|
+
response: null,
|
|
58838
|
+
assertions: [],
|
|
58839
|
+
...withLogs(),
|
|
58840
|
+
error: null,
|
|
58841
|
+
status: "skipped",
|
|
58842
|
+
skipped: { reason: control.skip },
|
|
58843
|
+
durationMs: performance.now() - startedHr
|
|
58844
|
+
};
|
|
58845
|
+
}
|
|
58325
58846
|
}
|
|
58326
58847
|
}
|
|
58327
58848
|
let payload;
|
|
58328
58849
|
try {
|
|
58329
58850
|
const prepared = await prepareRequest(
|
|
58330
|
-
toSentRequest(step, collection),
|
|
58851
|
+
edited ?? toSentRequest(step, collection),
|
|
58331
58852
|
step.body,
|
|
58332
58853
|
scope,
|
|
58333
|
-
|
|
58854
|
+
await fileRoots(
|
|
58855
|
+
step,
|
|
58856
|
+
set2?.path ?? context?.collectionPath ?? itemPath,
|
|
58857
|
+
context?.collectionPath ?? itemPath
|
|
58858
|
+
)
|
|
58334
58859
|
);
|
|
58335
58860
|
spec = prepared.request;
|
|
58336
58861
|
payload = prepared.payload;
|
|
@@ -58366,29 +58891,30 @@ async function runRequest(input2) {
|
|
|
58366
58891
|
const session = new CheckSession({ response, scope });
|
|
58367
58892
|
let testsError = null;
|
|
58368
58893
|
try {
|
|
58369
|
-
for (const layer of layers) {
|
|
58894
|
+
for (const [index, layer] of layers.entries()) {
|
|
58370
58895
|
const code = layer.tests;
|
|
58371
58896
|
if (!code || testsError) continue;
|
|
58372
58897
|
const pending = [];
|
|
58373
|
-
const
|
|
58898
|
+
const run2 = () => runScript(code, {
|
|
58374
58899
|
phase: "tests",
|
|
58375
58900
|
filename: filenameOf(layer, "tests"),
|
|
58376
58901
|
logs,
|
|
58377
58902
|
...checks ? { checks } : {},
|
|
58378
58903
|
pending: () => pending,
|
|
58379
58904
|
globals: (adopt) => ({
|
|
58380
|
-
...shared(adopt),
|
|
58905
|
+
...shared(adopt, index),
|
|
58381
58906
|
gta: testsGta({
|
|
58382
58907
|
session,
|
|
58383
58908
|
scope,
|
|
58384
58909
|
pending,
|
|
58910
|
+
control,
|
|
58385
58911
|
warn: (message) => logs.push({ level: "warn", phase: "tests", message })
|
|
58386
58912
|
}),
|
|
58387
58913
|
req: requestView(outcome.request, adopt),
|
|
58388
58914
|
res: responseView(response, adopt)
|
|
58389
58915
|
})
|
|
58390
58916
|
});
|
|
58391
|
-
const scriptError = layer.defaults ? await session.asDefaults(
|
|
58917
|
+
const scriptError = layer.defaults ? await session.asDefaults(run2) : await run2();
|
|
58392
58918
|
if (scriptError) testsError = { ...scriptError, script: layer.script };
|
|
58393
58919
|
}
|
|
58394
58920
|
} catch (cause) {
|
|
@@ -58411,8 +58937,37 @@ async function runRequest(input2) {
|
|
|
58411
58937
|
durationMs: performance.now() - startedHr
|
|
58412
58938
|
};
|
|
58413
58939
|
}
|
|
58414
|
-
function
|
|
58415
|
-
|
|
58940
|
+
function changedRequest(shown, view, body) {
|
|
58941
|
+
if (!view) return null;
|
|
58942
|
+
let next = null;
|
|
58943
|
+
if (view.body !== shown.body) {
|
|
58944
|
+
if (typeof view.body !== "string") {
|
|
58945
|
+
throw new Error(`req.body is the body's text; a script set it to ${typeof view.body}`);
|
|
58946
|
+
}
|
|
58947
|
+
const text = body?.json ?? body?.xml ?? body?.text ?? body?.graphql;
|
|
58948
|
+
if (text === void 0) {
|
|
58949
|
+
throw new Error(
|
|
58950
|
+
"req.body can be changed for a json, xml, text or graphql body; a form, multipart or file body is built from its parts, and a step with no body has none to change"
|
|
58951
|
+
);
|
|
58952
|
+
}
|
|
58953
|
+
next = { ...shown, body: view.body };
|
|
58954
|
+
}
|
|
58955
|
+
const was = Object.fromEntries(shown.headers.map((header) => [header.name, header.value]));
|
|
58956
|
+
if (JSON.stringify(view.headers) !== JSON.stringify(was)) {
|
|
58957
|
+
const headers = view.headers;
|
|
58958
|
+
if (headers === null || typeof headers !== "object" || Array.isArray(headers)) {
|
|
58959
|
+
throw new Error("req.headers is a map of header names to their values");
|
|
58960
|
+
}
|
|
58961
|
+
next = {
|
|
58962
|
+
...next ?? shown,
|
|
58963
|
+
headers: Object.entries(headers).filter(([, value]) => value !== void 0 && value !== null).map(([name, value]) => ({ name, value: String(value) }))
|
|
58964
|
+
};
|
|
58965
|
+
}
|
|
58966
|
+
return next;
|
|
58967
|
+
}
|
|
58968
|
+
async function fileRoots(step, file2, collection) {
|
|
58969
|
+
if (!file2 || bodyFiles(step.body).length === 0) return null;
|
|
58970
|
+
return fileRootsOf(file2, collection ?? file2);
|
|
58416
58971
|
}
|
|
58417
58972
|
function interpolateError(cause) {
|
|
58418
58973
|
return {
|
|
@@ -58442,82 +58997,16 @@ function toSentRequestSafely(step, collection) {
|
|
|
58442
58997
|
}
|
|
58443
58998
|
|
|
58444
58999
|
// ../../packages/core/src/run/runCollection.ts
|
|
58445
|
-
import path10 from "node:path";
|
|
58446
|
-
|
|
58447
|
-
// ../../packages/core/src/run/plan.ts
|
|
58448
59000
|
import path9 from "node:path";
|
|
58449
|
-
async function planSteps(collection, collectionPath) {
|
|
58450
|
-
const planned = [];
|
|
58451
|
-
let project;
|
|
58452
|
-
for (const [index, step] of collection.steps.entries()) {
|
|
58453
|
-
if (!isUseStep(step)) {
|
|
58454
|
-
planned.push({ kind: "request", index, step });
|
|
58455
|
-
continue;
|
|
58456
|
-
}
|
|
58457
|
-
try {
|
|
58458
|
-
if (!collectionPath)
|
|
58459
|
-
throw new Error(`use: ${step.use} \u2014 save the collection in a project first`);
|
|
58460
|
-
project ??= await projectOf(collectionPath);
|
|
58461
|
-
const set2 = await resolveRequestSet(project.root, project.global, step.use);
|
|
58462
|
-
checkWith(step.use, set2.doc, step.with ?? {});
|
|
58463
|
-
if (set2.doc.steps.length === 0) throw new Error(`use: ${step.use} \u2014 the set has no steps`);
|
|
58464
|
-
const planSet = {
|
|
58465
|
-
name: step.use,
|
|
58466
|
-
path: set2.path,
|
|
58467
|
-
doc: set2.doc,
|
|
58468
|
-
with: step.with ?? {},
|
|
58469
|
-
useTests: step.tests
|
|
58470
|
-
};
|
|
58471
|
-
set2.doc.steps.forEach((child, number4) => {
|
|
58472
|
-
planned.push({ kind: "request", index, step: child, set: planSet, child: number4 });
|
|
58473
|
-
});
|
|
58474
|
-
} catch (cause) {
|
|
58475
|
-
planned.push({
|
|
58476
|
-
kind: "broken",
|
|
58477
|
-
index,
|
|
58478
|
-
step,
|
|
58479
|
-
error: { phase: "use", message: cause instanceof Error ? cause.message : String(cause) }
|
|
58480
|
-
});
|
|
58481
|
-
}
|
|
58482
|
-
}
|
|
58483
|
-
return planned;
|
|
58484
|
-
}
|
|
58485
|
-
async function projectOf(collectionPath) {
|
|
58486
|
-
const root = projectRootOf(collectionPath) ?? path9.dirname(collectionPath);
|
|
58487
|
-
const { global } = await readProject(root);
|
|
58488
|
-
return { root, global };
|
|
58489
|
-
}
|
|
58490
|
-
function checkWith(name, set2, given) {
|
|
58491
|
-
const params = set2.params ?? {};
|
|
58492
|
-
const unknown2 = Object.keys(given).filter((key) => !(key in params));
|
|
58493
|
-
if (unknown2.length > 0) {
|
|
58494
|
-
const takes = Object.keys(params).join(", ") || "none";
|
|
58495
|
-
throw new Error(`use: ${name} \u2014 it takes no ${unknown2.join(", ")} (it takes: ${takes})`);
|
|
58496
|
-
}
|
|
58497
|
-
const missing = Object.entries(params).filter(([key, spec]) => readParam(spec).required && !(key in given)).map(([key]) => key);
|
|
58498
|
-
if (missing.length > 0) {
|
|
58499
|
-
throw new Error(`use: ${name} \u2014 needs ${missing.join(", ")} in with:`);
|
|
58500
|
-
}
|
|
58501
|
-
}
|
|
58502
|
-
function resolveParams(set2, scope) {
|
|
58503
|
-
const params = {};
|
|
58504
|
-
for (const [key, spec] of Object.entries(set2.doc.params ?? {})) {
|
|
58505
|
-
const given = set2.with[key];
|
|
58506
|
-
if (given !== void 0)
|
|
58507
|
-
params[key] = typeof given === "string" ? interpolate(given, scope) : given;
|
|
58508
|
-
else {
|
|
58509
|
-
const fallback = readParam(spec).default;
|
|
58510
|
-
if (fallback !== void 0) params[key] = fallback;
|
|
58511
|
-
}
|
|
58512
|
-
}
|
|
58513
|
-
return params;
|
|
58514
|
-
}
|
|
58515
|
-
|
|
58516
|
-
// ../../packages/core/src/run/runCollection.ts
|
|
58517
59001
|
async function runCollection(options) {
|
|
58518
59002
|
const { collection, collectionPath = null, context, signal, onResult, bail = false } = options;
|
|
59003
|
+
const stage = options.stage ?? "steps";
|
|
58519
59004
|
const startedHr = performance.now();
|
|
58520
|
-
const scope = context ? await buildScope({
|
|
59005
|
+
const scope = context ? await buildScope({
|
|
59006
|
+
collectionExtends: collection.extends ?? null,
|
|
59007
|
+
...context,
|
|
59008
|
+
...options.run ? { run: options.run } : {}
|
|
59009
|
+
}) : withRun(new VariableScope(), options.run);
|
|
58521
59010
|
const library = collectionPath ? await loadLibrary(collectionPath) : null;
|
|
58522
59011
|
const checks = library?.checks ?? [];
|
|
58523
59012
|
const endpoints = library?.endpoints ?? [];
|
|
@@ -58532,50 +59021,101 @@ async function runCollection(options) {
|
|
|
58532
59021
|
baseError = { phase: "use", message: cause.message };
|
|
58533
59022
|
}
|
|
58534
59023
|
}
|
|
59024
|
+
const running = stage === "steps" ? collection : { ...collection, steps: collection[stage] ?? [] };
|
|
58535
59025
|
const own2 = collection.params ? selfAsSet(collection, collectionPath) : void 0;
|
|
58536
|
-
const plan = await planSteps(
|
|
59026
|
+
const plan = await planSteps(running, collectionPath);
|
|
58537
59027
|
const results = [];
|
|
58538
|
-
let params =
|
|
58539
|
-
|
|
59028
|
+
let params = null;
|
|
59029
|
+
let unstarted = null;
|
|
59030
|
+
const paramsOf = (using) => () => {
|
|
59031
|
+
if (unstarted) throw new Error(unstarted.message);
|
|
59032
|
+
if (!params) {
|
|
59033
|
+
try {
|
|
59034
|
+
params = resolveParams(using.doc.params, using.with, scope);
|
|
59035
|
+
} catch (cause) {
|
|
59036
|
+
unstarted = { phase: "use", message: `use: ${using.name} \u2014 ${cause.message}` };
|
|
59037
|
+
throw new Error(unstarted.message);
|
|
59038
|
+
}
|
|
59039
|
+
}
|
|
59040
|
+
return params;
|
|
59041
|
+
};
|
|
59042
|
+
let rest = null;
|
|
59043
|
+
let attempted = 0;
|
|
59044
|
+
const emit = (index, result) => {
|
|
59045
|
+
const marked = stage === "steps" ? result : { ...result, stage };
|
|
59046
|
+
results.push(marked);
|
|
59047
|
+
onResult?.(index, marked);
|
|
59048
|
+
};
|
|
59049
|
+
const failing = (result) => result.status === "fail" || result.status === "error";
|
|
59050
|
+
planning: for (const planned of plan) {
|
|
58540
59051
|
if (signal?.aborted) break;
|
|
58541
|
-
|
|
59052
|
+
attempted++;
|
|
58542
59053
|
if (baseError) {
|
|
58543
|
-
|
|
58544
|
-
|
|
58545
|
-
|
|
58546
|
-
}
|
|
58547
|
-
|
|
58548
|
-
|
|
58549
|
-
|
|
58550
|
-
|
|
59054
|
+
emit(planned.index, brokenUse(planned.step, baseError, collectionPath));
|
|
59055
|
+
if (bail) break;
|
|
59056
|
+
continue;
|
|
59057
|
+
}
|
|
59058
|
+
if (planned.kind === "broken") {
|
|
59059
|
+
emit(planned.index, brokenUse(planned.step, planned.error, collectionPath));
|
|
59060
|
+
if (bail) break;
|
|
59061
|
+
continue;
|
|
59062
|
+
}
|
|
59063
|
+
const set2 = planned.set ? positionOf(planned.set, planned.child ?? 0) : void 0;
|
|
59064
|
+
const inSet = set2 ? { use: useOf(set2) } : {};
|
|
59065
|
+
if (rest !== null) {
|
|
59066
|
+
emit(planned.index, { ...skipped(planned.step, rest, collectionPath), ...inSet });
|
|
59067
|
+
continue;
|
|
59068
|
+
}
|
|
59069
|
+
if (set2 || own2) {
|
|
59070
|
+
const using = set2?.planned ?? own2;
|
|
59071
|
+
const starting = set2 ? set2.child === 0 : planned.index === 0;
|
|
59072
|
+
if (starting) {
|
|
59073
|
+
params = null;
|
|
59074
|
+
unstarted = null;
|
|
59075
|
+
if (!set2) {
|
|
58551
59076
|
try {
|
|
58552
|
-
|
|
58553
|
-
} catch
|
|
58554
|
-
params = {};
|
|
58555
|
-
result = brokenUse(
|
|
58556
|
-
planned.step,
|
|
58557
|
-
{
|
|
58558
|
-
phase: "use",
|
|
58559
|
-
message: `use: ${(set2?.planned ?? own2).name} \u2014 ${cause.message}`
|
|
58560
|
-
},
|
|
58561
|
-
collectionPath
|
|
58562
|
-
);
|
|
58563
|
-
results.push(result);
|
|
58564
|
-
onResult?.(planned.index, result);
|
|
58565
|
-
if (bail) break;
|
|
58566
|
-
continue;
|
|
59077
|
+
paramsOf(using)();
|
|
59078
|
+
} catch {
|
|
58567
59079
|
}
|
|
58568
59080
|
}
|
|
58569
59081
|
}
|
|
58570
|
-
|
|
58571
|
-
|
|
58572
|
-
|
|
58573
|
-
|
|
58574
|
-
|
|
58575
|
-
|
|
59082
|
+
}
|
|
59083
|
+
const gate = flagGate(running, planned.index, planned.step, scope);
|
|
59084
|
+
if (gate) {
|
|
59085
|
+
const result = gate(collectionPath);
|
|
59086
|
+
emit(planned.index, result);
|
|
59087
|
+
if (bail && result.status === "error") break;
|
|
59088
|
+
continue;
|
|
59089
|
+
}
|
|
59090
|
+
if (unstarted && (set2 || own2)) {
|
|
59091
|
+
emit(planned.index, { ...brokenUse(planned.step, unstarted, collectionPath), ...inSet });
|
|
59092
|
+
if (bail) break;
|
|
59093
|
+
continue;
|
|
59094
|
+
}
|
|
59095
|
+
let items = [null];
|
|
59096
|
+
if (planned.step.forEach !== void 0) {
|
|
59097
|
+
try {
|
|
59098
|
+
items = forEachItems(planned.step.forEach, scope).map((value) => ({ value }));
|
|
59099
|
+
} catch (cause) {
|
|
59100
|
+
const error62 = { phase: "forEach", message: cause.message };
|
|
59101
|
+
emit(planned.index, { ...brokenUse(planned.step, error62, collectionPath), ...inSet });
|
|
59102
|
+
if (bail) break;
|
|
59103
|
+
continue;
|
|
59104
|
+
}
|
|
59105
|
+
if (items.length === 0) {
|
|
59106
|
+
const reason = `forEach: ${planned.step.forEach} is an empty list`;
|
|
59107
|
+
emit(planned.index, { ...skipped(planned.step, reason, collectionPath), ...inSet });
|
|
58576
59108
|
continue;
|
|
58577
59109
|
}
|
|
58578
|
-
|
|
59110
|
+
}
|
|
59111
|
+
for (const [index, each] of items.entries()) {
|
|
59112
|
+
if (signal?.aborted) break planning;
|
|
59113
|
+
if (rest !== null) {
|
|
59114
|
+
emit(planned.index, { ...skipped(planned.step, rest, collectionPath), ...inSet });
|
|
59115
|
+
continue;
|
|
59116
|
+
}
|
|
59117
|
+
const control = newStepControl();
|
|
59118
|
+
const result = await runRequest({
|
|
58579
59119
|
step: planned.step,
|
|
58580
59120
|
collection,
|
|
58581
59121
|
itemPath: collectionPath,
|
|
@@ -58583,45 +59123,76 @@ async function runCollection(options) {
|
|
|
58583
59123
|
checks,
|
|
58584
59124
|
endpoints,
|
|
58585
59125
|
base: base2,
|
|
59126
|
+
control,
|
|
58586
59127
|
...library ? { tls: library.tls } : {},
|
|
59128
|
+
...each ? { item: { value: each.value, index, of: items.length } } : {},
|
|
58587
59129
|
...set2 ? {
|
|
58588
59130
|
set: {
|
|
58589
59131
|
name: set2.planned.name,
|
|
59132
|
+
...set2.planned.useName ? { useName: set2.planned.useName } : {},
|
|
58590
59133
|
path: set2.planned.path,
|
|
58591
59134
|
doc: set2.planned.doc,
|
|
58592
|
-
params,
|
|
59135
|
+
params: paramsOf(set2.planned),
|
|
58593
59136
|
child: set2.child,
|
|
58594
59137
|
of: set2.of,
|
|
58595
59138
|
useTests: set2.planned.useTests
|
|
58596
59139
|
}
|
|
58597
|
-
} : own2 ? { params } : {},
|
|
59140
|
+
} : own2 ? { params: params ?? {} } : {},
|
|
58598
59141
|
...signal ? { signal } : {}
|
|
58599
59142
|
});
|
|
59143
|
+
emit(planned.index, result);
|
|
59144
|
+
rest ??= control.rest;
|
|
59145
|
+
if (bail && failing(result)) break planning;
|
|
58600
59146
|
}
|
|
58601
|
-
results.push(result);
|
|
58602
|
-
onResult?.(planned.index, result);
|
|
58603
|
-
if (bail && result.status !== "pass") break;
|
|
58604
59147
|
}
|
|
59148
|
+
const notBegun = plan.length - attempted;
|
|
58605
59149
|
return {
|
|
58606
|
-
total:
|
|
59150
|
+
total: results.length + notBegun,
|
|
58607
59151
|
passed: results.filter((r) => r.status === "pass").length,
|
|
58608
59152
|
failed: results.filter((r) => r.status === "fail").length,
|
|
58609
59153
|
errored: results.filter((r) => r.status === "error").length,
|
|
58610
|
-
// A step a feature flag skipped, and one never
|
|
58611
|
-
skipped:
|
|
59154
|
+
// A step a feature flag or a script skipped, and one never begun, are all not run.
|
|
59155
|
+
skipped: notBegun + results.filter((r) => r.status === "skipped").length,
|
|
58612
59156
|
durationMs: performance.now() - startedHr,
|
|
58613
59157
|
results
|
|
58614
59158
|
};
|
|
58615
59159
|
}
|
|
59160
|
+
function withRun(scope, run) {
|
|
59161
|
+
if (!run) return scope;
|
|
59162
|
+
const built = new VariableScope([{ source: "run", vars: Object.fromEntries(run.values) }]);
|
|
59163
|
+
built.runValues = run.values;
|
|
59164
|
+
built.runWide = run.wide === true;
|
|
59165
|
+
return built;
|
|
59166
|
+
}
|
|
59167
|
+
function forEachItems(expression, scope) {
|
|
59168
|
+
const value = interpolate(expression, scope);
|
|
59169
|
+
if (typeof value === "string") {
|
|
59170
|
+
try {
|
|
59171
|
+
const parsed = JSON.parse(value);
|
|
59172
|
+
if (Array.isArray(parsed)) return parsed;
|
|
59173
|
+
} catch {
|
|
59174
|
+
}
|
|
59175
|
+
}
|
|
59176
|
+
throw new Error(
|
|
59177
|
+
`forEach: ${expression} is ${show(value)}, not a list; it needs a JSON array, such as ["a", "b"]`
|
|
59178
|
+
);
|
|
59179
|
+
}
|
|
58616
59180
|
function positionOf(planned, child) {
|
|
58617
59181
|
return { planned, child, of: planned.doc.steps.length };
|
|
58618
59182
|
}
|
|
59183
|
+
var useOf = (set2) => ({
|
|
59184
|
+
set: set2.planned.name,
|
|
59185
|
+
...set2.planned.useName ? { name: set2.planned.useName } : {},
|
|
59186
|
+
child: set2.child,
|
|
59187
|
+
of: set2.of
|
|
59188
|
+
});
|
|
58619
59189
|
function selfAsSet(collection, collectionPath) {
|
|
58620
59190
|
return {
|
|
58621
|
-
name: collectionPath ?
|
|
59191
|
+
name: collectionPath ? path9.basename(collectionPath, ".yml") : collection.id ?? "set",
|
|
58622
59192
|
path: collectionPath ?? "",
|
|
58623
59193
|
// Its own before, tests, headers and settings already apply as the collection's.
|
|
58624
59194
|
doc: { params: collection.params, steps: collection.steps },
|
|
59195
|
+
useName: void 0,
|
|
58625
59196
|
with: {},
|
|
58626
59197
|
useTests: void 0
|
|
58627
59198
|
};
|
|
@@ -58657,6 +59228,10 @@ function flagGate(collection, index, step, scope) {
|
|
|
58657
59228
|
return (collectionPath) => brokenUse(step, { phase: "flags", message: cause.message }, collectionPath);
|
|
58658
59229
|
}
|
|
58659
59230
|
}
|
|
59231
|
+
var skipped = (step, reason, collectionPath) => ({
|
|
59232
|
+
...notRun(step, collectionPath),
|
|
59233
|
+
skipped: { reason }
|
|
59234
|
+
});
|
|
58660
59235
|
var notRun = (step, collectionPath) => ({
|
|
58661
59236
|
item: { path: collectionPath, name: stepLabel(step), seq: null },
|
|
58662
59237
|
request: {
|
|
@@ -58672,6 +59247,62 @@ var notRun = (step, collectionPath) => ({
|
|
|
58672
59247
|
durationMs: 0
|
|
58673
59248
|
});
|
|
58674
59249
|
|
|
59250
|
+
// ../../packages/core/src/run/runSuite.ts
|
|
59251
|
+
async function runSuite(options) {
|
|
59252
|
+
const { collection, collectionPath = null, context, signal, bail = false, onResult } = options;
|
|
59253
|
+
const values = /* @__PURE__ */ new Map();
|
|
59254
|
+
const summaries = [];
|
|
59255
|
+
const once = (stage, stopEarly) => runCollection({
|
|
59256
|
+
collection,
|
|
59257
|
+
collectionPath,
|
|
59258
|
+
stage,
|
|
59259
|
+
run: { values, wide: true },
|
|
59260
|
+
...context ? { context: { ...context, dataRow: null } } : {},
|
|
59261
|
+
...signal ? { signal } : {},
|
|
59262
|
+
bail: stopEarly,
|
|
59263
|
+
onResult: (index, result) => onResult?.(index, result, void 0)
|
|
59264
|
+
});
|
|
59265
|
+
let stopped = false;
|
|
59266
|
+
if (collection.setup?.length) {
|
|
59267
|
+
const setup = await once("setup", bail);
|
|
59268
|
+
summaries.push(setup);
|
|
59269
|
+
stopped = setup.failed + setup.errored > 0;
|
|
59270
|
+
}
|
|
59271
|
+
const rows = options.rows?.length ? options.rows : null;
|
|
59272
|
+
const passes = rows ?? [null];
|
|
59273
|
+
let unrun = 0;
|
|
59274
|
+
for (const [i, row] of passes.entries()) {
|
|
59275
|
+
if (stopped || signal?.aborted) {
|
|
59276
|
+
unrun = (await planSteps(collection, collectionPath)).length * (passes.length - i);
|
|
59277
|
+
break;
|
|
59278
|
+
}
|
|
59279
|
+
const iteration = rows && row ? { index: i + 1, of: rows.length, label: row.label } : void 0;
|
|
59280
|
+
const summary = await runCollection({
|
|
59281
|
+
collection,
|
|
59282
|
+
collectionPath,
|
|
59283
|
+
run: { values },
|
|
59284
|
+
...context ? {
|
|
59285
|
+
context: row ? { ...context, dataRow: { source: row.source, vars: row.vars } } : context
|
|
59286
|
+
} : {},
|
|
59287
|
+
...signal ? { signal } : {},
|
|
59288
|
+
bail,
|
|
59289
|
+
onResult: (index, result) => onResult?.(index, result, iteration)
|
|
59290
|
+
});
|
|
59291
|
+
summaries.push(summary);
|
|
59292
|
+
if (bail && summary.failed + summary.errored > 0) stopped = true;
|
|
59293
|
+
}
|
|
59294
|
+
if (collection.teardown?.length && !signal?.aborted) summaries.push(await once("teardown", false));
|
|
59295
|
+
return {
|
|
59296
|
+
total: summaries.reduce((n, s) => n + s.total, 0) + unrun,
|
|
59297
|
+
passed: summaries.reduce((n, s) => n + s.passed, 0),
|
|
59298
|
+
failed: summaries.reduce((n, s) => n + s.failed, 0),
|
|
59299
|
+
errored: summaries.reduce((n, s) => n + s.errored, 0),
|
|
59300
|
+
skipped: summaries.reduce((n, s) => n + s.skipped, 0) + unrun,
|
|
59301
|
+
durationMs: summaries.reduce((n, s) => n + s.durationMs, 0),
|
|
59302
|
+
results: summaries.flatMap((s) => s.results)
|
|
59303
|
+
};
|
|
59304
|
+
}
|
|
59305
|
+
|
|
58675
59306
|
// ../../packages/core/src/flags/resolve.ts
|
|
58676
59307
|
import { spawn } from "node:child_process";
|
|
58677
59308
|
var FLAG_COMMAND_TIMEOUT_MS = 6e4;
|
|
@@ -58860,41 +59491,29 @@ async function runJob(job) {
|
|
|
58860
59491
|
const context = { collectionPath: loaded.path, environmentName: job.environment };
|
|
58861
59492
|
const lines = await stepLines(loaded.path);
|
|
58862
59493
|
const data = loaded.dataFile ? await readDataFile(loaded.dataFile.path) : null;
|
|
58863
|
-
const rows = data ? data.rows : [null];
|
|
58864
|
-
const summaries = [];
|
|
58865
59494
|
const refs = [];
|
|
58866
|
-
|
|
58867
|
-
|
|
58868
|
-
|
|
58869
|
-
|
|
58870
|
-
|
|
58871
|
-
|
|
58872
|
-
|
|
58873
|
-
|
|
58874
|
-
|
|
58875
|
-
|
|
58876
|
-
|
|
58877
|
-
|
|
58878
|
-
|
|
58879
|
-
|
|
58880
|
-
|
|
58881
|
-
|
|
58882
|
-
|
|
58883
|
-
|
|
58884
|
-
|
|
58885
|
-
|
|
58886
|
-
break;
|
|
59495
|
+
const summary = await runSuite({
|
|
59496
|
+
collection,
|
|
59497
|
+
collectionPath: loaded.path,
|
|
59498
|
+
context: { ...context, flags: job.flags, dataRow: null },
|
|
59499
|
+
rows: data ? data.rows.map((row, i) => ({
|
|
59500
|
+
source: `${path10.basename(data.path)} row ${i + 1}`,
|
|
59501
|
+
vars: row.values,
|
|
59502
|
+
label: row.label
|
|
59503
|
+
})) : null,
|
|
59504
|
+
bail: job.bail,
|
|
59505
|
+
// Each result reports the step it ran under — a use step's requests all under it.
|
|
59506
|
+
onResult: (index, result, iteration) => {
|
|
59507
|
+
const stage = result.stage;
|
|
59508
|
+
const step = stage ? index : job.steps ? job.steps[index] ?? index : index;
|
|
59509
|
+
refs.push({
|
|
59510
|
+
index: step,
|
|
59511
|
+
line: lines[stage ?? "steps"][step] ?? null,
|
|
59512
|
+
...stage ? { stage } : {},
|
|
59513
|
+
...iteration ? { iteration } : {}
|
|
59514
|
+
});
|
|
58887
59515
|
}
|
|
58888
|
-
}
|
|
58889
|
-
const summary = {
|
|
58890
|
-
total: summaries.reduce((n, s) => n + s.total, 0) + unrun,
|
|
58891
|
-
passed: summaries.reduce((n, s) => n + s.passed, 0),
|
|
58892
|
-
failed: summaries.reduce((n, s) => n + s.failed, 0),
|
|
58893
|
-
errored: summaries.reduce((n, s) => n + s.errored, 0),
|
|
58894
|
-
skipped: summaries.reduce((n, s) => n + s.skipped, 0) + unrun,
|
|
58895
|
-
durationMs: summaries.reduce((n, s) => n + s.durationMs, 0),
|
|
58896
|
-
results: summaries.flatMap((s) => s.results)
|
|
58897
|
-
};
|
|
59516
|
+
});
|
|
58898
59517
|
return {
|
|
58899
59518
|
ok: true,
|
|
58900
59519
|
summary: redact(summary, await secretsOf(context)),
|
|
@@ -58935,22 +59554,25 @@ function redact(value, secrets) {
|
|
|
58935
59554
|
return walk(value);
|
|
58936
59555
|
}
|
|
58937
59556
|
async function stepLines(file2) {
|
|
59557
|
+
const lines = { setup: [], steps: [], teardown: [] };
|
|
58938
59558
|
try {
|
|
58939
59559
|
const counter = new import_yaml7.LineCounter();
|
|
58940
59560
|
const document = (0, import_yaml7.parseDocument)(await fs9.readFile(file2, "utf8"), { lineCounter: counter });
|
|
58941
|
-
const
|
|
58942
|
-
|
|
58943
|
-
|
|
58944
|
-
|
|
58945
|
-
|
|
59561
|
+
const of = (key) => {
|
|
59562
|
+
const list = document.get(key, true);
|
|
59563
|
+
if (!list || typeof list !== "object" || !("items" in list)) return [];
|
|
59564
|
+
return list.items.map(
|
|
59565
|
+
(item) => item?.range ? counter.linePos(item.range[0]).line : null
|
|
59566
|
+
);
|
|
59567
|
+
};
|
|
59568
|
+
return { setup: of("setup"), steps: of("steps"), teardown: of("teardown") };
|
|
58946
59569
|
} catch {
|
|
58947
|
-
return
|
|
59570
|
+
return lines;
|
|
58948
59571
|
}
|
|
58949
59572
|
}
|
|
58950
59573
|
|
|
58951
59574
|
export {
|
|
58952
59575
|
__toESM,
|
|
58953
|
-
require_dist,
|
|
58954
59576
|
external_exports,
|
|
58955
59577
|
TagSchema,
|
|
58956
59578
|
stepsForTags,
|
|
@@ -58959,7 +59581,9 @@ export {
|
|
|
58959
59581
|
samePath,
|
|
58960
59582
|
relativePosix,
|
|
58961
59583
|
environmentNames,
|
|
59584
|
+
resultName,
|
|
58962
59585
|
parseMarkdown,
|
|
59586
|
+
require_dist,
|
|
58963
59587
|
COLLECTIONS_DIR,
|
|
58964
59588
|
SETTINGS_FILE,
|
|
58965
59589
|
DOC_EXTENSION,
|
|
@@ -58968,6 +59592,7 @@ export {
|
|
|
58968
59592
|
projectEnvironments,
|
|
58969
59593
|
loadProjectCollections,
|
|
58970
59594
|
loadProjectTls,
|
|
59595
|
+
referenceProblems,
|
|
58971
59596
|
resolveFlags,
|
|
58972
59597
|
flagOverrides,
|
|
58973
59598
|
unattempted,
|