shop-client 3.16.0 → 3.17.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
@@ -359,7 +359,7 @@ Fetches all products from the store with automatic pagination handling.
359
359
  const allProducts = await shop.products.all();
360
360
  ```
361
361
 
362
- **Returns:** `Product[]` - Array of all products in the store
362
+ **Returns:** `Product[] | null`
363
363
 
364
364
  #### `products.paginated(options)`
365
365
 
@@ -379,7 +379,7 @@ const products = await shop.products.paginated({
379
379
  - `limit` (number, optional): Products per page (default: 250, max: 250)
380
380
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']` (e.g., `"USD"`, `"EUR"`, `"JPY"`)
381
381
 
382
- **Returns:** `Product[]` - Array of products for the specified page
382
+ **Returns:** `Product[] | null`
383
383
 
384
384
  #### `products.find(handle)`
385
385
 
@@ -397,7 +397,7 @@ const productEur = await shop.products.find("product-handle", { currency: "EUR"
397
397
  - `options` (object, optional): Additional options
398
398
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']`
399
399
 
400
- **Returns:** `Product | null` - Product object or null if not found
400
+ **Returns:** `Product | null`
401
401
 
402
402
  #### `products.showcased()`
403
403
 
@@ -407,7 +407,7 @@ Fetches products featured on the store's homepage.
407
407
  const showcasedProducts = await shop.products.showcased();
408
408
  ```
409
409
 
410
- **Returns:** `Product[]` - Array of featured products
410
+ **Returns:** `Product[]`
411
411
 
412
412
  #### `products.infoHtml(productHandle, content?)`
413
413
 
@@ -475,6 +475,8 @@ const results = await shop.products.predictiveSearch("dress", {
475
475
  - Extracts handles from Ajax results, fetches full products via `find`
476
476
  - Falls back to non-locale path when locale returns 404/417
477
477
 
478
+ **Returns:** `Product[]`
479
+
478
480
  ### Recommendations
479
481
 
480
482
  #### `products.recommendations(productId, options?)`
@@ -493,6 +495,30 @@ const recos = await shop.products.recommendations(1234567890, {
493
495
  - Returns normalized `Product[]`
494
496
  - Locale-aware endpoint `/{locale}/recommendations/products.json`
495
497
 
498
+ ### Minimal Products
499
+
500
+ Convenience methods for minimal product returns:
501
+
502
+ ```typescript
503
+ // All products (minimal)
504
+ const minimalAll = await shop.products.minimal.all();
505
+
506
+ // Paginated (minimal)
507
+ const minimalPage = await shop.products.minimal.paginated({ page: 1, limit: 25 });
508
+
509
+ // Find one (minimal)
510
+ const minimalOne = await shop.products.minimal.find("product-handle");
511
+
512
+ // Showcased (minimal)
513
+ const minimalShowcased = await shop.products.showcase.minimal();
514
+
515
+ // Predictive search (minimal)
516
+ const minimalSearch = await shop.products.minimal.predictiveSearch("dress", { limit: 10 });
517
+
518
+ // Recommendations (minimal)
519
+ const minimalRecos = await shop.products.minimal.recommendations(1234567890, { limit: 6 });
520
+ ```
521
+
496
522
  ### Collections
497
523
 
498
524
  #### `collections.all()`
@@ -558,7 +584,7 @@ const products = await shop.collections.products.all("collection-handle");
558
584
  **Parameters:**
559
585
  - `handle` (string): The collection handle
560
586
 
561
- **Returns:** `Product[] | null` - Array of products in the collection
587
+ **Returns:** `Product[] | null`
562
588
 
563
589
  #### `collections.products.paginated(handle, options)`
564
590
 
@@ -579,13 +605,52 @@ const products = await shop.collections.products.paginated("collection-handle",
579
605
  - `limit` (number, optional): Products per page (default: 250)
580
606
  - `currency` (CurrencyCode, optional): ISO 4217 code aligned with `Intl.NumberFormatOptions['currency']`
581
607
 
582
- **Returns:** `Product[]` - Array of products for the specified page
608
+ **Returns:** `Product[] | null`
609
+
610
+ #### `collections.products.minimal.*`
611
+
612
+ Convenience methods for minimal product returns from collections:
613
+
614
+ ```typescript
615
+ // All products (minimal)
616
+ const minimalCollectionAll = await shop.collections.products.minimal.all("collection-handle");
617
+
618
+ // Paginated (minimal)
619
+ const minimalCollectionPage = await shop.collections.products.minimal.paginated("collection-handle", {
620
+ page: 1,
621
+ limit: 25,
622
+ });
623
+ ```
583
624
 
584
625
  #### Currency Override
585
626
 
586
627
  By default, pricing is formatted using the store’s detected currency.
587
628
  You can override the currency for product and collection queries by passing a `currency` option.
588
- This override updates `Product.currency` and `Product.localizedPricing.currency` (and related formatted strings) only.
629
+ This override updates product pricing display fields only:
630
+ - `Product.localizedPricing` formatted strings
631
+ - `MinimalProduct.localizedPricing` formatted strings
632
+
633
+ ### Showcased Products
634
+
635
+ #### `products.showcased()`
636
+
637
+ Fetches products showcased on the store’s homepage as full products.
638
+
639
+ ```typescript
640
+ const featuredProducts = await shop.products.showcased();
641
+ ```
642
+
643
+ **Returns:** `Product[]`
644
+
645
+ #### `products.showcase.minimal()`
646
+
647
+ Fetches showcased products as minimal product items.
648
+
649
+ ```typescript
650
+ const minimalFeatured = await shop.products.showcase.minimal();
651
+ ```
652
+
653
+ **Returns:** `MinimalProduct[]`
589
654
 
590
655
  ```typescript
591
656
  // Products
@@ -1001,6 +1066,7 @@ type MetaTag =
1001
1066
  ```typescript
1002
1067
  async function searchProducts(shop: ShopClient, query: string) {
1003
1068
  const allProducts = await shop.products.all();
1069
+ if (!allProducts) return [];
1004
1070
  return allProducts.filter(product =>
1005
1071
  product.title.toLowerCase().includes(query.toLowerCase()) ||
1006
1072
  product.tags.some(tag => tag.toLowerCase().includes(query.toLowerCase()))
@@ -1013,6 +1079,7 @@ async function searchProducts(shop: ShopClient, query: string) {
1013
1079
  ```typescript
1014
1080
  async function monitorPrices(shop: ShopClient) {
1015
1081
  const products = await shop.products.all();
1082
+ if (!products) return [];
1016
1083
  return products.map(product => ({
1017
1084
  handle: product.handle,
1018
1085
  title: product.title,
@@ -1,4 +1,4 @@
1
- import { O as OpenRouterConfig, k as ProductClassification, l as SEOContent, m as SystemUserPrompt, a as ShopifySingleProduct } from '../types-BRXamZMS.js';
1
+ import { O as OpenRouterConfig, l as ProductClassification, m as SEOContent, n as SystemUserPrompt, a as ShopifySingleProduct } from '../types-w9n4csBQ.js';
2
2
 
3
3
  declare function buildEnrichPrompt(args: {
4
4
  bodyInput: string;
@@ -13,8 +13,8 @@ import {
13
13
  htmlToMarkdown,
14
14
  mergeWithLLM,
15
15
  pruneBreakdownForSignals
16
- } from "../chunk-ZX4IG4TY.mjs";
17
- import "../chunk-D5MTUWFO.mjs";
16
+ } from "../chunk-5TGMDRUF.mjs";
17
+ import "../chunk-O77Z6OBJ.mjs";
18
18
  export {
19
19
  buildClassifyPrompt,
20
20
  buildClassifyPromptForProduct,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rateLimitedFetch
3
- } from "./chunk-D5MTUWFO.mjs";
3
+ } from "./chunk-O77Z6OBJ.mjs";
4
4
  import {
5
5
  formatPrice
6
6
  } from "./chunk-U3RQRBXZ.mjs";
@@ -37,10 +37,25 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
37
37
  }
38
38
  };
39
39
  }
40
+ function applyCurrencyOverrideMinimal(product, currency) {
41
+ var _a;
42
+ const compareAtPrice = (_a = product.compareAtPrice) != null ? _a : 0;
43
+ return {
44
+ ...product,
45
+ localizedPricing: {
46
+ priceFormatted: formatPrice(product.price, currency),
47
+ compareAtPriceFormatted: formatPrice(compareAtPrice, currency)
48
+ }
49
+ };
50
+ }
40
51
  function maybeOverrideProductsCurrency(products, currency) {
41
- if (!products || !currency) return products;
52
+ if (!products || !currency || products.length === 0) return products;
42
53
  return products.map((p) => applyCurrencyOverride(p, currency));
43
54
  }
55
+ function maybeOverrideMinimalProductsCurrency(products, currency) {
56
+ if (!products || !currency || products.length === 0) return products;
57
+ return products.map((p) => applyCurrencyOverrideMinimal(p, currency));
58
+ }
44
59
  return {
45
60
  /**
46
61
  * Fetches collections with pagination support.
@@ -141,7 +156,7 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
141
156
  * ```
142
157
  */
143
158
  find: async (collectionHandle) => {
144
- var _a, _b;
159
+ var _a, _b, _c;
145
160
  if (!collectionHandle || typeof collectionHandle !== "string") {
146
161
  throw new Error("Collection handle is required and must be a string");
147
162
  }
@@ -174,17 +189,25 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
174
189
  result.collection.handle,
175
190
  {
176
191
  limit: 1,
177
- page: 1
192
+ page: 1,
193
+ minimal: true
178
194
  }
179
195
  )) == null ? void 0 : _a.at(0);
180
196
  const collectionProductImage = (_b = collectionProduct == null ? void 0 : collectionProduct.images) == null ? void 0 : _b[0];
181
197
  if (collectionProduct && collectionProductImage) {
182
- collectionImage = {
183
- id: collectionProductImage.id,
184
- src: collectionProductImage.src,
185
- alt: collectionProductImage.alt || collectionProduct.title,
186
- created_at: collectionProductImage.createdAt || (/* @__PURE__ */ new Date()).toISOString()
187
- };
198
+ const rec = collectionProductImage;
199
+ const src = typeof rec.src === "string" ? rec.src : String((_c = rec.src) != null ? _c : "");
200
+ if (src) {
201
+ const id = typeof rec.id === "number" ? rec.id : 0;
202
+ const alt = typeof rec.alt === "string" && rec.alt.trim() ? rec.alt : collectionProduct.title;
203
+ const createdAt = typeof rec.createdAt === "string" && rec.createdAt.trim() ? rec.createdAt : typeof rec.created_at === "string" && rec.created_at.trim() ? rec.created_at : (/* @__PURE__ */ new Date()).toISOString();
204
+ collectionImage = {
205
+ id,
206
+ src,
207
+ alt,
208
+ created_at: createdAt
209
+ };
210
+ }
188
211
  }
189
212
  }
190
213
  const collectionData = collectionsDto([
@@ -256,6 +279,7 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
256
279
  * @param options - Pagination options
257
280
  * @param options.page - Page number (default: 1)
258
281
  * @param options.limit - Number of products per page (default: 250, max: 250)
282
+ * Use `shop.collections.products.minimal.paginated()` for MinimalProduct returns.
259
283
  *
260
284
  * @returns {Promise<Product[] | null>} Array of products from the collection or null if error occurs
261
285
  *
@@ -296,14 +320,22 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
296
320
  }
297
321
  const products = await fetchPaginatedProductsFromCollection(
298
322
  sanitizedHandle,
299
- { page, limit }
323
+ {
324
+ page,
325
+ limit,
326
+ minimal: false
327
+ }
328
+ );
329
+ return maybeOverrideProductsCurrency(
330
+ products,
331
+ options == null ? void 0 : options.currency
300
332
  );
301
- return maybeOverrideProductsCurrency(products, options == null ? void 0 : options.currency);
302
333
  },
303
334
  /**
304
335
  * Fetches all products from a specific collection.
305
336
  *
306
337
  * @param collectionHandle - The collection handle to fetch products from
338
+ * Use `shop.collections.products.minimal.all()` for MinimalProduct returns.
307
339
  *
308
340
  * @returns {Promise<Product[] | null>} Array of all products from the collection or null if error occurs
309
341
  *
@@ -342,7 +374,8 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
342
374
  sanitizedHandle,
343
375
  {
344
376
  page: currentPage,
345
- limit
377
+ limit,
378
+ minimal: false
346
379
  }
347
380
  );
348
381
  if (!products || products.length === 0 || products.length < limit) {
@@ -354,7 +387,10 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
354
387
  allProducts.push(...products);
355
388
  currentPage++;
356
389
  }
357
- return maybeOverrideProductsCurrency(allProducts, options == null ? void 0 : options.currency);
390
+ return maybeOverrideProductsCurrency(
391
+ allProducts,
392
+ options == null ? void 0 : options.currency
393
+ );
358
394
  } catch (error) {
359
395
  console.error(
360
396
  `Error fetching all products for collection ${sanitizedHandle}:`,
@@ -421,6 +457,92 @@ function createCollectionOperations(baseUrl, storeDomain, fetchCollections, coll
421
457
  );
422
458
  return null;
423
459
  }
460
+ },
461
+ minimal: {
462
+ paginated: async (collectionHandle, options) => {
463
+ var _a, _b;
464
+ if (!collectionHandle || typeof collectionHandle !== "string") {
465
+ throw new Error(
466
+ "Collection handle is required and must be a string"
467
+ );
468
+ }
469
+ const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
470
+ if (!sanitizedHandle) {
471
+ throw new Error("Invalid collection handle format");
472
+ }
473
+ if (sanitizedHandle.length > 255) {
474
+ throw new Error("Collection handle is too long");
475
+ }
476
+ const page = (_a = options == null ? void 0 : options.page) != null ? _a : 1;
477
+ const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 250;
478
+ if (page < 1 || limit < 1 || limit > 250) {
479
+ throw new Error(
480
+ "Invalid pagination parameters: page must be >= 1, limit must be between 1 and 250"
481
+ );
482
+ }
483
+ const products = await fetchPaginatedProductsFromCollection(
484
+ sanitizedHandle,
485
+ {
486
+ page,
487
+ limit,
488
+ minimal: true
489
+ }
490
+ );
491
+ const final = maybeOverrideMinimalProductsCurrency(
492
+ products,
493
+ options == null ? void 0 : options.currency
494
+ );
495
+ return final || null;
496
+ },
497
+ all: async (collectionHandle, options) => {
498
+ if (!collectionHandle || typeof collectionHandle !== "string") {
499
+ throw new Error(
500
+ "Collection handle is required and must be a string"
501
+ );
502
+ }
503
+ const sanitizedHandle = collectionHandle.trim().replace(/[^a-zA-Z0-9\-_]/g, "");
504
+ if (!sanitizedHandle) {
505
+ throw new Error("Invalid collection handle format");
506
+ }
507
+ if (sanitizedHandle.length > 255) {
508
+ throw new Error("Collection handle is too long");
509
+ }
510
+ try {
511
+ const limit = 250;
512
+ const allProducts = [];
513
+ let currentPage = 1;
514
+ while (true) {
515
+ const products = await fetchPaginatedProductsFromCollection(
516
+ sanitizedHandle,
517
+ {
518
+ page: currentPage,
519
+ limit,
520
+ minimal: true
521
+ }
522
+ );
523
+ if (!products || products.length === 0 || products.length < limit) {
524
+ if (products && products.length > 0) {
525
+ allProducts.push(...products);
526
+ }
527
+ break;
528
+ }
529
+ allProducts.push(...products);
530
+ currentPage++;
531
+ }
532
+ const final = maybeOverrideMinimalProductsCurrency(
533
+ allProducts,
534
+ options == null ? void 0 : options.currency
535
+ );
536
+ return final || null;
537
+ } catch (error) {
538
+ console.error(
539
+ `Error fetching all products for collection ${sanitizedHandle}:`,
540
+ baseUrl,
541
+ error
542
+ );
543
+ return null;
544
+ }
545
+ }
424
546
  }
425
547
  }
426
548
  };