{"version":3,"sources":["../src/ai/determine-store-type.ts","../src/dto/collections.dto.ts","../src/dto/products.mapped.ts","../src/index.ts"],"sourcesContent":["import type { StoreInfo } from \"../store\";\nimport type { StoreTypeBreakdown } from \"../types\";\nimport { determineStoreType as determineStoreTypeViaLLM } from \"./enrich\";\n\ntype Args = {\n  getInfo: () => Promise<StoreInfo>;\n  baseUrl: string;\n  findProduct: (handle: string) => Promise<unknown>;\n  apiKey?: string;\n  model?: string;\n  maxShowcaseProducts?: number;\n  maxShowcaseCollections?: number;\n};\n\n/**\n * Lightweight wrapper for determining store type by delegating to utils/enrich.\n * It first fetches StoreInfo via getInfo, then passes showcase samples\n * directly to the enrichment function.\n */\nexport async function determineStoreTypeForStore(\n  args: Args\n): Promise<StoreTypeBreakdown> {\n  const info = await args.getInfo();\n\n  const maxProducts = Math.max(0, Math.min(50, args.maxShowcaseProducts ?? 10));\n  const maxCollections = Math.max(\n    0,\n    Math.min(50, args.maxShowcaseCollections ?? 10)\n  );\n\n  const take = <T>(arr: T[], n: number): T[] => arr.slice(0, Math.max(0, n));\n\n  const productsSample = Array.isArray(info.showcase.products)\n    ? take(info.showcase.products, maxProducts)\n    : [];\n  const collectionsSample = Array.isArray(info.showcase.collections)\n    ? take(info.showcase.collections, maxCollections)\n    : [];\n\n  const breakdown = await determineStoreTypeViaLLM(\n    {\n      title: info.title || info.name,\n      description: info.description ?? null,\n      showcase: {\n        products: productsSample,\n        collections: collectionsSample,\n      },\n    },\n    { apiKey: args.apiKey, model: args.model }\n  );\n\n  return breakdown as StoreTypeBreakdown;\n}\n","import type { Collection, ShopifyCollection } from \"../types\";\n\nexport function collectionsDto(\n  collections: ShopifyCollection[] | null\n): Collection[] | null {\n  if (!collections || collections.length === 0) return null;\n\n  return collections.map((collection) => ({\n    id: collection.id.toString(),\n    title: collection.title,\n    handle: collection.handle,\n    description: collection.description,\n    image: collection.image\n      ? {\n          id: collection.image.id,\n          createdAt: collection.image.created_at,\n          src: collection.image.src,\n          alt: collection.image.alt,\n        }\n      : undefined,\n    productsCount: collection.products_count,\n    publishedAt: collection.published_at,\n    updatedAt: collection.updated_at,\n  }));\n}\n","import type { Product, ShopifyProduct, ShopifySingleProduct } from \"../types\";\nimport {\n  buildVariantOptionsMap,\n  genProductSlug,\n  normalizeKey,\n  safeParseDate,\n} from \"../utils/func\";\n\ntype Ctx = {\n  storeDomain: string;\n  storeSlug: string;\n  currency: string;\n  normalizeImageUrl: (url: string | null | undefined) => string;\n  formatPrice: (amountInCents: number) => string;\n};\n\nfunction mapVariants(\n  product: ShopifyProduct | ShopifySingleProduct\n): NonNullable<Product[\"variants\"]> {\n  const variants = (product as ShopifyProduct).variants ?? [];\n  return variants.map((variant: any) => ({\n    id: variant.id.toString(),\n    platformId: variant.id.toString(),\n    name: variant.name,\n    title: variant.title,\n    option1: variant.option1 || null,\n    option2: variant.option2 || null,\n    option3: variant.option3 || null,\n    options: [variant.option1, variant.option2, variant.option3].filter(\n      Boolean\n    ) as string[],\n    sku: variant.sku || null,\n    requiresShipping: variant.requires_shipping,\n    taxable: variant.taxable,\n    featuredImage: variant.featured_image\n      ? {\n          id: variant.featured_image.id,\n          src: variant.featured_image.src,\n          width: variant.featured_image.width,\n          height: variant.featured_image.height,\n          position: variant.featured_image.position,\n          productId: variant.featured_image.product_id,\n          aspectRatio: variant.featured_image.aspect_ratio || 0,\n          variantIds: variant.featured_image.variant_ids || [],\n          createdAt: variant.featured_image.created_at,\n          updatedAt: variant.featured_image.updated_at,\n          alt: variant.featured_image.alt,\n        }\n      : null,\n    available: Boolean(variant.available),\n    price:\n      typeof variant.price === \"string\"\n        ? Number.parseFloat(variant.price) * 100\n        : variant.price,\n    weightInGrams: variant.weightInGrams ?? variant.grams,\n    compareAtPrice: variant.compare_at_price\n      ? typeof variant.compare_at_price === \"string\"\n        ? Number.parseFloat(variant.compare_at_price) * 100\n        : variant.compare_at_price\n      : 0,\n    position: variant.position,\n    productId: variant.product_id,\n    createdAt: variant.created_at,\n    updatedAt: variant.updated_at,\n  }));\n}\n\nexport function mapProductsDto(\n  products: ShopifyProduct[] | null,\n  ctx: Ctx\n): Product[] | null {\n  if (!products || products.length === 0) return null;\n\n  return products.map((product) => {\n    const optionNames = product.options.map((o) => o.name);\n    const variantOptionsMap = buildVariantOptionsMap(\n      optionNames,\n      product.variants\n    );\n    const mappedVariants = mapVariants(product);\n\n    const priceValues = mappedVariants\n      .map((v) => v.price)\n      .filter((p) => typeof p === \"number\" && !Number.isNaN(p));\n    const compareAtValues = mappedVariants\n      .map((v) => v.compareAtPrice || 0)\n      .filter((p) => typeof p === \"number\" && !Number.isNaN(p));\n\n    const priceMin = priceValues.length ? Math.min(...priceValues) : 0;\n    const priceMax = priceValues.length ? Math.max(...priceValues) : 0;\n    const priceVaries = mappedVariants.length > 1 && priceMin !== priceMax;\n\n    const compareAtMin = compareAtValues.length\n      ? Math.min(...compareAtValues)\n      : 0;\n    const compareAtMax = compareAtValues.length\n      ? Math.max(...compareAtValues)\n      : 0;\n    const compareAtVaries =\n      mappedVariants.length > 1 && compareAtMin !== compareAtMax;\n\n    return {\n      slug: genProductSlug({\n        handle: product.handle,\n        storeDomain: ctx.storeDomain,\n      }),\n      handle: product.handle,\n      platformId: product.id.toString(),\n      title: product.title,\n      available: mappedVariants.some((v) => v.available),\n      price: priceMin,\n      priceMin: priceMin,\n      priceMax: priceMax,\n      priceVaries,\n      compareAtPrice: compareAtMin,\n      compareAtPriceMin: compareAtMin,\n      compareAtPriceMax: compareAtMax,\n      compareAtPriceVaries: compareAtVaries,\n      discount: 0,\n      currency: ctx.currency,\n      localizedPricing: {\n        currency: ctx.currency,\n        priceFormatted: ctx.formatPrice(priceMin),\n        priceMinFormatted: ctx.formatPrice(priceMin),\n        priceMaxFormatted: ctx.formatPrice(priceMax),\n        compareAtPriceFormatted: ctx.formatPrice(compareAtMin),\n      },\n      options: product.options.map((option) => ({\n        key: normalizeKey(option.name),\n        data: option.values,\n        name: option.name,\n        position: option.position,\n        values: option.values,\n      })),\n      variantOptionsMap,\n      bodyHtml: product.body_html || null,\n      active: true,\n      productType: product.product_type || null,\n      tags: Array.isArray(product.tags) ? product.tags : [],\n      vendor: product.vendor,\n      featuredImage: product.images?.[0]?.src\n        ? ctx.normalizeImageUrl(product.images[0].src)\n        : null,\n      isProxyFeaturedImage: false,\n      createdAt: safeParseDate(product.created_at),\n      updatedAt: safeParseDate(product.updated_at),\n      variants: mappedVariants,\n      images: product.images.map((image) => ({\n        id: image.id,\n        productId: image.product_id,\n        alt: null,\n        position: image.position,\n        src: ctx.normalizeImageUrl(image.src),\n        width: image.width,\n        height: image.height,\n        mediaType: \"image\" as const,\n        variantIds: image.variant_ids || [],\n        createdAt: image.created_at,\n        updatedAt: image.updated_at,\n      })),\n      publishedAt: safeParseDate(product.published_at) ?? null,\n      seo: null,\n      metaTags: null,\n      displayScore: undefined,\n      deletedAt: null,\n      storeSlug: ctx.storeSlug,\n      storeDomain: ctx.storeDomain,\n      url: `${ctx.storeDomain}/products/${product.handle}`,\n    } as Product;\n  });\n}\n\nexport function mapProductDto(\n  product: ShopifySingleProduct,\n  ctx: Ctx\n): Product {\n  const optionNames = product.options.map((o) => o.name);\n  const variantOptionsMap = buildVariantOptionsMap(\n    optionNames,\n    product.variants\n  );\n\n  const mapped: Product = {\n    slug: genProductSlug({\n      handle: product.handle,\n      storeDomain: ctx.storeDomain,\n    }),\n    handle: product.handle,\n    platformId: product.id.toString(),\n    title: product.title,\n    available: product.available,\n    price: product.price,\n    priceMin: product.price_min,\n    priceMax: product.price_max,\n    priceVaries: product.price_varies,\n    compareAtPrice: product.compare_at_price || 0,\n    compareAtPriceMin: product.compare_at_price_min,\n    compareAtPriceMax: product.compare_at_price_max,\n    compareAtPriceVaries: product.compare_at_price_varies,\n    discount: 0,\n    currency: ctx.currency,\n    localizedPricing: {\n      currency: ctx.currency,\n      priceFormatted: ctx.formatPrice(product.price),\n      priceMinFormatted: ctx.formatPrice(product.price_min),\n      priceMaxFormatted: ctx.formatPrice(product.price_max),\n      compareAtPriceFormatted: ctx.formatPrice(product.compare_at_price || 0),\n    },\n    options: product.options.map((option) => ({\n      key: normalizeKey(option.name),\n      data: option.values,\n      name: option.name,\n      position: option.position,\n      values: option.values,\n    })),\n    variantOptionsMap,\n    bodyHtml: product.description || null,\n    active: true,\n    productType: product.type || null,\n    tags: Array.isArray(product.tags)\n      ? product.tags\n      : typeof product.tags === \"string\"\n        ? [product.tags]\n        : [],\n    vendor: product.vendor,\n    featuredImage: ctx.normalizeImageUrl(product.featured_image),\n    isProxyFeaturedImage: false,\n    createdAt: safeParseDate(product.created_at),\n    updatedAt: safeParseDate(product.updated_at),\n    variants: mapVariants(product),\n    images: Array.isArray(product.images)\n      ? product.images.map((imageSrc, index) => ({\n          id: index + 1,\n          productId: product.id,\n          alt: null,\n          position: index + 1,\n          src: ctx.normalizeImageUrl(imageSrc),\n          width: 0,\n          height: 0,\n          mediaType: \"image\" as const,\n          variantIds: [],\n          createdAt: product.created_at,\n          updatedAt: product.updated_at,\n        }))\n      : [],\n    publishedAt: safeParseDate(product.published_at) ?? null,\n    seo: null,\n    metaTags: null,\n    displayScore: undefined,\n    deletedAt: null,\n    storeSlug: ctx.storeSlug,\n    storeDomain: ctx.storeDomain,\n    url: product.url || `${ctx.storeDomain}/products/${product.handle}`,\n  };\n\n  return mapped;\n}\n","import { determineStoreTypeForStore } from \"./ai/determine-store-type\";\nimport type { CheckoutOperations } from \"./checkout\";\nimport { createCheckoutOperations } from \"./checkout\";\nimport { getInfoForStore } from \"./client/get-info\";\nimport type { CollectionOperations } from \"./collections\";\nimport { createCollectionOperations } from \"./collections\";\nimport { collectionsDto as dtoCollections } from \"./dto/collections.dto\";\nimport { mapProductDto, mapProductsDto } from \"./dto/products.mapped\";\nimport type { ProductOperations } from \"./products\";\nimport { createProductOperations } from \"./products\";\nimport type { StoreInfo, StoreOperations } from \"./store\";\nimport { createStoreOperations } from \"./store\";\nimport type {\n  Collection,\n  Product,\n  ShopifyCollection,\n  ShopifyProduct,\n  ShopifySingleProduct,\n  StoreTypeBreakdown,\n} from \"./types\";\nimport { generateStoreSlug } from \"./utils/func\";\nimport { rateLimitedFetch } from \"./utils/rate-limit\";\n\n/**\n * A comprehensive Shopify store client for fetching products, collections, and store information.\n *\n * @example\n * ```typescript\n * import { ShopClient } from 'shop-search';\n *\n * const shop = new ShopClient('https://exampleshop.com');\n *\n * // Fetch all products\n * const products = await shop.products.all();\n *\n * // Get store information\n * const storeInfo = await shop.getInfo();\n * ```\n */\nexport class ShopClient {\n  private storeDomain: string;\n  private baseUrl: string;\n  private storeSlug: string;\n  private validationCache: Map<string, boolean> = new Map(); // Simple cache for validation results\n  private cacheExpiry: number = 5 * 60 * 1000; // 5 minutes cache expiry\n  private cacheTimestamps: Map<string, number> = new Map();\n  private normalizeImageUrlCache: Map<string, string> = new Map();\n  private storeCurrency?: string;\n\n  // Public operations interfaces\n  public products: ProductOperations;\n  public collections: CollectionOperations;\n  public checkout: CheckoutOperations;\n  public storeOperations: StoreOperations;\n\n  /**\n   * Creates a new ShopClient instance for interacting with a Shopify store.\n   *\n   * @param urlPath - The Shopify store URL (e.g., 'https://exampleshop.com' or 'exampleshop.com')\n   *\n   * @throws {Error} When the URL is invalid or contains malicious patterns\n   *\n   * @example\n   * ```typescript\n   * // With full URL\n   * const shop = new ShopClient('https://exampleshop.com');\n   *\n   * // Without protocol (automatically adds https://)\n   * const shop = new ShopClient('exampleshop.com');\n   *\n   * // Works with any Shopify store domain\n   * const shop1 = new ShopClient('https://example.myshopify.com');\n   * const shop2 = new ShopClient('https://boutique.fashion');\n   * ```\n   */\n  constructor(urlPath: string) {\n    // Validate input URL\n    if (!urlPath || typeof urlPath !== \"string\") {\n      throw new Error(\"Store URL is required and must be a string\");\n    }\n\n    // Sanitize and validate URL\n    let normalizedUrl = urlPath.trim();\n    if (\n      !normalizedUrl.startsWith(\"http://\") &&\n      !normalizedUrl.startsWith(\"https://\")\n    ) {\n      normalizedUrl = `https://${normalizedUrl}`;\n    }\n\n    let storeUrl: URL;\n    try {\n      storeUrl = new URL(normalizedUrl);\n    } catch (_error) {\n      throw new Error(\"Invalid store URL format\");\n    }\n\n    // Validate domain format (basic check for Shopify domains)\n    const hostname = storeUrl.hostname;\n    if (!hostname || hostname.length < 3) {\n      throw new Error(\"Invalid domain name\");\n    }\n\n    // Check for potentially malicious patterns\n    if (\n      hostname.includes(\"..\") ||\n      hostname.includes(\"//\") ||\n      hostname.includes(\"@\")\n    ) {\n      throw new Error(\"Invalid characters in domain name\");\n    }\n\n    // Validate domain structure - must contain at least one dot for TLD\n    if (\n      !hostname.includes(\".\") ||\n      hostname.startsWith(\".\") ||\n      hostname.endsWith(\".\")\n    ) {\n      throw new Error(\n        \"Invalid domain format - must be a valid domain with TLD\"\n      );\n    }\n\n    // Check for valid domain pattern (basic regex)\n    const domainPattern =\n      /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\n    if (!domainPattern.test(hostname)) {\n      throw new Error(\"Invalid domain format\");\n    }\n\n    this.storeDomain = `https://${hostname}`;\n    let fetchUrl = `https://${hostname}${storeUrl.pathname}`;\n    if (!fetchUrl.endsWith(\"/\")) {\n      fetchUrl = `${fetchUrl}/`;\n    }\n    this.baseUrl = fetchUrl;\n\n    // Pre-calculate store slug once\n    this.storeSlug = generateStoreSlug(this.storeDomain);\n\n    // Initialize operations\n    this.storeOperations = createStoreOperations({\n      baseUrl: this.baseUrl,\n      storeDomain: this.storeDomain,\n      validateProductExists: this.validateProductExists.bind(this),\n      validateCollectionExists: this.validateCollectionExists.bind(this),\n      validateLinksInBatches: this.validateLinksInBatches.bind(this),\n      handleFetchError: this.handleFetchError.bind(this),\n    });\n\n    this.products = createProductOperations(\n      this.baseUrl,\n      this.storeDomain,\n      this.fetchProducts.bind(this),\n      this.productsDto.bind(this),\n      this.productDto.bind(this),\n      () => this.getInfo(),\n      (handle: string) => this.products.find(handle)\n    );\n\n    this.collections = createCollectionOperations(\n      this.baseUrl,\n      this.storeDomain,\n      this.fetchCollections.bind(this),\n      this.collectionsDto.bind(this),\n      this.fetchPaginatedProductsFromCollection.bind(this),\n      () => this.getInfo(),\n      (handle: string) => this.collections.find(handle)\n    );\n\n    this.checkout = createCheckoutOperations(this.baseUrl);\n  }\n\n  /**\n   * Optimized image URL normalization with caching\n   */\n  private normalizeImageUrl(url?: string | null): string {\n    if (!url) {\n      return \"\";\n    }\n\n    if (this.normalizeImageUrlCache.has(url)) {\n      return this.normalizeImageUrlCache.get(url)!;\n    }\n\n    const normalized = url.startsWith(\"//\") ? `https:${url}` : url;\n    this.normalizeImageUrlCache.set(url, normalized);\n    return normalized;\n  }\n\n  /**\n   * Format a price amount (in cents) using the store currency.\n   */\n  private formatPrice(amountInCents: number): string {\n    const currency = this.storeCurrency ?? \"USD\";\n    try {\n      return new Intl.NumberFormat(undefined, {\n        style: \"currency\",\n        currency,\n      }).format((amountInCents || 0) / 100);\n    } catch {\n      const val = (amountInCents || 0) / 100;\n      return `${val} ${currency}`;\n    }\n  }\n\n  /**\n   * Transform Shopify products to our Product format\n   */\n  productsDto(products: ShopifyProduct[]): Product[] | null {\n    return mapProductsDto(products, {\n      storeDomain: this.storeDomain,\n      storeSlug: this.storeSlug,\n      currency: this.storeCurrency ?? \"USD\",\n      normalizeImageUrl: (url) => this.normalizeImageUrl(url),\n      formatPrice: (amount) => this.formatPrice(amount),\n    });\n  }\n\n  productDto(product: ShopifySingleProduct): Product {\n    return mapProductDto(product, {\n      storeDomain: this.storeDomain,\n      storeSlug: this.storeSlug,\n      currency: this.storeCurrency ?? \"USD\",\n      normalizeImageUrl: (url) => this.normalizeImageUrl(url),\n      formatPrice: (amount) => this.formatPrice(amount),\n    });\n  }\n\n  collectionsDto(collections: ShopifyCollection[]): Collection[] {\n    return dtoCollections(collections) ?? [];\n  }\n\n  /**\n   * Enhanced error handling with context\n   */\n  private handleFetchError(\n    error: unknown,\n    context: string,\n    url: string\n  ): never {\n    let errorMessage = `Error ${context}`;\n    let statusCode: number | undefined;\n\n    if (error instanceof Error) {\n      errorMessage += `: ${error.message}`;\n\n      // Check if it's a fetch error with response\n      if (\"status\" in error) {\n        statusCode = error.status as number;\n      }\n    } else if (typeof error === \"string\") {\n      errorMessage += `: ${error}`;\n    } else {\n      errorMessage += \": Unknown error occurred\";\n    }\n\n    // Add URL context for debugging\n    errorMessage += ` (URL: ${url})`;\n\n    // Add status code if available\n    if (statusCode) {\n      errorMessage += ` (Status: ${statusCode})`;\n    }\n\n    // Create enhanced error with additional properties\n    const enhancedError = new Error(errorMessage);\n    (enhancedError as any).context = context;\n    (enhancedError as any).url = url;\n    (enhancedError as any).statusCode = statusCode;\n    (enhancedError as any).originalError = error;\n\n    throw enhancedError;\n  }\n\n  /**\n   * Fetch products with pagination\n   */\n  private async fetchProducts(\n    page: number,\n    limit: number\n  ): Promise<Product[] | null> {\n    try {\n      const url = `${this.baseUrl}products.json?page=${page}&limit=${limit}`;\n      const response = await rateLimitedFetch(url);\n\n      if (!response.ok) {\n        throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n      }\n\n      const data: { products: ShopifyProduct[] } = await response.json();\n      return this.productsDto(data.products);\n    } catch (error) {\n      this.handleFetchError(\n        error,\n        \"fetching products\",\n        `${this.baseUrl}products.json`\n      );\n    }\n  }\n\n  /**\n   * Fetch collections with pagination\n   */\n  private async fetchCollections(page: number, limit: number) {\n    try {\n      const url = `${this.baseUrl}collections.json?page=${page}&limit=${limit}`;\n      const response = await rateLimitedFetch(url);\n\n      if (!response.ok) {\n        throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n      }\n\n      const data = await response.json();\n      return this.collectionsDto(data.collections);\n    } catch (error) {\n      this.handleFetchError(\n        error,\n        \"fetching collections\",\n        `${this.baseUrl}collections.json`\n      );\n    }\n  }\n\n  /**\n   * Fetch paginated products from a specific collection\n   */\n  private async fetchPaginatedProductsFromCollection(\n    collectionHandle: string,\n    options: { page?: number; limit?: number } = {}\n  ) {\n    try {\n      const { page = 1, limit = 250 } = options;\n      // Resolve canonical collection handle via HTML redirect if handle has changed\n      let finalHandle = collectionHandle;\n      try {\n        const htmlResp = await rateLimitedFetch(\n          `${this.baseUrl}collections/${encodeURIComponent(collectionHandle)}`\n        );\n        if (htmlResp.ok) {\n          const finalUrl = htmlResp.url;\n          if (finalUrl) {\n            const pathname = new URL(finalUrl).pathname.replace(/\\/$/, \"\");\n            const parts = pathname.split(\"/\").filter(Boolean);\n            const idx = parts.indexOf(\"collections\");\n            const maybeHandle = idx >= 0 ? parts[idx + 1] : undefined;\n            if (typeof maybeHandle === \"string\" && maybeHandle.length) {\n              finalHandle = maybeHandle;\n            }\n          }\n        }\n      } catch {\n        // Ignore redirect resolution errors and proceed with original handle\n      }\n\n      const url = `${this.baseUrl}collections/${finalHandle}/products.json?page=${page}&limit=${limit}`;\n      const response = await rateLimitedFetch(url);\n\n      if (!response.ok) {\n        if (response.status === 404) {\n          return null; // Collection not found\n        }\n        throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n      }\n\n      const data: { products: ShopifyProduct[] } = await response.json();\n      return this.productsDto(data.products);\n    } catch (error) {\n      this.handleFetchError(\n        error,\n        \"fetching products from collection\",\n        `${this.baseUrl}collections/${collectionHandle}/products.json`\n      );\n    }\n  }\n\n  /**\n   * Validate if a product exists (with caching)\n   */\n  private async validateProductExists(handle: string): Promise<boolean> {\n    const cacheKey = `product:${handle}`;\n\n    if (this.isCacheValid(cacheKey)) {\n      return this.validationCache.get(cacheKey) || false;\n    }\n\n    try {\n      const url = `${this.baseUrl}products/${handle}.js`;\n      const response = await rateLimitedFetch(url, { method: \"HEAD\" });\n      const exists = response.ok;\n\n      this.setCacheValue(cacheKey, exists);\n      return exists;\n    } catch (_error) {\n      this.setCacheValue(cacheKey, false);\n      return false;\n    }\n  }\n\n  /**\n   * Validate if a collection exists (with caching)\n   */\n  private async validateCollectionExists(handle: string): Promise<boolean> {\n    const cacheKey = `collection:${handle}`;\n\n    if (this.isCacheValid(cacheKey)) {\n      return this.validationCache.get(cacheKey) || false;\n    }\n\n    try {\n      const url = `${this.baseUrl}collections/${handle}.json`;\n      const response = await rateLimitedFetch(url, { method: \"HEAD\" });\n      const exists = response.ok;\n\n      this.setCacheValue(cacheKey, exists);\n      return exists;\n    } catch (_error) {\n      this.setCacheValue(cacheKey, false);\n      return false;\n    }\n  }\n\n  /**\n   * Check if cache entry is still valid\n   */\n  private isCacheValid(key: string): boolean {\n    const timestamp = this.cacheTimestamps.get(key);\n    if (!timestamp) return false;\n\n    return Date.now() - timestamp < this.cacheExpiry;\n  }\n\n  /**\n   * Set cache value with timestamp\n   */\n  private setCacheValue(key: string, value: boolean): void {\n    this.validationCache.set(key, value);\n    this.cacheTimestamps.set(key, Date.now());\n  }\n\n  /**\n   * Validate links in batches to avoid overwhelming the server\n   */\n  private async validateLinksInBatches<T>(\n    items: T[],\n    validator: (item: T) => Promise<boolean>,\n    batchSize = 10\n  ): Promise<T[]> {\n    const validItems: T[] = [];\n\n    for (let i = 0; i < items.length; i += batchSize) {\n      const batch = items.slice(i, i + batchSize);\n      const validationPromises = batch.map(async (item) => {\n        const isValid = await validator(item);\n        return isValid ? item : null;\n      });\n\n      const results = await Promise.all(validationPromises);\n      const validBatchItems = results.filter(\n        (item): item is NonNullable<typeof item> => item !== null\n      );\n      validItems.push(...validBatchItems);\n\n      // Add small delay between batches to be respectful\n      if (i + batchSize < items.length) {\n        await new Promise((resolve) => setTimeout(resolve, 100));\n      }\n    }\n\n    return validItems;\n  }\n\n  /**\n   * Fetches comprehensive store information including metadata, social links, and showcase content.\n   *\n   * @returns {Promise<StoreInfo>} Store information object containing:\n   * - `name` - Store name from meta tags or domain\n   * - `domain` - Store domain URL\n   * - `slug` - Generated store slug\n   * - `title` - Store title from meta tags\n   * - `description` - Store description from meta tags\n   * - `logoUrl` - Store logo URL from Open Graph or CDN\n   * - `socialLinks` - Object with social media links (facebook, twitter, instagram, etc.)\n   * - `contactLinks` - Object with contact information (tel, email, contactPage)\n   * - `headerLinks` - Array of navigation links from header\n   * - `showcase` - Object with featured products and collections from homepage\n   * - `jsonLdData` - Structured data from JSON-LD scripts\n   * - `techProvider` - Shopify-specific information (walletId, subDomain)\n   * - `country` - Country detection results with ISO 3166-1 alpha-2 codes (e.g., \"US\", \"GB\")\n   *\n   * @throws {Error} When the store URL is unreachable or returns an error\n   *\n   * @example\n   * ```typescript\n   * const shop = new ShopClient('https://exampleshop.com');\n   * const storeInfo = await shop.getInfo();\n   *\n   * console.log(storeInfo.name); // \"Example Store\"\n   * console.log(storeInfo.socialLinks.instagram); // \"https://instagram.com/example\"\n   * console.log(storeInfo.showcase.products); // [\"product-handle-1\", \"product-handle-2\"]\n   * console.log(storeInfo.country); // \"US\"\n   * ```\n   */\n  async getInfo(): Promise<StoreInfo> {\n    try {\n      const { info, currencyCode } = await getInfoForStore({\n        baseUrl: this.baseUrl,\n        storeDomain: this.storeDomain,\n        validateProductExists: (handle) => this.validateProductExists(handle),\n        validateCollectionExists: (handle) =>\n          this.validateCollectionExists(handle),\n        validateLinksInBatches: (items, validator, batchSize) =>\n          this.validateLinksInBatches(items, validator, batchSize),\n      });\n      if (typeof currencyCode === \"string\") {\n        this.storeCurrency = currencyCode;\n      }\n      return info;\n    } catch (error) {\n      this.handleFetchError(error, \"fetching store info\", this.baseUrl);\n    }\n  }\n\n  /**\n   * Determine the store's primary vertical and target audience.\n   * Uses `getInfo()` internally; no input required.\n   */\n  async determineStoreType(options?: {\n    apiKey?: string;\n    model?: string;\n    maxShowcaseProducts?: number;\n    maxShowcaseCollections?: number;\n  }): Promise<StoreTypeBreakdown> {\n    try {\n      const breakdown = await determineStoreTypeForStore({\n        baseUrl: this.baseUrl,\n        getInfo: () => this.getInfo(),\n        findProduct: (handle: string) => this.products.find(handle),\n        apiKey: options?.apiKey,\n        model: options?.model,\n        maxShowcaseProducts: options?.maxShowcaseProducts,\n        maxShowcaseCollections: options?.maxShowcaseCollections,\n      });\n      return breakdown;\n    } catch (error: unknown) {\n      throw this.handleFetchError(error, \"determineStoreType\", this.baseUrl);\n    }\n  }\n}\n\nexport { classifyProduct, generateSEOContent } from \"./ai/enrich\";\nexport type { CheckoutOperations } from \"./checkout\";\nexport type { CollectionOperations } from \"./collections\";\n// Export operation interfaces\nexport type { ProductOperations } from \"./products\";\nexport type { StoreInfo, StoreOperations } from \"./store\";\n// Export all types for external use\n// Classification utility\nexport type * from \"./types\";\nexport { detectShopifyCountry } from \"./utils/detect-country\";\n// Export utility functions\nexport {\n  calculateDiscount,\n  extractDomainWithoutSuffix,\n  generateStoreSlug,\n  genProductSlug,\n  safeParseDate,\n  sanitizeDomain,\n} from \"./utils/func\";\nexport { configureRateLimit } from \"./utils/rate-limit\";\n"],"mappings":"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","names":["_a"]}