@misiki/gocommerce-connector 0.12.0 → 0.13.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.
@@ -466,9 +466,27 @@ function productImages(p) {
466
466
  if (url && !out.includes(url)) out.push(url);
467
467
  };
468
468
  push(mediaUrl(p.image_url));
469
+ for (const m of arr(p.media)) if (m.kind === "image") push(mediaUrl(m.url));
469
470
  for (const v of arr(p.variants)) for (const url of variantImages(v)) push(url);
470
471
  return out;
471
472
  }
473
+ function productVideos(p) {
474
+ const out = [];
475
+ for (const m of arr(p.media)) {
476
+ const url = m.kind === "video" ? mediaUrl(m.url) : null;
477
+ if (url && !out.includes(url)) out.push(url);
478
+ }
479
+ return out;
480
+ }
481
+ function highlightsOf(p) {
482
+ const raw = p.metadata?.highlights;
483
+ if (!Array.isArray(raw)) return [];
484
+ return raw.filter((s) => typeof s === "string").map((s) => s.trim()).filter(Boolean);
485
+ }
486
+ function freeGiftOf(p) {
487
+ const raw = p.metadata?.free_gift;
488
+ return typeof raw === "string" && raw.trim() ? raw.trim() : null;
489
+ }
472
490
  function toVariant(v, p, optionless) {
473
491
  const images = variantImages(v);
474
492
  const options = arr(p.options);
@@ -516,6 +534,7 @@ function toProduct(p, extra = {}) {
516
534
  const lead = live[0] ?? arr(p.variants)[0];
517
535
  const optionless = arr(p.options).length === 0;
518
536
  const images = productImages(p);
537
+ const videos = productVideos(p);
519
538
  const prices = live.map((v) => toMajor(v.price));
520
539
  const tracked = live.filter((v) => v.track_inventory);
521
540
  const category = p.category;
@@ -542,8 +561,14 @@ function toProduct(p, extra = {}) {
542
561
  originCountry: lead?.origin_country ?? null,
543
562
  thumbnail: images[0] ?? null,
544
563
  image_url: images[0] ?? null,
545
- images: images.join(","),
564
+ images: [...images, ...videos].join(","),
546
565
  imageList: images,
566
+ videos,
567
+ // What the buy box says beside the price (D134): plain text, drawn as text.
568
+ highlights: highlightsOf(p),
569
+ freeGift: freeGiftOf(p),
570
+ // Counted by the engine, rounded down, and absent rather than zero.
571
+ soldAtLeast: typeof p.sold_at_least === "number" && p.sold_at_least > 0 ? p.sold_at_least : null,
547
572
  // Product-level stock is what a card shows before a variant is picked:
548
573
  // buyable when any live variant is, counted only where counting means
549
574
  // something.
@@ -716,7 +741,9 @@ function toIdentityAddress(a) {
716
741
  state: e.state ?? "",
717
742
  postal_code: e.postal_code,
718
743
  country: e.country,
719
- ...a.label ? { label: String(a.label) } : {},
744
+ // Sent whenever the form has it, empty included: the engine keeps a label it is not sent, so
745
+ // leaving out an emptied one would keep the old Home or Work (D134).
746
+ ...typeof a.label === "string" ? { label: a.label } : {},
720
747
  ...a.isPrimary ? { is_default: true } : {}
721
748
  };
722
749
  }
@@ -2669,6 +2696,24 @@ var AddressService = class extends BaseService {
2669
2696
  });
2670
2697
  return fromIdentityAddress(a, currentMe()?.email);
2671
2698
  }
2699
+ /**
2700
+ * The city and state for a postcode (D134), for the address form to fill
2701
+ * in. India's six-digit PIN codes only, from the directory the engine was
2702
+ * given; null for anything it cannot answer, so the form simply leaves the
2703
+ * fields to the shopper.
2704
+ */
2705
+ async lookupPostcode({ country = "IN", postcode }) {
2706
+ const code = String(postcode ?? "").trim();
2707
+ const cc = String(country ?? "").trim().toUpperCase();
2708
+ if (cc !== "IN" || !/^[1-9][0-9]{5}$/.test(code)) return null;
2709
+ try {
2710
+ const p = await this.data(`/api/postcodes/${cc}/${code}`);
2711
+ return { country: p.country, postcode: p.postcode, city: p.city, state: p.state, stateCode: p.state_code };
2712
+ } catch (err) {
2713
+ if (err instanceof GoCommerceError && (err.status === 404 || err.status === 400)) return null;
2714
+ throw err;
2715
+ }
2716
+ }
2672
2717
  async deleteAddress(id2) {
2673
2718
  await this.engine(`/x/identity/me/addresses/${enc(id2)}`, { method: "DELETE", auth: true });
2674
2719
  return { id: String(id2), deleted: true };