@misiki/gocommerce-connector 0.3.0 → 0.3.1

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.cjs CHANGED
@@ -138,6 +138,313 @@ function forgetAll() {
138
138
  entries.clear();
139
139
  }
140
140
 
141
+ // src/browser.ts
142
+ var inBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
143
+ function readLocal(key) {
144
+ if (!inBrowser()) return null;
145
+ try {
146
+ return window.localStorage.getItem(key);
147
+ } catch {
148
+ return null;
149
+ }
150
+ }
151
+ function writeLocal(key, value) {
152
+ if (!inBrowser()) return;
153
+ try {
154
+ window.localStorage.setItem(key, value);
155
+ } catch {
156
+ }
157
+ }
158
+ function removeLocal(key) {
159
+ if (!inBrowser()) return;
160
+ try {
161
+ window.localStorage.removeItem(key);
162
+ } catch {
163
+ }
164
+ }
165
+ function readJSON(key) {
166
+ const raw = readLocal(key);
167
+ if (!raw) return null;
168
+ try {
169
+ return JSON.parse(raw);
170
+ } catch {
171
+ return null;
172
+ }
173
+ }
174
+ var YEAR = 60 * 60 * 24 * 365;
175
+ function setCookie(name, value, maxAge = YEAR) {
176
+ if (!inBrowser()) return;
177
+ document.cookie = `${name}=${value}; path=/; max-age=${maxAge}; samesite=lax`;
178
+ }
179
+ function clearCookie(name) {
180
+ if (!inBrowser()) return;
181
+ document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
182
+ }
183
+ function readCookie(name) {
184
+ if (!inBrowser()) return null;
185
+ for (const pair of document.cookie.split(";")) {
186
+ const at = pair.indexOf("=");
187
+ if (at < 0) continue;
188
+ if (pair.slice(0, at).trim() === name) return pair.slice(at + 1).trim();
189
+ }
190
+ return null;
191
+ }
192
+ var TOKEN = "gocommerce_token";
193
+ var sessionToken = () => readLocal(TOKEN);
194
+ function toMe(c) {
195
+ const [firstName, ...rest] = (c.name ?? "").trim().split(/\s+/);
196
+ return {
197
+ id: String(c.id),
198
+ userId: String(c.id),
199
+ email: c.email,
200
+ phone: c.phone || null,
201
+ firstName: firstName || "",
202
+ lastName: rest.join(" "),
203
+ name: c.name ?? "",
204
+ fullName: c.name ?? "",
205
+ avatar: null,
206
+ role: "USER",
207
+ emailVerified: c.email_verified,
208
+ storeId: null
209
+ };
210
+ }
211
+ function startSession(auth) {
212
+ writeLocal(TOKEN, auth.token);
213
+ const me = toMe(auth.record);
214
+ const expires = Math.max(60, Math.floor((Date.parse(auth.expires_at) - Date.now()) / 1e3)) || YEAR;
215
+ setCookie("me", encodeURIComponent(JSON.stringify(me)), expires);
216
+ setCookie("connect.sid", "gocommerce", expires);
217
+ return me;
218
+ }
219
+ function updateMe(c) {
220
+ const me = toMe(c);
221
+ setCookie("me", encodeURIComponent(JSON.stringify(me)));
222
+ return me;
223
+ }
224
+ function endSession() {
225
+ removeLocal(TOKEN);
226
+ clearCookie("me");
227
+ clearCookie("connect.sid");
228
+ }
229
+ function currentMe() {
230
+ const raw = readCookie("me");
231
+ if (!raw) return null;
232
+ try {
233
+ return JSON.parse(decodeURIComponent(raw));
234
+ } catch {
235
+ return null;
236
+ }
237
+ }
238
+ function storedCartId() {
239
+ const v = readLocal("cart_id");
240
+ if (!v || v === "undefined" || v === "null") return null;
241
+ return v;
242
+ }
243
+ var rememberCartId = (id2) => writeLocal("cart_id", id2);
244
+ var extrasKey = (cartId) => `gocommerce_cart_${cartId}`;
245
+ var cartExtras = (cartId) => readJSON(extrasKey(cartId)) ?? {};
246
+ function saveCartExtras(cartId, patch) {
247
+ const next = { ...cartExtras(cartId), ...patch };
248
+ writeLocal(extrasKey(cartId), JSON.stringify(next));
249
+ return next;
250
+ }
251
+ var forgetCartExtras = (cartId) => removeLocal(extrasKey(cartId));
252
+ var ORDERS = "gocommerce_orders";
253
+ var placedOrders = () => readJSON(ORDERS) ?? [];
254
+ function rememberOrder(o) {
255
+ const kept = placedOrders().filter((p) => p.number !== o.number);
256
+ writeLocal(ORDERS, JSON.stringify([o, ...kept].slice(0, 50)));
257
+ }
258
+ var placedOrder = (number) => placedOrders().find((p) => p.number === number);
259
+ var placedOrderForCart = (cartId) => placedOrders().find((p) => p.cartId === cartId);
260
+ var placedOrderByReference = (reference) => placedOrders().find((p) => p.reference === reference);
261
+ var WISHLIST = "gocommerce_wishlist";
262
+ var wishlistToken = () => readLocal(WISHLIST);
263
+ var rememberWishlistToken = (token) => writeLocal(WISHLIST, token);
264
+ var forgetWishlistToken = () => removeLocal(WISHLIST);
265
+
266
+ // src/services/base.service.ts
267
+ function mediaUrl(url) {
268
+ if (!url) return null;
269
+ if (!url.startsWith("/") || url.startsWith("//")) return url;
270
+ const { apiUrl, proxyPath } = BaseService.getCredentials();
271
+ return (proxyPath || apiUrl || "").trim().replace(/\/+$/, "") + url;
272
+ }
273
+ var BaseService = class _BaseService {
274
+ static _credentials = { apiUrl: "" };
275
+ _fetch;
276
+ constructor(fetchFn) {
277
+ this._fetch = fetchFn ?? ((input, init) => globalThis.fetch(input, init));
278
+ }
279
+ static setCredentials(creds) {
280
+ _BaseService._credentials = { ..._BaseService._credentials, ...creds };
281
+ }
282
+ static getCredentials() {
283
+ return _BaseService._credentials;
284
+ }
285
+ get creds() {
286
+ return _BaseService._credentials;
287
+ }
288
+ /**
289
+ * The engine's base URL from wherever this code runs. In the browser a
290
+ * configured proxy path wins, because the engine answers no CORS preflight.
291
+ */
292
+ engineBase() {
293
+ const { apiUrl, proxyPath } = this.creds;
294
+ if (proxyPath && typeof window !== "undefined" && window.location) {
295
+ return new URL(proxyPath, window.location.origin).href.replace(/\/+$/, "");
296
+ }
297
+ const url = (apiUrl ?? "").trim();
298
+ if (!url) {
299
+ throw new GoCommerceError(
300
+ "PUBLIC_GOCOMMERCE_API_URL is not set, so this storefront does not know where its commerce engine is. Point it at a running GoCommerce, e.g. http://127.0.0.1:8080.",
301
+ 0
302
+ );
303
+ }
304
+ return url.replace(/\/+$/, "");
305
+ }
306
+ /** An absolute engine URL for a path and query, without sending anything. */
307
+ engineURL(path, query) {
308
+ return this.engineBase() + path + qs(query);
309
+ }
310
+ /**
311
+ * One request to the engine, envelope and all.
312
+ *
313
+ * The body is read as text first, so a proxy's HTML error page is reported
314
+ * as what it is rather than as a JSON parse error three frames away.
315
+ */
316
+ async engine(path, req = {}) {
317
+ const lang = (req.method ?? "GET") === "GET" ? this.creds.language : void 0;
318
+ const url = this.engineURL(path, lang ? { lang, ...req.query } : req.query);
319
+ const headers = { Accept: "application/json", ...req.headers };
320
+ if (req.body !== void 0) headers["Content-Type"] = "application/json";
321
+ if (this.creds.store) headers["X-Store"] = this.creds.store;
322
+ if (req.auth) {
323
+ const token = sessionToken();
324
+ if (!token) throw new GoCommerceError("Please sign in to continue.", 401, "unauthorized");
325
+ headers.Authorization = `Bearer ${token}`;
326
+ }
327
+ const init = {
328
+ method: req.method ?? "GET",
329
+ headers,
330
+ body: req.body === void 0 ? void 0 : JSON.stringify(req.body)
331
+ };
332
+ let res;
333
+ try {
334
+ res = await this._fetch.call(globalThis, url, init);
335
+ } catch (cause) {
336
+ if (typeof window === "undefined" && /CORS/i.test(String(cause?.message))) {
337
+ try {
338
+ res = await globalThis.fetch(url, init);
339
+ } catch (again) {
340
+ throw unreachable(this.engineBase(), again);
341
+ }
342
+ } else {
343
+ throw unreachable(this.engineBase(), cause);
344
+ }
345
+ }
346
+ return this.unwrap(res);
347
+ }
348
+ /** The envelope opened: the payload, or the engine's error as a GoCommerceError. */
349
+ async unwrap(res) {
350
+ const text = await res.text();
351
+ let parsed = null;
352
+ if (text) {
353
+ try {
354
+ parsed = JSON.parse(text);
355
+ } catch {
356
+ throw new GoCommerceError(
357
+ `The commerce engine answered ${res.status} with something that is not JSON: ${text.slice(0, 120)}`,
358
+ res.status
359
+ );
360
+ }
361
+ }
362
+ if (!res.ok) {
363
+ const err = parsed?.error ?? {};
364
+ throw new GoCommerceError(
365
+ err.message ?? `The commerce engine answered ${res.status}.`,
366
+ res.status,
367
+ err.code,
368
+ err.details
369
+ );
370
+ }
371
+ return parsed ?? { data: null };
372
+ }
373
+ /** The bare payload, for the many callers that never look at `meta`. */
374
+ async data(path, req = {}) {
375
+ return (await this.engine(path, req)).data;
376
+ }
377
+ /**
378
+ * Prices a cart at the signed-in shopper's customer-group prices. The
379
+ * engine does this only for an account whose email is confirmed (403
380
+ * otherwise), and the cart stays the shopper's either way — so a refusal
381
+ * is not an error, and neither is a build without ext/identity.
382
+ */
383
+ async claimCartForAccount(cartId) {
384
+ try {
385
+ await this.engine("/x/identity/me/carts", { method: "POST", body: { cart_id: cartId }, auth: true });
386
+ } catch {
387
+ }
388
+ }
389
+ // ------------------------------------------------------------ Litekart verbs
390
+ /**
391
+ * The family's path-addressed verbs. An absolute URL is fetched as-is; a
392
+ * relative one is a Litekart REST path, answered from the storefront's own
393
+ * data where it has some and refused otherwise (rest-guard.ts).
394
+ */
395
+ get(path) {
396
+ return this.raw("get", path);
397
+ }
398
+ post(path, data) {
399
+ return this.raw("post", path, data);
400
+ }
401
+ put(path, data) {
402
+ return this.raw("put", path, data);
403
+ }
404
+ patch(path, data) {
405
+ return this.raw("patch", path, data);
406
+ }
407
+ delete(path) {
408
+ return this.raw("delete", path);
409
+ }
410
+ async raw(method, path, data) {
411
+ if (!/^https?:\/\//i.test(path)) return await resolveRestLocally(method, path);
412
+ const res = await this._fetch.call(globalThis, path, {
413
+ method: method.toUpperCase(),
414
+ headers: { Accept: "application/json", ...data === void 0 ? {} : { "Content-Type": "application/json" } },
415
+ body: data === void 0 ? void 0 : JSON.stringify(data)
416
+ });
417
+ const body = await res.json().catch(() => ({}));
418
+ if (!res.ok)
419
+ throw new GoCommerceError(body?.error?.message ?? `Request failed with status ${res.status}`, res.status);
420
+ return body;
421
+ }
422
+ };
423
+ var unreachable = (base, cause) => new GoCommerceError(`Could not reach the commerce engine at ${base}: ${cause?.message ?? cause}`, 0);
424
+ function qs(query) {
425
+ if (!query) return "";
426
+ const sp = new URLSearchParams();
427
+ for (const [key, value] of Object.entries(query)) {
428
+ if (value === void 0 || value === null || value === "") continue;
429
+ if (Array.isArray(value)) for (const v of value) sp.append(key, String(v));
430
+ else sp.append(key, String(value));
431
+ }
432
+ const s = sp.toString();
433
+ return s ? `?${s}` : "";
434
+ }
435
+ function toPage(env, map) {
436
+ const rows = env.data ?? [];
437
+ const meta = env.meta;
438
+ return {
439
+ data: rows.map(map),
440
+ count: meta?.total ?? rows.length,
441
+ pageSize: meta?.limit ?? rows.length,
442
+ noOfPage: meta?.total_pages ?? 1,
443
+ page: meta?.page ?? 1
444
+ };
445
+ }
446
+ var emptyPage = () => ({ data: [], count: 0, pageSize: 0, noOfPage: 0, page: 1 });
447
+
141
448
  // src/map.ts
142
449
  var str = (v) => v === null || v === void 0 ? "" : String(v);
143
450
  var arr = (v) => v ?? [];
@@ -145,7 +452,8 @@ var liveVariants = (p) => arr(p.variants).filter((v) => v.active);
145
452
  function variantImages(v) {
146
453
  const out = [];
147
454
  for (const img of [v.image, ...arr(v.images)]) {
148
- if (img?.url && (img.kind ?? "image") === "image" && !out.includes(img.url)) out.push(img.url);
455
+ const url = mediaUrl(img?.url);
456
+ if (url && (img?.kind ?? "image") === "image" && !out.includes(url)) out.push(url);
149
457
  }
150
458
  return out;
151
459
  }
@@ -154,7 +462,7 @@ function productImages(p) {
154
462
  const push = (url) => {
155
463
  if (url && !out.includes(url)) out.push(url);
156
464
  };
157
- push(p.image_url);
465
+ push(mediaUrl(p.image_url));
158
466
  for (const v of arr(p.variants)) for (const url of variantImages(v)) push(url);
159
467
  return out;
160
468
  }
@@ -284,9 +592,9 @@ function fromSearchDoc(d) {
284
592
  mrp: price,
285
593
  minPrice: price,
286
594
  maxPrice: minorToMajor(d.price_max_minor, d.currency),
287
- thumbnail: d.image ?? null,
288
- image_url: d.image ?? null,
289
- images: d.image ?? "",
595
+ thumbnail: mediaUrl(d.image),
596
+ image_url: mediaUrl(d.image),
597
+ images: mediaUrl(d.image) ?? "",
290
598
  stock: d.in_stock ? 1 : 0,
291
599
  hasStock: d.in_stock,
292
600
  // The index cannot say how much is left, only whether any is; a card
@@ -315,7 +623,7 @@ function toCategory(c) {
315
623
  level: c.depth,
316
624
  rank: c.position,
317
625
  childCount: c.child_count,
318
- thumbnail: c.metadata?.image ?? null,
626
+ thumbnail: mediaUrl(c.metadata?.image),
319
627
  description: c.metadata?.description ?? null,
320
628
  isActive: true,
321
629
  isFeatured: false,
@@ -335,7 +643,7 @@ function toCollection(c) {
335
643
  description: c.description || null,
336
644
  subTitle: null,
337
645
  rank: str(c.position),
338
- thumbnail: c.metadata?.image ?? null,
646
+ thumbnail: mediaUrl(c.metadata?.image),
339
647
  isActive: true,
340
648
  metaTitle: c.title,
341
649
  metaDescription: c.description || null,
@@ -418,7 +726,7 @@ function toCartLine(l, extra = {}) {
418
726
  title: l.title,
419
727
  name: l.title,
420
728
  slug: extra.slug ?? "",
421
- thumbnail: extra.thumbnail ?? null,
729
+ thumbnail: mediaUrl(extra.thumbnail),
422
730
  variantTitle: l.variant_label ?? "",
423
731
  qty: l.quantity,
424
732
  price: toMajor(l.unit_price),
@@ -526,8 +834,8 @@ function toOrderLine(l, currency) {
526
834
  title: l.title,
527
835
  name: l.title,
528
836
  slug: "",
529
- thumbnail: l.image_url ?? null,
530
- img: l.image_url ?? null,
837
+ thumbnail: mediaUrl(l.image_url),
838
+ img: mediaUrl(l.image_url),
531
839
  variantTitle: l.variant_label ?? "",
532
840
  qty: l.quantity,
533
841
  shippedQty: l.shipped_quantity,
@@ -627,335 +935,34 @@ function toVendor(v) {
627
935
  id: str(v.id),
628
936
  slug: v.slug,
629
937
  name: v.name,
630
- businessName: v.name,
631
- about: v.about,
632
- description: v.about,
633
- website: v.website,
634
- address: v.address,
635
- banners: [],
636
- rating: null
637
- };
638
- }
639
- function toUser(c) {
640
- const [firstName, ...rest] = (c.name ?? "").trim().split(/\s+/);
641
- return {
642
- id: str(c.id),
643
- userId: str(c.id),
644
- email: c.email,
645
- emailVerified: c.email_verified,
646
- phone: c.phone || null,
647
- firstName: firstName || "",
648
- lastName: rest.join(" "),
649
- name: c.name,
650
- fullName: c.name,
651
- avatar: null,
652
- role: "USER",
653
- createdAt: c.created_at,
654
- updatedAt: c.updated_at
655
- };
656
- }
657
- var priceOf = (m) => m ? toMajor(m) : 0;
658
-
659
- // src/browser.ts
660
- var inBrowser = () => typeof window !== "undefined" && typeof document !== "undefined";
661
- function readLocal(key) {
662
- if (!inBrowser()) return null;
663
- try {
664
- return window.localStorage.getItem(key);
665
- } catch {
666
- return null;
667
- }
668
- }
669
- function writeLocal(key, value) {
670
- if (!inBrowser()) return;
671
- try {
672
- window.localStorage.setItem(key, value);
673
- } catch {
674
- }
675
- }
676
- function removeLocal(key) {
677
- if (!inBrowser()) return;
678
- try {
679
- window.localStorage.removeItem(key);
680
- } catch {
681
- }
682
- }
683
- function readJSON(key) {
684
- const raw = readLocal(key);
685
- if (!raw) return null;
686
- try {
687
- return JSON.parse(raw);
688
- } catch {
689
- return null;
690
- }
691
- }
692
- var YEAR = 60 * 60 * 24 * 365;
693
- function setCookie(name, value, maxAge = YEAR) {
694
- if (!inBrowser()) return;
695
- document.cookie = `${name}=${value}; path=/; max-age=${maxAge}; samesite=lax`;
696
- }
697
- function clearCookie(name) {
698
- if (!inBrowser()) return;
699
- document.cookie = `${name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
700
- }
701
- function readCookie(name) {
702
- if (!inBrowser()) return null;
703
- for (const pair of document.cookie.split(";")) {
704
- const at = pair.indexOf("=");
705
- if (at < 0) continue;
706
- if (pair.slice(0, at).trim() === name) return pair.slice(at + 1).trim();
707
- }
708
- return null;
938
+ businessName: v.name,
939
+ about: v.about,
940
+ description: v.about,
941
+ website: v.website,
942
+ address: v.address,
943
+ banners: [],
944
+ rating: null
945
+ };
709
946
  }
710
- var TOKEN = "gocommerce_token";
711
- var sessionToken = () => readLocal(TOKEN);
712
- function toMe(c) {
947
+ function toUser(c) {
713
948
  const [firstName, ...rest] = (c.name ?? "").trim().split(/\s+/);
714
949
  return {
715
- id: String(c.id),
716
- userId: String(c.id),
950
+ id: str(c.id),
951
+ userId: str(c.id),
717
952
  email: c.email,
953
+ emailVerified: c.email_verified,
718
954
  phone: c.phone || null,
719
955
  firstName: firstName || "",
720
956
  lastName: rest.join(" "),
721
- name: c.name ?? "",
722
- fullName: c.name ?? "",
957
+ name: c.name,
958
+ fullName: c.name,
723
959
  avatar: null,
724
960
  role: "USER",
725
- emailVerified: c.email_verified,
726
- storeId: null
727
- };
728
- }
729
- function startSession(auth) {
730
- writeLocal(TOKEN, auth.token);
731
- const me = toMe(auth.record);
732
- const expires = Math.max(60, Math.floor((Date.parse(auth.expires_at) - Date.now()) / 1e3)) || YEAR;
733
- setCookie("me", encodeURIComponent(JSON.stringify(me)), expires);
734
- setCookie("connect.sid", "gocommerce", expires);
735
- return me;
736
- }
737
- function updateMe(c) {
738
- const me = toMe(c);
739
- setCookie("me", encodeURIComponent(JSON.stringify(me)));
740
- return me;
741
- }
742
- function endSession() {
743
- removeLocal(TOKEN);
744
- clearCookie("me");
745
- clearCookie("connect.sid");
746
- }
747
- function currentMe() {
748
- const raw = readCookie("me");
749
- if (!raw) return null;
750
- try {
751
- return JSON.parse(decodeURIComponent(raw));
752
- } catch {
753
- return null;
754
- }
755
- }
756
- function storedCartId() {
757
- const v = readLocal("cart_id");
758
- if (!v || v === "undefined" || v === "null") return null;
759
- return v;
760
- }
761
- var rememberCartId = (id2) => writeLocal("cart_id", id2);
762
- var extrasKey = (cartId) => `gocommerce_cart_${cartId}`;
763
- var cartExtras = (cartId) => readJSON(extrasKey(cartId)) ?? {};
764
- function saveCartExtras(cartId, patch) {
765
- const next = { ...cartExtras(cartId), ...patch };
766
- writeLocal(extrasKey(cartId), JSON.stringify(next));
767
- return next;
768
- }
769
- var forgetCartExtras = (cartId) => removeLocal(extrasKey(cartId));
770
- var ORDERS = "gocommerce_orders";
771
- var placedOrders = () => readJSON(ORDERS) ?? [];
772
- function rememberOrder(o) {
773
- const kept = placedOrders().filter((p) => p.number !== o.number);
774
- writeLocal(ORDERS, JSON.stringify([o, ...kept].slice(0, 50)));
775
- }
776
- var placedOrder = (number) => placedOrders().find((p) => p.number === number);
777
- var placedOrderForCart = (cartId) => placedOrders().find((p) => p.cartId === cartId);
778
- var placedOrderByReference = (reference) => placedOrders().find((p) => p.reference === reference);
779
- var WISHLIST = "gocommerce_wishlist";
780
- var wishlistToken = () => readLocal(WISHLIST);
781
- var rememberWishlistToken = (token) => writeLocal(WISHLIST, token);
782
- var forgetWishlistToken = () => removeLocal(WISHLIST);
783
-
784
- // src/services/base.service.ts
785
- var BaseService = class _BaseService {
786
- static _credentials = { apiUrl: "" };
787
- _fetch;
788
- constructor(fetchFn) {
789
- this._fetch = fetchFn ?? ((input, init) => globalThis.fetch(input, init));
790
- }
791
- static setCredentials(creds) {
792
- _BaseService._credentials = { ..._BaseService._credentials, ...creds };
793
- }
794
- static getCredentials() {
795
- return _BaseService._credentials;
796
- }
797
- get creds() {
798
- return _BaseService._credentials;
799
- }
800
- /**
801
- * The engine's base URL from wherever this code runs. In the browser a
802
- * configured proxy path wins, because the engine answers no CORS preflight.
803
- */
804
- engineBase() {
805
- const { apiUrl, proxyPath } = this.creds;
806
- if (proxyPath && typeof window !== "undefined" && window.location) {
807
- return new URL(proxyPath, window.location.origin).href.replace(/\/+$/, "");
808
- }
809
- const url = (apiUrl ?? "").trim();
810
- if (!url) {
811
- throw new GoCommerceError(
812
- "PUBLIC_GOCOMMERCE_API_URL is not set, so this storefront does not know where its commerce engine is. Point it at a running GoCommerce, e.g. http://127.0.0.1:8080.",
813
- 0
814
- );
815
- }
816
- return url.replace(/\/+$/, "");
817
- }
818
- /** An absolute engine URL for a path and query, without sending anything. */
819
- engineURL(path, query) {
820
- return this.engineBase() + path + qs(query);
821
- }
822
- /**
823
- * One request to the engine, envelope and all.
824
- *
825
- * The body is read as text first, so a proxy's HTML error page is reported
826
- * as what it is rather than as a JSON parse error three frames away.
827
- */
828
- async engine(path, req = {}) {
829
- const lang = (req.method ?? "GET") === "GET" ? this.creds.language : void 0;
830
- const url = this.engineURL(path, lang ? { lang, ...req.query } : req.query);
831
- const headers = { Accept: "application/json", ...req.headers };
832
- if (req.body !== void 0) headers["Content-Type"] = "application/json";
833
- if (this.creds.store) headers["X-Store"] = this.creds.store;
834
- if (req.auth) {
835
- const token = sessionToken();
836
- if (!token) throw new GoCommerceError("Please sign in to continue.", 401, "unauthorized");
837
- headers.Authorization = `Bearer ${token}`;
838
- }
839
- const init = {
840
- method: req.method ?? "GET",
841
- headers,
842
- body: req.body === void 0 ? void 0 : JSON.stringify(req.body)
843
- };
844
- let res;
845
- try {
846
- res = await this._fetch.call(globalThis, url, init);
847
- } catch (cause) {
848
- if (typeof window === "undefined" && /CORS/i.test(String(cause?.message))) {
849
- try {
850
- res = await globalThis.fetch(url, init);
851
- } catch (again) {
852
- throw unreachable(this.engineBase(), again);
853
- }
854
- } else {
855
- throw unreachable(this.engineBase(), cause);
856
- }
857
- }
858
- return this.unwrap(res);
859
- }
860
- /** The envelope opened: the payload, or the engine's error as a GoCommerceError. */
861
- async unwrap(res) {
862
- const text = await res.text();
863
- let parsed = null;
864
- if (text) {
865
- try {
866
- parsed = JSON.parse(text);
867
- } catch {
868
- throw new GoCommerceError(
869
- `The commerce engine answered ${res.status} with something that is not JSON: ${text.slice(0, 120)}`,
870
- res.status
871
- );
872
- }
873
- }
874
- if (!res.ok) {
875
- const err = parsed?.error ?? {};
876
- throw new GoCommerceError(
877
- err.message ?? `The commerce engine answered ${res.status}.`,
878
- res.status,
879
- err.code,
880
- err.details
881
- );
882
- }
883
- return parsed ?? { data: null };
884
- }
885
- /** The bare payload, for the many callers that never look at `meta`. */
886
- async data(path, req = {}) {
887
- return (await this.engine(path, req)).data;
888
- }
889
- /**
890
- * Prices a cart at the signed-in shopper's customer-group prices. The
891
- * engine does this only for an account whose email is confirmed (403
892
- * otherwise), and the cart stays the shopper's either way — so a refusal
893
- * is not an error, and neither is a build without ext/identity.
894
- */
895
- async claimCartForAccount(cartId) {
896
- try {
897
- await this.engine("/x/identity/me/carts", { method: "POST", body: { cart_id: cartId }, auth: true });
898
- } catch {
899
- }
900
- }
901
- // ------------------------------------------------------------ Litekart verbs
902
- /**
903
- * The family's path-addressed verbs. An absolute URL is fetched as-is; a
904
- * relative one is a Litekart REST path, answered from the storefront's own
905
- * data where it has some and refused otherwise (rest-guard.ts).
906
- */
907
- get(path) {
908
- return this.raw("get", path);
909
- }
910
- post(path, data) {
911
- return this.raw("post", path, data);
912
- }
913
- put(path, data) {
914
- return this.raw("put", path, data);
915
- }
916
- patch(path, data) {
917
- return this.raw("patch", path, data);
918
- }
919
- delete(path) {
920
- return this.raw("delete", path);
921
- }
922
- async raw(method, path, data) {
923
- if (!/^https?:\/\//i.test(path)) return await resolveRestLocally(method, path);
924
- const res = await this._fetch.call(globalThis, path, {
925
- method: method.toUpperCase(),
926
- headers: { Accept: "application/json", ...data === void 0 ? {} : { "Content-Type": "application/json" } },
927
- body: data === void 0 ? void 0 : JSON.stringify(data)
928
- });
929
- const body = await res.json().catch(() => ({}));
930
- if (!res.ok)
931
- throw new GoCommerceError(body?.error?.message ?? `Request failed with status ${res.status}`, res.status);
932
- return body;
933
- }
934
- };
935
- var unreachable = (base, cause) => new GoCommerceError(`Could not reach the commerce engine at ${base}: ${cause?.message ?? cause}`, 0);
936
- function qs(query) {
937
- if (!query) return "";
938
- const sp = new URLSearchParams();
939
- for (const [key, value] of Object.entries(query)) {
940
- if (value === void 0 || value === null || value === "") continue;
941
- if (Array.isArray(value)) for (const v of value) sp.append(key, String(v));
942
- else sp.append(key, String(value));
943
- }
944
- const s = sp.toString();
945
- return s ? `?${s}` : "";
946
- }
947
- function toPage(env, map) {
948
- const rows = env.data ?? [];
949
- const meta = env.meta;
950
- return {
951
- data: rows.map(map),
952
- count: meta?.total ?? rows.length,
953
- pageSize: meta?.limit ?? rows.length,
954
- noOfPage: meta?.total_pages ?? 1,
955
- page: meta?.page ?? 1
961
+ createdAt: c.created_at,
962
+ updatedAt: c.updated_at
956
963
  };
957
964
  }
958
- var emptyPage = () => ({ data: [], count: 0, pageSize: 0, noOfPage: 0, page: 1 });
965
+ var priceOf = (m) => m ? toMajor(m) : 0;
959
966
 
960
967
  // src/services/facts.ts
961
968
  var StoreFacts = class extends BaseService {
@@ -1973,7 +1980,7 @@ var OrderService = class extends BaseService {
1973
1980
  productId: l.product_id,
1974
1981
  variantId: l.variant_id,
1975
1982
  title: l.title,
1976
- img: l.image_url ?? null,
1983
+ img: mediaUrl(l.image_url),
1977
1984
  price: toMajor(l.unit_price),
1978
1985
  qty: l.quantity
1979
1986
  });
@@ -3159,6 +3166,7 @@ exports.galleryService = galleryService;
3159
3166
  exports.hasStaticStore = hasStaticStore;
3160
3167
  exports.homeService = homeService;
3161
3168
  exports.initService = initService;
3169
+ exports.mediaUrl = mediaUrl;
3162
3170
  exports.meilisearchService = meilisearchService;
3163
3171
  exports.menuService = menuService;
3164
3172
  exports.minorToMajor = minorToMajor;