@binaryandthread/cli 0.4.5 → 0.4.7

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.
@@ -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
- if (fit === "regular") return "gildan-5000";
578
- return (countryCode ?? "").trim().toLowerCase() === "us" ? "shaka-shmhss" : "sols-03996";
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 colourBuyable(fit, colour, countryCode) {
590
- return BLANK_COLOURS[blankFor(fit, countryCode)].includes(colour.trim().toLowerCase());
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 sizeBuyable(fit, size, countryCode) {
593
- return BLANK_SIZES[blankFor(fit, countryCode)].includes(sizeKey(size));
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
+ // made, not shipped: to the customer it is simply not shipped yet
943
+ case "partially_fulfilled":
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", "100% cotton") },
845
- { key: "weight", value: pick("weight", "180 g/m\xB2") },
846
- { key: "fit", value: pick("fit", "Unisex heavyweight crewneck") },
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
- { key: "delivery", value: pick("delivery", "Ships in 2\u20135 business days + transit") },
849
- { key: "care", value: pick("care", "Cold wash, line dry") }
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
- const region = rr.region;
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-PG7YCPAN.js.map
1946
+ //# sourceMappingURL=chunk-CE324N5B.js.map