@fire-spark/core 0.12.4 → 0.12.5
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/index.d.ts +1 -0
- package/dist/index.js +94 -14
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -941,6 +941,7 @@ declare const capRedeems: <T extends CapOrder>(order: T) => T & {
|
|
|
941
941
|
id: string;
|
|
942
942
|
parent_uid: string | null;
|
|
943
943
|
parent_id: string | null;
|
|
944
|
+
group_id?: string | undefined;
|
|
944
945
|
name: string;
|
|
945
946
|
image_url?: string | undefined;
|
|
946
947
|
menu_id?: string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -1415,9 +1415,11 @@ const flattenMenuCategories = (categories, categoriesById, options) => {
|
|
|
1415
1415
|
//#endregion
|
|
1416
1416
|
//#region src/productCustomization/fromOrderLines.ts
|
|
1417
1417
|
/** Group slot of a child line: listed directly, or as the variant of a base
|
|
1418
|
-
* listed in one of the parent's modifier groups.
|
|
1419
|
-
|
|
1418
|
+
* listed in one of the parent's modifier groups. With `onlyGroupId` (the
|
|
1419
|
+
* line's declared `group_id`) only that group of this parent is searched. */
|
|
1420
|
+
const matchModifierLine = (lookup, parent, childId, onlyGroupId) => {
|
|
1420
1421
|
const groups = parent.pricing.modifier_group_ids.flatMap((groupId) => {
|
|
1422
|
+
if (onlyGroupId !== void 0 && groupId !== onlyGroupId) return [];
|
|
1421
1423
|
const group = lookup.modifierGroupsById[groupId];
|
|
1422
1424
|
return group ? [group] : [];
|
|
1423
1425
|
});
|
|
@@ -1463,7 +1465,13 @@ const fromOrderLines = (root, lines, lookup) => {
|
|
|
1463
1465
|
const parentProduct = lookup.productsById[parentLine.id];
|
|
1464
1466
|
if (!parentProduct) return;
|
|
1465
1467
|
for (const child of childrenByParent.get(parentLine.uid) ?? []) {
|
|
1466
|
-
const
|
|
1468
|
+
const p = [
|
|
1469
|
+
lookup,
|
|
1470
|
+
parentProduct,
|
|
1471
|
+
child.id,
|
|
1472
|
+
child.group_id
|
|
1473
|
+
];
|
|
1474
|
+
const match = matchModifierLine(...p);
|
|
1467
1475
|
if (!match) continue;
|
|
1468
1476
|
const { groupId, modifierId, selection } = match;
|
|
1469
1477
|
const path = `${pathPrefix}/group/${groupId}/modifier/${modifierId}`;
|
|
@@ -1750,6 +1758,7 @@ const buildLine = (args) => {
|
|
|
1750
1758
|
name: args.name
|
|
1751
1759
|
};
|
|
1752
1760
|
const r4 = {
|
|
1761
|
+
...args.group_id ? { group_id: args.group_id } : {},
|
|
1753
1762
|
...imagePatch,
|
|
1754
1763
|
...catalog
|
|
1755
1764
|
};
|
|
@@ -1835,7 +1844,8 @@ const appendModifierLine = (modifier, groupId, parent, locale) => {
|
|
|
1835
1844
|
const line = buildLine({
|
|
1836
1845
|
...l1,
|
|
1837
1846
|
...l2,
|
|
1838
|
-
...l3
|
|
1847
|
+
...l3,
|
|
1848
|
+
group_id: groupId
|
|
1839
1849
|
});
|
|
1840
1850
|
parent.children.push(line);
|
|
1841
1851
|
if (modifier.product) appendGroupLines(modifier.product.groups, line, locale);
|
|
@@ -3687,7 +3697,8 @@ const computeLineFingerprint = (root, lines) => {
|
|
|
3687
3697
|
const keys = lines.filter((line) => {
|
|
3688
3698
|
return line.parent_uid === parentUid;
|
|
3689
3699
|
}).map((line) => {
|
|
3690
|
-
|
|
3700
|
+
const slot = line.group_id ? `@${line.group_id}` : "";
|
|
3701
|
+
return `${line.id}${slot}x${line.quantity}(${childKeys(line.uid)})`;
|
|
3691
3702
|
});
|
|
3692
3703
|
keys.sort((left, right) => left.localeCompare(right));
|
|
3693
3704
|
return keys.join(",");
|
|
@@ -6643,7 +6654,8 @@ const selectionKey = (line, kidsOf, cache) => {
|
|
|
6643
6654
|
return selectionKey(child, kidsOf, cache);
|
|
6644
6655
|
});
|
|
6645
6656
|
nested.sort((left, right) => left.localeCompare(right));
|
|
6646
|
-
const
|
|
6657
|
+
const slot = line.group_id ? `@${line.group_id}` : "";
|
|
6658
|
+
const key = `${line.id}${slot}x${line.quantity}(${nested.join(",")})`;
|
|
6647
6659
|
cache.set(line.uid, key);
|
|
6648
6660
|
return key;
|
|
6649
6661
|
};
|
|
@@ -6730,6 +6742,36 @@ const hasRepeatedProductSibling = (lines, rootUid) => {
|
|
|
6730
6742
|
};
|
|
6731
6743
|
return walk(rootUid);
|
|
6732
6744
|
};
|
|
6745
|
+
/** A line whose product the parent's menu lists in more than one slot, at
|
|
6746
|
+
* any depth. Cart lines carry no group id, so the slot is chosen by
|
|
6747
|
+
* `placeCartLines`; with a single listing the session path is unambiguous. */
|
|
6748
|
+
const hasMultiSlotChild = (lines, rootUid, lookup) => {
|
|
6749
|
+
const kidsOf = /* @__PURE__ */ new Map();
|
|
6750
|
+
for (const line of lines) {
|
|
6751
|
+
if (line.parent_uid == null) continue;
|
|
6752
|
+
const list = kidsOf.get(line.parent_uid) ?? [];
|
|
6753
|
+
list.push(line);
|
|
6754
|
+
kidsOf.set(line.parent_uid, list);
|
|
6755
|
+
}
|
|
6756
|
+
const walk = (line) => {
|
|
6757
|
+
const parent = lookup.productsById[line.id];
|
|
6758
|
+
const groups = parent ? parentGroups(lookup, parent) : [];
|
|
6759
|
+
for (const kid of kidsOf.get(line.uid) ?? []) {
|
|
6760
|
+
const ids = listingsFor(lookup, groups, kid.id).map((row) => slotKey(row.group.id, row.modifierId));
|
|
6761
|
+
if (new Set(ids).size > 1) return true;
|
|
6762
|
+
if (walk(kid)) return true;
|
|
6763
|
+
}
|
|
6764
|
+
return false;
|
|
6765
|
+
};
|
|
6766
|
+
const root = lines.find((line) => line.uid === rootUid);
|
|
6767
|
+
return root ? walk(root) : false;
|
|
6768
|
+
};
|
|
6769
|
+
/** Cart shapes the slot search must place: a repeated sibling product, or
|
|
6770
|
+
* a product listed in several slots. Everything else keeps the session. */
|
|
6771
|
+
const needsSlotPlacement = (lines, rootUid, lookup) => {
|
|
6772
|
+
if (hasRepeatedProductSibling(lines, rootUid)) return true;
|
|
6773
|
+
return hasMultiSlotChild(lines, rootUid, lookup);
|
|
6774
|
+
};
|
|
6733
6775
|
const noteRules = (state, broken) => {
|
|
6734
6776
|
if (broken) state.rulesBroken = true;
|
|
6735
6777
|
};
|
|
@@ -6897,13 +6939,21 @@ const greedyAssignment = (plans) => {
|
|
|
6897
6939
|
overCapacity
|
|
6898
6940
|
};
|
|
6899
6941
|
};
|
|
6942
|
+
/** The groups a line may sit in under this parent: only its declared
|
|
6943
|
+
* `group_id` when it names one, else every group of the parent. A declared id
|
|
6944
|
+
* the parent does not own leaves none, so the line is never placed. */
|
|
6945
|
+
const groupsDeclared = (groups, line) => {
|
|
6946
|
+
if (line.group_id === void 0) return groups;
|
|
6947
|
+
return groups.filter((group) => group.id === line.group_id);
|
|
6948
|
+
};
|
|
6900
6949
|
const planKids = (lookup, groups, byKey, kids, prefix, state) => {
|
|
6901
6950
|
const plans = [];
|
|
6902
6951
|
let previous = "";
|
|
6903
6952
|
for (const child of kids) {
|
|
6904
6953
|
if (pathVisits(prefix, child.id)) continue;
|
|
6905
6954
|
const ordered = lookup.productsById[child.id];
|
|
6906
|
-
const
|
|
6955
|
+
const scope = groupsDeclared(groups, child);
|
|
6956
|
+
const listings = listingsFor(lookup, scope, child.id);
|
|
6907
6957
|
if (!ordered || listings.length === 0) continue;
|
|
6908
6958
|
const listed = [];
|
|
6909
6959
|
for (const item of listings) {
|
|
@@ -7123,14 +7173,17 @@ const emit = (node, parentUid, parentId, locale, out) => {
|
|
|
7123
7173
|
type: "PRODUCT",
|
|
7124
7174
|
uid: randomUUID()
|
|
7125
7175
|
};
|
|
7176
|
+
const id = node.product.id;
|
|
7177
|
+
const groupPatch = node.group ? { group_id: node.group.id } : {};
|
|
7126
7178
|
const r2 = {
|
|
7127
|
-
id
|
|
7179
|
+
id,
|
|
7128
7180
|
parent_uid: parentUid,
|
|
7129
7181
|
parent_id: parentId
|
|
7130
7182
|
};
|
|
7131
7183
|
const r3 = {
|
|
7132
7184
|
name: displayName(node.product.name, locale),
|
|
7133
|
-
quantity: node.quantity
|
|
7185
|
+
quantity: node.quantity,
|
|
7186
|
+
...groupPatch
|
|
7134
7187
|
};
|
|
7135
7188
|
const r4 = {
|
|
7136
7189
|
redeem: [],
|
|
@@ -7321,10 +7374,25 @@ const childrenOf = (lines, parentUid) => {
|
|
|
7321
7374
|
if (byShape !== 0) return byShape;
|
|
7322
7375
|
const bySubtotal = new Big(a.unit_subtotal).cmp(b.unit_subtotal);
|
|
7323
7376
|
if (bySubtotal !== 0) return bySubtotal;
|
|
7324
|
-
|
|
7377
|
+
const byTax = new Big(a.unit_tax_total).cmp(b.unit_tax_total);
|
|
7378
|
+
if (byTax !== 0) return byTax;
|
|
7379
|
+
return (a.group_id ?? "").localeCompare(b.group_id ?? "");
|
|
7325
7380
|
});
|
|
7326
7381
|
return children;
|
|
7327
7382
|
};
|
|
7383
|
+
/** A declared `group_id` that the parent's menu does not back (unknown under
|
|
7384
|
+
* this parent, or it does not hold the product) names the field; a line that
|
|
7385
|
+
* is no modifier of its parent at all keeps the plain code. */
|
|
7386
|
+
const notFoundIssue = (lookup, parent, child) => {
|
|
7387
|
+
const code = "MODIFIER_NOT_FOUND";
|
|
7388
|
+
if (child.group_id === void 0) return { code };
|
|
7389
|
+
if (!matchModifierLine(lookup, parent, child.id)) return { code };
|
|
7390
|
+
return {
|
|
7391
|
+
code,
|
|
7392
|
+
field: "group_id",
|
|
7393
|
+
actual: child.group_id
|
|
7394
|
+
};
|
|
7395
|
+
};
|
|
7328
7396
|
const collectUnmatchedModifiers = (lines, lookup, parentProductId, parentUid, out) => {
|
|
7329
7397
|
const parent = lookup.productsById[parentProductId];
|
|
7330
7398
|
if (!parent) return;
|
|
@@ -7336,9 +7404,14 @@ const collectUnmatchedModifiers = (lines, lookup, parentProductId, parentUid, ou
|
|
|
7336
7404
|
pushLineIssue(out, child.uid, { code: "VARIANT_BASE_NOT_ORDERABLE" });
|
|
7337
7405
|
continue;
|
|
7338
7406
|
}
|
|
7339
|
-
const match = matchModifierLine(
|
|
7407
|
+
const match = matchModifierLine(...[
|
|
7408
|
+
lookup,
|
|
7409
|
+
parent,
|
|
7410
|
+
child.id,
|
|
7411
|
+
child.group_id
|
|
7412
|
+
]);
|
|
7340
7413
|
if (!match) {
|
|
7341
|
-
pushLineIssue(out, child.uid,
|
|
7414
|
+
pushLineIssue(out, child.uid, notFoundIssue(lookup, parent, child));
|
|
7342
7415
|
continue;
|
|
7343
7416
|
}
|
|
7344
7417
|
const base = lookup.productsById[match.modifierId];
|
|
@@ -7481,6 +7554,13 @@ const compareTrees = (actualLines, expectedLines, actualUid, expectedUid, out) =
|
|
|
7481
7554
|
});
|
|
7482
7555
|
return;
|
|
7483
7556
|
}
|
|
7557
|
+
const declared = actual.group_id;
|
|
7558
|
+
if (declared !== void 0 && declared !== expected.group_id) pushLineIssue(out, actual.uid, {
|
|
7559
|
+
code: "STRUCTURE_MISMATCH",
|
|
7560
|
+
field: "group_id",
|
|
7561
|
+
expected: expected.group_id,
|
|
7562
|
+
actual: declared
|
|
7563
|
+
});
|
|
7484
7564
|
if (actual.quantity !== expected.quantity) pushLineIssue(out, actual.uid, {
|
|
7485
7565
|
code: "QUANTITY_MISMATCH",
|
|
7486
7566
|
field: "quantity",
|
|
@@ -7566,7 +7646,7 @@ const validateProductRoot = (root, lines, lookup, locale, out) => {
|
|
|
7566
7646
|
if (!isOnSchedule(product.availability.schedules)) pushLineIssue(out, root.uid, { code: "OUTSIDE_HOURS" });
|
|
7567
7647
|
collectUnmatchedModifiers(lines, lookup, root.id, root.uid, out);
|
|
7568
7648
|
let expected;
|
|
7569
|
-
if (
|
|
7649
|
+
if (needsSlotPlacement(lines, root.uid, lookup)) {
|
|
7570
7650
|
const placed = placeCartLines(root, lines, lookup, locale);
|
|
7571
7651
|
if (placed.rulesBroken) pushLineIssue(out, root.uid, { code: "MODIFIER_RULES_INVALID" });
|
|
7572
7652
|
expected = placed.lines;
|
|
@@ -7898,7 +7978,7 @@ const collectOrderLineDiffs = (input) => {
|
|
|
7898
7978
|
continue;
|
|
7899
7979
|
}
|
|
7900
7980
|
try {
|
|
7901
|
-
if (
|
|
7981
|
+
if (needsSlotPlacement(input.lines, root.uid, lookup)) {
|
|
7902
7982
|
const placed = placeCartLines(root, input.lines, lookup, locale);
|
|
7903
7983
|
const next = placed.rulesBroken ? null : placed.lines;
|
|
7904
7984
|
diffs.push({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fire-spark/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"description": "Fire Spark headless SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"big.js": "6.2.1",
|
|
21
21
|
"dayjs": "1.11.9",
|
|
22
22
|
"@types/big.js": "6.2.2",
|
|
23
|
-
"@fire-spark/payments": "^0.12.
|
|
24
|
-
"@fire-spark/types": "^0.12.
|
|
23
|
+
"@fire-spark/payments": "^0.12.5",
|
|
24
|
+
"@fire-spark/types": "^0.12.5"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsdown": "^0.22.14",
|