@enricai/barnacle 1.12.51 → 1.12.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scraper/captcha-callback-capture.d.ts +5 -1
- package/dist/scraper/captcha-callback-capture.d.ts.map +1 -1
- package/dist/scraper/captcha-callback-capture.js +46 -1
- package/dist/scraper/captcha-callback-capture.js.map +1 -1
- package/dist/scripts/recon-generate-multicall-fixture.d.ts +156 -0
- package/dist/scripts/recon-generate-multicall-fixture.d.ts.map +1 -1
- package/dist/scripts/recon-generate-multicall-fixture.js +489 -0
- package/dist/scripts/recon-generate-multicall-fixture.js.map +1 -1
- package/dist/scripts/recon-generate.d.ts +6 -0
- package/dist/scripts/recon-generate.d.ts.map +1 -1
- package/dist/scripts/recon-generate.js +246 -87
- package/dist/scripts/recon-generate.js.map +1 -1
- package/dist/scripts/recon-summarize.d.ts +11 -1
- package/dist/scripts/recon-summarize.d.ts.map +1 -1
- package/dist/scripts/recon-summarize.js +51 -32
- package/dist/scripts/recon-summarize.js.map +1 -1
- package/dist/scripts/smoke-test.d.ts +20 -1
- package/dist/scripts/smoke-test.d.ts.map +1 -1
- package/dist/scripts/smoke-test.js +13 -4
- package/dist/scripts/smoke-test.js.map +1 -1
- package/package.json +1 -1
|
@@ -21,12 +21,18 @@ exports.buildMulticallTwoIndependentPrimariesSecondHeaderThreadedActionSteps = b
|
|
|
21
21
|
exports.buildMulticallSingleShotSearchHeuristicAndSpecTwoTargetActionSteps = buildMulticallSingleShotSearchHeuristicAndSpecTwoTargetActionSteps;
|
|
22
22
|
exports.buildMulticallTwoOccurrencesSamePrimaryDistinctDrillsActionSteps = buildMulticallTwoOccurrencesSamePrimaryDistinctDrillsActionSteps;
|
|
23
23
|
exports.buildMulticallNestedGroupedDrillDownMultiGroupActionSteps = buildMulticallNestedGroupedDrillDownMultiGroupActionSteps;
|
|
24
|
+
exports.buildMulticallTwoIndependentPrimariesNestedFieldLoopScopeActionSteps = buildMulticallTwoIndependentPrimariesNestedFieldLoopScopeActionSteps;
|
|
24
25
|
exports.buildMulticallNestedGroupedDrillDownTwoScopeParamsActionSteps = buildMulticallNestedGroupedDrillDownTwoScopeParamsActionSteps;
|
|
25
26
|
exports.buildMulticallNestedGroupedDrillDownAncestorOnlyParamsActionSteps = buildMulticallNestedGroupedDrillDownAncestorOnlyParamsActionSteps;
|
|
26
27
|
exports.buildMulticallNestedGroupedDrillDownScopeCoincidentParamActionSteps = buildMulticallNestedGroupedDrillDownScopeCoincidentParamActionSteps;
|
|
27
28
|
exports.buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamActionSteps = buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamActionSteps;
|
|
29
|
+
exports.buildMulticallNestedGroupedDrillDownSparseFirstElementAncestorScopedParamActionSteps = buildMulticallNestedGroupedDrillDownSparseFirstElementAncestorScopedParamActionSteps;
|
|
30
|
+
exports.buildMulticallNestedGroupedDrillDownAncestorItemValueCoincidenceActionSteps = buildMulticallNestedGroupedDrillDownAncestorItemValueCoincidenceActionSteps;
|
|
31
|
+
exports.buildMulticallNestedGroupedDrillDownTwoLevelNestedAncestorFieldActionSteps = buildMulticallNestedGroupedDrillDownTwoLevelNestedAncestorFieldActionSteps;
|
|
28
32
|
exports.buildMulticallNestedGroupedDrillDownDualScopeCoincidentParamsActionSteps = buildMulticallNestedGroupedDrillDownDualScopeCoincidentParamsActionSteps;
|
|
29
33
|
exports.buildMulticallNestedGroupedDrillDownDualItemLiteralDistinctSubpathAncestorScopedParamsActionSteps = buildMulticallNestedGroupedDrillDownDualItemLiteralDistinctSubpathAncestorScopedParamsActionSteps;
|
|
34
|
+
exports.buildMulticallAncestorOnlyMultiTargetDrillDownActionSteps = buildMulticallAncestorOnlyMultiTargetDrillDownActionSteps;
|
|
35
|
+
exports.buildMulticallAncestorScopedDualThreadedFieldDrillDownActionSteps = buildMulticallAncestorScopedDualThreadedFieldDrillDownActionSteps;
|
|
30
36
|
exports.buildMulticallSingleShotSearchDrillDownNumericJoinActionSteps = buildMulticallSingleShotSearchDrillDownNumericJoinActionSteps;
|
|
31
37
|
exports.buildMulticallSingleShotSearchDrillDownPathThreadedJoinActionSteps = buildMulticallSingleShotSearchDrillDownPathThreadedJoinActionSteps;
|
|
32
38
|
exports.buildMulticallSingleShotSearchDrillDownNestedJoinFieldActionSteps = buildMulticallSingleShotSearchDrillDownNestedJoinFieldActionSteps;
|
|
@@ -67,6 +73,7 @@ exports.buildMulticallSingleShotSearchDrillDownConstantParamCoincidentValueActio
|
|
|
67
73
|
exports.buildMulticallSingleShotSearchDrillDownBoundConstantParamCoincidentValueActionSteps = buildMulticallSingleShotSearchDrillDownBoundConstantParamCoincidentValueActionSteps;
|
|
68
74
|
exports.buildManyRepeatPagedListingDrillWithNoiseVariantActionSteps = buildManyRepeatPagedListingDrillWithNoiseVariantActionSteps;
|
|
69
75
|
exports.buildSessionHeartbeatNoiseStep = buildSessionHeartbeatNoiseStep;
|
|
76
|
+
exports.buildMulticallOrdersLineItemPromoEligibilityActionSteps = buildMulticallOrdersLineItemPromoEligibilityActionSteps;
|
|
70
77
|
const date_fns_1 = require("date-fns");
|
|
71
78
|
function buildCapture(overrides) {
|
|
72
79
|
return {
|
|
@@ -800,6 +807,85 @@ function buildMulticallNestedGroupedDrillDownMultiGroupActionSteps() {
|
|
|
800
807
|
];
|
|
801
808
|
}
|
|
802
809
|
const CATALOG_ENTRY_DETAILS_URL = "https://api.example.com/catalog/entries/details";
|
|
810
|
+
/**
|
|
811
|
+
* TWO fully independent fold plans in one action-step sequence, each bound to
|
|
812
|
+
* its OWN loop-variable name (`item0`/`item1` — every loop var is suffixed by
|
|
813
|
+
* plan index once more than one independent plan resolves): a flat,
|
|
814
|
+
* heuristically-detected primary/drill pair (products/reviews, `item0`) and a
|
|
815
|
+
* nested GROUPED primary/drill pair (sections/entries, `item1`) whose
|
|
816
|
+
* per-item join field lives under a NESTED path (`identifiers.code`).
|
|
817
|
+
*
|
|
818
|
+
* That nested path is the exact shape that regresses the fold-hoist decision
|
|
819
|
+
* in `emitMultiStepExecuteHttp`/`buildFoldMergeLines`: `scopedAccessor`/
|
|
820
|
+
* `unknownValueAccessor` wrap every non-leaf hop of a nested field path in a
|
|
821
|
+
* `(item1.identifiers as Record<string, unknown>)` cast, so the drill's
|
|
822
|
+
* itemVar reference renders as `${(item1.identifiers...` rather than
|
|
823
|
+
* `${item1...}`. An `itemVarRefPattern` anchored on `${itemVar` immediately
|
|
824
|
+
* following the interpolation brace misses that cast-wrapped shape entirely,
|
|
825
|
+
* wrongly concludes the drill never references `item1`, and hoists it above
|
|
826
|
+
* `item1`'s own loop — into a scope where `item1` is undeclared — even
|
|
827
|
+
* though `entries/details`' `code` value differs per item (`e1`/`e2`), which
|
|
828
|
+
* is only resolvable per-item, never once per group.
|
|
829
|
+
*
|
|
830
|
+
* Regression coverage: `item1`'s own chain fetch must stay lexically INSIDE
|
|
831
|
+
* `item1`'s own loop, and must never appear inside `item0`'s loop (and vice
|
|
832
|
+
* versa) — even though both plans' drills structurally target the same
|
|
833
|
+
* `entries/details` endpoint shape, so a scope-defeating fold-hoist bug has
|
|
834
|
+
* every opportunity to bleed one loop's bound identifier into the other's
|
|
835
|
+
* request body.
|
|
836
|
+
*/
|
|
837
|
+
function buildMulticallTwoIndependentPrimariesNestedFieldLoopScopeActionSteps() {
|
|
838
|
+
return [
|
|
839
|
+
buildStep("r0", {
|
|
840
|
+
url: CATALOG_SEARCH_URL,
|
|
841
|
+
requestPostData: '{"page":1}',
|
|
842
|
+
responseBody: {
|
|
843
|
+
products: [{ productId: "p1" }, { productId: "p2" }],
|
|
844
|
+
},
|
|
845
|
+
timestamp: "2025-05-01T00:00:00Z",
|
|
846
|
+
}),
|
|
847
|
+
buildStep("r1", {
|
|
848
|
+
url: CATALOG_PRICING_URL,
|
|
849
|
+
requestPostData: '{"productId":"p1"}',
|
|
850
|
+
responseBody: { reviews: [{ productId: "p1", rating: 5 }] },
|
|
851
|
+
timestamp: "2025-05-01T00:00:01Z",
|
|
852
|
+
}),
|
|
853
|
+
buildStep("r2", {
|
|
854
|
+
url: CATALOG_SECTIONS_URL,
|
|
855
|
+
requestPostData: null,
|
|
856
|
+
responseBody: {
|
|
857
|
+
sections: [
|
|
858
|
+
{
|
|
859
|
+
masterCode: "sec1",
|
|
860
|
+
entries: [
|
|
861
|
+
{ entryId: "e1", identifiers: { code: "code-e1" } },
|
|
862
|
+
{ entryId: "e2", identifiers: { code: "code-e2" } },
|
|
863
|
+
],
|
|
864
|
+
},
|
|
865
|
+
],
|
|
866
|
+
},
|
|
867
|
+
timestamp: "2025-05-01T00:00:02Z",
|
|
868
|
+
}),
|
|
869
|
+
buildStep("r3", {
|
|
870
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=code-e1`,
|
|
871
|
+
requestPostData: null,
|
|
872
|
+
responseBody: { details: [{ entryId: "e1", description: "d-e1" }] },
|
|
873
|
+
timestamp: "2025-05-01T00:00:03Z",
|
|
874
|
+
}),
|
|
875
|
+
buildStep("r4", {
|
|
876
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=code-e2`,
|
|
877
|
+
requestPostData: null,
|
|
878
|
+
responseBody: { details: [{ entryId: "e2", description: "d-e2" }] },
|
|
879
|
+
timestamp: "2025-05-01T00:00:04Z",
|
|
880
|
+
}),
|
|
881
|
+
buildStep("r5", {
|
|
882
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=zzz-unrelated`,
|
|
883
|
+
requestPostData: null,
|
|
884
|
+
responseBody: { details: [] },
|
|
885
|
+
timestamp: "2025-05-01T00:00:05Z",
|
|
886
|
+
}),
|
|
887
|
+
];
|
|
888
|
+
}
|
|
803
889
|
/**
|
|
804
890
|
* A grouped, nested-primary drill-down whose drilled endpoint requires TWO
|
|
805
891
|
* threaded params at once: the PARENT group's own `id` (a field that lives
|
|
@@ -1080,6 +1166,214 @@ function buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamAct
|
|
|
1080
1166
|
}),
|
|
1081
1167
|
];
|
|
1082
1168
|
}
|
|
1169
|
+
/**
|
|
1170
|
+
* A grouped, nested-primary drill-down identical in shape to
|
|
1171
|
+
* {@link buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamActionSteps}
|
|
1172
|
+
* except the group's FIRST entry (`e1`) is sparse — it carries no `code`
|
|
1173
|
+
* field at all, unlike every other entry in the group. The matched item
|
|
1174
|
+
* (`e2`) does carry `code`, and the drill's literal query value equals only
|
|
1175
|
+
* that item's own field, never any top-level ancestor field, so the fold
|
|
1176
|
+
* plan must still structurally rebind the drill to the ancestor via a
|
|
1177
|
+
* sibling ARRAY ELEMENT's `code` — but only one that actually HAS it (`e2`
|
|
1178
|
+
* or `e3`), not blindly assuming the array's first element does. A fold
|
|
1179
|
+
* plan whose structural search only ever inspects element `[0]` degrades to
|
|
1180
|
+
* an item-bound drill here (fetching once per item instead of once per
|
|
1181
|
+
* group) purely because the group's first entry happens to lack the field
|
|
1182
|
+
* every other sibling carries.
|
|
1183
|
+
*/
|
|
1184
|
+
function buildMulticallNestedGroupedDrillDownSparseFirstElementAncestorScopedParamActionSteps() {
|
|
1185
|
+
return [
|
|
1186
|
+
buildStep("r0", {
|
|
1187
|
+
url: CATALOG_SECTIONS_URL,
|
|
1188
|
+
requestPostData: null,
|
|
1189
|
+
responseBody: {
|
|
1190
|
+
sections: [
|
|
1191
|
+
{
|
|
1192
|
+
masterCode: "group-sec1",
|
|
1193
|
+
entries: [
|
|
1194
|
+
{ entryId: "e1", name: "Widget" },
|
|
1195
|
+
{ entryId: "e2", code: "e2-code", name: "Gadget" },
|
|
1196
|
+
{ entryId: "e3", code: "e3-code", name: "Doohickey" },
|
|
1197
|
+
],
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
masterCode: "group-sec2",
|
|
1201
|
+
entries: [
|
|
1202
|
+
{ entryId: "e4", name: "Thingamajig" },
|
|
1203
|
+
{ entryId: "e5", code: "e5-code", name: "Contraption" },
|
|
1204
|
+
{ entryId: "e6", code: "e6-code", name: "Gizmo" },
|
|
1205
|
+
],
|
|
1206
|
+
},
|
|
1207
|
+
],
|
|
1208
|
+
},
|
|
1209
|
+
timestamp: "2025-04-01T00:00:00Z",
|
|
1210
|
+
}),
|
|
1211
|
+
buildStep("r1", {
|
|
1212
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=e2-code`,
|
|
1213
|
+
requestPostData: null,
|
|
1214
|
+
responseBody: {
|
|
1215
|
+
details: [
|
|
1216
|
+
{ entryId: "e1", description: "A widget." },
|
|
1217
|
+
{ entryId: "e2", description: "A gadget." },
|
|
1218
|
+
{ entryId: "e3", description: "A doohickey." },
|
|
1219
|
+
],
|
|
1220
|
+
},
|
|
1221
|
+
timestamp: "2025-04-01T00:00:01Z",
|
|
1222
|
+
}),
|
|
1223
|
+
buildStep("r2", {
|
|
1224
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=zzz-unrelated`,
|
|
1225
|
+
requestPostData: null,
|
|
1226
|
+
responseBody: {
|
|
1227
|
+
details: [{ entryId: "zzz-unrelated", description: "An unrelated entry." }],
|
|
1228
|
+
},
|
|
1229
|
+
timestamp: "2025-04-01T00:00:02Z",
|
|
1230
|
+
}),
|
|
1231
|
+
];
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* A grouped, nested-primary drill-down whose drilled endpoint's TWO literal
|
|
1235
|
+
* query values (`code`, `zone`) each equal BOTH the matched (first) item's
|
|
1236
|
+
* own top-level fields AND the ancestor group's own structurally-
|
|
1237
|
+
* corresponding fields, which themselves live inside a NESTED ancestor
|
|
1238
|
+
* array (`tags.0.code` / `tags.0.zone`) rather than directly on the
|
|
1239
|
+
* ancestor object — unlike
|
|
1240
|
+
* {@link buildMulticallNestedGroupedDrillDownTwoLevelNestedAncestorFieldActionSteps}'s
|
|
1241
|
+
* ancestor-ONLY nested field (absent from the item scope entirely), here
|
|
1242
|
+
* the SAME field names and values are genuinely present on both scopes at
|
|
1243
|
+
* once, for two independently-resolved params. A literal-value search over
|
|
1244
|
+
* the captured request necessarily lands on the item's own field first
|
|
1245
|
+
* (it's the shallower, directly-typed match), so this is the exact shape
|
|
1246
|
+
* that requires {@link findStructurallyCorrespondingAncestorField}'s
|
|
1247
|
+
* traversal into the ancestor's own nested array — independently, for each
|
|
1248
|
+
* param — to correctly REBIND the rendered accessor onto the ancestor's
|
|
1249
|
+
* structural counterpart. A fold plan that skips or fails that rebind for
|
|
1250
|
+
* either param will emit an accessor reading off the item loop's own bound
|
|
1251
|
+
* variable at a splice point where it is not yet declared.
|
|
1252
|
+
*
|
|
1253
|
+
* Every OTHER item in the same group carries its own `code`/`zone`
|
|
1254
|
+
* diverging from the matched item's, and the drill's response still
|
|
1255
|
+
* resolves onto every one of them, proving the drilled value is genuinely
|
|
1256
|
+
* ancestor-scoped — not merely coincident with the matched item's own
|
|
1257
|
+
* field — so a correct fold plan hoists the chain fetch above the item loop
|
|
1258
|
+
* and fetches once per group, never once per item.
|
|
1259
|
+
*/
|
|
1260
|
+
function buildMulticallNestedGroupedDrillDownAncestorItemValueCoincidenceActionSteps() {
|
|
1261
|
+
return [
|
|
1262
|
+
buildStep("r0", {
|
|
1263
|
+
url: CATALOG_SECTIONS_URL,
|
|
1264
|
+
requestPostData: null,
|
|
1265
|
+
responseBody: {
|
|
1266
|
+
sections: [
|
|
1267
|
+
{
|
|
1268
|
+
masterCode: "group-sec1",
|
|
1269
|
+
tags: [{ code: "meta-code-1", zone: "west" }],
|
|
1270
|
+
entries: [
|
|
1271
|
+
{ entryId: "e1", code: "meta-code-1", zone: "west", name: "Widget" },
|
|
1272
|
+
{ entryId: "e2", code: "e2-own-code", zone: "e2-own-zone", name: "Gadget" },
|
|
1273
|
+
],
|
|
1274
|
+
},
|
|
1275
|
+
{
|
|
1276
|
+
masterCode: "group-sec2",
|
|
1277
|
+
tags: [{ code: "meta-code-2", zone: "east" }],
|
|
1278
|
+
entries: [
|
|
1279
|
+
{ entryId: "e3", code: "meta-code-2", zone: "east", name: "Thingamajig" },
|
|
1280
|
+
{ entryId: "e4", code: "e4-own-code", zone: "e4-own-zone", name: "Contraption" },
|
|
1281
|
+
],
|
|
1282
|
+
},
|
|
1283
|
+
],
|
|
1284
|
+
},
|
|
1285
|
+
timestamp: "2025-06-15T00:00:00Z",
|
|
1286
|
+
}),
|
|
1287
|
+
buildStep("r1", {
|
|
1288
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=meta-code-1&zone=west`,
|
|
1289
|
+
requestPostData: null,
|
|
1290
|
+
responseBody: {
|
|
1291
|
+
details: [
|
|
1292
|
+
{ entryId: "e1", description: "A widget." },
|
|
1293
|
+
{ entryId: "e2", description: "A gadget." },
|
|
1294
|
+
],
|
|
1295
|
+
},
|
|
1296
|
+
timestamp: "2025-06-15T00:00:01Z",
|
|
1297
|
+
}),
|
|
1298
|
+
buildStep("r2", {
|
|
1299
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=zzz-unrelated&zone=zzz-zone`,
|
|
1300
|
+
requestPostData: null,
|
|
1301
|
+
responseBody: {
|
|
1302
|
+
details: [{ entryId: "zzz-unrelated", description: "An unrelated entry." }],
|
|
1303
|
+
},
|
|
1304
|
+
timestamp: "2025-06-15T00:00:02Z",
|
|
1305
|
+
}),
|
|
1306
|
+
];
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* A grouped, nested-primary drill-down whose drilled endpoint's literal
|
|
1310
|
+
* query value equals ONLY the matched (first) item's own field (`ownCode`)
|
|
1311
|
+
* — never the ancestor's own field directly — but the ancestor's structural
|
|
1312
|
+
* counterpart lives TWO levels deep (`meta.summary.code`), generalizing
|
|
1313
|
+
* {@link buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamActionSteps}'s
|
|
1314
|
+
* single-level ancestor nesting to a two-level one. This is the exact
|
|
1315
|
+
* structural shape from the 1.12.52 report (a `g0`-only ancestor group loop
|
|
1316
|
+
* whose hoisted chain fetch reads a nested field off the ancestor's own
|
|
1317
|
+
* object, with no separate item sub-loop wrapping the hoisted call itself)
|
|
1318
|
+
* — the report substituted a totally unrelated, undeclared `item`
|
|
1319
|
+
* identifier for the correct `g0.meta.summary.code` ancestor accessor.
|
|
1320
|
+
*
|
|
1321
|
+
* Every OTHER item in the same group carries its own `ownCode` diverging
|
|
1322
|
+
* from the matched item's, and the drill's response still resolves onto
|
|
1323
|
+
* every one of them, proving the drilled value is genuinely ancestor-scoped
|
|
1324
|
+
* — not merely coincident with the matched item's own field — so a correct
|
|
1325
|
+
* fold plan hoists the chain fetch above the item loop and fetches once per
|
|
1326
|
+
* group, never once per item, and never references the item loop's own
|
|
1327
|
+
* bound variable.
|
|
1328
|
+
*/
|
|
1329
|
+
function buildMulticallNestedGroupedDrillDownTwoLevelNestedAncestorFieldActionSteps() {
|
|
1330
|
+
return [
|
|
1331
|
+
buildStep("r0", {
|
|
1332
|
+
url: CATALOG_SECTIONS_URL,
|
|
1333
|
+
requestPostData: null,
|
|
1334
|
+
responseBody: {
|
|
1335
|
+
sections: [
|
|
1336
|
+
{
|
|
1337
|
+
masterCode: "group-sec1",
|
|
1338
|
+
meta: { summary: { code: "meta-code-1" } },
|
|
1339
|
+
entries: [
|
|
1340
|
+
{ entryId: "e1", ownCode: "meta-code-1", name: "Widget" },
|
|
1341
|
+
{ entryId: "e2", ownCode: "e2-own-code", name: "Gadget" },
|
|
1342
|
+
],
|
|
1343
|
+
},
|
|
1344
|
+
{
|
|
1345
|
+
masterCode: "group-sec2",
|
|
1346
|
+
meta: { summary: { code: "meta-code-2" } },
|
|
1347
|
+
entries: [
|
|
1348
|
+
{ entryId: "e3", ownCode: "meta-code-2", name: "Thingamajig" },
|
|
1349
|
+
{ entryId: "e4", ownCode: "e4-own-code", name: "Contraption" },
|
|
1350
|
+
],
|
|
1351
|
+
},
|
|
1352
|
+
],
|
|
1353
|
+
},
|
|
1354
|
+
timestamp: "2025-05-01T00:00:00Z",
|
|
1355
|
+
}),
|
|
1356
|
+
buildStep("r1", {
|
|
1357
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=meta-code-1`,
|
|
1358
|
+
requestPostData: null,
|
|
1359
|
+
responseBody: {
|
|
1360
|
+
details: [
|
|
1361
|
+
{ entryId: "e1", description: "A widget." },
|
|
1362
|
+
{ entryId: "e2", description: "A gadget." },
|
|
1363
|
+
],
|
|
1364
|
+
},
|
|
1365
|
+
timestamp: "2025-05-01T00:00:01Z",
|
|
1366
|
+
}),
|
|
1367
|
+
buildStep("r2", {
|
|
1368
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=zzz-unrelated`,
|
|
1369
|
+
requestPostData: null,
|
|
1370
|
+
responseBody: {
|
|
1371
|
+
details: [{ entryId: "zzz-unrelated", description: "An unrelated entry." }],
|
|
1372
|
+
},
|
|
1373
|
+
timestamp: "2025-05-01T00:00:02Z",
|
|
1374
|
+
}),
|
|
1375
|
+
];
|
|
1376
|
+
}
|
|
1083
1377
|
/**
|
|
1084
1378
|
* A grouped, nested-primary drill-down whose drilled endpoint's literal
|
|
1085
1379
|
* query threads TWO params, each coincidentally equal to both a value the
|
|
@@ -1244,6 +1538,166 @@ function buildMulticallNestedGroupedDrillDownDualItemLiteralDistinctSubpathAnces
|
|
|
1244
1538
|
}),
|
|
1245
1539
|
];
|
|
1246
1540
|
}
|
|
1541
|
+
const CATALOG_ENTRY_LABELS_URL = "https://api.example.com/catalog/entries/labels";
|
|
1542
|
+
/**
|
|
1543
|
+
* TWO fully independent drill-down targets sharing one ancestor group,
|
|
1544
|
+
* whose literal query values each equal ONLY the matched (first) entry's
|
|
1545
|
+
* own `entryId` — never any distinct ancestor-level field — but whose
|
|
1546
|
+
* responses each return every OTHER sibling's row in the same group too,
|
|
1547
|
+
* so both targets independently prove {@link isFoldTargetAncestorScoped}
|
|
1548
|
+
* and rebind through the ancestor's own nested array (mirroring
|
|
1549
|
+
* {@link buildMulticallNestedGroupedDrillDownDistinctValueAncestorScopedParamActionSteps}'s
|
|
1550
|
+
* single-target rebind, generalized to two independent, CO-HOISTED targets
|
|
1551
|
+
* at once). Regression coverage for a fold-hoist decision that derives
|
|
1552
|
+
* whether a call may hoist above the item loop from the FINAL rendered
|
|
1553
|
+
* text rather than from the value/placeholder bindings that actually feed
|
|
1554
|
+
* the splice: a bug there can let one target's hoist decision silently
|
|
1555
|
+
* disagree with what its own accessor bindings prove, emitting a call that
|
|
1556
|
+
* references the item loop's own bound variable above the loop that
|
|
1557
|
+
* declares it.
|
|
1558
|
+
*
|
|
1559
|
+
* `r1`/`r2` are the real drills (both resolve group `sec1` via `e1`'s own
|
|
1560
|
+
* `entryId`). `r3`/`r4` are decoys — same drilled pathnames, but each
|
|
1561
|
+
* returns an EMPTY result set — so {@link findFrozenVaryingDrillParams}'s
|
|
1562
|
+
* same-endpoint variance check has a second, genuinely differing capture to
|
|
1563
|
+
* compare each target's own param against, without themselves being
|
|
1564
|
+
* mistaken for an independent primary/drill pair of their own.
|
|
1565
|
+
*/
|
|
1566
|
+
function buildMulticallAncestorOnlyMultiTargetDrillDownActionSteps() {
|
|
1567
|
+
return [
|
|
1568
|
+
buildStep("r0", {
|
|
1569
|
+
url: CATALOG_SECTIONS_URL,
|
|
1570
|
+
requestPostData: null,
|
|
1571
|
+
responseBody: {
|
|
1572
|
+
sections: [
|
|
1573
|
+
{
|
|
1574
|
+
masterCode: "sec1",
|
|
1575
|
+
entries: [
|
|
1576
|
+
{ entryId: "e1", name: "Widget" },
|
|
1577
|
+
{ entryId: "e2", name: "Gadget" },
|
|
1578
|
+
{ entryId: "e3", name: "Doohickey" },
|
|
1579
|
+
],
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
masterCode: "sec2",
|
|
1583
|
+
entries: [
|
|
1584
|
+
{ entryId: "e4", name: "Thingamajig" },
|
|
1585
|
+
{ entryId: "e5", name: "Contraption" },
|
|
1586
|
+
{ entryId: "e6", name: "Gizmo" },
|
|
1587
|
+
],
|
|
1588
|
+
},
|
|
1589
|
+
],
|
|
1590
|
+
},
|
|
1591
|
+
timestamp: "2025-08-01T00:00:00Z",
|
|
1592
|
+
}),
|
|
1593
|
+
buildStep("r1", {
|
|
1594
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=e1`,
|
|
1595
|
+
requestPostData: null,
|
|
1596
|
+
responseBody: {
|
|
1597
|
+
details: [
|
|
1598
|
+
{ entryId: "e1", description: "A widget." },
|
|
1599
|
+
{ entryId: "e2", description: "A gadget." },
|
|
1600
|
+
{ entryId: "e3", description: "A doohickey." },
|
|
1601
|
+
],
|
|
1602
|
+
},
|
|
1603
|
+
timestamp: "2025-08-01T00:00:01Z",
|
|
1604
|
+
}),
|
|
1605
|
+
buildStep("r2", {
|
|
1606
|
+
url: `${CATALOG_ENTRY_LABELS_URL}?tag=e1`,
|
|
1607
|
+
requestPostData: null,
|
|
1608
|
+
responseBody: {
|
|
1609
|
+
labels: [
|
|
1610
|
+
{ entryId: "e1", label: "north-widget" },
|
|
1611
|
+
{ entryId: "e2", label: "north-gadget" },
|
|
1612
|
+
{ entryId: "e3", label: "north-doohickey" },
|
|
1613
|
+
],
|
|
1614
|
+
},
|
|
1615
|
+
timestamp: "2025-08-01T00:00:02Z",
|
|
1616
|
+
}),
|
|
1617
|
+
buildStep("r3", {
|
|
1618
|
+
url: `${CATALOG_ENTRY_DETAILS_URL}?code=zzz-unrelated`,
|
|
1619
|
+
requestPostData: null,
|
|
1620
|
+
responseBody: { details: [] },
|
|
1621
|
+
timestamp: "2025-08-01T00:00:03Z",
|
|
1622
|
+
}),
|
|
1623
|
+
buildStep("r4", {
|
|
1624
|
+
url: `${CATALOG_ENTRY_LABELS_URL}?tag=zzz-unrelated`,
|
|
1625
|
+
requestPostData: null,
|
|
1626
|
+
responseBody: { labels: [] },
|
|
1627
|
+
timestamp: "2025-08-01T00:00:04Z",
|
|
1628
|
+
}),
|
|
1629
|
+
];
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* An ancestor-scoped drill target generalizing
|
|
1633
|
+
* {@link buildMulticallAncestorOnlyMultiTargetDrillDownActionSteps} from ONE
|
|
1634
|
+
* threaded field to TWO: the drilled endpoint's query threads BOTH the
|
|
1635
|
+
* primary join field (`entryId`, declared via `joinFields` and therefore
|
|
1636
|
+
* always forced item-bound in {@link buildThreadedFieldPairs}'s raw input)
|
|
1637
|
+
* AND a second, independently-discovered field (`regionCode`) that
|
|
1638
|
+
* {@link findThreadedJoinFields} threads purely because its literal value is
|
|
1639
|
+
* present in the drilled request — never declared in `joinFields` at all.
|
|
1640
|
+
* `regionCode` is homogeneous across every sibling entry in a group (every
|
|
1641
|
+
* entry in `sec1` shares `"north"`, every entry in `sec2` shares `"south"`),
|
|
1642
|
+
* so it is genuinely ancestor-scoped data, not a per-item value — proving
|
|
1643
|
+
* {@link buildThreadedFieldPairs}'s rebind must independently resolve EACH
|
|
1644
|
+
* threaded field's own structural correspondence rather than deciding
|
|
1645
|
+
* hoistability once for the whole target off a single post-hoc scan of the
|
|
1646
|
+
* rendered text. Regression coverage for
|
|
1647
|
+
* {@link https://github.com | recon-generate}'s fold-hoist ground-truth
|
|
1648
|
+
* `referencesItemVar` signal (computed per value/placeholder binding, not by
|
|
1649
|
+
* re-scanning final text): with two independently-rebound fields on one
|
|
1650
|
+
* target, a hoist decision that silently disagrees with what either field's
|
|
1651
|
+
* OWN accessor binding proves can no longer hide behind the other field's
|
|
1652
|
+
* successful rebind.
|
|
1653
|
+
*/
|
|
1654
|
+
function buildMulticallAncestorScopedDualThreadedFieldDrillDownActionSteps() {
|
|
1655
|
+
return [
|
|
1656
|
+
buildStep("r0", {
|
|
1657
|
+
url: CATALOG_SECTIONS_URL,
|
|
1658
|
+
requestPostData: null,
|
|
1659
|
+
responseBody: {
|
|
1660
|
+
sections: [
|
|
1661
|
+
{
|
|
1662
|
+
masterCode: "sec1",
|
|
1663
|
+
entries: [
|
|
1664
|
+
{ entryId: "e1", regionCode: "north", name: "Widget" },
|
|
1665
|
+
{ entryId: "e2", regionCode: "north", name: "Gadget" },
|
|
1666
|
+
{ entryId: "e3", regionCode: "north", name: "Doohickey" },
|
|
1667
|
+
],
|
|
1668
|
+
},
|
|
1669
|
+
{
|
|
1670
|
+
masterCode: "sec2",
|
|
1671
|
+
entries: [
|
|
1672
|
+
{ entryId: "e4", regionCode: "south", name: "Thingamajig" },
|
|
1673
|
+
{ entryId: "e5", regionCode: "south", name: "Contraption" },
|
|
1674
|
+
{ entryId: "e6", regionCode: "south", name: "Gizmo" },
|
|
1675
|
+
],
|
|
1676
|
+
},
|
|
1677
|
+
],
|
|
1678
|
+
},
|
|
1679
|
+
timestamp: "2025-09-01T00:00:00Z",
|
|
1680
|
+
}),
|
|
1681
|
+
buildStep("r1", {
|
|
1682
|
+
url: `${CATALOG_ENTRY_LABELS_URL}?code=e1®ion=north`,
|
|
1683
|
+
requestPostData: null,
|
|
1684
|
+
responseBody: {
|
|
1685
|
+
labels: [
|
|
1686
|
+
{ entryId: "e1", label: "north-widget" },
|
|
1687
|
+
{ entryId: "e2", label: "north-gadget" },
|
|
1688
|
+
{ entryId: "e3", label: "north-doohickey" },
|
|
1689
|
+
],
|
|
1690
|
+
},
|
|
1691
|
+
timestamp: "2025-09-01T00:00:01Z",
|
|
1692
|
+
}),
|
|
1693
|
+
buildStep("r2", {
|
|
1694
|
+
url: `${CATALOG_ENTRY_LABELS_URL}?code=zzz-unrelated®ion=zzz-region`,
|
|
1695
|
+
requestPostData: null,
|
|
1696
|
+
responseBody: { labels: [] },
|
|
1697
|
+
timestamp: "2025-09-01T00:00:02Z",
|
|
1698
|
+
}),
|
|
1699
|
+
];
|
|
1700
|
+
}
|
|
1247
1701
|
const ACCOUNT_SEARCH_URL = "https://api.example.com/accounts/search";
|
|
1248
1702
|
const ACCOUNT_DETAIL_URL = "https://api.example.com/accounts/detail";
|
|
1249
1703
|
/**
|
|
@@ -2852,4 +3306,39 @@ function buildSessionHeartbeatNoiseStep(timestamp) {
|
|
|
2852
3306
|
timestamp,
|
|
2853
3307
|
});
|
|
2854
3308
|
}
|
|
3309
|
+
const ORDERS_LINE_ITEMS_URL = "https://api.example.com/orders/line-items";
|
|
3310
|
+
const ORDERS_PROMO_URL = "https://api.example.com/orders/promo-eligibility";
|
|
3311
|
+
/**
|
|
3312
|
+
* A flat, non-ancestor single-shot search → per-item drill-down whose primary
|
|
3313
|
+
* array (`lineItems[]`) has no nested wildcard crossing at all, so its fold
|
|
3314
|
+
* loop variable renders as bare `item`, never `g<n>` — structurally unrelated
|
|
3315
|
+
* to any ancestor-grouped fold plan. Exists solely to be emitted as a SEPARATE
|
|
3316
|
+
* `emitMultiStepExecuteHttp` call (its own generated function) and
|
|
3317
|
+
* concatenated after an ancestor-grouped fold's own output, so a test can
|
|
3318
|
+
* assert that this function's own, legitimately-declared `item` binding never
|
|
3319
|
+
* bleeds into an unrelated, EARLIER ancestor (`g0`)-scoped hoisted call
|
|
3320
|
+
* elsewhere in the same generated file — the two functions share no runtime
|
|
3321
|
+
* scope, only file-level adjacency.
|
|
3322
|
+
*/
|
|
3323
|
+
function buildMulticallOrdersLineItemPromoEligibilityActionSteps() {
|
|
3324
|
+
return [
|
|
3325
|
+
buildStep("r0", {
|
|
3326
|
+
url: ORDERS_LINE_ITEMS_URL,
|
|
3327
|
+
requestPostData: '{"orderId":"ord-1"}',
|
|
3328
|
+
responseBody: {
|
|
3329
|
+
lineItems: [
|
|
3330
|
+
{ sku: "sku-a", quantity: 2 },
|
|
3331
|
+
{ sku: "sku-b", quantity: 1 },
|
|
3332
|
+
],
|
|
3333
|
+
},
|
|
3334
|
+
timestamp: "2025-06-01T00:00:00Z",
|
|
3335
|
+
}),
|
|
3336
|
+
buildStep("r1", {
|
|
3337
|
+
url: ORDERS_PROMO_URL,
|
|
3338
|
+
requestPostData: '{"sku":"sku-a"}',
|
|
3339
|
+
responseBody: { eligibility: [{ sku: "sku-a", eligible: true }] },
|
|
3340
|
+
timestamp: "2025-06-01T00:00:01Z",
|
|
3341
|
+
}),
|
|
3342
|
+
];
|
|
3343
|
+
}
|
|
2855
3344
|
//# sourceMappingURL=recon-generate-multicall-fixture.js.map
|