@binaryandthread/cli 0.4.4 → 0.4.6
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 +39 -0
- package/dist/bin.js +24 -28
- package/dist/bin.js.map +1 -1
- package/dist/{chunk-PG7YCPAN.js → chunk-5W5O6G6Y.js} +207 -21
- package/dist/chunk-5W5O6G6Y.js.map +1 -0
- package/dist/{interactive-HI3LDK5U.js → interactive-I6KDKLEO.js} +6 -5
- package/dist/interactive-I6KDKLEO.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-PG7YCPAN.js.map +0 -1
- package/dist/interactive-HI3LDK5U.js.map +0 -1
|
@@ -573,24 +573,116 @@ var BLANK_COLOURS = {
|
|
|
573
573
|
"sols-03996": ["black", "white"],
|
|
574
574
|
"shaka-shmhss": ["black", "white", "khaki"]
|
|
575
575
|
};
|
|
576
|
+
var STOCK_REGION_BY_COUNTRY = {
|
|
577
|
+
us: "US-CA",
|
|
578
|
+
se: "EU",
|
|
579
|
+
at: "EU",
|
|
580
|
+
be: "EU",
|
|
581
|
+
bg: "EU",
|
|
582
|
+
hr: "EU",
|
|
583
|
+
cy: "EU",
|
|
584
|
+
cz: "EU",
|
|
585
|
+
dk: "EU",
|
|
586
|
+
ee: "EU",
|
|
587
|
+
fi: "EU",
|
|
588
|
+
fr: "EU",
|
|
589
|
+
de: "EU",
|
|
590
|
+
gr: "EU",
|
|
591
|
+
hu: "EU",
|
|
592
|
+
ie: "EU",
|
|
593
|
+
it: "EU",
|
|
594
|
+
lv: "EU",
|
|
595
|
+
lt: "EU",
|
|
596
|
+
lu: "EU",
|
|
597
|
+
mt: "EU",
|
|
598
|
+
nl: "EU",
|
|
599
|
+
pl: "EU",
|
|
600
|
+
pt: "EU",
|
|
601
|
+
ro: "EU",
|
|
602
|
+
sk: "EU",
|
|
603
|
+
si: "EU",
|
|
604
|
+
es: "EU"
|
|
605
|
+
};
|
|
606
|
+
var BLANK_BY_REGION = {
|
|
607
|
+
regular: { "*": "gildan-5000" },
|
|
608
|
+
oversize: { EU: "sols-03996", "US-CA": "shaka-shmhss" }
|
|
609
|
+
};
|
|
576
610
|
function blankFor(fit, countryCode) {
|
|
577
|
-
|
|
578
|
-
|
|
611
|
+
const region = STOCK_REGION_BY_COUNTRY[(countryCode ?? "").trim().toLowerCase()];
|
|
612
|
+
if (!region) return null;
|
|
613
|
+
const map = BLANK_BY_REGION[fit];
|
|
614
|
+
return map["*"] ?? map[region] ?? null;
|
|
579
615
|
}
|
|
580
616
|
var BLANK_SIZES = {
|
|
581
617
|
"gildan-5000": ["s", "m", "l", "xl", "2xl", "3xl", "4xl", "5xl"],
|
|
582
618
|
"shaka-shmhss": ["s", "m", "l", "xl", "2xl", "3xl", "4xl", "5xl"],
|
|
583
619
|
"sols-03996": ["xs", "s", "m", "l", "xl", "2xl", "3xl"]
|
|
584
620
|
};
|
|
621
|
+
function supplierOf(p) {
|
|
622
|
+
const v = (p.metadata ?? {})["bt_supplier"];
|
|
623
|
+
if (v === void 0 || v === null) return "gelato";
|
|
624
|
+
return v === "gelato" || v === "printful" ? v : null;
|
|
625
|
+
}
|
|
626
|
+
var PRINTFUL_BLANK_COLOURS = {
|
|
627
|
+
"ascolour-5082": ["black", "white"]
|
|
628
|
+
};
|
|
629
|
+
var PRINTFUL_BLANK_SIZES = {
|
|
630
|
+
"ascolour-5082": ["s", "m", "l", "xl", "2xl"]
|
|
631
|
+
};
|
|
632
|
+
var PRINTFUL_SERVED_COUNTRIES = [
|
|
633
|
+
"se",
|
|
634
|
+
"us",
|
|
635
|
+
"at",
|
|
636
|
+
"be",
|
|
637
|
+
"bg",
|
|
638
|
+
"hr",
|
|
639
|
+
"cy",
|
|
640
|
+
"cz",
|
|
641
|
+
"dk",
|
|
642
|
+
"ee",
|
|
643
|
+
"fi",
|
|
644
|
+
"fr",
|
|
645
|
+
"de",
|
|
646
|
+
"gr",
|
|
647
|
+
"hu",
|
|
648
|
+
"ie",
|
|
649
|
+
"it",
|
|
650
|
+
"lv",
|
|
651
|
+
"lt",
|
|
652
|
+
"lu",
|
|
653
|
+
"mt",
|
|
654
|
+
"nl",
|
|
655
|
+
"pl",
|
|
656
|
+
"pt",
|
|
657
|
+
"ro",
|
|
658
|
+
"sk",
|
|
659
|
+
"si",
|
|
660
|
+
"es"
|
|
661
|
+
];
|
|
662
|
+
function printfulBlankFor(fit, countryCode) {
|
|
663
|
+
if (!PRINTFUL_SERVED_COUNTRIES.includes((countryCode ?? "").trim().toLowerCase())) return null;
|
|
664
|
+
return fit === "regular" ? "ascolour-5082" : null;
|
|
665
|
+
}
|
|
585
666
|
function sizeKey(size) {
|
|
586
667
|
const s = size.trim().toLowerCase();
|
|
587
668
|
return s === "xxl" ? "2xl" : s === "xxxl" ? "3xl" : s;
|
|
588
669
|
}
|
|
589
|
-
function
|
|
590
|
-
|
|
670
|
+
function blankRule(fit, countryCode, supplier) {
|
|
671
|
+
if (supplier === null) return null;
|
|
672
|
+
if (supplier === "printful") {
|
|
673
|
+
const pb = printfulBlankFor(fit, countryCode);
|
|
674
|
+
return pb ? { colours: PRINTFUL_BLANK_COLOURS[pb], sizes: PRINTFUL_BLANK_SIZES[pb] } : null;
|
|
675
|
+
}
|
|
676
|
+
const blank = blankFor(fit, countryCode);
|
|
677
|
+
return blank ? { colours: BLANK_COLOURS[blank], sizes: BLANK_SIZES[blank] } : null;
|
|
591
678
|
}
|
|
592
|
-
function
|
|
593
|
-
|
|
679
|
+
function colourBuyable(fit, colour, countryCode, supplier = "gelato") {
|
|
680
|
+
const rule2 = blankRule(fit, countryCode, supplier);
|
|
681
|
+
return !!rule2 && rule2.colours.includes(colour.trim().toLowerCase());
|
|
682
|
+
}
|
|
683
|
+
function sizeBuyable(fit, size, countryCode, supplier = "gelato") {
|
|
684
|
+
const rule2 = blankRule(fit, countryCode, supplier);
|
|
685
|
+
return !!rule2 && rule2.sizes.includes(sizeKey(size));
|
|
594
686
|
}
|
|
595
687
|
function legacyFit(p) {
|
|
596
688
|
const md = p.metadata ?? {};
|
|
@@ -607,24 +699,26 @@ function variantsOfFit(p, fit) {
|
|
|
607
699
|
}
|
|
608
700
|
function coloursFor(p, fit, countryCode) {
|
|
609
701
|
const gate = gateFit(p, fit);
|
|
702
|
+
const supplier = supplierOf(p);
|
|
610
703
|
const out = [];
|
|
611
704
|
for (const v of variantsOfFit(p, fit)) {
|
|
612
705
|
const c = variantColour(v);
|
|
613
706
|
if (!c || out.includes(c)) continue;
|
|
614
|
-
if (gate && countryCode !== void 0 && !colourBuyable(gate, c, countryCode)) continue;
|
|
707
|
+
if (gate && countryCode !== void 0 && !colourBuyable(gate, c, countryCode, supplier)) continue;
|
|
615
708
|
out.push(c);
|
|
616
709
|
}
|
|
617
710
|
return out;
|
|
618
711
|
}
|
|
619
712
|
function sizesFor(p, fit, colour, countryCode) {
|
|
620
713
|
const gate = gateFit(p, fit);
|
|
714
|
+
const supplier = supplierOf(p);
|
|
621
715
|
const target = colour.trim().toLowerCase();
|
|
622
716
|
const out = [];
|
|
623
717
|
for (const v of variantsOfFit(p, fit)) {
|
|
624
718
|
if (variantColour(v) !== target) continue;
|
|
625
719
|
const s = sizeOfVariant(v);
|
|
626
720
|
if (!s || out.includes(s)) continue;
|
|
627
|
-
if (gate && countryCode !== void 0 && !sizeBuyable(gate, s, countryCode)) continue;
|
|
721
|
+
if (gate && countryCode !== void 0 && !sizeBuyable(gate, s, countryCode, supplier)) continue;
|
|
628
722
|
out.push(s);
|
|
629
723
|
}
|
|
630
724
|
return out;
|
|
@@ -662,21 +756,22 @@ function resolveVariant(p, opts) {
|
|
|
662
756
|
}
|
|
663
757
|
const pool = variantsOfFit(p, fit);
|
|
664
758
|
const gate = gateFit(p, fit);
|
|
759
|
+
const supplier = supplierOf(p);
|
|
665
760
|
const colours = coloursFor(p, fit, opts.countryCode);
|
|
666
761
|
const colour = (opts.colour ?? "").trim().toLowerCase() || (colours[0] ?? null);
|
|
667
|
-
if (gate && colour && opts.countryCode !== void 0 && !colourBuyable(gate, colour, opts.countryCode)) {
|
|
762
|
+
if (gate && colour && opts.countryCode !== void 0 && !colourBuyable(gate, colour, opts.countryCode, supplier)) {
|
|
668
763
|
return { ok: false, reason: "fit_unavailable", fit: gate, colour };
|
|
669
764
|
}
|
|
670
765
|
const size = (opts.size ?? "").trim() || null;
|
|
671
766
|
const sizeLc = size?.toLowerCase();
|
|
672
767
|
const buyableSizes = colour ? sizesFor(p, fit, colour, opts.countryCode) : [];
|
|
673
768
|
const sizeExists = !!size && pool.some((x) => (sizeOfVariant(x) ?? x.title ?? "").toLowerCase() === size.toLowerCase());
|
|
674
|
-
if (gate && size && sizeExists && opts.countryCode !== void 0 && !sizeBuyable(gate, size, opts.countryCode)) {
|
|
769
|
+
if (gate && size && sizeExists && opts.countryCode !== void 0 && !sizeBuyable(gate, size, opts.countryCode, supplier)) {
|
|
675
770
|
return { ok: false, reason: "size_unavailable", fit: gate, size, sizes: buyableSizes };
|
|
676
771
|
}
|
|
677
772
|
const sellable = gate && opts.countryCode !== void 0 ? pool.filter((x) => {
|
|
678
773
|
const s = sizeOfVariant(x);
|
|
679
|
-
return !s || sizeBuyable(gate, s, opts.countryCode);
|
|
774
|
+
return !s || sizeBuyable(gate, s, opts.countryCode, supplier);
|
|
680
775
|
}) : pool;
|
|
681
776
|
const v = sellable.find((x) => {
|
|
682
777
|
const colourOk = !colour || variantColour(x) === colour;
|
|
@@ -831,22 +926,75 @@ function firstImageUrl(images) {
|
|
|
831
926
|
function escapeRegex(s) {
|
|
832
927
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
833
928
|
}
|
|
929
|
+
function orderStage(o) {
|
|
930
|
+
const status = (o.status ?? "").trim().toLowerCase();
|
|
931
|
+
if (status === "canceled" || status === "refunded") return "reverted";
|
|
932
|
+
switch ((o.fulfillment_status ?? "").trim().toLowerCase()) {
|
|
933
|
+
case "canceled":
|
|
934
|
+
return "reverted";
|
|
935
|
+
case "delivered":
|
|
936
|
+
case "partially_delivered":
|
|
937
|
+
return "delivered";
|
|
938
|
+
case "shipped":
|
|
939
|
+
case "partially_shipped":
|
|
940
|
+
return "shipped";
|
|
941
|
+
case "fulfilled":
|
|
942
|
+
case "partially_fulfilled":
|
|
943
|
+
return "printed";
|
|
944
|
+
case "not_fulfilled":
|
|
945
|
+
default:
|
|
946
|
+
return "committed";
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
async function cartShipTo(cart, regions) {
|
|
950
|
+
const embedded = cart.region?.countries?.length ? cart.region : null;
|
|
951
|
+
const id = cart.region_id ?? cart.region?.id ?? null;
|
|
952
|
+
const region = embedded ?? (id ? (await regions()).find((r) => r.id === id) ?? null : null);
|
|
953
|
+
if (!region) return null;
|
|
954
|
+
const regionCountries = (region.countries ?? []).map((c) => (c.iso_2 ?? "").trim().toLowerCase()).filter(Boolean);
|
|
955
|
+
const address = (cart.shipping_address?.country_code ?? "").trim().toLowerCase() || null;
|
|
956
|
+
const country = address ?? regionCountries[0] ?? null;
|
|
957
|
+
if (!country) return null;
|
|
958
|
+
return { region, country, fromAddress: address !== null, regionCountries };
|
|
959
|
+
}
|
|
960
|
+
function shipToDisagrees(requested, shipTo) {
|
|
961
|
+
const cc = (requested ?? "").trim().toLowerCase();
|
|
962
|
+
if (!cc || cc === shipTo.country) return false;
|
|
963
|
+
return shipTo.fromAddress || !shipTo.regionCountries.includes(cc);
|
|
964
|
+
}
|
|
834
965
|
function str(v, fallback) {
|
|
835
966
|
return typeof v === "string" && v.length > 0 ? v : fallback;
|
|
836
967
|
}
|
|
968
|
+
var GELATO_FALLBACK = {
|
|
969
|
+
material: "100% cotton",
|
|
970
|
+
weight: "180 g/m\xB2",
|
|
971
|
+
fit: "Unisex heavyweight crewneck",
|
|
972
|
+
delivery: "Ships in 2\u20135 business days + transit",
|
|
973
|
+
care: "Cold wash, line dry"
|
|
974
|
+
};
|
|
975
|
+
var PRINTFUL_FALLBACK = {
|
|
976
|
+
material: "100% cotton",
|
|
977
|
+
weight: "240 g/m\xB2",
|
|
978
|
+
fit: "Unisex heavyweight crewneck, garment-dyed",
|
|
979
|
+
delivery: "Ships in 2\u20135 business days + transit",
|
|
980
|
+
care: "Machine wash cold, inside out. Do not tumble dry or iron the print. Line dry in shade."
|
|
981
|
+
};
|
|
837
982
|
function productSpecs(p, fit) {
|
|
838
983
|
const md = p.metadata ?? {};
|
|
839
984
|
const byFit = md.specs_by_fit ?? null;
|
|
840
985
|
const fitKey = fit ?? (byFit && Object.keys(byFit).length === 1 ? Object.keys(byFit)[0] : void 0);
|
|
841
986
|
const src = fitKey && byFit?.[fitKey] || md;
|
|
842
987
|
const pick = (k, fallback) => str(src[k] ?? md[k], fallback);
|
|
988
|
+
const d = supplierOf(p) === "printful" ? PRINTFUL_FALLBACK : GELATO_FALLBACK;
|
|
843
989
|
return [
|
|
844
|
-
{ key: "material", value: pick("material",
|
|
845
|
-
{ key: "weight", value: pick("weight",
|
|
846
|
-
{ key: "fit", value: pick("fit",
|
|
990
|
+
{ key: "material", value: pick("material", d.material) },
|
|
991
|
+
{ key: "weight", value: pick("weight", d.weight) },
|
|
992
|
+
{ key: "fit", value: pick("fit", d.fit) },
|
|
847
993
|
{ key: "print", value: pick("print", "Front print") },
|
|
848
|
-
|
|
849
|
-
|
|
994
|
+
// Delivery: the product's own line first (Sam 2026-10-01, as the storefront since U1), else the same
|
|
995
|
+
// fallback wording for both suppliers. No per-region times.
|
|
996
|
+
{ key: "delivery", value: pick("delivery", d.delivery) },
|
|
997
|
+
{ key: "care", value: pick("care", d.care) }
|
|
850
998
|
];
|
|
851
999
|
}
|
|
852
1000
|
function productLore(p) {
|
|
@@ -1306,6 +1454,11 @@ function printResult(res, json) {
|
|
|
1306
1454
|
process.stdout.write(res.lines.join("\n") + "\n");
|
|
1307
1455
|
}
|
|
1308
1456
|
|
|
1457
|
+
// src/ship-to.ts
|
|
1458
|
+
function shipToCountry(requested, region) {
|
|
1459
|
+
return (requested ?? region?.countries?.[0]?.iso_2 ?? "").toLowerCase() || null;
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1309
1462
|
// src/image-ladder.ts
|
|
1310
1463
|
var DEFAULT_RENDER_HEIGHT = 28;
|
|
1311
1464
|
function urlFloor(url) {
|
|
@@ -1534,7 +1687,41 @@ async function runStage(client, config, args) {
|
|
|
1534
1687
|
fix: "bt region --list (see where we ship, then bt region <cc>)"
|
|
1535
1688
|
});
|
|
1536
1689
|
}
|
|
1537
|
-
|
|
1690
|
+
let region = rr.region;
|
|
1691
|
+
let countryCode = shipToCountry(rr.requested, region);
|
|
1692
|
+
let cartId = config.cart_id;
|
|
1693
|
+
let recovered = false;
|
|
1694
|
+
if (cartId) {
|
|
1695
|
+
let existing = null;
|
|
1696
|
+
try {
|
|
1697
|
+
existing = await client.getCart(cartId);
|
|
1698
|
+
} catch (e) {
|
|
1699
|
+
if (!(e instanceof RecoverableCartError)) throw e;
|
|
1700
|
+
cartId = void 0;
|
|
1701
|
+
recovered = true;
|
|
1702
|
+
}
|
|
1703
|
+
if (existing) {
|
|
1704
|
+
const to = await cartShipTo(existing, () => client.getRegions());
|
|
1705
|
+
if (!to) {
|
|
1706
|
+
return failResult({
|
|
1707
|
+
code: EXIT.DATAERR,
|
|
1708
|
+
what: "can't tell where your staged cart ships, so it can't be checked.",
|
|
1709
|
+
money: "nothing staged, nothing charged.",
|
|
1710
|
+
fix: "bt checkout (finish the staged cart first)"
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
if (shipToDisagrees(rr.requested, to)) {
|
|
1714
|
+
return failResult({
|
|
1715
|
+
code: EXIT.DATAERR,
|
|
1716
|
+
what: `your staged cart ships to ${to.country}, but your region is ${rr.requested}.`,
|
|
1717
|
+
money: "nothing staged, nothing charged.",
|
|
1718
|
+
fix: `bt region ${to.country} (to keep staging into this cart, or bt checkout it first)`
|
|
1719
|
+
});
|
|
1720
|
+
}
|
|
1721
|
+
region = to.region;
|
|
1722
|
+
countryCode = to.country;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1538
1725
|
const resolved = await resolveProduct(client, region, args.handle);
|
|
1539
1726
|
if (!resolved.product) {
|
|
1540
1727
|
if (resolved.candidates && resolved.candidates.length > 1) {
|
|
@@ -1547,7 +1734,6 @@ async function runStage(client, config, args) {
|
|
|
1547
1734
|
const product = resolved.product;
|
|
1548
1735
|
const matchNote = resolved.fuzzy && (product.handle ?? "") !== args.handle.trim() ? working(`matched "${product.handle}" from "${args.handle}"`) : null;
|
|
1549
1736
|
const size = args.size ?? config.defaultSize;
|
|
1550
|
-
const countryCode = (rr.requested ?? region.countries?.[0]?.iso_2 ?? "").toLowerCase() || null;
|
|
1551
1737
|
const explicitFit = args.fit ?? resolved.impliedFit;
|
|
1552
1738
|
const fitArg = explicitFit ?? (productFits(product).length > 1 ? config.defaultFit : void 0);
|
|
1553
1739
|
const r = resolveVariant(product, { fit: fitArg, size, colour: args.colour ?? config.defaultColour, countryCode });
|
|
@@ -1640,8 +1826,6 @@ async function runStage(client, config, args) {
|
|
|
1640
1826
|
if (resolved.aliasNote) {
|
|
1641
1827
|
lines.push(warn(resolved.aliasNote));
|
|
1642
1828
|
}
|
|
1643
|
-
let cartId = config.cart_id;
|
|
1644
|
-
let recovered = false;
|
|
1645
1829
|
if (!cartId) {
|
|
1646
1830
|
const fresh = await client.createCart(region);
|
|
1647
1831
|
cartId = fresh.id;
|
|
@@ -1717,6 +1901,7 @@ export {
|
|
|
1717
1901
|
priceFor,
|
|
1718
1902
|
productColours,
|
|
1719
1903
|
findVariant,
|
|
1904
|
+
orderStage,
|
|
1720
1905
|
productLore,
|
|
1721
1906
|
isCartTaxInclusive,
|
|
1722
1907
|
cartMoneyRows,
|
|
@@ -1752,9 +1937,10 @@ export {
|
|
|
1752
1937
|
resolveOutput,
|
|
1753
1938
|
failResult,
|
|
1754
1939
|
printResult,
|
|
1940
|
+
shipToCountry,
|
|
1755
1941
|
runView,
|
|
1756
1942
|
registerView,
|
|
1757
1943
|
runStage,
|
|
1758
1944
|
registerStage
|
|
1759
1945
|
};
|
|
1760
|
-
//# sourceMappingURL=chunk-
|
|
1946
|
+
//# sourceMappingURL=chunk-5W5O6G6Y.js.map
|