shop-client 3.23.0 → 3.25.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.
package/README.md CHANGED
@@ -351,6 +351,8 @@ const storeInfo = await shop.getInfo();
351
351
 
352
352
  ### Products
353
353
 
354
+ - Gift cards are excluded from product responses. Any product whose `product_type` / `type` contains `"gift card"` will be skipped (and `products.find()` returns `null` for gift cards).
355
+
354
356
  #### `products.all()`
355
357
 
356
358
  Fetches all products from the store with automatic pagination handling.
@@ -359,7 +361,7 @@ Fetches all products from the store with automatic pagination handling.
359
361
  const allProducts = await shop.products.all();
360
362
  ```
361
363
 
362
- **Returns:** `ProductResult[] | null`
364
+ **Returns:** `ProductResult[] | null` (typed based on `columns`, defaults to minimal)
363
365
 
364
366
  #### `products.paginated(options)`
365
367
 
@@ -379,7 +381,7 @@ const products = await shop.products.paginated({
379
381
  - `limit` (number, optional): Products per page (default: 250, max: 250)
380
382
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']` (e.g., `"USD"`, `"EUR"`, `"JPY"`)
381
383
 
382
- **Returns:** `ProductResult[] | null`
384
+ **Returns:** `ProductResult[] | null` (typed based on `columns`, defaults to minimal)
383
385
 
384
386
  #### `products.find(handle)`
385
387
 
@@ -397,7 +399,26 @@ const productEur = await shop.products.find("product-handle", { currency: "EUR"
397
399
  - `options` (object, optional): Additional options
398
400
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']`
399
401
 
400
- **Returns:** `ProductResult | null`
402
+ **Returns:** `ProductResult | null` (typed based on `columns`, defaults to minimal)
403
+
404
+ #### `products.findEnhanced(handle, options)`
405
+
406
+ Finds a product by handle and returns the product plus AI enrichment from the worker endpoint. The `product` field is typed the same way as `products.find()` based on `columns`.
407
+
408
+ ```typescript
409
+ const enhanced = await shop.products.findEnhanced("product-handle", {
410
+ apiKey: process.env.ENRICH_API_KEY!,
411
+ columns: { mode: "full", images: "full", options: "full" },
412
+ });
413
+
414
+ if (enhanced) {
415
+ console.log(enhanced.cache); // e.g. "hit" | "miss"
416
+ console.log(enhanced.enrichment.markdown);
417
+ console.log(enhanced.product.handle); // available when mode: "full"
418
+ }
419
+ ```
420
+
421
+ **Returns:** `EnhancedProductResponse<ProductResult> | null` (typed based on `columns`)
401
422
 
402
423
  #### `products.showcased()`
403
424
 
@@ -475,7 +496,7 @@ const results = await shop.products.predictiveSearch("dress", {
475
496
  - Extracts handles from Ajax results, fetches full products via `find`
476
497
  - Falls back to non-locale path when locale returns 404/417
477
498
 
478
- **Returns:** `ProductResult[]`
499
+ **Returns:** `ProductResult[]` (typed based on `columns`, defaults to minimal)
479
500
 
480
501
  ### Recommendations
481
502
 
@@ -497,7 +518,7 @@ const recos = await shop.products.recommendations(1234567890, {
497
518
 
498
519
  ### Product Columns
499
520
 
500
- Default product payload is minimal. Use `columns` to override the product payload shape (full vs minimal):
521
+ Default product payload is minimal. Use `columns` to override the product payload shape, and TypeScript will reflect the shape in the returned type:
501
522
 
502
523
  ```typescript
503
524
  // Minimal products (default)
@@ -514,6 +535,11 @@ const minimalOne = await shop.products.find("product-handle", {
514
535
  });
515
536
  ```
516
537
 
538
+ Quick mental model:
539
+ - `mode: "minimal"` returns a minimal product shape (no `handle`, no `priceMin/priceMax`, no `currency` field)
540
+ - `mode: "full"` returns a full product shape (includes `handle`, pricing range fields, `currency`, variants, etc.)
541
+ - `images: "full"` and `options: "full"` expand those subfields while keeping the chosen `mode`
542
+
517
543
  ### Collections
518
544
 
519
545
  #### `collections.all()`
@@ -568,6 +594,8 @@ const collectionsPage = await shop.collections.paginated({
568
594
 
569
595
  ### Collection Products
570
596
 
597
+ - Gift cards are excluded from collection product responses (same rules as `Products`).
598
+
571
599
  #### `collections.products.all(handle)`
572
600
 
573
601
  Fetches all products from a specific collection.
@@ -579,7 +607,7 @@ const products = await shop.collections.products.all("collection-handle");
579
607
  **Parameters:**
580
608
  - `handle` (string): The collection handle
581
609
 
582
- **Returns:** `ProductResult[] | null`
610
+ **Returns:** `ProductResult[] | null` (typed based on `columns`, defaults to minimal)
583
611
 
584
612
  #### `collections.products.paginated(handle, options)`
585
613
 
@@ -600,7 +628,7 @@ const products = await shop.collections.products.paginated("collection-handle",
600
628
  - `limit` (number, optional): Products per page (default: 250)
601
629
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']`
602
630
 
603
- **Returns:** `ProductResult[] | null`
631
+ **Returns:** `ProductResult[] | null` (typed based on `columns`, defaults to minimal)
604
632
 
605
633
  Collection products also default to minimal. To request full products from collections, pass `columns`:
606
634
 
@@ -616,6 +644,7 @@ By default, pricing is formatted using the store’s detected currency.
616
644
  You can override the currency for product and collection queries by passing a `currency` option.
617
645
  This override updates pricing display fields only:
618
646
  - `ProductResult.localizedPricing` formatted strings
647
+ - For full products (`mode: "full"`), `ProductResult.currency` is also set to the override
619
648
 
620
649
  ### Showcased Products
621
650
 
@@ -899,7 +928,9 @@ type Product = {
899
928
  sellingPlanGroups?: unknown;
900
929
  // Keys formatted as name#value parts joined by '##' (alphabetically sorted), e.g., "color#blue##size#xl"
901
930
  variantOptionsMap: Record<string, string>;
931
+ variantPriceMap: Record<string, number>;
902
932
  };
933
+ ```
903
934
 
904
935
  #### Date Handling
905
936
 
@@ -909,9 +940,19 @@ type Product = {
909
940
  #### Variant Options Map
910
941
 
911
942
  - Each product includes `variantOptionsMap: Record<string, string>` when variants are present.
943
+ - Each product includes `variantPriceMap: Record<string, number>` using the same keys; values are prices in cents.
912
944
  - Keys are composed of normalized option name/value pairs in the form `name#value`, joined by `##` and sorted alphabetically for stability.
913
945
  - Example: `{ "color#blue##size#xl": "123", "color#red##size#m": "456" }`.
914
946
  - Normalization uses `normalizeKey` (lowercases; spaces → `_`; non-space separators like `-` remain intact).
947
+
948
+ Generate keys using `buildVariantKey` (exported from the main entrypoint):
949
+
950
+ ```typescript
951
+ import { buildVariantKey } from "shop-client";
952
+
953
+ const key = buildVariantKey({ Size: "XL", Color: "Blue" }); // "color#blue##size#xl"
954
+ const variantId = product.variantOptionsMap[key];
955
+ const priceInCents = product.variantPriceMap[key];
915
956
  ```
916
957
 
917
958
  ### ProductVariant
@@ -1,4 +1,4 @@
1
- import { O as OpenRouterConfig, n as ProductClassification, o as SEOContent, p as SystemUserPrompt, b as ShopifySingleProduct } from '../types-C0NvqVL-.js';
1
+ import { O as OpenRouterConfig, q as ProductClassification, r as SEOContent, s as SystemUserPrompt, e as ShopifySingleProduct } from '../types-CpduFbl-.js';
2
2
 
3
3
  declare function buildEnrichPrompt(args: {
4
4
  bodyInput: string;
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4GPP2KXF.mjs";
4
4
  import {
5
5
  formatPrice
6
- } from "./chunk-U3RQRBXZ.mjs";
6
+ } from "./chunk-YIDIKN7A.mjs";
7
7
 
8
8
  // src/products.ts
9
9
  import { filter, isNonNullish } from "remeda";
@@ -21,12 +21,10 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
21
21
  findCache.set(key, { ts: Date.now(), value });
22
22
  };
23
23
  function applyCurrencyOverride(product, currency) {
24
- var _a, _b, _c, _d, _e;
25
24
  if ("priceMin" in product) {
26
- const p = product;
27
- const priceMin = typeof p.priceMin === "number" ? p.priceMin : (_a = p.price) != null ? _a : 0;
28
- const priceMax = typeof p.priceMax === "number" ? p.priceMax : (_b = p.price) != null ? _b : 0;
29
- const compareAtMin = typeof p.compareAtPriceMin === "number" ? p.compareAtPriceMin : (_c = p.compareAtPrice) != null ? _c : 0;
25
+ const priceMin = product.priceMin;
26
+ const priceMax = product.priceMax;
27
+ const compareAtMin = product.compareAtPriceMin;
30
28
  return {
31
29
  ...product,
32
30
  currency,
@@ -39,12 +37,11 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
39
37
  }
40
38
  };
41
39
  }
42
- const compareAtPrice = (_d = product.compareAtPrice) != null ? _d : 0;
43
40
  return {
44
41
  ...product,
45
42
  localizedPricing: {
46
- priceFormatted: formatPrice((_e = product.price) != null ? _e : 0, currency),
47
- compareAtPriceFormatted: formatPrice(compareAtPrice, currency)
43
+ priceFormatted: formatPrice(product.price, currency),
44
+ compareAtPriceFormatted: formatPrice(product.compareAtPrice, currency)
48
45
  }
49
46
  };
50
47
  }
@@ -61,6 +58,13 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
61
58
  options: (_f = (_e = override == null ? void 0 : override.options) != null ? _e : base.options) != null ? _f : "minimal"
62
59
  };
63
60
  };
61
+ const isGiftCardType = (value) => {
62
+ if (typeof value !== "string") return false;
63
+ const s = value.trim().toLowerCase();
64
+ if (!s) return false;
65
+ if (s === "gift card" || s === "giftcard") return true;
66
+ return s.includes("gift card") || s.includes("giftcard");
67
+ };
64
68
  async function allInternal(options) {
65
69
  const limit = 250;
66
70
  const allProducts = [];
@@ -68,16 +72,23 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
68
72
  async function fetchAll() {
69
73
  let currentPage = 1;
70
74
  while (true) {
71
- const products = await fetchProducts(currentPage, limit, {
72
- columns
75
+ const url = `${baseUrl}products.json?page=${currentPage}&limit=${limit}`;
76
+ const response = await rateLimitedFetch(url, {
77
+ rateLimitClass: "products:list"
73
78
  });
74
- if (!products || products.length === 0 || products.length < limit) {
75
- if (products && products.length > 0) {
76
- allProducts.push(...products);
77
- }
79
+ if (!response.ok) {
80
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
81
+ }
82
+ const data = await response.json();
83
+ const rawProducts = Array.isArray(data.products) ? data.products : [];
84
+ const filteredRawProducts = rawProducts.filter(
85
+ (p) => !isGiftCardType(p.product_type)
86
+ );
87
+ const normalized = productsDto(filteredRawProducts, { columns }) || [];
88
+ allProducts.push(...normalized);
89
+ if (rawProducts.length === 0 || rawProducts.length < limit) {
78
90
  break;
79
91
  }
80
- allProducts.push(...products);
81
92
  currentPage++;
82
93
  }
83
94
  return allProducts;
@@ -107,10 +118,14 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
107
118
  throw new Error(`HTTP error! status: ${response.status}`);
108
119
  }
109
120
  const data = await response.json();
110
- if (data.products.length === 0) {
121
+ const rawProducts = Array.isArray(data.products) ? data.products : [];
122
+ const filteredRawProducts = rawProducts.filter(
123
+ (p) => !isGiftCardType(p.product_type)
124
+ );
125
+ if (rawProducts.length === 0) {
111
126
  return [];
112
127
  }
113
- const normalized = productsDto(data.products, {
128
+ const normalized = productsDto(filteredRawProducts, {
114
129
  columns
115
130
  });
116
131
  return maybeOverrideProductsCurrency(
@@ -184,6 +199,14 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
184
199
  throw new Error(`HTTP error! status: ${response.status}`);
185
200
  }
186
201
  const product = await response.json();
202
+ if (isGiftCardType(product.type)) {
203
+ setCached(cacheKey, null);
204
+ if (finalHandle !== sanitizedHandle) {
205
+ const finalKey = `${finalHandle}|${columns.mode}|${columns.images}|${columns.options}`;
206
+ setCached(finalKey, null);
207
+ }
208
+ return null;
209
+ }
187
210
  const productData = productDto(product, { columns });
188
211
  setCached(cacheKey, productData);
189
212
  if (finalHandle !== sanitizedHandle) {
@@ -232,15 +255,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
232
255
  }
233
256
  const data = await resp.json();
234
257
  const raw = (_d = (_c = (_b = data == null ? void 0 : data.resources) == null ? void 0 : _b.results) == null ? void 0 : _c.products) != null ? _d : [];
235
- const handles = raw.filter((p) => p.available !== false).map((p) => p.handle).filter((h) => typeof h === "string" && h.length > 0).slice(0, limit);
258
+ const handles = raw.filter((p) => p.available !== false && !isGiftCardType(p.type)).map((p) => p.handle).filter((h) => typeof h === "string" && h.length > 0).slice(0, limit);
236
259
  const fetched = await Promise.all(
237
260
  handles.map((h) => findInternal(h, { columns }))
238
261
  );
239
262
  const results = filter(fetched, isNonNullish);
240
- return (_e = maybeOverrideProductsCurrency(
241
- results,
242
- options.currency
243
- )) != null ? _e : [];
263
+ return (_e = maybeOverrideProductsCurrency(results, options.currency)) != null ? _e : [];
244
264
  }
245
265
  async function recommendationsInternal(productId, options) {
246
266
  var _a, _b;
@@ -267,11 +287,11 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
267
287
  const data = await resp.json();
268
288
  const isRecord = (v) => typeof v === "object" && v !== null;
269
289
  const productsArray = Array.isArray(data) ? data : isRecord(data) && Array.isArray(data.products) ? data.products : [];
270
- const normalized = productsDto(productsArray, { columns }) || [];
271
- return maybeOverrideProductsCurrency(
272
- normalized,
273
- options.currency
290
+ const filtered = productsArray.filter(
291
+ (p) => !isGiftCardType(p.product_type)
274
292
  );
293
+ const normalized = productsDto(filtered, { columns }) || [];
294
+ return maybeOverrideProductsCurrency(normalized, options.currency);
275
295
  }
276
296
  async function findEnhancedInternal(productHandle, options) {
277
297
  var _a;
@@ -279,12 +299,11 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
279
299
  if (!apiKey || typeof apiKey !== "string" || !apiKey.trim()) {
280
300
  throw new Error("apiKey is required");
281
301
  }
282
- const updatedAt = options.updatedAt;
283
302
  let updatedAtTrimmed;
284
- if (typeof updatedAt === "string") {
285
- const trimmed = updatedAt.trim();
303
+ if (typeof options.updatedAt === "string") {
304
+ const trimmed = options.updatedAt.trim();
286
305
  updatedAtTrimmed = trimmed ? trimmed : void 0;
287
- } else if (updatedAt != null) {
306
+ } else if (options.updatedAt != null) {
288
307
  throw new Error("updatedAt must be a string");
289
308
  }
290
309
  const columns = resolveColumns(options.columns);
@@ -358,12 +377,26 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
358
377
  const raw = parsed.shopify;
359
378
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
360
379
  if ("body_html" in raw) {
380
+ if (isGiftCardType(raw.product_type)) {
381
+ return {
382
+ enrichment: parsed.enrichment,
383
+ cache: parsed.cache,
384
+ product: mappedProduct
385
+ };
386
+ }
361
387
  const mapped = productsDto([raw], {
362
388
  columns
363
389
  });
364
390
  const first = Array.isArray(mapped) ? mapped[0] : null;
365
391
  if (first) mappedProduct = first;
366
392
  } else if ("description" in raw) {
393
+ if (isGiftCardType(raw.type)) {
394
+ return {
395
+ enrichment: parsed.enrichment,
396
+ cache: parsed.cache,
397
+ product: mappedProduct
398
+ };
399
+ }
367
400
  mappedProduct = productDto(raw, {
368
401
  columns
369
402
  });
@@ -396,10 +429,13 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
396
429
  * });
397
430
  * ```
398
431
  */
399
- all: async (options) => allInternal({
400
- currency: options == null ? void 0 : options.currency,
401
- columns: options == null ? void 0 : options.columns
402
- }),
432
+ all: async (options) => {
433
+ const res = await allInternal({
434
+ currency: options == null ? void 0 : options.currency,
435
+ columns: options == null ? void 0 : options.columns
436
+ });
437
+ return res;
438
+ },
403
439
  /**
404
440
  * Fetches products with pagination support.
405
441
  *
@@ -422,12 +458,15 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
422
458
  * const secondPage = await shop.products.paginated({ page: 2, limit: 50 });
423
459
  * ```
424
460
  */
425
- paginated: async (options) => paginatedInternal({
426
- page: options == null ? void 0 : options.page,
427
- limit: options == null ? void 0 : options.limit,
428
- currency: options == null ? void 0 : options.currency,
429
- columns: options == null ? void 0 : options.columns
430
- }),
461
+ paginated: async (options) => {
462
+ const res = await paginatedInternal({
463
+ page: options == null ? void 0 : options.page,
464
+ limit: options == null ? void 0 : options.limit,
465
+ currency: options == null ? void 0 : options.currency,
466
+ columns: options == null ? void 0 : options.columns
467
+ });
468
+ return res;
469
+ },
431
470
  /**
432
471
  * Finds a specific product by its handle.
433
472
  *
@@ -453,10 +492,13 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
453
492
  * const productWithVariant = await shop.products.find('t-shirt?variant=123');
454
493
  * ```
455
494
  */
456
- find: async (productHandle, options) => findInternal(productHandle, {
457
- currency: options == null ? void 0 : options.currency,
458
- columns: options == null ? void 0 : options.columns
459
- }),
495
+ find: async (productHandle, options) => {
496
+ const res = await findInternal(productHandle, {
497
+ currency: options == null ? void 0 : options.currency,
498
+ columns: options == null ? void 0 : options.columns
499
+ });
500
+ return res;
501
+ },
460
502
  findEnhanced: async (productHandle, options) => findEnhancedInternal(productHandle, options),
461
503
  /**
462
504
  * Enrich a product by generating merged markdown from body_html and product page.
@@ -466,9 +508,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
466
508
  if (!productHandle || typeof productHandle !== "string") {
467
509
  throw new Error("Product handle is required and must be a string");
468
510
  }
469
- const baseProduct = await findInternal(productHandle, {
470
- columns: { mode: "full", images: "full", options: "full" }
471
- });
511
+ const baseProduct = await findInternal(
512
+ productHandle,
513
+ {
514
+ columns: { mode: "full", images: "full", options: "full" }
515
+ }
516
+ );
472
517
  if (!baseProduct) return null;
473
518
  const handle = baseProduct.handle;
474
519
  const { enrichProduct } = await import("./ai/enrich.mjs");
@@ -490,9 +535,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
490
535
  if (!productHandle || typeof productHandle !== "string") {
491
536
  throw new Error("Product handle is required and must be a string");
492
537
  }
493
- const baseProduct = await findInternal(productHandle, {
494
- columns: { mode: "full", images: "full", options: "full" }
495
- });
538
+ const baseProduct = await findInternal(
539
+ productHandle,
540
+ {
541
+ columns: { mode: "full", images: "full", options: "full" }
542
+ }
543
+ );
496
544
  if (!baseProduct) throw new Error("Product not found");
497
545
  const handle = baseProduct.handle;
498
546
  const { buildEnrichPromptForProduct } = await import("./ai/enrich.mjs");
@@ -546,9 +594,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
546
594
  if (!productHandle || typeof productHandle !== "string") {
547
595
  throw new Error("Product handle is required and must be a string");
548
596
  }
549
- const baseProduct = await findInternal(productHandle, {
550
- columns: { mode: "full", images: "full", options: "full" }
551
- });
597
+ const baseProduct = await findInternal(
598
+ productHandle,
599
+ {
600
+ columns: { mode: "full", images: "full", options: "full" }
601
+ }
602
+ );
552
603
  if (!baseProduct) throw new Error("Product not found");
553
604
  const handle = baseProduct.handle;
554
605
  const { buildClassifyPromptForProduct } = await import("./ai/enrich.mjs");
@@ -562,9 +613,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
562
613
  if (!productHandle || typeof productHandle !== "string") {
563
614
  throw new Error("Product handle is required and must be a string");
564
615
  }
565
- const baseProduct = await findInternal(productHandle, {
566
- columns: { mode: "full", images: "full", options: "full" }
567
- });
616
+ const baseProduct = await findInternal(
617
+ productHandle,
618
+ {
619
+ columns: { mode: "full", images: "full", options: "full" }
620
+ }
621
+ );
568
622
  if (!baseProduct) return null;
569
623
  const payload = {
570
624
  title: baseProduct.title,
@@ -606,9 +660,12 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
606
660
  if (content) {
607
661
  return extractMainSection(content);
608
662
  }
609
- const baseProduct = await findInternal(productHandle, {
610
- columns: { mode: "full", images: "full", options: "full" }
611
- });
663
+ const baseProduct = await findInternal(
664
+ productHandle,
665
+ {
666
+ columns: { mode: "full", images: "full", options: "full" }
667
+ }
668
+ );
612
669
  if (!baseProduct) return null;
613
670
  const pageHtml = await fetchProductPage(storeDomain, baseProduct.handle);
614
671
  return extractMainSection(pageHtml);
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4GPP2KXF.mjs";
4
4
  import {
5
5
  formatPrice
6
- } from "./chunk-U3RQRBXZ.mjs";
6
+ } from "./chunk-YIDIKN7A.mjs";
7
7
 
8
8
  // src/collections.ts
9
9
  import { filter, isNonNullish } from "remeda";
@@ -21,12 +21,10 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
21
21
  findCache.set(key, { ts: Date.now(), value });
22
22
  };
23
23
  function applyCurrencyOverride(product, currency) {
24
- var _a, _b, _c, _d, _e;
25
24
  if ("priceMin" in product) {
26
- const p = product;
27
- const priceMin = typeof p.priceMin === "number" ? p.priceMin : (_a = p.price) != null ? _a : 0;
28
- const priceMax = typeof p.priceMax === "number" ? p.priceMax : (_b = p.price) != null ? _b : 0;
29
- const compareAtMin = typeof p.compareAtPriceMin === "number" ? p.compareAtPriceMin : (_c = p.compareAtPrice) != null ? _c : 0;
25
+ const priceMin = product.priceMin;
26
+ const priceMax = product.priceMax;
27
+ const compareAtMin = product.compareAtPriceMin;
30
28
  return {
31
29
  ...product,
32
30
  currency,
@@ -39,12 +37,11 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
39
37
  }
40
38
  };
41
39
  }
42
- const compareAtPrice = (_d = product.compareAtPrice) != null ? _d : 0;
43
40
  return {
44
41
  ...product,
45
42
  localizedPricing: {
46
- priceFormatted: formatPrice((_e = product.price) != null ? _e : 0, currency),
47
- compareAtPriceFormatted: formatPrice(compareAtPrice, currency)
43
+ priceFormatted: formatPrice(product.price, currency),
44
+ compareAtPriceFormatted: formatPrice(product.compareAtPrice, currency)
48
45
  }
49
46
  };
50
47
  }
@@ -8,7 +8,7 @@ import {
8
8
  extractDomainWithoutSuffix,
9
9
  generateStoreSlug,
10
10
  sanitizeDomain
11
- } from "./chunk-U3RQRBXZ.mjs";
11
+ } from "./chunk-YIDIKN7A.mjs";
12
12
 
13
13
  // src/client/get-info.ts
14
14
  import { unique } from "remeda";
@@ -110,6 +110,35 @@ function buildVariantOptionsMap(optionNames, variants) {
110
110
  }
111
111
  return map;
112
112
  }
113
+ function buildVariantPriceMap(optionNames, variants) {
114
+ const toCents = (value) => {
115
+ if (typeof value === "number" && Number.isFinite(value)) return value;
116
+ if (typeof value === "string") {
117
+ const n = Number.parseFloat(value);
118
+ return Number.isFinite(n) ? Math.round(n * 100) : 0;
119
+ }
120
+ return 0;
121
+ };
122
+ const keys = optionNames.map(normalizeKey);
123
+ const map = {};
124
+ for (const v of variants) {
125
+ const parts = [];
126
+ if (keys[0] && v.option1)
127
+ parts.push(`${keys[0]}#${normalizeKey(v.option1)}`);
128
+ if (keys[1] && v.option2)
129
+ parts.push(`${keys[1]}#${normalizeKey(v.option2)}`);
130
+ if (keys[2] && v.option3)
131
+ parts.push(`${keys[2]}#${normalizeKey(v.option3)}`);
132
+ if (parts.length > 0) {
133
+ if (parts.length > 1) parts.sort();
134
+ const key = parts.join("##");
135
+ if (map[key] === void 0) {
136
+ map[key] = toCents(v.price);
137
+ }
138
+ }
139
+ }
140
+ return map;
141
+ }
113
142
  function buildVariantKey(obj) {
114
143
  const parts = [];
115
144
  for (const [name, value] of Object.entries(obj)) {
@@ -142,6 +171,7 @@ export {
142
171
  safeParseDate,
143
172
  normalizeKey,
144
173
  buildVariantOptionsMap,
174
+ buildVariantPriceMap,
145
175
  buildVariantKey,
146
176
  formatPrice
147
177
  };
@@ -1,5 +1,5 @@
1
1
  import { ShopInfo } from './store.js';
2
- import { d as Collection, h as CurrencyCode, P as ProductColumnsConfig, a as ProductResult, c as ShopifyCollection } from './types-C0NvqVL-.js';
2
+ import { g as Collection, a as ProductColumnsMode, b as ProductImagesMode, c as ProductOptionsMode, k as CurrencyCode, P as ProductColumnsConfig, d as ProductResult, f as ShopifyCollection } from './types-CpduFbl-.js';
3
3
 
4
4
  /**
5
5
  * Interface for collection operations
@@ -37,19 +37,19 @@ interface CollectionOperations {
37
37
  /**
38
38
  * Fetches products from a specific collection with pagination support.
39
39
  */
40
- paginated(collectionHandle: string, options?: {
40
+ paginated<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(collectionHandle: string, options?: {
41
41
  page?: number;
42
42
  limit?: number;
43
43
  currency?: CurrencyCode;
44
- columns?: ProductColumnsConfig;
45
- }): Promise<ProductResult[] | null>;
44
+ columns?: ProductColumnsConfig<C, I, O>;
45
+ }): Promise<ProductResult<C, I, O>[] | null>;
46
46
  /**
47
47
  * Fetches all products from a specific collection.
48
48
  */
49
- all(collectionHandle: string, options?: {
49
+ all<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(collectionHandle: string, options?: {
50
50
  currency?: CurrencyCode;
51
- columns?: ProductColumnsConfig;
52
- }): Promise<ProductResult[] | null>;
51
+ columns?: ProductColumnsConfig<C, I, O>;
52
+ }): Promise<ProductResult<C, I, O>[] | null>;
53
53
  /**
54
54
  * Fetches all product slugs from a specific collection.
55
55
  */
@@ -59,10 +59,10 @@ interface CollectionOperations {
59
59
  /**
60
60
  * Creates collection operations for a store instance
61
61
  */
62
- declare function createCollectionOperations(baseUrl: string, storeDomain: string, fetchCollections: (page: number, limit: number) => Promise<Collection[] | null>, collectionsDto: (collections: ShopifyCollection[]) => Collection[], fetchPaginatedProductsFromCollection: (collectionHandle: string, options?: {
62
+ declare function createCollectionOperations(baseUrl: string, storeDomain: string, fetchCollections: (page: number, limit: number) => Promise<Collection[] | null>, collectionsDto: (collections: ShopifyCollection[]) => Collection[], fetchPaginatedProductsFromCollection: <C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(collectionHandle: string, options?: {
63
63
  page?: number;
64
64
  limit?: number;
65
- columns?: ProductColumnsConfig;
66
- }) => Promise<ProductResult[] | null>, getStoreInfo: () => Promise<ShopInfo>, findCollection: (handle: string) => Promise<Collection | null>): CollectionOperations;
65
+ columns?: ProductColumnsConfig<C, I, O>;
66
+ }) => Promise<ProductResult<C, I, O>[] | null>, getStoreInfo: () => Promise<ShopInfo>, findCollection: (handle: string) => Promise<Collection | null>): CollectionOperations;
67
67
 
68
68
  export { type CollectionOperations, createCollectionOperations };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createCollectionOperations
3
- } from "./chunk-LAJWR2GQ.mjs";
3
+ } from "./chunk-RWIOOEQS.mjs";
4
4
  import "./chunk-4GPP2KXF.mjs";
5
- import "./chunk-U3RQRBXZ.mjs";
5
+ import "./chunk-YIDIKN7A.mjs";
6
6
  export {
7
7
  createCollectionOperations
8
8
  };
package/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { O as OpenRouterConfig, P as ProductColumnsConfig, C as CollectionColumnsConfig, S as ShopifyProduct, a as ProductResult, b as ShopifySingleProduct, c as ShopifyCollection, d as Collection, J as JsonLdEntry, e as StoreTypeBreakdown } from './types-C0NvqVL-.js';
2
- export { f as CountryDetectionResult, g as CountryScores, h as CurrencyCode, L as LocalizedPricing, M as MetaTag, i as Product, j as ProductImage, k as ProductOption, l as ProductVariant, m as ProductVariantImage } from './types-C0NvqVL-.js';
1
+ import { O as OpenRouterConfig, P as ProductColumnsConfig, C as CollectionColumnsConfig, a as ProductColumnsMode, b as ProductImagesMode, c as ProductOptionsMode, S as ShopifyProduct, d as ProductResult, e as ShopifySingleProduct, f as ShopifyCollection, g as Collection, J as JsonLdEntry, h as StoreTypeBreakdown } from './types-CpduFbl-.js';
2
+ export { i as CountryDetectionResult, j as CountryScores, k as CurrencyCode, L as LocalizedPricing, M as MetaTag, l as Product, m as ProductImage, n as ProductOption, o as ProductVariant, p as ProductVariantImage } from './types-CpduFbl-.js';
3
3
  import { CheckoutOperations } from './checkout.js';
4
4
  import { CollectionOperations } from './collections.js';
5
5
  import { ProductOperations } from './products.js';
6
6
  import { ShopOperations, ShopInfo, OpenGraphMeta } from './store.js';
7
7
  export { classifyProduct, generateSEOContent } from './ai/enrich.js';
8
8
  export { detectShopCountry } from './utils/detect-country.js';
9
- export { calculateDiscount, extractDomainWithoutSuffix, genProductSlug, generateStoreSlug, safeParseDate, sanitizeDomain } from './utils/func.js';
9
+ export { buildVariantKey, calculateDiscount, extractDomainWithoutSuffix, genProductSlug, generateStoreSlug, safeParseDate, sanitizeDomain } from './utils/func.js';
10
10
  export { configureRateLimit } from './utils/rate-limit.js';
11
11
 
12
12
  /**
@@ -85,12 +85,12 @@ declare class ShopClient {
85
85
  /**
86
86
  * Transform Shopify products to our Product format
87
87
  */
88
- productsDto(products: ShopifyProduct[], options?: {
89
- columns?: ProductColumnsConfig;
90
- }): ProductResult[] | null;
91
- productDto(product: ShopifySingleProduct, options?: {
92
- columns?: ProductColumnsConfig;
93
- }): ProductResult;
88
+ productsDto<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(products: ShopifyProduct[], options?: {
89
+ columns?: ProductColumnsConfig<C, I, O>;
90
+ }): ProductResult<C, I, O>[] | null;
91
+ productDto<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(product: ShopifySingleProduct, options?: {
92
+ columns?: ProductColumnsConfig<C, I, O>;
93
+ }): ProductResult<C, I, O>;
94
94
  collectionsDto(collections: ShopifyCollection[]): Collection[];
95
95
  /**
96
96
  * Enhanced error handling with context
@@ -108,6 +108,7 @@ declare class ShopClient {
108
108
  * Fetch paginated products from a specific collection
109
109
  */
110
110
  private fetchPaginatedProductsFromCollection;
111
+ private isGiftCardProductType;
111
112
  /**
112
113
  * Validate if a product exists (with caching)
113
114
  */
package/dist/index.mjs CHANGED
@@ -3,14 +3,14 @@ import {
3
3
  } from "./chunk-W4SF6W2P.mjs";
4
4
  import {
5
5
  createCollectionOperations
6
- } from "./chunk-LAJWR2GQ.mjs";
6
+ } from "./chunk-RWIOOEQS.mjs";
7
7
  import {
8
8
  createProductOperations
9
- } from "./chunk-HEQDULXV.mjs";
9
+ } from "./chunk-ISOBE3NA.mjs";
10
10
  import {
11
11
  createShopOperations,
12
12
  getInfoForShop
13
- } from "./chunk-BNTNHHDI.mjs";
13
+ } from "./chunk-X5KZU6K4.mjs";
14
14
  import {
15
15
  classifyProduct,
16
16
  determineStoreType,
@@ -24,7 +24,9 @@ import {
24
24
  detectShopCountry
25
25
  } from "./chunk-SBHTEKLB.mjs";
26
26
  import {
27
+ buildVariantKey,
27
28
  buildVariantOptionsMap,
29
+ buildVariantPriceMap,
28
30
  calculateDiscount,
29
31
  extractDomainWithoutSuffix,
30
32
  genProductSlug,
@@ -32,7 +34,7 @@ import {
32
34
  normalizeKey,
33
35
  safeParseDate,
34
36
  sanitizeDomain
35
- } from "./chunk-U3RQRBXZ.mjs";
37
+ } from "./chunk-YIDIKN7A.mjs";
36
38
 
37
39
  // src/ai/determine-store-type.ts
38
40
  async function determineStoreTypeForStore(args) {
@@ -193,6 +195,7 @@ function mapProductsDto(products, ctx, options) {
193
195
  optionNames,
194
196
  product.variants
195
197
  );
198
+ const variantPriceMap = buildVariantPriceMap(optionNames, product.variants);
196
199
  const mappedVariants = mapVariants(product);
197
200
  const priceValues = mappedVariants.map((v) => v.price).filter((p) => typeof p === "number" && !Number.isNaN(p));
198
201
  const compareAtValues = mappedVariants.map((v) => v.compareAtPrice || 0).filter((p) => typeof p === "number" && !Number.isNaN(p));
@@ -255,6 +258,7 @@ function mapProductsDto(products, ctx, options) {
255
258
  compareAtPriceFormatted: ctx.formatPrice(compareAtMin)
256
259
  },
257
260
  variantOptionsMap,
261
+ variantPriceMap,
258
262
  url,
259
263
  slug,
260
264
  platformId: product.id.toString()
@@ -289,6 +293,7 @@ function mapProductsDto(products, ctx, options) {
289
293
  compareAtPriceFormatted: ctx.formatPrice(compareAtMin)
290
294
  },
291
295
  variantOptionsMap,
296
+ variantPriceMap,
292
297
  bodyHtml: product.body_html || null,
293
298
  active: true,
294
299
  productType: product.product_type || null,
@@ -329,6 +334,7 @@ function mapProductDto(product, ctx, options) {
329
334
  optionNames,
330
335
  product.variants
331
336
  );
337
+ const variantPriceMap = buildVariantPriceMap(optionNames, product.variants);
332
338
  const slug = genProductSlug({
333
339
  handle: product.handle,
334
340
  storeDomain: ctx.storeDomain
@@ -385,6 +391,7 @@ function mapProductDto(product, ctx, options) {
385
391
  compareAtPriceFormatted: ctx.formatPrice(product.compare_at_price || 0)
386
392
  },
387
393
  variantOptionsMap,
394
+ variantPriceMap,
388
395
  url,
389
396
  slug,
390
397
  platformId: product.id.toString()
@@ -419,6 +426,7 @@ function mapProductDto(product, ctx, options) {
419
426
  compareAtPriceFormatted: ctx.formatPrice(product.compare_at_price || 0)
420
427
  },
421
428
  variantOptionsMap,
429
+ variantPriceMap,
422
430
  bodyHtml: product.description || null,
423
431
  active: true,
424
432
  productType: product.type || null,
@@ -608,7 +616,9 @@ var ShopClient = class {
608
616
  normalizeImageUrl: (url) => this.normalizeImageUrl(url),
609
617
  formatPrice: (amount) => this.formatPrice(amount)
610
618
  },
611
- { columns: (_b = options == null ? void 0 : options.columns) != null ? _b : this.productColumns }
619
+ {
620
+ columns: (_b = options == null ? void 0 : options.columns) != null ? _b : this.productColumns
621
+ }
612
622
  );
613
623
  }
614
624
  productDto(product, options) {
@@ -622,7 +632,9 @@ var ShopClient = class {
622
632
  normalizeImageUrl: (url) => this.normalizeImageUrl(url),
623
633
  formatPrice: (amount) => this.formatPrice(amount)
624
634
  },
625
- { columns: (_b = options == null ? void 0 : options.columns) != null ? _b : this.productColumns }
635
+ {
636
+ columns: (_b = options == null ? void 0 : options.columns) != null ? _b : this.productColumns
637
+ }
626
638
  );
627
639
  }
628
640
  collectionsDto(collections) {
@@ -678,7 +690,11 @@ var ShopClient = class {
678
690
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
679
691
  }
680
692
  const data = await response.json();
681
- return this.productsDto(data.products, {
693
+ const rawProducts = Array.isArray(data.products) ? data.products : [];
694
+ const filteredRawProducts = rawProducts.filter(
695
+ (p) => !this.isGiftCardProductType(p.product_type)
696
+ );
697
+ return this.productsDto(filteredRawProducts, {
682
698
  columns: (_a = options == null ? void 0 : options.columns) != null ? _a : this.productColumns
683
699
  });
684
700
  } catch (error) {
@@ -749,7 +765,11 @@ var ShopClient = class {
749
765
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
750
766
  }
751
767
  const data = await response.json();
752
- return this.productsDto(data.products, {
768
+ const rawProducts = Array.isArray(data.products) ? data.products : [];
769
+ const filteredRawProducts = rawProducts.filter(
770
+ (p) => !this.isGiftCardProductType(p.product_type)
771
+ );
772
+ return this.productsDto(filteredRawProducts, {
753
773
  columns: (_a = options == null ? void 0 : options.columns) != null ? _a : this.productColumns
754
774
  });
755
775
  } catch (error) {
@@ -760,6 +780,13 @@ var ShopClient = class {
760
780
  );
761
781
  }
762
782
  }
783
+ isGiftCardProductType(value) {
784
+ if (typeof value !== "string") return false;
785
+ const s = value.trim().toLowerCase();
786
+ if (!s) return false;
787
+ if (s === "gift card" || s === "giftcard") return true;
788
+ return s.includes("gift card") || s.includes("giftcard");
789
+ }
763
790
  /**
764
791
  * Validate if a product exists (with caching)
765
792
  */
@@ -1009,6 +1036,7 @@ var ShopClient = class {
1009
1036
  };
1010
1037
  export {
1011
1038
  ShopClient,
1039
+ buildVariantKey,
1012
1040
  calculateDiscount,
1013
1041
  classifyProduct,
1014
1042
  configureRateLimit,
@@ -1,5 +1,5 @@
1
1
  import { ShopInfo } from './store.js';
2
- import { h as CurrencyCode, P as ProductColumnsConfig, a as ProductResult, E as EnhancedProductResponse, i as Product, n as ProductClassification, o as SEOContent, S as ShopifyProduct, b as ShopifySingleProduct, O as OpenRouterConfig } from './types-C0NvqVL-.js';
2
+ import { a as ProductColumnsMode, b as ProductImagesMode, c as ProductOptionsMode, k as CurrencyCode, P as ProductColumnsConfig, d as ProductResult, E as EnhancedProductResponse, l as Product, q as ProductClassification, r as SEOContent, S as ShopifyProduct, e as ShopifySingleProduct, O as OpenRouterConfig } from './types-CpduFbl-.js';
3
3
 
4
4
  /**
5
5
  * Interface for product operations
@@ -8,26 +8,26 @@ interface ProductOperations {
8
8
  /**
9
9
  * Fetches all products from the store across all pages.
10
10
  */
11
- all(options?: {
11
+ all<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(options?: {
12
12
  currency?: CurrencyCode;
13
- columns?: ProductColumnsConfig;
14
- }): Promise<ProductResult[] | null>;
13
+ columns?: ProductColumnsConfig<C, I, O>;
14
+ }): Promise<ProductResult<C, I, O>[] | null>;
15
15
  /**
16
16
  * Fetches products with pagination support.
17
17
  */
18
- paginated(options?: {
18
+ paginated<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(options?: {
19
19
  page?: number;
20
20
  limit?: number;
21
21
  currency?: CurrencyCode;
22
- columns?: ProductColumnsConfig;
23
- }): Promise<ProductResult[] | null>;
22
+ columns?: ProductColumnsConfig<C, I, O>;
23
+ }): Promise<ProductResult<C, I, O>[] | null>;
24
24
  /**
25
25
  * Finds a specific product by its handle.
26
26
  */
27
- find(productHandle: string, options?: {
27
+ find<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(productHandle: string, options?: {
28
28
  currency?: CurrencyCode;
29
- columns?: ProductColumnsConfig;
30
- }): Promise<ProductResult | null>;
29
+ columns?: ProductColumnsConfig<C, I, O>;
30
+ }): Promise<ProductResult<C, I, O> | null>;
31
31
  /**
32
32
  * Finds a product and enhances it with AI-generated content using an external service.
33
33
  *
@@ -37,12 +37,12 @@ interface ProductOperations {
37
37
  * @param options.updatedAt - Optional product updatedAt timestamp used to cache-bust/invalidate enrichment.
38
38
  * @param options.endpoint - Optional custom endpoint URL for the enhancement service. Defaults to the standard worker URL.
39
39
  */
40
- findEnhanced(productHandle: string, options: {
40
+ findEnhanced<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(productHandle: string, options: {
41
41
  apiKey: string;
42
42
  updatedAt?: string;
43
43
  endpoint?: string;
44
- columns?: ProductColumnsConfig;
45
- }): Promise<EnhancedProductResponse<ProductResult> | null>;
44
+ columns?: ProductColumnsConfig<C, I, O>;
45
+ }): Promise<EnhancedProductResponse<ProductResult<C, I, O>> | null>;
46
46
  /**
47
47
  * Finds a product by handle and enriches its content using LLM.
48
48
  * Requires an OpenRouter API key via options.apiKey or ShopClient options.
@@ -93,9 +93,9 @@ interface ProductOperations {
93
93
  /**
94
94
  * Fetches products that are showcased/featured on the store's homepage.
95
95
  */
96
- showcased(options?: {
97
- columns?: ProductColumnsConfig;
98
- }): Promise<ProductResult[]>;
96
+ showcased<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(options?: {
97
+ columns?: ProductColumnsConfig<C, I, O>;
98
+ }): Promise<ProductResult<C, I, O>[]>;
99
99
  /**
100
100
  * Creates a filter map of variant options and their distinct values from all products.
101
101
  */
@@ -103,36 +103,36 @@ interface ProductOperations {
103
103
  /**
104
104
  * Predictive product search using Shopify Ajax API.
105
105
  */
106
- predictiveSearch(query: string, options?: {
106
+ predictiveSearch<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(query: string, options?: {
107
107
  limit?: number;
108
108
  locale?: string;
109
109
  currency?: CurrencyCode;
110
110
  unavailableProducts?: "show" | "hide" | "last";
111
- columns?: ProductColumnsConfig;
112
- }): Promise<ProductResult[]>;
111
+ columns?: ProductColumnsConfig<C, I, O>;
112
+ }): Promise<ProductResult<C, I, O>[]>;
113
113
  /**
114
114
  * Product recommendations for a given product ID using Shopify Ajax API.
115
115
  */
116
- recommendations(productId: number, options?: {
116
+ recommendations<C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(productId: number, options?: {
117
117
  limit?: number;
118
118
  intent?: "related" | "complementary";
119
119
  locale?: string;
120
120
  currency?: CurrencyCode;
121
- columns?: ProductColumnsConfig;
122
- }): Promise<ProductResult[] | null>;
121
+ columns?: ProductColumnsConfig<C, I, O>;
122
+ }): Promise<ProductResult<C, I, O>[] | null>;
123
123
  }
124
124
  /**
125
125
  * Creates product operations for a store instance
126
126
  */
127
- declare function createProductOperations(baseUrl: string, storeDomain: string, fetchProducts: (page: number, limit: number, options?: {
128
- columns?: ProductColumnsConfig;
129
- }) => Promise<ProductResult[] | null>, productsDto: (products: ShopifyProduct[], options?: {
130
- columns?: ProductColumnsConfig;
131
- }) => ProductResult[] | null, productDto: (product: ShopifySingleProduct, options?: {
132
- columns?: ProductColumnsConfig;
133
- }) => ProductResult, getStoreInfo: () => Promise<ShopInfo>, _findProduct: (handle: string, options?: {
134
- columns?: ProductColumnsConfig;
135
- }) => Promise<ProductResult | null>, getDefaultProductColumns: () => ProductColumnsConfig, ai?: {
127
+ declare function createProductOperations(baseUrl: string, storeDomain: string, fetchProducts: <C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(page: number, limit: number, options?: {
128
+ columns?: ProductColumnsConfig<C, I, O>;
129
+ }) => Promise<ProductResult<C, I, O>[] | null>, productsDto: <C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(products: ShopifyProduct[], options?: {
130
+ columns?: ProductColumnsConfig<C, I, O>;
131
+ }) => ProductResult<C, I, O>[] | null, productDto: <C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(product: ShopifySingleProduct, options?: {
132
+ columns?: ProductColumnsConfig<C, I, O>;
133
+ }) => ProductResult<C, I, O>, getStoreInfo: () => Promise<ShopInfo>, _findProduct: <C extends ProductColumnsMode = "minimal", I extends ProductImagesMode = "minimal", O extends ProductOptionsMode = "minimal">(handle: string, options?: {
134
+ columns?: ProductColumnsConfig<C, I, O>;
135
+ }) => Promise<ProductResult<C, I, O> | null>, getDefaultProductColumns: () => ProductColumnsConfig, ai?: {
136
136
  openRouter?: OpenRouterConfig;
137
137
  }): ProductOperations;
138
138
 
package/dist/products.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  createProductOperations
3
- } from "./chunk-HEQDULXV.mjs";
3
+ } from "./chunk-ISOBE3NA.mjs";
4
4
  import "./chunk-4GPP2KXF.mjs";
5
- import "./chunk-U3RQRBXZ.mjs";
5
+ import "./chunk-YIDIKN7A.mjs";
6
6
  export {
7
7
  createProductOperations
8
8
  };
package/dist/store.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { J as JsonLdEntry, f as CountryDetectionResult, h as CurrencyCode } from './types-C0NvqVL-.js';
1
+ import { J as JsonLdEntry, i as CountryDetectionResult, k as CurrencyCode } from './types-CpduFbl-.js';
2
2
 
3
3
  /**
4
4
  * Store operations interface for managing store-related functionality.
package/dist/store.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createShopOperations
3
- } from "./chunk-BNTNHHDI.mjs";
3
+ } from "./chunk-X5KZU6K4.mjs";
4
4
  import "./chunk-4GPP2KXF.mjs";
5
5
  import "./chunk-SBHTEKLB.mjs";
6
- import "./chunk-U3RQRBXZ.mjs";
6
+ import "./chunk-YIDIKN7A.mjs";
7
7
  export {
8
8
  createShopOperations
9
9
  };
@@ -321,6 +321,7 @@ type Product = {
321
321
  requiresSellingPlan?: boolean | null;
322
322
  sellingPlanGroups?: unknown;
323
323
  variantOptionsMap: Record<string, string>;
324
+ variantPriceMap: Record<string, number>;
324
325
  enriched_content?: string;
325
326
  };
326
327
  /**
@@ -345,6 +346,7 @@ type MinimalProduct = {
345
346
  values: string[];
346
347
  }[];
347
348
  variantOptionsMap: Record<string, string>;
349
+ variantPriceMap: Record<string, number>;
348
350
  url: string;
349
351
  slug: string;
350
352
  platformId: string;
@@ -519,4 +521,4 @@ type EnhancedProductResponse<TProduct = Product> = {
519
521
  };
520
522
  type StoreTypeBreakdown = Partial<Record<"adult_male" | "adult_female" | "kid_male" | "kid_female" | "generic", Partial<Record<"clothing" | "beauty" | "accessories" | "home-decor" | "food-and-beverages", string[]>>>>;
521
523
 
522
- export type { CollectionColumnsConfig as C, EnhancedProductResponse as E, JsonLdEntry as J, LocalizedPricing as L, MetaTag as M, OpenRouterConfig as O, ProductColumnsConfig as P, ShopifyProduct as S, ProductResult as a, ShopifySingleProduct as b, ShopifyCollection as c, Collection as d, StoreTypeBreakdown as e, CountryDetectionResult as f, CountryScores as g, CurrencyCode as h, Product as i, ProductImage as j, ProductOption as k, ProductVariant as l, ProductVariantImage as m, ProductClassification as n, SEOContent as o, SystemUserPrompt as p };
524
+ export type { CollectionColumnsConfig as C, EnhancedProductResponse as E, JsonLdEntry as J, LocalizedPricing as L, MetaTag as M, OpenRouterConfig as O, ProductColumnsConfig as P, ShopifyProduct as S, ProductColumnsMode as a, ProductImagesMode as b, ProductOptionsMode as c, ProductResult as d, ShopifySingleProduct as e, ShopifyCollection as f, Collection as g, StoreTypeBreakdown as h, CountryDetectionResult as i, CountryScores as j, CurrencyCode as k, Product as l, ProductImage as m, ProductOption as n, ProductVariant as o, ProductVariantImage as p, ProductClassification as q, SEOContent as r, SystemUserPrompt as s };
@@ -1,4 +1,4 @@
1
- import { f as CountryDetectionResult } from '../types-C0NvqVL-.js';
1
+ import { i as CountryDetectionResult } from '../types-CpduFbl-.js';
2
2
 
3
3
  /**
4
4
  * Detects the country of a Shopify store by analyzing various signals in the HTML content.
@@ -1,4 +1,4 @@
1
- import { h as CurrencyCode } from '../types-C0NvqVL-.js';
1
+ import { k as CurrencyCode } from '../types-CpduFbl-.js';
2
2
 
3
3
  declare function extractDomainWithoutSuffix(domain: string): string | null;
4
4
  declare function generateStoreSlug(domain: string): string;
@@ -43,6 +43,13 @@ declare function buildVariantOptionsMap(optionNames: string[], variants: Array<{
43
43
  option2: string | null;
44
44
  option3: string | null;
45
45
  }>): Record<string, string>;
46
+ declare function buildVariantPriceMap(optionNames: string[], variants: Array<{
47
+ id: number;
48
+ option1: string | null;
49
+ option2: string | null;
50
+ option3: string | null;
51
+ price: string | number;
52
+ }>): Record<string, number>;
46
53
  /**
47
54
  * Build a normalized variant key string from an object of option name → value.
48
55
  * - Normalizes both names and values using `normalizeKey`
@@ -58,4 +65,4 @@ declare function buildVariantKey(obj: Record<string, string | null | undefined>)
58
65
  */
59
66
  declare function formatPrice(amountInCents: number, currency: CurrencyCode): string;
60
67
 
61
- export { buildVariantKey, buildVariantOptionsMap, calculateDiscount, extractDomainWithoutSuffix, formatPrice, genProductSlug, generateStoreSlug, normalizeKey, safeParseDate, sanitizeDomain };
68
+ export { buildVariantKey, buildVariantOptionsMap, buildVariantPriceMap, calculateDiscount, extractDomainWithoutSuffix, formatPrice, genProductSlug, generateStoreSlug, normalizeKey, safeParseDate, sanitizeDomain };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  buildVariantKey,
3
3
  buildVariantOptionsMap,
4
+ buildVariantPriceMap,
4
5
  calculateDiscount,
5
6
  extractDomainWithoutSuffix,
6
7
  formatPrice,
@@ -9,10 +10,11 @@ import {
9
10
  normalizeKey,
10
11
  safeParseDate,
11
12
  sanitizeDomain
12
- } from "../chunk-U3RQRBXZ.mjs";
13
+ } from "../chunk-YIDIKN7A.mjs";
13
14
  export {
14
15
  buildVariantKey,
15
16
  buildVariantOptionsMap,
17
+ buildVariantPriceMap,
16
18
  calculateDiscount,
17
19
  extractDomainWithoutSuffix,
18
20
  formatPrice,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shop-client",
3
- "version": "3.23.0",
3
+ "version": "3.25.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.mjs",