shop-client 3.18.0 → 3.19.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.
@@ -1,4 +1,4 @@
1
- import { O as OpenRouterConfig, l as ProductClassification, m as SEOContent, n as SystemUserPrompt, a as ShopifySingleProduct } from '../types-B4WDm14E.js';
1
+ import { O as OpenRouterConfig, l as ProductClassification, m as SEOContent, n as SystemUserPrompt, a as ShopifySingleProduct } from '../types-BzKSPzbj.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-5TGMDRUF.mjs";
17
- import "../chunk-O77Z6OBJ.mjs";
16
+ } from "../chunk-OSMMFHDC.mjs";
17
+ import "../chunk-4GPP2KXF.mjs";
18
18
  export {
19
19
  buildClassifyPrompt,
20
20
  buildClassifyPromptForProduct,
@@ -177,6 +177,9 @@ async function rateLimitedFetch(input, init) {
177
177
  timeoutMs: _timeoutMs,
178
178
  ...fetchInit
179
179
  } = effInit;
180
+ if (fetchInit.redirect === void 0) {
181
+ fetchInit.redirect = "follow";
182
+ }
180
183
  const klass = init == null ? void 0 : init.rateLimitClass;
181
184
  const byClass = klass ? classLimiters.get(klass) : void 0;
182
185
  const byHost = getHostLimiter(getHost(input));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rateLimitedFetch
3
- } from "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-4GPP2KXF.mjs";
4
4
  import {
5
5
  formatPrice
6
6
  } from "./chunk-U3RQRBXZ.mjs";
@@ -300,7 +300,7 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
300
300
  }
301
301
  async function findEnhancedInternal(productHandle, options) {
302
302
  var _a;
303
- const apiKey = options == null ? void 0 : options.apiKey;
303
+ const apiKey = options.apiKey;
304
304
  if (!apiKey || typeof apiKey !== "string" || !apiKey.trim()) {
305
305
  throw new Error("apiKey is required");
306
306
  }
@@ -328,7 +328,7 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
328
328
  throw new Error("updatedAt missing for product");
329
329
  }
330
330
  }
331
- const endpoint = typeof (options == null ? void 0 : options.endpoint) === "string" && options.endpoint.trim() || "https://shopify-product-enrichment-worker.ninjacode.workers.dev";
331
+ const endpoint = typeof options.endpoint === "string" && options.endpoint.trim() || "https://shopify-product-enrichment-worker.ninjacode.workers.dev";
332
332
  let hostname = storeDomain;
333
333
  try {
334
334
  hostname = new URL(storeDomain).hostname;
@@ -365,7 +365,126 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
365
365
  if (!("shopify" in o) || !("enrichment" in o) || !("cache" in o)) {
366
366
  throw new Error("Invalid enhanced product response");
367
367
  }
368
- return data;
368
+ const parsed = data;
369
+ let mappedProduct = baseProduct;
370
+ try {
371
+ const raw = parsed.shopify;
372
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
373
+ if ("body_html" in raw) {
374
+ const mapped = productsDto([raw], {
375
+ minimal: false
376
+ });
377
+ const first = Array.isArray(mapped) ? mapped[0] : null;
378
+ if (first) mappedProduct = first;
379
+ } else if ("description" in raw) {
380
+ mappedProduct = productDto(raw, {
381
+ minimal: false
382
+ });
383
+ }
384
+ }
385
+ } catch {
386
+ }
387
+ return {
388
+ enrichment: parsed.enrichment,
389
+ cache: parsed.cache,
390
+ product: mappedProduct
391
+ };
392
+ }
393
+ async function findEnhancedMinimalInternal(productHandle, options) {
394
+ var _a;
395
+ const apiKey = options.apiKey;
396
+ if (!apiKey || typeof apiKey !== "string" || !apiKey.trim()) {
397
+ throw new Error("apiKey is required");
398
+ }
399
+ const baseProduct = await findInternal(productHandle, { minimal: false });
400
+ if (!baseProduct) return null;
401
+ let updatedAt = (_a = baseProduct.updatedAt) == null ? void 0 : _a.toISOString();
402
+ if (updatedAt == null ? void 0 : updatedAt.endsWith(".000Z")) {
403
+ updatedAt = updatedAt.replace(".000Z", "Z");
404
+ }
405
+ if (!updatedAt) {
406
+ const url = `${baseUrl}products/${encodeURIComponent(baseProduct.handle)}.js`;
407
+ const resp2 = await rateLimitedFetch(url, {
408
+ rateLimitClass: "products:single",
409
+ timeoutMs: 7e3,
410
+ retry: { maxRetries: 1, baseDelayMs: 200 }
411
+ });
412
+ if (!resp2.ok) {
413
+ if (resp2.status === 404) return null;
414
+ throw new Error(`HTTP ${resp2.status}: ${resp2.statusText}`);
415
+ }
416
+ const raw = await resp2.json();
417
+ if (typeof raw.updated_at === "string" && raw.updated_at.trim()) {
418
+ updatedAt = raw.updated_at;
419
+ } else {
420
+ throw new Error("updatedAt missing for product");
421
+ }
422
+ }
423
+ const endpoint = typeof options.endpoint === "string" && options.endpoint.trim() || "https://shopify-product-enrichment-worker.ninjacode.workers.dev";
424
+ let hostname = storeDomain;
425
+ try {
426
+ hostname = new URL(storeDomain).hostname;
427
+ } catch {
428
+ hostname = storeDomain.replace(/^https?:\/\//, "").replace(/\/.*$/, "");
429
+ }
430
+ const resp = await rateLimitedFetch(endpoint, {
431
+ method: "POST",
432
+ headers: {
433
+ "content-type": "application/json",
434
+ "x-api-key": apiKey
435
+ },
436
+ body: JSON.stringify({
437
+ storeDomain: hostname,
438
+ handle: baseProduct.handle,
439
+ updatedAt
440
+ }),
441
+ rateLimitClass: "products:enhanced",
442
+ timeoutMs: 15e3,
443
+ retry: {
444
+ maxRetries: 2,
445
+ baseDelayMs: 300,
446
+ retryOnStatuses: [429, 500, 502, 503, 504]
447
+ }
448
+ });
449
+ if (!resp.ok) {
450
+ throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
451
+ }
452
+ const data = await resp.json();
453
+ if (!data || typeof data !== "object" || Array.isArray(data)) {
454
+ throw new Error("Invalid enhanced product response");
455
+ }
456
+ const o = data;
457
+ if (!("shopify" in o) || !("enrichment" in o) || !("cache" in o)) {
458
+ throw new Error("Invalid enhanced product response");
459
+ }
460
+ const parsed = data;
461
+ let mappedMinimal = null;
462
+ try {
463
+ const raw = parsed.shopify;
464
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
465
+ if ("body_html" in raw) {
466
+ const mapped = productsDto([raw], {
467
+ minimal: true
468
+ });
469
+ const first = Array.isArray(mapped) ? mapped[0] : null;
470
+ mappedMinimal = first || null;
471
+ } else if ("description" in raw) {
472
+ mappedMinimal = productDto(raw, {
473
+ minimal: true
474
+ });
475
+ }
476
+ }
477
+ } catch {
478
+ }
479
+ if (!mappedMinimal) {
480
+ mappedMinimal = await findInternal(baseProduct.handle, { minimal: true });
481
+ }
482
+ if (!mappedMinimal) return null;
483
+ return {
484
+ enrichment: parsed.enrichment,
485
+ cache: parsed.cache,
486
+ product: mappedMinimal
487
+ };
369
488
  }
370
489
  const operations = {
371
490
  /**
@@ -750,6 +869,9 @@ function createProductOperations(baseUrl, storeDomain, fetchProducts, productsDt
750
869
  currency: options == null ? void 0 : options.currency
751
870
  });
752
871
  },
872
+ findEnhanced: async (productHandle, options) => {
873
+ return findEnhancedMinimalInternal(productHandle, options);
874
+ },
753
875
  showcased: async () => {
754
876
  const res = await operations.showcase.minimal();
755
877
  return res || [];
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rateLimitedFetch
3
- } from "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-4GPP2KXF.mjs";
4
4
  import {
5
5
  detectShopCountry
6
6
  } from "./chunk-SBHTEKLB.mjs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rateLimitedFetch
3
- } from "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-4GPP2KXF.mjs";
4
4
  import {
5
5
  formatPrice
6
6
  } from "./chunk-U3RQRBXZ.mjs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  rateLimitedFetch
3
- } from "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-4GPP2KXF.mjs";
4
4
 
5
5
  // src/ai/enrich.ts
6
6
  import TurndownService from "turndown";
@@ -1,5 +1,5 @@
1
1
  import { ShopInfo } from './store.js';
2
- import { C as Collection, f as CurrencyCode, P as Product, M as MinimalProduct, b as ShopifyCollection } from './types-B4WDm14E.js';
2
+ import { C as Collection, f as CurrencyCode, P as Product, M as MinimalProduct, b as ShopifyCollection } from './types-BzKSPzbj.js';
3
3
 
4
4
  /**
5
5
  * Interface for collection operations
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createCollectionOperations
3
- } from "./chunk-242GBM2V.mjs";
4
- import "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-GYQQU54C.mjs";
4
+ import "./chunk-4GPP2KXF.mjs";
5
5
  import "./chunk-U3RQRBXZ.mjs";
6
6
  export {
7
7
  createCollectionOperations
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OpenRouterConfig, S as ShopifyProduct, P as Product, M as MinimalProduct, a as ShopifySingleProduct, b as ShopifyCollection, C as Collection, J as JsonLdEntry, c as StoreTypeBreakdown } from './types-B4WDm14E.js';
2
- export { d as CountryDetectionResult, e as CountryScores, f as CurrencyCode, L as LocalizedPricing, g as MetaTag, h as ProductImage, i as ProductOption, j as ProductVariant, k as ProductVariantImage } from './types-B4WDm14E.js';
1
+ import { O as OpenRouterConfig, S as ShopifyProduct, P as Product, M as MinimalProduct, a as ShopifySingleProduct, b as ShopifyCollection, C as Collection, J as JsonLdEntry, c as StoreTypeBreakdown } from './types-BzKSPzbj.js';
2
+ export { d as CountryDetectionResult, e as CountryScores, f as CurrencyCode, L as LocalizedPricing, g as MetaTag, h as ProductImage, i as ProductOption, j as ProductVariant, k as ProductVariantImage } from './types-BzKSPzbj.js';
3
3
  import { CheckoutOperations } from './checkout.js';
4
4
  import { CollectionOperations } from './collections.js';
5
5
  import { ProductOperations } from './products.js';
package/dist/index.mjs CHANGED
@@ -3,23 +3,23 @@ import {
3
3
  } from "./chunk-W4SF6W2P.mjs";
4
4
  import {
5
5
  createCollectionOperations
6
- } from "./chunk-242GBM2V.mjs";
6
+ } from "./chunk-GYQQU54C.mjs";
7
7
  import {
8
8
  createProductOperations
9
- } from "./chunk-6XDBGOFZ.mjs";
9
+ } from "./chunk-5DGSCBYT.mjs";
10
10
  import {
11
11
  createShopOperations,
12
12
  getInfoForShop
13
- } from "./chunk-YWAW6C74.mjs";
13
+ } from "./chunk-BNTNHHDI.mjs";
14
14
  import {
15
15
  classifyProduct,
16
16
  determineStoreType,
17
17
  generateSEOContent
18
- } from "./chunk-5TGMDRUF.mjs";
18
+ } from "./chunk-OSMMFHDC.mjs";
19
19
  import {
20
20
  configureRateLimit,
21
21
  rateLimitedFetch
22
- } from "./chunk-O77Z6OBJ.mjs";
22
+ } from "./chunk-4GPP2KXF.mjs";
23
23
  import {
24
24
  detectShopCountry
25
25
  } from "./chunk-SBHTEKLB.mjs";
@@ -1,5 +1,5 @@
1
1
  import { ShopInfo } from './store.js';
2
- import { f as CurrencyCode, P as Product, E as EnhancedProductResponse, l as ProductClassification, m as SEOContent, M as MinimalProduct, S as ShopifyProduct, a as ShopifySingleProduct, O as OpenRouterConfig } from './types-B4WDm14E.js';
2
+ import { f as CurrencyCode, P as Product, E as EnhancedProductResponse, l as ProductClassification, m as SEOContent, M as MinimalProduct, S as ShopifyProduct, a as ShopifySingleProduct, O as OpenRouterConfig } from './types-BzKSPzbj.js';
3
3
 
4
4
  /**
5
5
  * Interface for product operations
@@ -33,11 +33,11 @@ interface ProductOperations {
33
33
  *
34
34
  * @param productHandle - The handle of the product to find.
35
35
  * @param options - Options for the request.
36
- * @param options.apiKey - API key for the enhancement service.
36
+ * @param options.apiKey - API key for the enhancement service. Required for authentication via x-api-key header.
37
37
  * @param options.endpoint - Optional custom endpoint URL for the enhancement service. Defaults to the standard worker URL.
38
38
  */
39
- findEnhanced(productHandle: string, options?: {
40
- apiKey?: string;
39
+ findEnhanced(productHandle: string, options: {
40
+ apiKey: string;
41
41
  endpoint?: string;
42
42
  }): Promise<EnhancedProductResponse | null>;
43
43
  /**
@@ -139,6 +139,10 @@ interface ProductOperations {
139
139
  find(productHandle: string, options?: {
140
140
  currency?: CurrencyCode;
141
141
  }): Promise<MinimalProduct | null>;
142
+ findEnhanced(productHandle: string, options: {
143
+ apiKey: string;
144
+ endpoint?: string;
145
+ }): Promise<EnhancedProductResponse<MinimalProduct> | null>;
142
146
  showcased(): Promise<MinimalProduct[]>;
143
147
  predictiveSearch(query: string, options?: {
144
148
  limit?: number;
package/dist/products.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createProductOperations
3
- } from "./chunk-6XDBGOFZ.mjs";
4
- import "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-5DGSCBYT.mjs";
4
+ import "./chunk-4GPP2KXF.mjs";
5
5
  import "./chunk-U3RQRBXZ.mjs";
6
6
  export {
7
7
  createProductOperations
package/dist/store.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { J as JsonLdEntry, d as CountryDetectionResult, f as CurrencyCode } from './types-B4WDm14E.js';
1
+ import { J as JsonLdEntry, d as CountryDetectionResult, f as CurrencyCode } from './types-BzKSPzbj.js';
2
2
 
3
3
  /**
4
4
  * Store operations interface for managing store-related functionality.
package/dist/store.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createShopOperations
3
- } from "./chunk-YWAW6C74.mjs";
4
- import "./chunk-O77Z6OBJ.mjs";
3
+ } from "./chunk-BNTNHHDI.mjs";
4
+ import "./chunk-4GPP2KXF.mjs";
5
5
  import "./chunk-SBHTEKLB.mjs";
6
6
  import "./chunk-U3RQRBXZ.mjs";
7
7
  export {
@@ -435,32 +435,55 @@ type SEOContent = {
435
435
  tags: string[];
436
436
  marketingCopy: string;
437
437
  };
438
+ /**
439
+ * Contextual image information extracted from product content.
440
+ */
438
441
  type EnhancedProductImage = {
442
+ /** The text surrounding the image reference. */
439
443
  textContext: string;
444
+ /** The image URL. */
440
445
  url: string;
446
+ /** The image alt text. */
441
447
  alt: string;
442
448
  };
449
+ /**
450
+ * Structured canonical product data extracted by AI.
451
+ */
443
452
  type EnhancedProductCanonical = {
453
+ /** The product title. */
444
454
  title: string;
455
+ /** A brief summary of the product. */
445
456
  summary: string;
457
+ /** Key highlights or features of the product. */
446
458
  highlights: string[];
459
+ /** Material information (array of strings or object). */
447
460
  materials: unknown;
461
+ /** Fit and sizing information. */
448
462
  fit_and_size: unknown;
463
+ /** Care instructions. */
449
464
  care: unknown;
465
+ /** Unique selling points. */
450
466
  what_makes_it_special: unknown;
467
+ /** Information that was looked for but not found. */
451
468
  missing_info: unknown[];
469
+ /** List of contextual images found in the description. */
452
470
  images: EnhancedProductImage[];
453
471
  };
472
+ /**
473
+ * The full enrichment result containing both structured and markdown formats.
474
+ */
454
475
  type EnhancedProductEnrichment = {
476
+ /** The structured canonical data. */
455
477
  canonical: EnhancedProductCanonical;
478
+ /** The generated markdown content. */
456
479
  markdown: string;
457
480
  };
458
481
  /**
459
482
  * The response object from the enhanced product search.
460
483
  */
461
- type EnhancedProductResponse = {
462
- /** The original Shopify product data. */
463
- shopify: ShopifyProduct;
484
+ type EnhancedProductResponse<TProduct = Product> = {
485
+ /** The product data after DTO transformations. */
486
+ product: TProduct;
464
487
  /** The AI-enriched content. */
465
488
  enrichment: EnhancedProductEnrichment;
466
489
  /** Cache status of the response (e.g., 'hit', 'miss'). */
@@ -1,4 +1,4 @@
1
- import { d as CountryDetectionResult } from '../types-B4WDm14E.js';
1
+ import { d as CountryDetectionResult } from '../types-BzKSPzbj.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 { f as CurrencyCode } from '../types-B4WDm14E.js';
1
+ import { f as CurrencyCode } from '../types-BzKSPzbj.js';
2
2
 
3
3
  declare function extractDomainWithoutSuffix(domain: string): string | null;
4
4
  declare function generateStoreSlug(domain: string): string;
@@ -2,7 +2,7 @@ import {
2
2
  configureRateLimit,
3
3
  getRateLimitStatus,
4
4
  rateLimitedFetch
5
- } from "../chunk-O77Z6OBJ.mjs";
5
+ } from "../chunk-4GPP2KXF.mjs";
6
6
  export {
7
7
  configureRateLimit,
8
8
  getRateLimitStatus,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shop-client",
3
- "version": "3.18.0",
3
+ "version": "3.19.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.mjs",