@misiki/gocommerce-connector 0.3.0 → 0.4.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.
@@ -191,6 +191,12 @@ var rememberWishlistToken = (token) => writeLocal(WISHLIST, token);
191
191
  var forgetWishlistToken = () => removeLocal(WISHLIST);
192
192
 
193
193
  // src/services/base.service.ts
194
+ function mediaUrl(url) {
195
+ if (!url) return null;
196
+ if (!url.startsWith("/") || url.startsWith("//")) return url;
197
+ const { apiUrl, proxyPath } = BaseService.getCredentials();
198
+ return (proxyPath || apiUrl || "").trim().replace(/\/+$/, "") + url;
199
+ }
194
200
  var BaseService = class _BaseService {
195
201
  static _credentials = { apiUrl: "" };
196
202
  _fetch;
@@ -206,6 +212,17 @@ var BaseService = class _BaseService {
206
212
  get creds() {
207
213
  return _BaseService._credentials;
208
214
  }
215
+ /**
216
+ * The store this call is for: the request host's subdomain under
217
+ * `baseDomain`, else the static `store`. Read per call, never stored on the
218
+ * instance, because the server shares one process (and one credentials
219
+ * object) across every concurrent request and each may be for a different host.
220
+ */
221
+ get store() {
222
+ const { baseDomain, store } = this.creds;
223
+ const host = typeof window !== "undefined" ? window.location?.hostname : requestHost?.();
224
+ return storeForHost(host, baseDomain) ?? store;
225
+ }
209
226
  /**
210
227
  * The engine's base URL from wherever this code runs. In the browser a
211
228
  * configured proxy path wins, because the engine answers no CORS preflight.
@@ -239,7 +256,8 @@ var BaseService = class _BaseService {
239
256
  const url = this.engineURL(path, lang ? { lang, ...req.query } : req.query);
240
257
  const headers = { Accept: "application/json", ...req.headers };
241
258
  if (req.body !== void 0) headers["Content-Type"] = "application/json";
242
- if (this.creds.store) headers["X-Store"] = this.creds.store;
259
+ const store = this.store;
260
+ if (store) headers["X-Store"] = store;
243
261
  if (req.auth) {
244
262
  const token = sessionToken();
245
263
  if (!token) throw new GoCommerceError("Please sign in to continue.", 401, "unauthorized");
@@ -341,6 +359,18 @@ var BaseService = class _BaseService {
341
359
  return body;
342
360
  }
343
361
  };
362
+ var requestHost;
363
+ function setRequestHost(fn) {
364
+ requestHost = fn;
365
+ }
366
+ function storeForHost(host, baseDomain) {
367
+ if (!host || !baseDomain) return void 0;
368
+ const h = host.toLowerCase().replace(/\.$/, "").replace(/:\d+$/, "");
369
+ const suffix = "." + baseDomain.toLowerCase().replace(/^\.+/, "").replace(/\.$/, "");
370
+ if (!h.endsWith(suffix)) return void 0;
371
+ const slug = h.slice(0, -suffix.length);
372
+ return slug && !slug.includes(".") ? slug : void 0;
373
+ }
344
374
  var unreachable = (base, cause) => new GoCommerceError(`Could not reach the commerce engine at ${base}: ${cause?.message ?? cause}`, 0);
345
375
  function qs(query) {
346
376
  if (!query) return "";
@@ -414,7 +444,8 @@ var liveVariants = (p) => arr(p.variants).filter((v) => v.active);
414
444
  function variantImages(v) {
415
445
  const out = [];
416
446
  for (const img of [v.image, ...arr(v.images)]) {
417
- if (img?.url && (img.kind ?? "image") === "image" && !out.includes(img.url)) out.push(img.url);
447
+ const url = mediaUrl(img?.url);
448
+ if (url && (img?.kind ?? "image") === "image" && !out.includes(url)) out.push(url);
418
449
  }
419
450
  return out;
420
451
  }
@@ -423,7 +454,7 @@ function productImages(p) {
423
454
  const push = (url) => {
424
455
  if (url && !out.includes(url)) out.push(url);
425
456
  };
426
- push(p.image_url);
457
+ push(mediaUrl(p.image_url));
427
458
  for (const v of arr(p.variants)) for (const url of variantImages(v)) push(url);
428
459
  return out;
429
460
  }
@@ -553,9 +584,9 @@ function fromSearchDoc(d) {
553
584
  mrp: price,
554
585
  minPrice: price,
555
586
  maxPrice: minorToMajor(d.price_max_minor, d.currency),
556
- thumbnail: d.image ?? null,
557
- image_url: d.image ?? null,
558
- images: d.image ?? "",
587
+ thumbnail: mediaUrl(d.image),
588
+ image_url: mediaUrl(d.image),
589
+ images: mediaUrl(d.image) ?? "",
559
590
  stock: d.in_stock ? 1 : 0,
560
591
  hasStock: d.in_stock,
561
592
  // The index cannot say how much is left, only whether any is; a card
@@ -584,7 +615,7 @@ function toCategory(c) {
584
615
  level: c.depth,
585
616
  rank: c.position,
586
617
  childCount: c.child_count,
587
- thumbnail: c.metadata?.image ?? null,
618
+ thumbnail: mediaUrl(c.metadata?.image),
588
619
  description: c.metadata?.description ?? null,
589
620
  isActive: true,
590
621
  isFeatured: false,
@@ -604,7 +635,7 @@ function toCollection(c) {
604
635
  description: c.description || null,
605
636
  subTitle: null,
606
637
  rank: str(c.position),
607
- thumbnail: c.metadata?.image ?? null,
638
+ thumbnail: mediaUrl(c.metadata?.image),
608
639
  isActive: true,
609
640
  metaTitle: c.title,
610
641
  metaDescription: c.description || null,
@@ -687,7 +718,7 @@ function toCartLine(l, extra = {}) {
687
718
  title: l.title,
688
719
  name: l.title,
689
720
  slug: extra.slug ?? "",
690
- thumbnail: extra.thumbnail ?? null,
721
+ thumbnail: mediaUrl(extra.thumbnail),
691
722
  variantTitle: l.variant_label ?? "",
692
723
  qty: l.quantity,
693
724
  price: toMajor(l.unit_price),
@@ -795,8 +826,8 @@ function toOrderLine(l, currency) {
795
826
  title: l.title,
796
827
  name: l.title,
797
828
  slug: "",
798
- thumbnail: l.image_url ?? null,
799
- img: l.image_url ?? null,
829
+ thumbnail: mediaUrl(l.image_url),
830
+ img: mediaUrl(l.image_url),
800
831
  variantTitle: l.variant_label ?? "",
801
832
  qty: l.quantity,
802
833
  shippedQty: l.shipped_quantity,
@@ -941,7 +972,7 @@ function remember(key, load, ttl = TTL_MS) {
941
972
  // src/services/facts.ts
942
973
  var StoreFacts = class extends BaseService {
943
974
  key(name) {
944
- return `${this.engineBase()}|${this.creds.store ?? ""}|${name}`;
975
+ return `${this.engineBase()}|${this.store ?? ""}|${name}`;
945
976
  }
946
977
  /** Enabled plugins by key. A module that is not installed has no key here. */
947
978
  plugins() {
@@ -1954,7 +1985,7 @@ var OrderService = class extends BaseService {
1954
1985
  productId: l.product_id,
1955
1986
  variantId: l.variant_id,
1956
1987
  title: l.title,
1957
- img: l.image_url ?? null,
1988
+ img: mediaUrl(l.image_url),
1958
1989
  price: toMajor(l.unit_price),
1959
1990
  qty: l.quantity
1960
1991
  });
@@ -2371,7 +2402,7 @@ var MenuService = class extends BaseService {
2371
2402
  /** The header and footer menus, or `null` when the module is not there. Cached: a menu is store-level. */
2372
2403
  async engineMenus() {
2373
2404
  if (!await this.facts.pluginOn("navigation")) return null;
2374
- return remember(`${this.engineBase()}|${this.creds.store ?? ""}|menus`, async () => {
2405
+ return remember(`${this.engineBase()}|${this.store ?? ""}|menus`, async () => {
2375
2406
  const out = [];
2376
2407
  for (const handle of ["header", "footer"]) {
2377
2408
  try {
@@ -2408,6 +2439,7 @@ var NewsletterService = class extends BaseService {
2408
2439
  var newsletterService = new NewsletterService();
2409
2440
 
2410
2441
  // src/services/store-service.ts
2442
+ var isStoreMissing = (err) => err instanceof GoCommerceError && err.status === 404 && (err.code === "store_not_found" || /store not found|no such store/i.test(err.message));
2411
2443
  function symbolFor(code) {
2412
2444
  try {
2413
2445
  const part = new Intl.NumberFormat("en", { style: "currency", currency: code }).formatToParts(0).find((p) => p.type === "currency");
@@ -2420,6 +2452,14 @@ var StoreService = class extends BaseService {
2420
2452
  facts = new StoreFacts(this._fetch);
2421
2453
  async getStoreByIdOrDomain(_args = {}) {
2422
2454
  const base = await readStaticStore();
2455
+ const store = this.store;
2456
+ if (store) {
2457
+ await this.facts.plugins().catch((err) => {
2458
+ if (isStoreMissing(err)) {
2459
+ throw new GoCommerceError(`store not found: no store "${store}" on this engine`, 404, "store_not_found");
2460
+ }
2461
+ });
2462
+ }
2423
2463
  const live = await this.live().catch(() => ({}));
2424
2464
  return { ...base, ...live, id: base.id || "gocommerce" };
2425
2465
  }
@@ -3133,6 +3173,7 @@ exports.feedbackService = feedbackService;
3133
3173
  exports.galleryService = galleryService;
3134
3174
  exports.homeService = homeService;
3135
3175
  exports.initService = initService;
3176
+ exports.mediaUrl = mediaUrl;
3136
3177
  exports.meilisearchService = meilisearchService;
3137
3178
  exports.menuService = menuService;
3138
3179
  exports.newsletterService = newsletterService;
@@ -3150,10 +3191,12 @@ exports.reelsService = reelsService;
3150
3191
  exports.regionService = regionService;
3151
3192
  exports.reviewService = reviewService;
3152
3193
  exports.searchService = searchService;
3194
+ exports.setRequestHost = setRequestHost;
3153
3195
  exports.settingService = settingService;
3154
3196
  exports.settingsService = settingsService;
3155
3197
  exports.stateService = stateService;
3156
3198
  exports.staticStore = staticStore;
3199
+ exports.storeForHost = storeForHost;
3157
3200
  exports.storeService = storeService;
3158
3201
  exports.toPage = toPage;
3159
3202
  exports.uploadService = uploadService;