@sazito/client-sdk 1.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/core/config.ts","../src/utils/token-storage.ts","../src/core/cache.ts","../src/utils/transformers.ts","../src/core/http-client.ts","../src/utils/credentials-manager.ts","../src/constants/endpoints.ts","../src/api/products.ts","../src/api/categories.ts","../src/api/cart.ts","../src/api/orders.ts","../src/api/invoices.ts","../src/api/shipping.ts","../src/api/payments.ts","../src/api/users.ts","../src/api/search.ts","../src/api/feedbacks.ts","../src/api/wallet.ts","../src/api/cms.ts","../src/api/images.ts","../src/api/visits.ts","../src/api/booking.ts","../src/api/entity-routes.ts","../src/api/menu.ts","../src/api/general.ts","../src/core/client.ts","../src/core/module-context.ts","../src/modules/products.ts","../src/modules/categories.ts","../src/modules/cart.ts","../src/modules/orders.ts","../src/modules/invoices.ts","../src/modules/shipping.ts","../src/modules/payments.ts","../src/modules/users.ts","../src/modules/search.ts","../src/modules/feedbacks.ts","../src/modules/wallet.ts","../src/modules/cms.ts","../src/modules/images.ts","../src/modules/visits.ts","../src/modules/booking.ts","../src/modules/entity-routes.ts","../src/modules/menu.ts","../src/modules/general.ts"],"sourcesContent":["/**\n * SDK Configuration\n */\n\nexport interface CacheConfig {\n enabled: boolean;\n ttl?: number; // Time to live in milliseconds\n}\n\nexport interface RetryConfig {\n enabled: boolean;\n retries: number; // 0-3\n retryDelay: number; // milliseconds\n}\n\nexport interface SazitoConfig {\n domain: string; // Without https (e.g., 'mystore.sazito.com')\n timeout?: number; // Request timeout in ms (default: 30000)\n retry?: RetryConfig;\n cache?: {\n products?: CacheConfig;\n categories?: CacheConfig;\n cart?: CacheConfig;\n orders?: CacheConfig;\n search?: CacheConfig;\n cms?: CacheConfig;\n tags?: CacheConfig;\n entityRoutes?: CacheConfig;\n };\n customFetchApi?: typeof fetch; // Custom fetch implementation\n debug?: boolean;\n}\n\nexport const DEFAULT_CONFIG: Required<Omit<SazitoConfig, 'domain' | 'customFetchApi'>> = {\n timeout: 30000,\n retry: {\n enabled: true,\n retries: 3,\n retryDelay: 1000\n },\n cache: {\n products: { enabled: true, ttl: 600000 }, // 10 min\n categories: { enabled: true, ttl: 600000 }, // 10 min\n cart: { enabled: false }, // Never cache\n orders: { enabled: false }, // Never cache\n search: { enabled: true, ttl: 300000 }, // 5 min\n cms: { enabled: true, ttl: 600000 }, // 10 min\n tags: { enabled: true, ttl: 600000 }, // 10 min\n entityRoutes: { enabled: true, ttl: 600000 } // 10 min\n },\n debug: false\n};\n\n/**\n * Merge user config with defaults\n */\nexport function mergeConfig(userConfig: SazitoConfig): Required<SazitoConfig> {\n return {\n ...DEFAULT_CONFIG,\n ...userConfig,\n retry: {\n ...DEFAULT_CONFIG.retry,\n ...userConfig.retry\n },\n cache: {\n ...DEFAULT_CONFIG.cache,\n ...userConfig.cache\n },\n customFetchApi: userConfig.customFetchApi || (typeof fetch !== 'undefined' ? fetch : undefined) as typeof fetch\n };\n}\n","/**\n * Token storage for auth token persistence\n * Primary storage: localStorage (user_id_token), with cookie fallback.\n */\n\nimport { CookieOptions } from '../types';\n\nexport class TokenStorage {\n private readonly tokenKey = 'user_id_token';\n\n /**\n * Get token from localStorage (fallback to cookie)\n */\n get(): string | null {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n // SSR environment - no access to browser storage\n return null;\n }\n\n const storageToken = this.getFromLocalStorage();\n if (storageToken) return storageToken;\n\n const cookies = this.parseCookies();\n return cookies[this.tokenKey] || null;\n }\n\n /**\n * Set token in localStorage and cookie fallback\n */\n set(token: string, options?: CookieOptions): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n // SSR environment - cannot set browser storage\n console.warn('[Sazito SDK] Cannot set token in SSR environment');\n return;\n }\n\n this.setInLocalStorage(token);\n\n const defaultOptions: CookieOptions = {\n secure: true,\n sameSite: 'Lax',\n maxAge: 30 * 24 * 60 * 60,\n path: '/',\n ...options\n };\n this.setCookie(this.tokenKey, token, defaultOptions);\n }\n\n /**\n * Remove token from both localStorage and cookie\n */\n remove(): void {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n this.removeFromLocalStorage();\n this.setCookie(this.tokenKey, '', { maxAge: -1, path: '/' });\n }\n\n private getFromLocalStorage(): string | null {\n try {\n return window.localStorage.getItem(this.tokenKey);\n } catch {\n return null;\n }\n }\n\n private setInLocalStorage(token: string): void {\n try {\n window.localStorage.setItem(this.tokenKey, token);\n } catch {\n // Ignore storage exceptions (private mode/quota/security)\n }\n }\n\n private removeFromLocalStorage(): void {\n try {\n window.localStorage.removeItem(this.tokenKey);\n } catch {\n // Ignore storage exceptions (private mode/quota/security)\n }\n }\n\n /**\n * Parse document.cookie into key-value pairs\n */\n private parseCookies(): Record<string, string> {\n if (typeof document === 'undefined') {\n return {};\n }\n\n return document.cookie.split(';').reduce((acc, cookie) => {\n const [key, value] = cookie.trim().split('=');\n if (key && value) {\n acc[key] = decodeURIComponent(value);\n }\n return acc;\n }, {} as Record<string, string>);\n }\n\n /**\n * Set a cookie with options\n */\n private setCookie(name: string, value: string, options: CookieOptions): void {\n let cookie = `${name}=${encodeURIComponent(value)}`;\n\n if (options.maxAge !== undefined) {\n cookie += `; Max-Age=${options.maxAge}`;\n }\n if (options.path) {\n cookie += `; Path=${options.path}`;\n }\n if (options.domain) {\n cookie += `; Domain=${options.domain}`;\n }\n if (options.secure) {\n cookie += `; Secure`;\n }\n if (options.httpOnly) {\n cookie += `; HttpOnly`;\n }\n if (options.sameSite) {\n cookie += `; SameSite=${options.sameSite}`;\n }\n\n document.cookie = cookie;\n }\n}\n","/**\n * Simple cache implementation with TTL support\n */\n\ninterface CacheEntry<T> {\n data: T;\n timestamp: number;\n}\n\nexport class CacheManager {\n private cache = new Map<string, CacheEntry<any>>();\n\n /**\n * Get cached value if it exists and hasn't expired\n */\n get<T>(key: string, ttl?: number): T | null {\n const entry = this.cache.get(key);\n\n if (!entry) {\n return null;\n }\n\n // Check if expired\n if (ttl && Date.now() - entry.timestamp > ttl) {\n this.cache.delete(key);\n return null;\n }\n\n return entry.data as T;\n }\n\n /**\n * Set cache value\n */\n set<T>(key: string, data: T): void {\n this.cache.set(key, {\n data,\n timestamp: Date.now()\n });\n }\n\n /**\n * Clear specific cache entry\n */\n delete(key: string): void {\n this.cache.delete(key);\n }\n\n /**\n * Clear cache entries matching a pattern\n */\n deletePattern(pattern: string): void {\n const regex = new RegExp(pattern);\n const keysToDelete: string[] = [];\n\n this.cache.forEach((_, key) => {\n if (regex.test(key)) {\n keysToDelete.push(key);\n }\n });\n\n keysToDelete.forEach(key => this.cache.delete(key));\n }\n\n /**\n * Clear all cache\n */\n clear(): void {\n this.cache.clear();\n }\n\n /**\n * Generate cache key from URL and params\n */\n static generateKey(method: string, url: string, params?: any): string {\n const paramString = params ? JSON.stringify(params) : '';\n return `${method}:${url}:${paramString}`;\n }\n}\n","/**\n * API Data Transformers\n * Convert between SDK-friendly camelCase and backend snake_case\n */\n\n/**\n * Field name mapping for beautification\n * Maps backend field names to more developer-friendly SDK names\n */\nconst FIELD_NAME_MAP: Record<string, string> = {\n // Quantity/Count fields\n no_of_items: 'quantity',\n\n // Price fields\n single_item_price: 'unitPrice',\n total_items_price: 'lineTotal',\n items_total_raw_price: 'totalOriginalPrice',\n items_discount: 'totalDiscount',\n customer_profit: 'savings',\n customer_profit_percentage: 'savingsPercentage',\n total_amount: 'totalAmount',\n net_total: 'subtotal',\n gross_total: 'total',\n final_total: 'finalTotal',\n discount_total: 'discountTotal',\n shipping_total: 'shippingTotal',\n tax_total: 'taxTotal',\n\n // Identifier fields\n unique_identifier: 'identifier',\n invoice_identifier: 'identifier',\n payment_identifier: 'identifier',\n shipping_address_identifier: 'identifier',\n\n // User/Address fields\n first_name: 'firstName',\n last_name: 'lastName',\n mobile_phone: 'mobilePhone',\n phone_number: 'phoneNumber',\n postal_code: 'postalCode',\n user_comment: 'comment',\n\n // Product fields\n product_id: 'productId',\n variant_id: 'variantId',\n product_name: 'name',\n product_image: 'image',\n product_variant: 'variant',\n product_variants: 'variants',\n product_categories: 'categories',\n product_attributes: 'attributes',\n product_type: 'productType',\n\n // CMS fields\n title: 'name', // CMS pages use 'title' field which we map to 'name'\n short_description: 'shortDescription',\n stock_quantity: 'stockQuantity',\n stock_number: 'stockQuantity',\n sale_price: 'salePrice',\n raw_price: 'originalPrice',\n has_max_order: 'hasMaxOrder',\n max_no_of_order: 'maxOrderQuantity',\n min_order_count: 'minOrderQuantity',\n sold_count: 'soldCount',\n static_url: 'staticUrl',\n dynamic_form_id: 'dynamicFormId',\n event_entity_id: 'eventEntityId',\n theme_config: 'themeConfig',\n image_id: 'imageId',\n is_stock_managed: 'isStockManaged',\n commercial_files: 'commercialFiles',\n sort_index: 'sortIndex',\n attribute_type: 'attributeType',\n\n // Cart fields\n cart_products: 'items',\n cart_product_id: 'cartProductId',\n\n // Invoice fields\n invoice_items: 'items',\n\n // Product list fields\n products: 'items',\n total_count: 'total',\n\n // Shipping fields\n shipping_method_needed: 'needsShipping',\n shipping_method: 'shippingMethod',\n shipping_address: 'shippingAddress',\n shipping_items: 'shippingItems',\n delivery_time: 'deliveryTime',\n min_delivery_days: 'minDays',\n max_delivery_days: 'maxDays',\n\n // Payment fields\n payment_type: 'paymentType',\n payment_types: 'methods',\n reference_code: 'code',\n is_default: 'isDefault',\n\n // Boolean fields\n is_available: 'isAvailable',\n delete_coupon: 'deleteCoupon',\n\n // Form fields\n form_attributes: 'formAttributes',\n booking_attributes: 'bookingAttributes',\n readable_form_attr: 'formFields',\n\n // Date fields\n created_at: 'createdAt',\n updated_at: 'updatedAt',\n\n // Pagination fields\n page_number: 'page',\n page_size: 'pageSize',\n total_count_raw: 'totalCountRaw',\n max_price: 'maxPrice',\n min_price: 'minPrice',\n stock_alert_limit: 'stockAlertLimit',\n sub_categories: 'subCategories',\n\n // Order fields\n order_number: 'orderNumber',\n\n // Sort fields\n sort_order: 'sortOrder',\n\n // Filter fields\n pinned_ids: 'pinnedIds',\n\n // Region/City fields\n region_id: 'regionId',\n city_id: 'cityId',\n parent_id: 'parentId',\n\n // Discount fields\n discount_code: 'discountCode',\n\n // Entity route fields\n entity_name: 'entityType',\n entity_id: 'entityId',\n other_props: 'entity',\n\n // Shipping method/rate fields\n shipping_methods: 'shippingMethods',\n shipping_rates: 'shippingRates',\n grouped_shipping_rates: 'groupedShippingRates',\n items_shipping_rate: 'itemsShippingRate',\n shipping_rate: 'shippingRate',\n rate_id: 'rateId',\n invoice_item_id: 'invoiceItemId',\n invoice_item_ids: 'invoiceItemIds',\n\n // Scheduler/Booking fields\n scheduler_booking_attributes: 'schedulerBookingAttributes',\n\n // Inventory fields\n inventory_count: 'inventoryCount',\n\n // Order fields (additional)\n order_identifier: 'orderIdentifier',\n self_only: 'selfOnly',\n\n // Coupon fields\n coupon: 'coupon',\n\n // Coordinates fields\n user_set_coordinates_before: 'userSetCoordinatesBefore',\n\n // Image fields\n alt: 'alt',\n url: 'url',\n\n // Shop feature flags (General API)\n activate_add_to_cart_alert: 'addToCardAlert',\n activate_advanced_card_to_card: 'advancedCardToCard',\n activate_ayria_payment_customization: 'ayriaPaymentGateway',\n activate_azki_payment_customization: 'azkiPaymentGateway',\n activate_bazar_payment_customization: 'bazarPaymentGateway',\n activate_blog: 'shopBlog',\n activate_card_to_card_payment: 'cardToCardPayment',\n activate_checkout_dynamic_form: 'checkoutDynamicForm',\n activate_different_register_customization: 'multiTypeRegister',\n activate_digipay_payment: 'digipayPaymentGateway',\n activate_digipay_payment_customization: 'digipayPaymentGateway',\n activate_filter_products: 'productFilters',\n activate_ghesta_payment_customization: 'ghestaPaymentGateway',\n activate_mega_footer: 'megaFooter',\n activate_mellat_payment_customization: 'mellatPaymentGateway',\n activate_min_basket: 'checkoutMinimumAmount',\n activate_novapay_payment_customization: 'novapayPaymentGateway',\n activate_ozon_payment_customization: 'ozonPaymentGateway',\n activate_payment_in_place: 'paymentInPlace',\n activate_payping_payment: 'paypingPaymentGateway',\n activate_pec_payment_customization: 'pecPaymentGateway',\n activate_sabin_payment_customization: 'sabinPaymentGateway',\n activate_sadad_payment_customization: 'sadadPaymentGateway',\n activate_search: 'shopSearch',\n activate_sep_payment_customization: 'sepPaymentGateway',\n activate_shop_vat: 'shopVat',\n activate_snapppay_payment_customization: 'snapppayPaymentGateway',\n activate_tajrobe: 'tajrobe',\n activate_tara_payment_customization: 'taraPaymentGateway',\n activate_theme_config_settings: 'themeConfigSettings',\n activate_toman_payment_customization: 'tomanPaymentGateway',\n activate_torobpay_payment_customization: 'torobpayPaymentGateway',\n activate_up_payment_customization: 'asanpardakhtPaymentGateway',\n activate_vandar_payment_customization: 'vandarPaymentGateway',\n activate_wallet: 'wallet',\n activate_yourgate_payment_customization: 'yourgatePaymentGateway',\n activate_zarinpal_payment: 'zarinpalPaymentGateway',\n activate_zarinplus_payment_customization: 'zarinplusPaymentGateway',\n activate_zibal_payment_customization: 'zibalPaymentGateway',\n activate_zify_payment_customization: 'zifyPaymentGateway',\n disable_ordering: 'disableOrdering',\n pwa: 'progressiveWebApp',\n remove_front_basket: 'hideCheckout',\n remove_front_taint: 'sazitoBrandingRemoval'\n};\n\n/**\n * Reverse mapping for request transformation\n */\nconst REVERSE_FIELD_NAME_MAP: Record<string, string> = Object.entries(FIELD_NAME_MAP).reduce(\n (acc, [key, value]) => {\n // Only add to reverse map if the value doesn't already exist\n // This prevents conflicts (e.g., both cart_products and invoice_items → items)\n if (!acc[value]) {\n acc[value] = key;\n }\n return acc;\n },\n {} as Record<string, string>\n);\n\n/**\n * Convert snake_case string to camelCase\n */\nfunction snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\n/**\n * Convert camelCase string to snake_case\n */\nfunction camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Check if value is a plain object\n */\nfunction isPlainObject(value: any): boolean {\n return value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date);\n}\n\nfunction removeKeys<T extends Record<string, any>>(obj: T, keys: string[]): Partial<T> {\n const cleaned = { ...obj };\n for (const key of keys) {\n delete (cleaned as Record<string, any>)[key];\n }\n return cleaned;\n}\n\n/**\n * Transform object keys from snake_case to camelCase with field name beautification\n * @param obj - Object to transform\n * @returns Transformed object with camelCase keys and beautiful field names\n */\nexport function transformResponseKeys(obj: any): any {\n if (!isPlainObject(obj)) {\n if (Array.isArray(obj)) {\n return obj.map(item => transformResponseKeys(item));\n }\n return obj;\n }\n\n const transformed: any = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // First try to use the beautiful field name mapping\n let newKey = FIELD_NAME_MAP[key];\n\n // If no mapping exists, convert snake_case to camelCase\n if (!newKey) {\n newKey = snakeToCamel(key);\n }\n\n // Recursively transform nested objects and arrays\n if (isPlainObject(value)) {\n transformed[newKey] = transformResponseKeys(value);\n } else if (Array.isArray(value)) {\n transformed[newKey] = value.map(item => transformResponseKeys(item));\n } else {\n transformed[newKey] = value;\n }\n }\n\n return transformed;\n}\n\n/**\n * Transform object keys from camelCase to snake_case for API requests\n * @param obj - Object to transform\n * @returns Transformed object with snake_case keys\n */\nexport function transformRequestKeys(obj: any): any {\n if (!isPlainObject(obj)) {\n if (Array.isArray(obj)) {\n return obj.map(item => transformRequestKeys(item));\n }\n return obj;\n }\n\n const transformed: any = {};\n\n for (const [key, value] of Object.entries(obj)) {\n // First try to use the reverse mapping for known fields\n let newKey = REVERSE_FIELD_NAME_MAP[key];\n\n // If no mapping exists, convert camelCase to snake_case\n if (!newKey) {\n newKey = camelToSnake(key);\n }\n\n // Recursively transform nested objects and arrays\n if (isPlainObject(value)) {\n transformed[newKey] = transformRequestKeys(value);\n } else if (Array.isArray(value)) {\n transformed[newKey] = value.map(item => transformRequestKeys(item));\n } else {\n transformed[newKey] = value;\n }\n }\n\n return transformed;\n}\n\n/**\n * Transform API response data structure\n * Unwraps the { data: { result: { ... } } } structure and transforms keys\n */\nexport function transformApiResponse<T = any>(response: any): T {\n // Handle standard Sazito API response structure\n if (response?.data?.result) {\n const result = response.data.result;\n\n // If result has a single key (e.g., { product: {...} }, { cart: {...} })\n // extract and transform that entity\n const keys = Object.keys(result);\n if (keys.length === 1 && isPlainObject(result[keys[0]])) {\n return transformResponseKeys(result[keys[0]]) as T;\n }\n\n // Otherwise transform the entire result object\n return transformResponseKeys(result) as T;\n }\n\n // If already unwrapped, just transform keys\n return transformResponseKeys(response) as T;\n}\n\n/**\n * Specific transformer for general info response\n * Merges 'general' and 'shop' fields into a single 'shop' field\n */\nexport function transformGeneralInfoResponse(data: any): any {\n if (!data) return data;\n\n const {\n general,\n shop,\n checkout,\n features,\n wallet,\n tajrobe,\n domain,\n enamad,\n google,\n logo,\n social,\n ...rest\n } = data;\n\n // Merge general and shop into a single shop object\n const mergedShop = {\n ...general,\n ...shop\n };\n\n const {\n registerType,\n showProductStockNumber,\n ...shopWithoutSettings\n } = mergedShop || {};\n\n let normalizedCheckout = checkout;\n if (isPlainObject(checkout)) {\n const checkoutCopy = { ...checkout };\n\n if (checkoutCopy.preventRedirect === undefined && checkoutCopy.manual !== undefined) {\n checkoutCopy.preventRedirect = checkoutCopy.manual;\n }\n\n delete checkoutCopy.manual;\n normalizedCheckout = checkoutCopy;\n }\n\n const transformed = {\n ...rest,\n scripts: {\n enamad,\n google\n },\n shop: normalizeGeneralShop({\n ...shopWithoutSettings,\n domain,\n logo,\n social\n }),\n settings: {\n checkout: normalizedCheckout,\n features: normalizeGeneralFeatures(features),\n wallet: normalizeGeneralWallet(wallet),\n tajrobe: normalizeGeneralTajrobe(tajrobe),\n registerType: normalizeGeneralRegisterType(registerType),\n showProductStockNumber: normalizeGeneralShowProductStockNumber(showProductStockNumber)\n }\n };\n\n return transformed;\n}\n\nfunction normalizeGeneralRegisterType(registerType: any): string {\n return typeof registerType === 'string' ? registerType : '';\n}\n\nfunction normalizeGeneralShowProductStockNumber(value: any): boolean {\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (isPlainObject(value) && Object.prototype.hasOwnProperty.call(value, 'enabled')) {\n return normalizeGeneralShowProductStockNumber((value as any).enabled);\n }\n\n if (value === 1 || value === '1' || value === 'true') {\n return true;\n }\n\n if (value === 0 || value === '0' || value === 'false') {\n return false;\n }\n\n return false;\n}\n\nfunction normalizeGeneralShop(shop: any): any {\n if (!isPlainObject(shop)) {\n return shop;\n }\n\n const normalizedShop = { ...shop };\n\n if (isPlainObject(normalizedShop.city)) {\n const cityWithoutMeta = removeKeys(normalizedShop.city, ['createdAt', 'updatedAt']) as any;\n\n let cleanedRegion = cityWithoutMeta.region;\n if (isPlainObject(cleanedRegion)) {\n cleanedRegion = removeKeys(cleanedRegion, ['createdAt', 'updatedAt', 'cities']);\n }\n\n cityWithoutMeta.region = cleanedRegion;\n normalizedShop.city = cityWithoutMeta;\n }\n\n return normalizedShop;\n}\n\nconst FEATURE_FLAG_NAME_MAP: Record<string, string> = {\n addToCardAlert: 'addToCartAlertEnabled',\n addToCartAlert: 'addToCartAlertEnabled',\n advancedCardToCard: 'advancedCardToCardEnabled',\n cardToCardPayment: 'cardToCardPaymentEnabled',\n checkoutDynamicForm: 'checkoutDynamicFormEnabled',\n multiTypeRegister: 'multiTypeRegisterEnabled',\n productFilters: 'productFiltersEnabled',\n megaFooter: 'megaFooterEnabled',\n checkoutMinimumAmount: 'checkoutMinimumAmountEnabled',\n paymentInPlace: 'paymentInPlaceEnabled',\n shopBlog: 'blogEnabled',\n shopSearch: 'searchEnabled',\n shopVat: 'shopVatEnabled',\n tajrobe: 'tajrobeEnabled',\n themeConfigSettings: 'themeConfigSettingsEnabled',\n wallet: 'walletEnabled',\n progressiveWebApp: 'progressiveWebAppEnabled',\n disableOrdering: 'orderingDisabled',\n hideCheckout: 'checkoutHidden',\n sazitoBrandingRemoval: 'sazitoBrandingRemoved',\n ayriaPaymentGateway: 'ayriaPaymentGatewayEnabled',\n azkiPaymentGateway: 'azkiPaymentGatewayEnabled',\n bazarPaymentGateway: 'bazarPaymentGatewayEnabled',\n digipayPaymentGateway: 'digipayPaymentGatewayEnabled',\n ghestaPaymentGateway: 'ghestaPaymentGatewayEnabled',\n mellatPaymentGateway: 'mellatPaymentGatewayEnabled',\n novapayPaymentGateway: 'novapayPaymentGatewayEnabled',\n ozonPaymentGateway: 'ozonPaymentGatewayEnabled',\n paypingPaymentGateway: 'paypingPaymentGatewayEnabled',\n pecPaymentGateway: 'pecPaymentGatewayEnabled',\n sabinPaymentGateway: 'sabinPaymentGatewayEnabled',\n sadadPaymentGateway: 'sadadPaymentGatewayEnabled',\n sepPaymentGateway: 'sepPaymentGatewayEnabled',\n snapppayPaymentGateway: 'snapppayPaymentGatewayEnabled',\n taraPaymentGateway: 'taraPaymentGatewayEnabled',\n tomanPaymentGateway: 'tomanPaymentGatewayEnabled',\n torobpayPaymentGateway: 'torobpayPaymentGatewayEnabled',\n asanpardakhtPaymentGateway: 'asanpardakhtPaymentGatewayEnabled',\n vandarPaymentGateway: 'vandarPaymentGatewayEnabled',\n yourgatePaymentGateway: 'yourgatePaymentGatewayEnabled',\n zarinpalPaymentGateway: 'zarinpalPaymentGatewayEnabled',\n zarinplusPaymentGateway: 'zarinplusPaymentGatewayEnabled',\n zibalPaymentGateway: 'zibalPaymentGatewayEnabled',\n zifyPaymentGateway: 'zifyPaymentGatewayEnabled',\n activateEditOrderCustomization: 'editOrderEnabled',\n activateEditOrderCustomizationEnabled: 'editOrderEnabled'\n};\n\nconst FEATURE_FLAG_BLOCKLIST = new Set([\n 'activateAlopeykAdvanced',\n 'activate_alopeyk_advanced'\n]);\n\nconst FEATURE_FLAG_NAME_BLOCKLIST = new Set([\n 'auditLogEnabled',\n 'editOrderEnabled',\n 'rahkaranAccountingCustomizationEnabled',\n 'advancedThemeDesignerEnabled',\n 'checkoutHidden',\n 'eventPublisherEnabled',\n 'exportOrdersEnabled',\n 'exportProductsEnabled',\n 'exportUsersEnabled',\n 'fontCustomizationEnabled',\n 'forwardShippingEnabled',\n 'podroShippingEnabled',\n 'postexShippingEnabled',\n 'quotaNotificationsEnabled',\n 'recaptchaEnabled',\n 'rolePoliciesEnabled',\n 'sepidarAccountingCustomizationEnabled',\n 'shortUrlEnabled',\n 'skuSearchEnabled',\n 'snappShopCustomizationEnabled',\n 'snappboxShippingEnabled',\n 'stockAlertNotificationsEnabled',\n 'tapsipackShippingEnabled',\n 'themeConfigSettingsEnabled',\n 'advancedTextEditorEnabled',\n 'advancedShippingEnabled',\n 'bulkActionEnabled',\n 'discountBulkEnabled',\n 'discountCodeEnabled',\n 'orderBulkActionEnabled',\n 'importProductsEnabled',\n 'mahakAccountingCustomizationEnabled',\n 'millipayPaymentCustomizationEnabled',\n 'orderSmsNotificationsEnabled'\n]);\n\nfunction normalizeFeatureFlagName(rawKey: string): string {\n const camelKey = rawKey.includes('_') ? snakeToCamel(rawKey) : rawKey;\n const mapped = FEATURE_FLAG_NAME_MAP[camelKey];\n if (mapped) return mapped;\n\n // UX normalization: strip \"activate\" prefix from unknown flags.\n const withoutActivatePrefix = camelKey.startsWith('activate') && camelKey.length > 'activate'.length\n ? `${camelKey.charAt('activate'.length).toLowerCase()}${camelKey.slice('activate'.length + 1)}`\n : camelKey;\n\n if (\n withoutActivatePrefix.endsWith('Enabled') ||\n withoutActivatePrefix.endsWith('Disabled') ||\n withoutActivatePrefix.endsWith('Hidden') ||\n withoutActivatePrefix.endsWith('Removed')\n ) {\n return withoutActivatePrefix;\n }\n\n return `${withoutActivatePrefix}Enabled`;\n}\n\nfunction normalizeGeneralFeatures(features: any): any {\n if (!isPlainObject(features)) {\n return {};\n }\n\n const readBooleanish = (value: any): boolean | undefined => {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'number') {\n if (value === 1) return true;\n if (value === 0) return false;\n return undefined;\n }\n if (typeof value === 'string') {\n const normalized = value.trim().toLowerCase();\n if (normalized === 'true' || normalized === '1') return true;\n if (normalized === 'false' || normalized === '0') return false;\n return undefined;\n }\n return undefined;\n };\n\n const rawFlags: Record<string, boolean> = {};\n const pushFlag = (key: string, value: any) => {\n if (FEATURE_FLAG_BLOCKLIST.has(key)) return;\n const normalized = readBooleanish(value);\n if (normalized === undefined) return;\n rawFlags[key] = normalized;\n };\n\n if (isPlainObject(features.flags)) {\n Object.entries(features.flags).forEach(([key, value]) => {\n pushFlag(key, value);\n });\n }\n\n if (isPlainObject((features as any).configurations)) {\n Object.entries((features as any).configurations).forEach(([key, value]) => {\n pushFlag(key, value);\n });\n }\n\n Object.entries(features).forEach(([key, value]) => {\n if (key === 'flags' || key === 'premium' || key === 'configurations') return;\n if (isPlainObject(value) && Object.prototype.hasOwnProperty.call(value, 'enabled')) {\n pushFlag(key, (value as any).enabled);\n return;\n }\n pushFlag(key, value);\n });\n\n const flags: Record<string, boolean> = {};\n Object.entries(rawFlags).forEach(([key, value]) => {\n const normalizedName = normalizeFeatureFlagName(key);\n if (FEATURE_FLAG_NAME_BLOCKLIST.has(normalizedName)) return;\n flags[normalizedName] = value;\n });\n\n const normalized: any = { ...flags };\n if (isPlainObject(features.premium)) {\n normalized.premium = features.premium;\n }\n\n return normalized;\n}\n\nfunction normalizeGeneralWallet(wallet: any): any {\n if (!isPlainObject(wallet)) {\n return wallet;\n }\n\n const source = isPlainObject(wallet.configurations)\n ? { ...wallet, ...wallet.configurations }\n : { ...wallet };\n\n const toBoolean = (value: any): boolean | undefined => {\n if (typeof value === 'boolean') return value;\n if (value === 1 || value === '1' || value === 'true') return true;\n if (value === 0 || value === '0' || value === 'false') return false;\n return undefined;\n };\n\n const toNumber = (value: any): number | undefined => {\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n };\n\n const enabled = toBoolean(source.enabled);\n const useWithDiscount = toBoolean(source.useWithDiscount);\n const minAmount = toNumber(source.minAmount ?? source.walletMinAmount);\n const minAmountRequired = toBoolean(source.minAmountRequired ?? source.walletMinStatus);\n\n return {\n enabled: enabled ?? false,\n useWithDiscount: useWithDiscount ?? false,\n minAmount: minAmount ?? 0,\n minAmountRequired: minAmountRequired ?? false\n };\n}\n\nfunction normalizeGeneralTajrobe(tajrobe: any): any {\n if (!isPlainObject(tajrobe)) {\n return tajrobe;\n }\n\n const source = isPlainObject(tajrobe.configurations)\n ? { ...tajrobe, ...tajrobe.configurations }\n : { ...tajrobe };\n\n let enabled: boolean = false;\n if (typeof source.enabled === 'boolean') {\n enabled = source.enabled;\n } else if (source.enabled === 1 || source.enabled === '1' || source.enabled === 'true') {\n enabled = true;\n }\n\n return { enabled };\n}\n\n/**\n * Specific transformer for cart responses\n * Handles the cart-specific data structure\n */\nexport function transformCartResponse(response: any): any {\n const cart = transformApiResponse(response);\n\n // Additional cart-specific transformations\n if (cart.items && Array.isArray(cart.items)) {\n cart.items = cart.items.map((item: any) => ({\n ...item,\n // Flatten product variant structure\n product: {\n variantId: item.variant?.id || item.product?.variantId,\n productId: item.variant?.product?.id || item.product?.productId,\n name: item.name || item.product?.name,\n image: item.image || item.product?.image,\n attributes: item.attributes || item.product?.attributes || [],\n hasMaxOrder: item.product?.hasMaxOrder || false,\n maxOrderQuantity: item.product?.maxOrderQuantity,\n minOrderQuantity: item.product?.minOrderQuantity\n }\n }));\n }\n\n return cart;\n}\n\n/**\n * Specific transformer for invoice responses\n * Handles the invoice-specific data structure\n */\nexport function transformInvoiceResponse(response: any): any {\n const invoice = transformApiResponse(response);\n\n // Additional invoice-specific transformations\n if (invoice.items && Array.isArray(invoice.items)) {\n invoice.items = invoice.items.map((item: any) => ({\n ...item,\n // Calculate discount from original price if not present\n discount: item.discount || (item.originalPrice ? item.originalPrice - item.unitPrice : 0)\n }));\n }\n\n return invoice;\n}\n\n/**\n * Clean product object by removing unwanted fields\n */\nfunction cleanProduct(product: any): any {\n if (!product) return product;\n\n // Fields to remove from product\n const cleanedProduct = removeKeys(product, ['staticUrl', 'summary', 'tags', 'slug']) as any;\n\n // Clean variants\n if (cleanedProduct.variants && Array.isArray(cleanedProduct.variants)) {\n cleanedProduct.variants = cleanedProduct.variants.map((variant: any) =>\n removeKeys(variant, ['name', 'title', 'product', 'status', 'soldCount'])\n );\n }\n\n // Clean categories - keep only id, name, url\n if (cleanedProduct.categories && Array.isArray(cleanedProduct.categories)) {\n cleanedProduct.categories = cleanedProduct.categories.map((category: any) => ({\n id: category.id,\n name: category.name,\n url: category.url\n }));\n }\n\n // Clean images - remove widthRatio, heightRatio, thumb\n if (cleanedProduct.images && Array.isArray(cleanedProduct.images)) {\n cleanedProduct.images = cleanedProduct.images.map((image: any) =>\n removeKeys(image, ['widthRatio', 'heightRatio', 'thumb'])\n );\n }\n\n return cleanedProduct;\n}\n\nfunction cleanProductListItem(product: any): any {\n const cleaned = cleanProduct(product);\n if (!cleaned) return cleaned;\n\n return removeKeys(cleaned, ['themeConfig']);\n}\n\n/**\n * Specific transformer for product list responses\n * Handles paginated product lists\n */\nexport function transformProductListResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n // Handle pagination structure\n if (transformed.items && Array.isArray(transformed.items)) {\n return {\n items: transformed.items.map((item: any) => cleanProductListItem(item)),\n total: transformed.total || transformed.items.length,\n page: transformed.page || 1,\n pageSize: transformed.pageSize || transformed.items.length,\n totalPages: transformed.totalPages || Math.ceil((transformed.total || transformed.items.length) / (transformed.pageSize || transformed.items.length))\n };\n }\n\n return transformed;\n}\n\n/**\n * Specific transformer for search responses\n * Search API returns multiple entity types (products, blog_pages, cms_pages, product_categories)\n * NOTE: Data comes already transformed to camelCase by http-client\n */\nexport function transformSearchResponse(data: any): any {\n if (!data) return data;\n\n const response: any = {\n products: {\n items: [],\n total: 0,\n page: 1,\n pageSize: 20\n },\n blogPages: {\n items: [],\n total: 0,\n page: 1,\n pageSize: 20\n },\n cmsPages: {\n items: [],\n total: 0,\n page: 1,\n pageSize: 20\n },\n productCategories: {\n items: [],\n total: 0,\n page: 1,\n pageSize: 20\n }\n };\n\n // Extract products (API returns as \"products\" but HTTP client converts to \"items\")\n if (data.items && Array.isArray(data.items)) {\n response.products.items = data.items.map((product: any) => cleanProductListItem(product));\n response.products.total = data.productsCount || 0;\n response.products.page = data.productsPageNumber || 1;\n response.products.pageSize = data.productsPageSize || 20;\n }\n\n // Extract blog pages\n if (data.blogPages && Array.isArray(data.blogPages)) {\n response.blogPages.items = data.blogPages.map((page: any) => cleanCmsPageListItem(page));\n response.blogPages.total = data.blogPagesCount || 0;\n response.blogPages.page = data.blogPagesPageNumber || 1;\n response.blogPages.pageSize = data.blogPagesPageSize || 20;\n }\n\n // Extract CMS pages\n if (data.cmsPages && Array.isArray(data.cmsPages)) {\n response.cmsPages.items = data.cmsPages.map((page: any) => cleanCmsPageListItem(page));\n response.cmsPages.total = data.cmsPagesCount || 0;\n response.cmsPages.page = data.cmsPagesPageNumber || 1;\n response.cmsPages.pageSize = data.cmsPagesPageSize || 20;\n }\n\n // Extract product categories (API returns as \"product_categories\" but HTTP client converts to \"categories\")\n if (data.categories && Array.isArray(data.categories)) {\n response.productCategories.items = data.categories.map((cat: any) => cleanCategoryListItem(cat));\n response.productCategories.total = data.productCategoriesCount || 0;\n response.productCategories.page = data.productCategoriesPageNumber || 1;\n response.productCategories.pageSize = data.productCategoriesPageSize || 20;\n }\n\n return response;\n}\n\n/**\n * Transform shipping address input for API request\n */\nexport function transformShippingAddressInput(input: any): any {\n return {\n shipping_address: transformRequestKeys(input)\n };\n}\n\n/**\n * Transform add to cart input for API request\n */\nexport function transformAddToCartInput(variantId: number, quantity: number, formAttributes?: any): any {\n const input: any = {\n product_variants: [\n {\n id: variantId,\n count: quantity\n }\n ]\n };\n\n if (formAttributes) {\n input.form_attributes = transformRequestKeys(formAttributes);\n }\n\n return input;\n}\n\n/**\n * Transform create cart input for API request\n */\nexport function transformCreateCartInput(input: any): any {\n const transformed: any = {\n product_variants: input.productVariants?.map((variant: any) => ({\n id: variant.id || variant.variantId,\n count: variant.count || variant.quantity,\n form_attributes: variant.formAttributes ? transformRequestKeys(variant.formAttributes) : undefined\n })) || []\n };\n\n if (input.coupon) {\n transformed.coupon = input.coupon;\n }\n\n return transformed;\n}\n\n/**\n * Extract and transform specific fields from response\n * Useful for extracting nested data\n */\nexport function extractField<T = any>(response: any, fieldPath: string): T | undefined {\n const transformed = transformApiResponse(response);\n const parts = fieldPath.split('.');\n\n let current = transformed;\n for (const part of parts) {\n if (current?.[part] === undefined) {\n return undefined;\n }\n current = current[part];\n }\n\n return current as T;\n}\n\n/**\n * Transform payment methods response\n */\nexport function transformPaymentMethodsResponse(response: any): any {\n const result = transformApiResponse(response);\n\n // Rename paymentTypes to methods if it exists\n if (result.paymentTypes) {\n return {\n methods: result.paymentTypes\n };\n }\n\n return result;\n}\n\n/**\n * Clean category object by removing unwanted fields\n */\nfunction cleanCategory(category: any): any {\n if (!category) return category;\n\n // Fields to remove from category\n return removeKeys(category, ['staticUrl', 'products', 'items']); // items is always null in list responses\n}\n\nfunction cleanCategoryListItem(category: any): any {\n const cleaned = cleanCategory(category);\n if (!cleaned) return cleaned;\n\n return removeKeys(cleaned, ['themeConfig']);\n}\n\n/**\n * Clean CMS/Blog page object by removing unwanted fields\n */\nfunction cleanCmsPage(page: any): any {\n if (!page) return page;\n\n // Fields to remove from CMS/blog page\n return removeKeys(page, ['staticUrl', 'urlKey']);\n}\n\nfunction cleanCmsPageListItem(page: any): any {\n const cleaned = cleanCmsPage(page);\n if (!cleaned) return cleaned;\n\n return removeKeys(cleaned, ['themeConfig']);\n}\n\n/**\n * Specific transformer for entity route responses\n * Cleans entity data based on entity type\n */\nexport function transformEntityRouteResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed || !transformed.route) {\n return transformed;\n }\n\n const route = transformed.route;\n\n // Clean entity based on type\n if (route.entity) {\n switch (route.entityType) {\n case 'product':\n route.entity = cleanProduct(route.entity);\n break;\n case 'product_category':\n route.entity = cleanCategory(route.entity);\n break;\n case 'cms_page':\n case 'blog_page':\n route.entity = cleanCmsPage(route.entity);\n break;\n }\n\n // Remove duplicate id from entity since we have entityId at root\n route.entity = removeKeys(route.entity, ['id']);\n\n // Add url field at root level from entity.url\n if (!route.url && route.entity.url) {\n route.url = route.entity.url;\n }\n }\n\n return route;\n}\n\n/**\n * Clean category tree node recursively\n */\nfunction cleanCategoryTreeNode(node: any): any {\n if (!node) return node;\n\n const cleanedNode = { ...node };\n\n // Clean the entity if it exists\n if (cleanedNode.entity) {\n cleanedNode.entity = cleanCategoryListItem(cleanedNode.entity);\n // Node already exposes `entityId`; drop duplicate `entity.id` from tree payload.\n if (cleanedNode.entity && typeof cleanedNode.entity === 'object') {\n cleanedNode.entity = removeKeys(cleanedNode.entity, ['id']);\n }\n }\n\n // Recursively clean children\n if (cleanedNode.children && Array.isArray(cleanedNode.children)) {\n cleanedNode.children = cleanedNode.children.map(cleanCategoryTreeNode);\n }\n\n return cleanedNode;\n}\n\n/**\n * Specific transformer for category list responses\n * Cleans both the categories array and the tree structure\n */\nexport function transformCategoryListResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed) return transformed;\n\n // Clean categories array\n if (transformed.categories && Array.isArray(transformed.categories)) {\n transformed.categories = transformed.categories.map(cleanCategoryListItem);\n }\n\n // Clean tree structure\n if (transformed.tree && transformed.tree.treeStructure && transformed.tree.treeStructure.nodes) {\n transformed.tree.treeStructure.nodes = transformed.tree.treeStructure.nodes.map(cleanCategoryTreeNode);\n }\n\n return transformed;\n}\n\n/**\n * Specific transformer for single category responses\n */\nexport function transformCategoryResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed) return transformed;\n\n // API returns { product_category: {...} } which becomes { productCategory: {...} }\n // Extract the nested category object\n const category = transformed.productCategory || transformed;\n\n return cleanCategory(category);\n}\n\n/**\n * Specific transformer for CMS pages list responses\n * Cleans CMS page data\n */\nexport function transformCMSListResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed) return transformed;\n\n // Backend returns: { cms_pages: [...], page_number: 1, page_size: 10, total_count: 50 }\n // After transformApiResponse: { cmsPages: [...], page: 1, pageSize: 10, total: 50 }\n // We need to convert to: { items: [...], page: 1, pageSize: 10, total: 50 }\n\n if (transformed.cmsPages && Array.isArray(transformed.cmsPages)) {\n return {\n items: transformed.cmsPages.map(cleanCmsPageListItem),\n total: transformed.total || transformed.cmsPages.length,\n page: transformed.page || transformed.pageNumber || 1,\n pageSize: transformed.pageSize || transformed.cmsPages.length\n };\n }\n\n // Fallback: if already has items array\n if (transformed.items && Array.isArray(transformed.items)) {\n return {\n items: transformed.items.map((item: any) => cleanCmsPageListItem(item)),\n total: transformed.total || transformed.items.length,\n page: transformed.page || 1,\n pageSize: transformed.pageSize || transformed.items.length\n };\n }\n\n return transformed;\n}\n\n/**\n * Specific transformer for single CMS page response\n */\nexport function transformCMSPageResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed) return transformed;\n\n // API returns { cms_page: {...} } which becomes { cmsPage: {...} }\n // Extract the nested page object\n const page = transformed.cmsPage || transformed;\n\n return cleanCmsPage(page);\n}\n\n/**\n * Transform CMS filters to backend format\n * Backend expects: page_number, page_size, filters[] (JSON string)\n */\nexport function transformCMSFilters(filters?: any): any {\n if (!filters) return {};\n\n const transformed: any = {};\n\n // Pagination\n if (filters.page !== undefined) {\n transformed.page_number = filters.page;\n }\n if (filters.pageSize !== undefined) {\n transformed.page_size = filters.pageSize;\n }\n\n // CMS page type filter\n // Backend expects: filters[]={ \"name\": \"cms_page_types\", \"value\": \"blog\" }\n if (filters.cmsPageTypes) {\n const pageType = Array.isArray(filters.cmsPageTypes)\n ? filters.cmsPageTypes[0]\n : filters.cmsPageTypes;\n\n transformed['filters[]'] = JSON.stringify({\n name: 'cms_page_types',\n value: pageType\n });\n }\n\n return transformed;\n}\n\n/**\n * Clean menu node by removing unnecessary fields\n * Recursively cleans nested children\n */\nfunction cleanMenuNode(node: any): any {\n if (!node) return node;\n\n const cleaned: any = {};\n\n // Keep only necessary fields\n if (node.entityType) cleaned.entityType = node.entityType;\n if (node.entityId !== undefined) cleaned.entityId = node.entityId;\n\n // Clean entity (remove staticUrl, id)\n if (node.entity) {\n const cleanedEntity = removeKeys(node.entity, ['staticUrl', 'id']);\n if (Object.keys(cleanedEntity).length > 0) {\n cleaned.entity = cleanedEntity;\n }\n }\n\n // Keep details\n if (node.details) {\n cleaned.details = node.details;\n }\n\n // Recursively clean children\n if (node.children && Array.isArray(node.children)) {\n cleaned.children = node.children.map((child: any) => cleanMenuNode(child));\n }\n\n return cleaned;\n}\n\n/**\n * Transform menu response\n * Cleans menu tree structure recursively\n */\nexport function transformMenuResponse(response: any): any {\n const transformed = transformApiResponse(response);\n\n if (!transformed || !transformed.tree) {\n return transformed;\n }\n\n const tree = transformed.tree;\n\n // Clean the tree structure recursively\n if (tree.treeStructure && tree.treeStructure.nodes) {\n tree.treeStructure.nodes = tree.treeStructure.nodes.map((node: any) => cleanMenuNode(node));\n }\n\n return transformed;\n}\n","/**\n * HTTP Client with native fetch\n * Provides unified response pattern, retry logic, caching, and automatic data transformation\n */\n\nimport { SazitoResponse, RequestOptions } from '../types';\nimport { SazitoConfig } from './config';\nimport { TokenStorage } from '../utils/token-storage';\nimport { CacheManager } from './cache';\nimport { transformRequestKeys, transformResponseKeys } from '../utils/transformers';\n\nexport class HttpClient {\n private baseUrl: string;\n private domain: string;\n private config: Required<SazitoConfig>;\n private tokenStorage: TokenStorage;\n private cache: CacheManager;\n private fetchApi: typeof fetch;\n\n constructor(config: Required<SazitoConfig>) {\n this.config = config;\n this.baseUrl = 'http://api.sazito.com:8080';\n this.domain = config.domain;\n this.tokenStorage = new TokenStorage();\n this.cache = new CacheManager();\n // Bind fetch to window context to avoid \"Illegal invocation\" error\n this.fetchApi = config.customFetchApi.bind(globalThis);\n }\n\n /**\n * GET request\n */\n async get<T>(\n endpoint: string,\n options?: RequestOptions & { params?: Record<string, any> }\n ): Promise<SazitoResponse<T>> {\n const url = this.buildUrl(endpoint, options?.params);\n const cacheKey = CacheManager.generateKey('GET', url, options?.params);\n\n // Check cache first (if not disabled)\n if (options?.cache !== false) {\n const apiName = this.getApiName(endpoint);\n const cacheConfig = this.config.cache[apiName];\n\n if (cacheConfig?.enabled && cacheConfig.ttl) {\n const cached = this.cache.get<T>(cacheKey, cacheConfig.ttl);\n if (cached) {\n if (this.config.debug) {\n console.log('[Sazito SDK] Cache hit:', endpoint);\n }\n return { data: cached };\n }\n }\n }\n\n const response = await this.request<T>('GET', url, options);\n\n // Cache successful responses\n if (response.data && options?.cache !== false) {\n this.cache.set(cacheKey, response.data);\n }\n\n return response;\n }\n\n /**\n * POST request\n */\n async post<T>(\n endpoint: string,\n body?: any,\n options?: RequestOptions\n ): Promise<SazitoResponse<T>> {\n const url = this.buildUrl(endpoint);\n\n // Transform request body to snake_case\n const transformedBody = body ? transformRequestKeys(body) : undefined;\n\n // Invalidate related cache\n const apiName = this.getApiName(endpoint);\n this.cache.deletePattern(`GET:.*${apiName}`);\n\n return this.request<T>('POST', url, {\n ...options,\n body: transformedBody\n });\n }\n\n /**\n * PUT request\n */\n async put<T>(\n endpoint: string,\n body?: any,\n options?: RequestOptions\n ): Promise<SazitoResponse<T>> {\n const url = this.buildUrl(endpoint);\n\n // Transform request body to snake_case\n const transformedBody = body ? transformRequestKeys(body) : undefined;\n\n // Invalidate related cache\n const apiName = this.getApiName(endpoint);\n this.cache.deletePattern(`GET:.*${apiName}`);\n\n return this.request<T>('PUT', url, {\n ...options,\n body: transformedBody\n });\n }\n\n /**\n * DELETE request\n */\n async delete<T>(\n endpoint: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<T>> {\n const url = this.buildUrl(endpoint);\n\n // Invalidate related cache\n const apiName = this.getApiName(endpoint);\n this.cache.deletePattern(`GET:.*${apiName}`);\n\n return this.request<T>('DELETE', url, options);\n }\n\n /**\n * Core request method\n */\n private async request<T>(\n method: string,\n url: string,\n options?: RequestOptions & { body?: any },\n retryCount = 0\n ): Promise<SazitoResponse<T>> {\n const controller = new AbortController();\n const signal = options?.signal || controller.signal;\n\n // Set timeout\n const timeout = options?.timeout || this.config.timeout;\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const response = await this.fetchApi(url, {\n method,\n headers: this.getHeaders(options?.headers),\n body: options?.body ? JSON.stringify(options.body) : undefined,\n signal\n });\n\n clearTimeout(timeoutId);\n\n // Check if we should retry\n const maxRetries = options?.retries !== undefined ? options.retries : this.config.retry.retries;\n if (!response.ok && this.shouldRetry(response.status) && retryCount < maxRetries) {\n if (this.config.debug) {\n console.log(`[Sazito SDK] Retrying request (${retryCount + 1}/${maxRetries}):`, url);\n }\n await this.delay(this.config.retry.retryDelay * (retryCount + 1));\n return this.request<T>(method, url, options, retryCount + 1);\n }\n\n // Parse response\n const contentType = response.headers.get('content-type');\n let data: any;\n\n if (contentType?.includes('application/json')) {\n data = await response.json();\n } else {\n data = await response.text();\n }\n\n // Extract result from data.result if present\n const result = data?.result !== undefined ? data.result : data;\n\n if (this.config.debug) {\n console.log(`[Sazito SDK] ${method} ${url}:`, { status: response.status, data: result });\n }\n\n // Transform response to camelCase and beautified field names\n let transformedResult = result ? transformResponseKeys(result) : result;\n\n // Unwrap single-key responses for specific entity types (e.g., { cart: {...} } -> {...})\n // Don't unwrap 'route' responses as they need to be accessed as response.data.route\n const unwrapKeys = ['cart', 'product', 'user', 'order', 'invoice', 'payment', 'shipping'];\n if (transformedResult && typeof transformedResult === 'object' && !Array.isArray(transformedResult)) {\n const keys = Object.keys(transformedResult);\n if (keys.length === 1 && unwrapKeys.includes(keys[0]) && \n typeof transformedResult[keys[0]] === 'object' && transformedResult[keys[0]] !== null) {\n transformedResult = transformedResult[keys[0]];\n }\n }\n\n // Return unified response - no exceptions\n if (response.ok) {\n return { data: transformedResult as T };\n } else {\n return {\n error: {\n status: response.status,\n message: transformedResult?.message || result?.message || response.statusText || 'Request failed',\n type: 'api',\n details: transformedResult\n }\n };\n }\n } catch (error: any) {\n clearTimeout(timeoutId);\n\n if (this.config.debug) {\n console.error('[Sazito SDK] Request failed:', error);\n }\n\n // Network error or abort\n return {\n error: {\n message: error.name === 'AbortError' ? 'Request timeout' : error.message || 'Network error',\n type: 'network',\n details: error\n }\n };\n }\n }\n\n /**\n * Build full URL with query params\n */\n private buildUrl(endpoint: string, params?: Record<string, any>): string {\n const url = `${this.baseUrl}${endpoint}`;\n\n if (!params || Object.keys(params).length === 0) {\n return url;\n }\n\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n searchParams.append(key, String(value));\n }\n });\n\n return `${url}?${searchParams.toString()}`;\n }\n\n /**\n * Get request headers\n */\n private getHeaders(customHeaders?: Record<string, string>): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-forwarded-host': this.domain, // Send domain in header\n ...customHeaders\n };\n\n // Auto-inject JWT from cookie (raw JWT, no Bearer prefix)\n const token = this.tokenStorage.get();\n if (token) {\n headers['Authorization'] = token; // Raw JWT, NOT \"Bearer {token}\"\n }\n\n return headers;\n }\n\n /**\n * Check if status code should trigger a retry\n */\n private shouldRetry(status: number): boolean {\n // Retry on 5xx server errors\n return status >= 500 && status < 600;\n }\n\n /**\n * Delay helper for retries\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n /**\n * Extract API name from endpoint for cache management\n */\n private getApiName(endpoint: string): keyof Required<SazitoConfig>['cache'] {\n if (endpoint.includes('/products')) return 'products';\n if (endpoint.includes('/product_categories')) return 'categories';\n if (endpoint.includes('/cart')) return 'cart'; // Matches both /cart and /carts\n if (endpoint.includes('/orders')) return 'orders';\n if (endpoint.includes('/search')) return 'search';\n if (endpoint.includes('/tags')) return 'tags';\n if (endpoint.includes('/entity_route')) return 'entityRoutes';\n return 'cms';\n }\n\n /**\n * Get token storage instance\n */\n getTokenStorage(): TokenStorage {\n return this.tokenStorage;\n }\n\n /**\n * Clear all cache\n */\n clearCache(): void {\n this.cache.clear();\n }\n}\n","/**\n * Credentials Manager for guest users\n * Manages cart, invoice, shipping, and payment credentials in localStorage\n */\n\nimport {\n CartCredentials,\n InvoiceCredentials,\n ShippingAddressCredentials,\n PaymentCredentials\n} from '../types';\n\nexport class CredentialsManager {\n private readonly CART_KEY = 'CART_CREDENTIALS';\n private readonly INVOICE_KEY = 'INVOICE_CREDENTIALS';\n private readonly SHIPPING_KEY = 'SHIPPING_ADDRESS_CREDENTIALS';\n private readonly PAYMENT_KEY = 'PAYMENT_CREDENTIALS';\n private readonly DISCOUNT_KEY = 'DISCOUNT_CODE_INFO';\n\n /**\n * Cart Credentials\n */\n getCartCredentials(): CartCredentials | null {\n return this.getItem<CartCredentials>(this.CART_KEY);\n }\n\n setCartCredentials(credentials: CartCredentials): void {\n this.setItem(this.CART_KEY, credentials);\n }\n\n clearCartCredentials(): void {\n this.removeItem(this.CART_KEY);\n }\n\n /**\n * Invoice Credentials\n */\n getInvoiceCredentials(): InvoiceCredentials | null {\n return this.getItem<InvoiceCredentials>(this.INVOICE_KEY);\n }\n\n setInvoiceCredentials(credentials: InvoiceCredentials): void {\n this.setItem(this.INVOICE_KEY, credentials);\n }\n\n clearInvoiceCredentials(): void {\n this.removeItem(this.INVOICE_KEY);\n }\n\n /**\n * Shipping Address Credentials\n */\n getShippingCredentials(): ShippingAddressCredentials | null {\n return this.getItem<ShippingAddressCredentials>(this.SHIPPING_KEY);\n }\n\n setShippingCredentials(credentials: ShippingAddressCredentials): void {\n this.setItem(this.SHIPPING_KEY, credentials);\n }\n\n clearShippingCredentials(): void {\n this.removeItem(this.SHIPPING_KEY);\n }\n\n /**\n * Payment Credentials\n */\n getPaymentCredentials(): PaymentCredentials | null {\n return this.getItem<PaymentCredentials>(this.PAYMENT_KEY);\n }\n\n setPaymentCredentials(credentials: PaymentCredentials): void {\n this.setItem(this.PAYMENT_KEY, credentials);\n }\n\n clearPaymentCredentials(): void {\n this.removeItem(this.PAYMENT_KEY);\n }\n\n /**\n * Discount Code\n */\n getDiscountCode(): string | null {\n return this.getItem<string>(this.DISCOUNT_KEY);\n }\n\n setDiscountCode(code: string): void {\n this.setItem(this.DISCOUNT_KEY, code);\n }\n\n clearDiscountCode(): void {\n this.removeItem(this.DISCOUNT_KEY);\n }\n\n /**\n * Clear all credentials\n */\n clearAll(): void {\n this.clearCartCredentials();\n this.clearInvoiceCredentials();\n this.clearShippingCredentials();\n this.clearPaymentCredentials();\n this.clearDiscountCode();\n }\n\n /**\n * Get item from localStorage\n */\n private getItem<T>(key: string): T | null {\n if (typeof localStorage === 'undefined') {\n return null;\n }\n\n try {\n const item = localStorage.getItem(key);\n return item ? JSON.parse(item) : null;\n } catch (error) {\n console.error(`[Sazito SDK] Error reading ${key} from localStorage:`, error);\n return null;\n }\n }\n\n /**\n * Set item in localStorage\n */\n private setItem<T>(key: string, value: T): void {\n if (typeof localStorage === 'undefined') {\n console.warn('[Sazito SDK] localStorage not available');\n return;\n }\n\n try {\n localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n console.error(`[Sazito SDK] Error writing ${key} to localStorage:`, error);\n }\n }\n\n /**\n * Remove item from localStorage\n */\n private removeItem(key: string): void {\n if (typeof localStorage === 'undefined') {\n return;\n }\n\n try {\n localStorage.removeItem(key);\n } catch (error) {\n console.error(`[Sazito SDK] Error removing ${key} from localStorage:`, error);\n }\n }\n}\n","/**\n * API Endpoint Constants\n * Centralized API route definitions\n */\n\n// Products\nexport const PRODUCTS_API = '/api/v1/products';\nexport const PRODUCT_CATEGORIES_API = '/api/v1/product_categories';\nexport const SEARCH_API = '/api/v1/search';\n\n// Cart & Checkout\nexport const CARTS_API = '/api/v2/carts';\nexport const INVOICES_API = '/api/v2/invoices';\nexport const SHIPPING_ADDRESSES_API = '/api/v2/shipping_addresses';\nexport const SHIPPING_METHODS_API = '/api/v2/shipping_methods';\nexport const PAYMENTS_API = '/api/v2/payments';\n\n// Orders\nexport const ORDERS_API = '/api/v1/orders';\n\n// Users\nexport const USERS_API = '/api/v1/users';\nexport const SESSIONS_API = '/api/v1/sessions';\n\n// Content\nexport const FEEDBACKS_API = '/api/v1/feedbacks';\nexport const CMS_PAGES_API = '/api/v1/cms_pages';\n\n// Wallet\nexport const WALLET_API = '/api/v1/users/wallet/balance';\nexport const WALLET_TRANSACTIONS_API = '/api/v1/wallet/transactions';\n\n// Media\nexport const IMAGES_API = '/api/v1/images';\n\n// Analytics\nexport const VISITS_API = '/api/v1/visits/add';\n\n// Booking\nexport const SCHEDULER_EVENTS_API = '/api/v1/scheduler/events';\nexport const SCHEDULER_BOOKINGS_API = '/api/v1/scheduler/bookings';\n\n// Entity Routes\nexport const ENTITY_ROUTE_API = '/api/v1/entity_route/route';\n\n// Menu & Navigation\nexport const MENU_API = '/api/v1/trees/fetch_single';\n\n// General\nexport const GENERAL_API = '/api/v2/general/info';\n\n// All endpoints exported above\n","/**\n * Products API\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n PaginatedResponse,\n Product,\n ProductFilters,\n RequestOptions,\n SearchResponse\n} from '../types';\nimport { PRODUCTS_API, SEARCH_API, ENTITY_ROUTE_API } from '../constants/endpoints';\nimport { transformProductListResponse, transformSearchResponse, transformEntityRouteResponse } from '../utils/transformers';\n\nexport class ProductsAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Map SDK sort values to API sort values\n */\n private mapSortToApi(sort?: string): { sort: string; sortOrder?: string } | null {\n if (!sort) return null;\n\n const sortMap: Record<string, { sort: string; sortOrder?: string }> = {\n 'newest': { sort: 'date' },\n 'best-selling': { sort: 'sold' },\n 'availability': { sort: 'stock_status' },\n 'discount': { sort: 'raw_price' },\n '!price': { sort: 'price', sortOrder: 'asc' },\n 'price': { sort: 'price' }\n };\n\n return sortMap[sort] || null;\n }\n\n /**\n * Transform filters to API request params\n */\n private transformFilters(filters?: ProductFilters): Record<string, any> {\n if (!filters) return {};\n\n const params: Record<string, any> = {};\n const filterArray: Array<{ name: string; value?: any }> = [];\n\n // Build filters array\n if (filters.categories) {\n const categories = Array.isArray(filters.categories)\n ? filters.categories\n : [filters.categories];\n\n if (categories.length > 0) {\n filterArray.push({ name: 'product_categories', value: categories.join(',') });\n }\n }\n\n // availableOnly: false means show only out-of-stock items\n if (filters.availableOnly === false) {\n filterArray.push({ name: 'in_stock' });\n }\n\n // discountedOnly: true means show only products with discounts\n if (filters.discountedOnly) {\n filterArray.push({ name: 'has_raw_price', value: true });\n }\n\n // Similar products\n if (filters.similarTo) {\n filterArray.push({\n name: 'similar_to',\n value: {\n entity_name: 'product',\n entity_id: filters.similarTo\n }\n });\n }\n\n if (filterArray.length > 0) {\n params['filters[]'] = JSON.stringify(filterArray);\n }\n\n // Pinned products\n if (filters.pinnedIds && filters.pinnedIds.length > 0) {\n params['pinned_ids'] = JSON.stringify(filters.pinnedIds);\n }\n\n // Handle sort mapping\n if (filters.sort) {\n const mapped = this.mapSortToApi(filters.sort);\n if (mapped) {\n params.sort = mapped.sort;\n if (mapped.sortOrder) {\n params.sort_order = mapped.sortOrder;\n }\n }\n }\n\n // Price range\n if (filters.priceMin !== undefined) params.min_price = filters.priceMin;\n if (filters.priceMax !== undefined) params.max_price = filters.priceMax;\n\n // Pagination\n if (filters.page) params.page = filters.page;\n if (filters.pageSize) params.page_size = filters.pageSize;\n\n return params;\n }\n\n /**\n * Get a single product by slug or URL path\n * Uses the entity route API to resolve the product\n */\n async get(\n slugOrPath: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<Product>> {\n // Ensure the path starts with /product/\n const urlPart = slugOrPath.startsWith('/product/')\n ? slugOrPath\n : `/product/${slugOrPath}`;\n\n const response = await this.http.get<any>(ENTITY_ROUTE_API, {\n ...options,\n params: { url_part: urlPart }\n });\n\n if (response.data) {\n const route = transformEntityRouteResponse(response.data);\n\n if (route.entityType === 'product' && route.entity) {\n return { data: route.entity };\n }\n\n if (route.entityType === 'unknown') {\n return {\n error: {\n message: 'Product not found',\n type: 'api',\n status: 404\n }\n };\n }\n\n return {\n error: {\n message: `Invalid entity type: expected 'product', got '${route.entityType}'`,\n type: 'api',\n status: 400\n }\n };\n }\n\n return response;\n }\n\n /**\n * List products with filters\n */\n async list(\n filters?: ProductFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<Product>>> {\n const params = this.transformFilters(filters);\n\n const response = await this.http.get<any>(PRODUCTS_API, {\n ...options,\n params\n });\n\n if (response.data) {\n const transformed = transformProductListResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n\n /**\n * Search across all entity types (products, blog pages, CMS pages, product categories)\n */\n async search(\n query: string,\n filters?: ProductFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<SearchResponse>> {\n // Search API uses different parameter names\n const params: Record<string, any> = {\n query,\n search_direction: 'center',\n page_size: filters?.pageSize || 20,\n page_number: filters?.page || 1\n };\n\n const response = await this.http.get<any>(SEARCH_API, {\n ...options,\n params\n });\n\n if (response.data) {\n const transformed = transformSearchResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n}\n","/**\n * Categories API\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n ProductCategory,\n RequestOptions\n} from '../types';\nimport { PRODUCT_CATEGORIES_API } from '../constants/endpoints';\nimport { transformCategoryListResponse, transformCategoryResponse } from '../utils/transformers';\n\n/**\n * Category tree node structure\n */\nexport interface CategoryTreeNode {\n id: number;\n entityType: 'product_category';\n entityId: number;\n entity: ProductCategory;\n details: any;\n children: CategoryTreeNode[];\n createdAt: string;\n updatedAt: string;\n}\n\n/**\n * Category tree structure\n */\nexport interface CategoryTree {\n id: number;\n treeType: 'product_categories';\n treeStructure: {\n nodes: CategoryTreeNode[];\n };\n}\n\n/**\n * Category list response with hierarchical tree\n */\nexport interface CategoryListResponse {\n categories: ProductCategory[];\n tree: CategoryTree;\n}\n\n/**\n * Category list filters\n */\nexport interface CategoryFilters {\n // Pagination\n page?: number;\n pageSize?: number;\n}\n\nexport class CategoriesAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Get a single category by ID or slug\n */\n async get(\n idOrSlug: string | number,\n options?: RequestOptions\n ): Promise<SazitoResponse<ProductCategory>> {\n const response = await this.http.get<any>(\n `${PRODUCT_CATEGORIES_API}/${idOrSlug}`,\n options\n );\n\n if (response.data) {\n const transformed = transformCategoryResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n\n /**\n * List all categories with hierarchical tree structure\n * @param filters Optional pagination filters\n * @param options Additional request options\n */\n async list(\n filters?: CategoryFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<CategoryListResponse>> {\n const params: any = {};\n\n if (filters?.page !== undefined) {\n params.page_number = filters.page;\n }\n if (filters?.pageSize !== undefined) {\n params.page_size = filters.pageSize;\n }\n\n const response = await this.http.get<any>(\n PRODUCT_CATEGORIES_API,\n {\n ...options,\n params\n }\n );\n\n if (response.data) {\n const transformed = transformCategoryListResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n}\n","/**\n * Cart API\n * Supports both authenticated and guest users via credentials\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { CredentialsManager } from '../utils/credentials-manager';\nimport {\n SazitoResponse,\n Cart,\n CreateCartInput,\n RequestOptions\n} from '../types';\nimport { CARTS_API } from '../constants/endpoints';\n\nexport class CartAPI {\n constructor(\n private http: HttpClient,\n private credentials: CredentialsManager\n ) {}\n\n /**\n * Get current cart\n */\n async get(options?: RequestOptions): Promise<SazitoResponse<Cart>> {\n const cartCreds = this.credentials.getCartCredentials();\n\n if (!cartCreds) {\n return {\n error: {\n message: 'No cart found. Please create a cart first.',\n type: 'validation'\n }\n };\n }\n\n return this.http.get<Cart>(`${CARTS_API}/${cartCreds.id}`, {\n ...options,\n params: { identifier: cartCreds.identifier }\n });\n }\n\n /**\n * Create a new cart\n */\n async create(\n input: CreateCartInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<Cart>> {\n const response = await this.http.post<Cart>(CARTS_API, input, options);\n\n // Store cart credentials for guest users\n if (response.data) {\n this.credentials.setCartCredentials({\n id: response.data.id,\n identifier: response.data.identifier\n });\n }\n\n return response;\n }\n\n /**\n * Add item to cart\n */\n async addItem(\n variantId: number,\n count: number,\n formAttributes?: Record<string, any>,\n options?: RequestOptions\n ): Promise<SazitoResponse<Cart>> {\n const cartCreds = this.credentials.getCartCredentials();\n\n if (!cartCreds) {\n // Create new cart if none exists\n return this.create({\n variants: [{\n id: variantId,\n count,\n formAttributes\n }]\n }, options);\n }\n\n const response = await this.http.post<Cart>(\n `${CARTS_API}/${cartCreds.id}/add_products_to_cart`,\n {\n identifier: cartCreds.identifier,\n variants: [{\n id: variantId,\n count\n }],\n formAttributes\n },\n options\n );\n\n return response;\n }\n\n /**\n * Update cart item quantity\n */\n async updateItem(\n cartProductId: number,\n count: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Cart>> {\n const cartCreds = this.credentials.getCartCredentials();\n\n if (!cartCreds) {\n return {\n error: {\n message: 'No cart found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Cart>(\n `${CARTS_API}/${cartCreds.id}/update_products_in_cart`,\n {\n identifier: cartCreds.identifier,\n cartProductId,\n variants: [{\n id: cartProductId,\n count\n }]\n },\n options\n );\n }\n\n /**\n * Remove item from cart\n */\n async removeItem(\n cartProductId: number,\n variantId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Cart>> {\n const cartCreds = this.credentials.getCartCredentials();\n\n if (!cartCreds) {\n return {\n error: {\n message: 'No cart found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Cart>(\n `${CARTS_API}/${cartCreds.id}/remove_products_from_cart`,\n {\n identifier: cartCreds.identifier,\n cartProductId,\n variants: [{\n id: variantId\n }]\n },\n options\n );\n }\n\n /**\n * Clear current cart credentials\n */\n clearCart(): void {\n this.credentials.clearCartCredentials();\n }\n}\n","/**\n * Orders API\n * Requires authentication\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n PaginatedResponse,\n Order,\n OrderFilters,\n RequestOptions\n} from '../types';\nimport { ORDERS_API } from '../constants/endpoints';\n\nexport class OrdersAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * List orders (requires authentication)\n */\n async list(\n filters?: OrderFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<Order>>> {\n return this.http.get<PaginatedResponse<Order>>(ORDERS_API, {\n ...options,\n params: filters\n });\n }\n\n /**\n * Get single order by ID (requires authentication)\n */\n async get(\n orderId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Order>> {\n return this.http.get<Order>(`${ORDERS_API}/${orderId}`, options);\n }\n}\n","/**\n * Invoices API (Checkout)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { CredentialsManager } from '../utils/credentials-manager';\nimport {\n SazitoResponse,\n Invoice,\n ShippingMethod,\n ShippingAssignment,\n RequestOptions\n} from '../types';\nimport { INVOICES_API } from '../constants/endpoints';\n\nexport class InvoicesAPI {\n constructor(\n private http: HttpClient,\n private credentials: CredentialsManager\n ) {}\n\n /**\n * Get current invoice\n */\n async get(options?: RequestOptions): Promise<SazitoResponse<Invoice>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found. Please create an invoice first.',\n type: 'validation'\n }\n };\n }\n\n return this.http.get<Invoice>(`${INVOICES_API}/${invoiceCreds.id}`, {\n ...options,\n params: { identifier: invoiceCreds.identifier }\n });\n }\n\n /**\n * Create a new invoice from cart\n */\n async create(options?: RequestOptions): Promise<SazitoResponse<Invoice>> {\n const cartCreds = this.credentials.getCartCredentials();\n\n if (!cartCreds) {\n return {\n error: {\n message: 'No cart found. Please create a cart first.',\n type: 'validation'\n }\n };\n }\n\n const response = await this.http.post<Invoice>(\n INVOICES_API,\n {\n cart_id: cartCreds.id,\n cart_identifier: cartCreds.identifier\n },\n options\n );\n\n // Store invoice credentials\n if (response.data) {\n this.credentials.setInvoiceCredentials({\n id: response.data.id,\n identifier: response.data.identifier\n });\n }\n\n return response;\n }\n\n /**\n * Refresh invoice (sync with cart)\n */\n async refresh(options?: RequestOptions): Promise<SazitoResponse<Invoice>> {\n const cartCreds = this.credentials.getCartCredentials();\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!cartCreds || !invoiceCreds) {\n return {\n error: {\n message: 'No cart or invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceCreds.id}/refresh`,\n {\n cart_id: cartCreds.id,\n cart_identifier: cartCreds.identifier,\n identifier: invoiceCreds.identifier\n },\n options\n );\n }\n\n /**\n * Add shipping address to invoice\n */\n async addShippingAddress(\n shippingAddressId: number,\n shippingAddressIdentifier: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const cartCreds = this.credentials.getCartCredentials();\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!cartCreds || !invoiceCreds) {\n return {\n error: {\n message: 'No cart or invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceCreds.id}/add_shipping_address`,\n {\n identifier: invoiceCreds.identifier,\n shipping_address_id: shippingAddressId,\n shipping_address_identifier: shippingAddressIdentifier,\n cart_id: cartCreds.id,\n cart_identifier: cartCreds.identifier\n },\n options\n );\n }\n\n /**\n * Add discount code to invoice\n */\n async addDiscountCode(\n code: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n const response = await this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceCreds.id}/add_discount_code`,\n {\n identifier: invoiceCreds.identifier,\n discount_code: code.toUpperCase()\n },\n options\n );\n\n // Save discount code\n if (response.data) {\n this.credentials.setDiscountCode(code);\n }\n\n return response;\n }\n\n /**\n * Assign shipping method to invoice\n */\n async assignShippingMethod(\n shippings: ShippingAssignment[],\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceCreds.id}/add_shipping_method`,\n {\n identifier: invoiceCreds.identifier,\n shippings\n },\n options\n );\n }\n\n /**\n * Add invoice details (user comment)\n */\n async addDetails(\n comment: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceCreds.id}/add_invoice_details`,\n {\n identifier: invoiceCreds.identifier,\n user_comment: comment\n },\n options\n );\n }\n\n /**\n * Get applicable shipping methods for invoice\n */\n async getApplicableShippingMethods(\n options?: RequestOptions\n ): Promise<SazitoResponse<ShippingMethod[]>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.get<ShippingMethod[]>(\n `/api/v1/invoices/${invoiceCreds.id}/applicable_shipping_methods`,\n {\n ...options,\n params: { identifier: invoiceCreds.identifier }\n }\n );\n }\n\n /**\n * Clear current invoice credentials\n */\n clearInvoice(): void {\n this.credentials.clearInvoiceCredentials();\n }\n}\n","/**\n * Shipping API (Addresses and Methods)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { CredentialsManager } from '../utils/credentials-manager';\nimport {\n SazitoResponse,\n ShippingAddress,\n ShippingAddressInput,\n ShippingMethod,\n RequestOptions\n} from '../types';\nimport { SHIPPING_ADDRESSES_API, SHIPPING_METHODS_API } from '../constants/endpoints';\n\nexport class ShippingAPI {\n constructor(\n private http: HttpClient,\n private credentials: CredentialsManager\n ) {}\n\n /**\n * Create shipping address\n */\n async createAddress(\n address: ShippingAddressInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<ShippingAddress>> {\n const response = await this.http.post<ShippingAddress>(\n SHIPPING_ADDRESSES_API,\n { shipping_address: address },\n options\n );\n\n // Store shipping address credentials\n if (response.data) {\n this.credentials.setShippingCredentials({\n id: response.data.id,\n identifier: response.data.identifier\n });\n }\n\n return response;\n }\n\n /**\n * Update shipping address\n */\n async updateAddress(\n address: ShippingAddressInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<ShippingAddress>> {\n const shippingCreds = this.credentials.getShippingCredentials();\n\n if (!shippingCreds) {\n // Create new address if none exists\n return this.createAddress(address, options);\n }\n\n const response = await this.http.post<ShippingAddress>(\n SHIPPING_ADDRESSES_API,\n {\n identifier: shippingCreds.identifier,\n shipping_address: address\n },\n options\n );\n\n // Update credentials\n if (response.data) {\n this.credentials.setShippingCredentials({\n id: response.data.id,\n identifier: response.data.identifier\n });\n }\n\n return response;\n }\n\n /**\n * Get shipping address\n */\n async getAddress(options?: RequestOptions): Promise<SazitoResponse<ShippingAddress>> {\n const shippingCreds = this.credentials.getShippingCredentials();\n\n if (!shippingCreds) {\n return {\n error: {\n message: 'No shipping address found',\n type: 'validation'\n }\n };\n }\n\n return this.http.get<ShippingAddress>(\n `${SHIPPING_ADDRESSES_API}/${shippingCreds.id}`,\n {\n ...options,\n params: { identifier: shippingCreds.identifier }\n }\n );\n }\n\n /**\n * Get list of enabled shipping methods\n */\n async getMethods(options?: RequestOptions): Promise<SazitoResponse<ShippingMethod[]>> {\n return this.http.post<ShippingMethod[]>(\n `${SHIPPING_METHODS_API}/list`,\n {},\n options\n );\n }\n\n /**\n * Clear shipping address credentials\n */\n clearAddress(): void {\n this.credentials.clearShippingCredentials();\n }\n}\n","/**\n * Payments API\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { CredentialsManager } from '../utils/credentials-manager';\nimport {\n SazitoResponse,\n PaymentMethod,\n Payment,\n PaymentAction,\n PaymentStepInput,\n RequestOptions\n} from '../types';\nimport { PAYMENTS_API } from '../constants/endpoints';\n\nexport class PaymentsAPI {\n constructor(\n private http: HttpClient,\n private credentials: CredentialsManager\n ) {}\n\n /**\n * Get list of payment methods for invoice\n */\n async getMethods(options?: RequestOptions): Promise<SazitoResponse<PaymentMethod[]>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<PaymentMethod[]>(\n `${PAYMENTS_API}/list`,\n {\n invoice_id: invoiceCreds.id,\n invoice_identifier: invoiceCreds.identifier\n },\n options\n );\n }\n\n /**\n * Create payment\n */\n async create(\n paymentTypeId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Payment>> {\n const invoiceCreds = this.credentials.getInvoiceCredentials();\n\n if (!invoiceCreds) {\n return {\n error: {\n message: 'No invoice found',\n type: 'validation'\n }\n };\n }\n\n const response = await this.http.post<Payment>(\n PAYMENTS_API,\n {\n invoice_id: invoiceCreds.id,\n invoice_identifier: invoiceCreds.identifier,\n payment_type: paymentTypeId\n },\n options\n );\n\n // Store payment credentials\n if (response.data) {\n this.credentials.setPaymentCredentials({\n id: response.data.id,\n identifier: response.data.identifier\n });\n }\n\n return response;\n }\n\n /**\n * Initialize payment (get payment action)\n */\n async initialize(options?: RequestOptions): Promise<SazitoResponse<PaymentAction>> {\n const paymentCreds = this.credentials.getPaymentCredentials();\n\n if (!paymentCreds) {\n return {\n error: {\n message: 'No payment found. Please create a payment first.',\n type: 'validation'\n }\n };\n }\n\n return this.http.post<PaymentAction>(\n `${PAYMENTS_API}/${paymentCreds.id}/process_payment_step`,\n {\n payment_identifier: paymentCreds.identifier\n },\n options\n );\n }\n\n /**\n * Process payment step (for card-to-card or multi-step payments)\n */\n async processStep(\n input: PaymentStepInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<any>> {\n const paymentCreds = this.credentials.getPaymentCredentials();\n\n if (!paymentCreds) {\n return {\n error: {\n message: 'No payment found',\n type: 'validation'\n }\n };\n }\n\n return this.http.post(\n `${PAYMENTS_API}/${paymentCreds.id}/process_payment_step`,\n {\n payment_identifier: paymentCreds.identifier,\n ...input\n },\n options\n );\n }\n\n /**\n * Clear payment credentials\n */\n clearPayment(): void {\n this.credentials.clearPaymentCredentials();\n }\n}\n","/**\n * Users API (Authentication and user management)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { SazitoResponse, User, RequestOptions } from '../types';\nimport { USERS_API, SESSIONS_API } from '../constants/endpoints';\n\n/**\n * Login input (SDK uses camelCase)\n */\nexport interface LoginInput {\n email: string;\n password: string;\n}\n\n/**\n * Register input (SDK uses camelCase)\n */\nexport interface RegisterInput {\n email: string;\n password: string;\n passwordConfirmation: string;\n firstName?: string;\n lastName?: string;\n mobilePhone?: string;\n}\n\n/**\n * Mobile login input\n */\nexport interface MobileLoginInput {\n mobilePhone: string;\n}\n\n/**\n * Verify mobile OTP input (SDK uses camelCase)\n */\nexport interface VerifyMobileInput {\n mobilePhone: string;\n token: string;\n}\n\n/**\n * Passwordless email login input\n */\nexport interface EmailLoginRequestInput {\n email: string;\n}\n\n/**\n * Forgot password input\n */\nexport interface ForgotPasswordInput {\n email: string;\n}\n\n/**\n * Reset password input (SDK uses camelCase)\n */\nexport interface ResetPasswordInput {\n forgotPasswordToken: string;\n password: string;\n passwordConfirmation: string;\n}\n\n/**\n * Update user profile input\n */\nexport interface UpdateProfileInput {\n firstName?: string;\n lastName?: string;\n email?: string;\n password?: string;\n passwordConfirmation?: string;\n birthDate?: string;\n}\n\n/**\n * Update user phone request input\n */\nexport interface UpdateMobilePhoneRequestInput {\n mobilePhone: string;\n}\n\n/**\n * Verify user phone update input\n */\nexport interface UpdateMobilePhoneVerificationInput {\n mobilePhone: string;\n token: string;\n}\n\nexport interface LoginResponse {\n jwt: string;\n user?: User;\n}\n\nexport class UsersAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Login with email and password\n */\n async login(\n input: LoginInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<LoginResponse>> {\n return this.http.post<LoginResponse>(`${SESSIONS_API}/login`, input, options);\n }\n\n /**\n * Request mobile OTP\n */\n async requestMobileOTP(\n input: MobileLoginInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<any>> {\n return this.http.post(`${SESSIONS_API}/login_request`, input, options);\n }\n\n /**\n * Verify mobile OTP\n */\n async verifyMobileOTP(\n input: VerifyMobileInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<LoginResponse>> {\n return this.http.post<LoginResponse>(\n `${SESSIONS_API}/login_request_verification`,\n input,\n options\n );\n }\n\n /**\n * Passwordless login request via email\n */\n async requestEmailLogin(\n input: EmailLoginRequestInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<any>> {\n return this.http.post(`${USERS_API}/email_login_request`, input, options);\n }\n\n /**\n * Register new user\n */\n async register(\n input: RegisterInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<User>> {\n return this.http.post<User>(`${USERS_API}/register`, input, options);\n }\n\n /**\n * Get current user (requires authentication)\n */\n async getCurrentUser(options?: RequestOptions): Promise<SazitoResponse<User>> {\n return this.http.get<User>(`${USERS_API}/current`, options);\n }\n\n /**\n * Update user profile (requires authentication)\n */\n async updateProfile(\n userId: number,\n data: UpdateProfileInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<User>> {\n return this.http.put<User>(`${USERS_API}/${userId}`, data, options);\n }\n\n /**\n * Request mobile phone update (requires authentication)\n */\n async requestMobilePhoneUpdate(\n input: UpdateMobilePhoneRequestInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<any>> {\n return this.http.post(`${USERS_API}/update_mobile_phone_request`, input, options);\n }\n\n /**\n * Verify mobile phone update (requires authentication)\n */\n async verifyMobilePhoneUpdate(\n input: UpdateMobilePhoneVerificationInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<User>> {\n return this.http.post<User>(`${USERS_API}/update_mobile_phone_verification`, input, options);\n }\n\n /**\n * Forgot password - send reset email\n */\n async forgotPassword(\n input: ForgotPasswordInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<any>> {\n return this.http.post(`${USERS_API}/forgot_password`, input, options);\n }\n\n /**\n * Revive/Reset password with token\n */\n async revivePassword(\n input: ResetPasswordInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<LoginResponse>> {\n return this.http.post<LoginResponse>(`${USERS_API}/revive_password`, input, options);\n }\n\n /**\n * Merge guest and current user accounts after login\n */\n async mergeUser(options?: RequestOptions): Promise<SazitoResponse<any>> {\n return this.http.post(`${USERS_API}/merge_user`, {}, options);\n }\n}\n","/**\n * Search API\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n SearchResponse,\n RequestOptions\n} from '../types';\nimport { SEARCH_API } from '../constants/endpoints';\nimport { transformSearchResponse } from '../utils/transformers';\n\nexport interface SearchFilters {\n page?: number;\n pageSize?: number;\n categoryId?: number;\n minPrice?: number;\n maxPrice?: number;\n}\n\nexport class SearchAPI {\n constructor(private http: HttpClient) {}\n\n private transformFilters(filters?: SearchFilters): Record<string, any> {\n if (!filters) return {};\n\n const params: Record<string, any> = {};\n\n if (filters.page !== undefined) params.page_number = filters.page;\n if (filters.pageSize !== undefined) params.page_size = filters.pageSize;\n if (filters.categoryId !== undefined) params.category_id = filters.categoryId;\n if (filters.minPrice !== undefined) params.min_price = filters.minPrice;\n if (filters.maxPrice !== undefined) params.max_price = filters.maxPrice;\n\n return params;\n }\n\n /**\n * Query across multiple entity types (products, blog pages, CMS pages, categories)\n */\n async query(\n term: string,\n filters?: SearchFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<SearchResponse>> {\n const transformedFilters = this.transformFilters(filters);\n\n const response = await this.http.get<any>(SEARCH_API, {\n ...options,\n params: {\n ...transformedFilters,\n query: term,\n page_number: transformedFilters.page_number ?? 1,\n page_size: transformedFilters.page_size ?? 20,\n search_direction: 'center'\n }\n });\n\n // Transform and clean the response\n if (response.data) {\n const transformed = transformSearchResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n}\n","/**\n * Feedbacks API (Comments and reviews)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n PaginatedResponse,\n RequestOptions\n} from '../types';\nimport { FEEDBACKS_API } from '../constants/endpoints';\n\nexport interface Feedback {\n id: number;\n user?: {\n id: number;\n name: string;\n };\n productId?: number;\n rating?: number; // 1-5 stars\n comment: string;\n status: 'pending' | 'approved' | 'rejected';\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface CreateFeedbackInput {\n productId?: number;\n rating?: number;\n comment: string;\n}\n\nexport interface FeedbackFilters {\n productId?: number;\n page?: number;\n pageSize?: number;\n}\n\nexport class FeedbacksAPI {\n constructor(private http: HttpClient) {}\n\n private transformFilters(filters?: FeedbackFilters): Record<string, any> {\n if (!filters) return {};\n\n const params: Record<string, any> = {};\n\n if (filters.productId !== undefined) params.product_id = filters.productId;\n if (filters.page !== undefined) params.page = filters.page;\n if (filters.pageSize !== undefined) params.page_size = filters.pageSize;\n\n return params;\n }\n\n /**\n * List feedbacks\n */\n async list(\n filters?: FeedbackFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<Feedback>>> {\n return this.http.get<PaginatedResponse<Feedback>>(FEEDBACKS_API, {\n ...options,\n params: this.transformFilters(filters)\n });\n }\n\n /**\n * Create feedback/review\n */\n async create(\n input: CreateFeedbackInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<Feedback>> {\n return this.http.post<Feedback>(FEEDBACKS_API, input, options);\n }\n\n /**\n * Get single feedback\n */\n async get(\n feedbackId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Feedback>> {\n return this.http.get<Feedback>(`${FEEDBACKS_API}/${feedbackId}`, options);\n }\n}\n","/**\n * Wallet API (User wallet and transactions)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n Invoice,\n RequestOptions\n} from '../types';\nimport { WALLET_API, WALLET_TRANSACTIONS_API } from '../constants/endpoints';\n\nexport type WalletTransactionReason =\n | 'redeem'\n | 'NthPurchase'\n | 'merge-user'\n | 'SimpleCashbackRule'\n | 'BirthdateGift'\n | 'TajrobehAppreciation'\n | 'edit_order'\n | 'cancel_order'\n | 'edit_shipping_cost'\n | 'edit_cashback'\n | 'gift'\n | 'others'\n | 'Refund'\n | 'Charge'\n | 'Expired'\n | `${string}:activity`;\n\nexport interface WalletTransaction {\n id: string | number;\n reason: WalletTransactionReason;\n amount: number;\n createdAt: string;\n metaData?: Record<string, unknown>;\n}\n\nexport interface WalletBalance {\n balance: number;\n enabled: boolean;\n}\n\nexport interface Wallet extends WalletBalance {\n currency?: string;\n transactions?: WalletTransaction[];\n}\n\nexport interface TransactionFilters {\n page_number?: number;\n page_size?: number;\n}\n\nexport interface WalletTransactionsResponse {\n transactions: WalletTransaction[];\n}\n\nexport class WalletAPI {\n constructor(private http: HttpClient) {}\n\n private validateInvoiceId(invoiceId: number): SazitoResponse<never> | null {\n if (!Number.isFinite(invoiceId) || invoiceId <= 0) {\n return {\n error: {\n message: 'Invalid invoice ID',\n type: 'validation'\n }\n };\n }\n\n return null;\n }\n\n /**\n * Get wallet balance (requires authentication)\n */\n async getBalance(options?: RequestOptions): Promise<SazitoResponse<Wallet>> {\n return this.http.get<Wallet>(WALLET_API, options);\n }\n\n /**\n * List wallet transactions (requires authentication)\n */\n async listTransactions(\n filters?: TransactionFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<WalletTransactionsResponse>> {\n const pageNumber = filters?.page_number ?? 1;\n const pageSize = filters?.page_size ?? 100;\n\n return this.http.get<WalletTransactionsResponse>(\n WALLET_TRANSACTIONS_API,\n {\n ...options,\n params: {\n page_number: pageNumber,\n page_size: pageSize\n }\n }\n );\n }\n\n /**\n * Apply wallet credit on an invoice (requires authentication)\n */\n async applyCredit(\n invoiceId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const validation = this.validateInvoiceId(invoiceId);\n if (validation) return validation;\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceId}/add_credit`,\n {},\n options\n );\n }\n\n /**\n * Remove wallet credit from an invoice (requires authentication)\n */\n async removeCredit(\n invoiceId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Invoice>> {\n const validation = this.validateInvoiceId(invoiceId);\n if (validation) return validation;\n\n return this.http.post<Invoice>(\n `/api/v1/invoices/${invoiceId}/remove_credit`,\n {},\n options\n );\n }\n}\n","/**\n * CMS API (Content Management - Pages, Blogs, etc.)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n PaginatedResponse,\n RequestOptions\n} from '../types';\nimport { CmsPage, CMSPageType } from '../types/search';\nimport { CMS_PAGES_API, ENTITY_ROUTE_API } from '../constants/endpoints';\nimport {\n transformCMSListResponse,\n transformCMSFilters,\n transformEntityRouteResponse\n} from '../utils/transformers';\n\n/**\n * CMS Page type (re-exported from search types for convenience)\n * Both regular pages and blog posts use this structure\n */\nexport type CMSPage = CmsPage;\n\n/**\n * Re-export CMSPageType for convenience\n */\nexport type { CMSPageType };\n\n/**\n * Filters for CMS pages list\n * Backend uses: page_number, page_size, filters[]\n */\nexport interface CMSFilters {\n page?: number;\n pageSize?: number;\n cmsPageTypes?: CMSPageType | CMSPageType[]; // Filter by page type: 'normal' or 'blog'\n}\n\nexport class CMSAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Get CMS page by URL path\n * Uses entity routes API (recommended approach)\n * @param urlPath - Page URL path (e.g., '/about-us')\n * @param options - Request options\n */\n async getPage(\n urlPath: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<CMSPage>> {\n const response = await this.http.get<any>(\n ENTITY_ROUTE_API,\n {\n ...options,\n params: { url_part: urlPath }\n }\n );\n\n // Transform entity route response and extract the entity\n const transformed = transformEntityRouteResponse(response.data);\n\n // Verify it's a CMS page (not blog, product, etc.)\n if (transformed.entityType !== 'cms_page' || transformed.entity?.cmsPageType === 'blog') {\n throw new Error(`Expected CMS page at ${urlPath}, but got ${transformed.entityType}`);\n }\n\n return {\n ...response,\n data: transformed.entity\n };\n }\n\n /**\n * List CMS pages (excludes blog posts)\n * @param filters - Filter options (will automatically exclude blog type)\n * @param options - Request options\n */\n async listPages(\n filters?: CMSFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<CMSPage>>> {\n // Ensure we're only getting normal CMS pages, not blog posts\n const cmsFilters = {\n ...filters,\n cmsPageTypes: 'normal' as CMSPageType\n };\n\n const transformedParams = transformCMSFilters(cmsFilters);\n\n const response = await this.http.get<PaginatedResponse<CMSPage>>(\n CMS_PAGES_API,\n {\n ...options,\n params: transformedParams\n }\n );\n\n return {\n ...response,\n data: transformCMSListResponse(response.data)\n };\n }\n\n /**\n * Get blog post by URL path\n * Uses entity routes API (recommended approach)\n * @param urlPath - Blog post URL path (e.g., '/blog/my-post')\n * @param options - Request options\n */\n async getBlogPost(\n urlPath: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<CMSPage>> {\n const response = await this.http.get<any>(\n ENTITY_ROUTE_API,\n {\n ...options,\n params: { url_part: urlPath }\n }\n );\n\n // Transform entity route response and extract the entity\n const transformed = transformEntityRouteResponse(response.data);\n\n // Verify it's a blog post\n if (transformed.entityType !== 'cms_page' || transformed.entity?.cmsPageType !== 'blog') {\n throw new Error(`Expected blog post at ${urlPath}, but got ${transformed.entityType}`);\n }\n\n return {\n ...response,\n data: transformed.entity\n };\n }\n\n /**\n * List blog posts\n * @param filters - Filter options (will automatically filter for blog type)\n * @param options - Request options\n */\n async listBlogPosts(\n filters?: CMSFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<CMSPage>>> {\n // Ensure we're only getting blog posts, not normal CMS pages\n const blogFilters = {\n ...filters,\n cmsPageTypes: 'blog' as CMSPageType\n };\n\n const transformedParams = transformCMSFilters(blogFilters);\n\n const response = await this.http.get<PaginatedResponse<CMSPage>>(\n CMS_PAGES_API,\n {\n ...options,\n params: transformedParams\n }\n );\n\n return {\n ...response,\n data: transformCMSListResponse(response.data)\n };\n }\n\n /**\n * List all CMS content (both pages and blog posts)\n * @param filters - Filter options\n * @param options - Request options\n */\n async listAll(\n filters?: CMSFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<CMSPage>>> {\n const transformedParams = transformCMSFilters(filters);\n\n const response = await this.http.get<PaginatedResponse<CMSPage>>(\n CMS_PAGES_API,\n {\n ...options,\n params: transformedParams\n }\n );\n\n return {\n ...response,\n data: transformCMSListResponse(response.data)\n };\n }\n}\n","/**\n * Images API (File upload)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { SazitoResponse, RequestOptions } from '../types';\nimport { IMAGES_API } from '../constants/endpoints';\n\n\nexport interface UploadImageResponse {\n id: number;\n url: string;\n filename: string;\n size: number;\n mime_type: string;\n}\n\nexport class ImagesAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Upload image file\n * @param file - File or Blob to upload\n */\n async upload(\n file: File | Blob,\n options?: RequestOptions\n ): Promise<SazitoResponse<UploadImageResponse>> {\n const formData = new FormData();\n formData.append('image', file);\n\n // Note: We need to override Content-Type for FormData\n const customHeaders = {\n ...options?.headers\n };\n // Remove Content-Type to let browser set it with boundary\n delete customHeaders['Content-Type'];\n\n return this.http.post<UploadImageResponse>(IMAGES_API, formData, {\n ...options,\n headers: customHeaders\n } as any);\n }\n\n /**\n * Delete image\n */\n async delete(\n imageId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<void>> {\n return this.http.delete<void>(`${IMAGES_API}/${imageId}`, options);\n }\n}\n","/**\n * Visits API (Analytics and page views)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { SazitoResponse, RequestOptions } from '../types';\nimport { VISITS_API } from '../constants/endpoints';\n\n/**\n * Visit tracking input (SDK uses camelCase)\n */\nexport interface VisitInput {\n url: string;\n referrer?: string;\n userAgent?: string;\n entityType?: 'product' | 'category' | 'page';\n entityId?: number;\n}\n\n/**\n * Visit tracking response (auto-transformed to camelCase by HTTP client)\n */\nexport interface VisitResponse {\n id: number;\n createdAt: string;\n}\n\nfunction isRequestOptions(input: unknown): input is RequestOptions {\n if (!input || typeof input !== 'object') return false;\n const candidate = input as Record<string, unknown>;\n return (\n 'retries' in candidate ||\n 'timeout' in candidate ||\n 'cache' in candidate ||\n 'headers' in candidate ||\n 'signal' in candidate\n );\n}\n\nexport class VisitsAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Track visit analytics event.\n * Backend endpoint `/api/v1/visits/add` does not accept a payload.\n */\n async track(\n inputOrOptions?: VisitInput | RequestOptions,\n options?: RequestOptions\n ): Promise<SazitoResponse<VisitResponse>> {\n const resolvedOptions = options ?? (isRequestOptions(inputOrOptions) ? inputOrOptions : undefined);\n return this.http.post<VisitResponse>(VISITS_API, undefined, resolvedOptions);\n }\n\n /**\n * Track product view\n */\n async trackProduct(\n productId: number,\n url: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<VisitResponse>> {\n void productId;\n void url;\n return this.track(options);\n }\n\n /**\n * Track category view\n */\n async trackCategory(\n categoryId: number,\n url: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<VisitResponse>> {\n void categoryId;\n void url;\n return this.track(options);\n }\n}\n","/**\n * Booking API (Event scheduling and appointments)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n PaginatedResponse,\n RequestOptions\n} from '../types';\nimport { SCHEDULER_EVENTS_API, SCHEDULER_BOOKINGS_API } from '../constants/endpoints';\n\nexport interface Event {\n id: number;\n title: string;\n description?: string;\n start_time: string;\n end_time: string;\n capacity: number;\n booked_count: number;\n available_slots: number;\n price?: number;\n location?: string;\n created_at: string;\n}\n\nexport interface Booking {\n id: number;\n event_id: number;\n event: Event;\n user_id?: number;\n attendee_name: string;\n attendee_email?: string;\n attendee_phone?: string;\n status: 'pending' | 'confirmed' | 'cancelled';\n booking_time: string;\n created_at: string;\n}\n\nexport interface CreateBookingInput {\n event_entity_id: number;\n timezone: string;\n attendee_name: string;\n attendee_email?: string;\n attendee_phone?: string;\n}\n\nexport interface EventFilters {\n start_date?: string;\n end_date?: string;\n available_only?: boolean;\n page?: number;\n page_size?: number;\n}\n\nexport class BookingAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * List available events\n */\n async listEvents(\n filters?: EventFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<Event>>> {\n return this.http.get<PaginatedResponse<Event>>(SCHEDULER_EVENTS_API, {\n ...options,\n params: filters\n });\n }\n\n /**\n * Get single event\n */\n async getEvent(\n eventId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Event>> {\n return this.http.get<Event>(`${SCHEDULER_EVENTS_API}/${eventId}`, options);\n }\n\n /**\n * Create booking\n */\n async createBooking(\n input: CreateBookingInput,\n options?: RequestOptions\n ): Promise<SazitoResponse<Booking>> {\n return this.http.post<Booking>(SCHEDULER_BOOKINGS_API, input, options);\n }\n\n /**\n * List user bookings (requires authentication)\n */\n async listBookings(\n options?: RequestOptions\n ): Promise<SazitoResponse<PaginatedResponse<Booking>>> {\n return this.http.get<PaginatedResponse<Booking>>(\n SCHEDULER_BOOKINGS_API,\n options\n );\n }\n\n /**\n * Cancel booking\n */\n async cancelBooking(\n bookingId: number,\n options?: RequestOptions\n ): Promise<SazitoResponse<Booking>> {\n return this.http.post<Booking>(\n `${SCHEDULER_BOOKINGS_API}/${bookingId}/cancel`,\n {},\n options\n );\n }\n}\n","/**\n * Entity Routes API\n * Resolves URLs to entity data (products, categories, CMS pages)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { SazitoResponse, EntityRouteResponse, RequestOptions } from '../types';\nimport { ENTITY_ROUTE_API } from '../constants/endpoints';\nimport { transformEntityRouteResponse } from '../utils/transformers';\n\nexport class EntityRoutesAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Resolve URL path to entity data\n * @param urlPart - URL pathname (e.g., '/product/laptop-abc' or '/category/electronics')\n * @returns Entity route with cleaned entity data based on type\n */\n async resolve(\n urlPart: string,\n options?: RequestOptions\n ): Promise<SazitoResponse<EntityRouteResponse>> {\n const response = await this.http.get<any>(ENTITY_ROUTE_API, {\n ...options,\n params: { url_part: urlPart }\n });\n\n if (response.data) {\n const transformed = transformEntityRouteResponse(response.data);\n return { data: transformed };\n }\n\n return response;\n }\n}\n","/**\n * Menu API (Header Menu, Navigation Trees)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport {\n SazitoResponse,\n RequestOptions\n} from '../types';\nimport { MenuTree, MenuItem } from '../types/menu';\nimport { MENU_API } from '../constants/endpoints';\nimport { transformMenuResponse } from '../utils/transformers';\n\nexport class MenuAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Fetch header menu by identifier\n * @param identifier - Menu identifier (default: 'headermenu')\n * @param options - Request options\n */\n async getHeaderMenu(\n identifier: string = 'headermenu',\n options?: RequestOptions\n ): Promise<SazitoResponse<MenuItem[]>> {\n const response = await this.http.get<{ tree: MenuTree }>(\n MENU_API,\n {\n ...options,\n params: { identifier }\n }\n );\n\n // Transform and clean the response (removes staticUrl, unnecessary fields)\n const transformed = response.data ? transformMenuResponse(response.data) : response.data;\n\n // Transform the raw tree structure into a clean navigation array\n // Response is camelCased by HTTP client: tree.treeStructure.nodes\n const nodes = transformed?.tree?.treeStructure?.nodes || [];\n const processedMenu = this.convertRawTreeToNavigation(nodes);\n\n return {\n ...response,\n data: processedMenu\n };\n }\n\n /**\n * Convert raw tree structure to clean navigation items\n * Filters out disabled items and processes nested children recursively\n */\n private convertRawTreeToNavigation(nodes: any[]): MenuItem[] {\n if (!nodes || nodes.length === 0) return [];\n\n const output = nodes.map(node => ({\n name: this.findNodeTitle(node),\n url: this.findNodeUrl(node),\n children: this.convertRawTreeToNavigation(node.children || []),\n shouldBeDropped: this.shouldDropNode(node)\n }));\n\n // Filter out disabled items\n return output\n .filter(item => !item.shouldBeDropped)\n .map(({ shouldBeDropped: _shouldBeDropped, ...item }) => item);\n }\n\n /**\n * Extract the display title for a menu node\n */\n private findNodeTitle(node: any): string {\n const { entityType, details, entity } = node;\n\n // If isTitleDefault is true, use entity name/title\n // If isTitleDefault is false or undefined, use custom title from details\n if (details && !details.isTitleDefault && details.title) {\n // Custom title set by user\n return details.title;\n } else if (details && !details.isTitleDefault && details.name) {\n // For entityType \"url\", use details.name\n return details.name;\n } else if (entityType === 'product_category' || entityType === 'product') {\n // Use entity name for products/categories\n return entity?.name || '';\n } else if (entityType === 'cms_page' || entityType === 'blog_page') {\n // Use entity name for CMS pages (not title!)\n return entity?.name || '';\n }\n\n return '';\n }\n\n /**\n * Extract the URL for a menu node\n */\n private findNodeUrl(node: any): string {\n if (\n node.entityType === 'product' ||\n node.entityType === 'product_category' ||\n node.entityType === 'cms_page' ||\n node.entityType === 'blog_page'\n ) {\n return node.entity?.url || '#';\n } else if (node.entityType === 'url') {\n return node.details?.url || '#';\n }\n return '#';\n }\n\n /**\n * Determine if a node should be filtered out (disabled items)\n */\n private shouldDropNode(node: any): boolean {\n if (\n node.entityType === 'product' ||\n node.entityType === 'product_category' ||\n node.entityType === 'cms_page' ||\n node.entityType === 'blog_page'\n ) {\n return !node.entity?.enabled;\n }\n return false;\n }\n}\n","/**\n * General API (shop configuration and feature flags)\n */\n\nimport { HttpClient } from '../core/http-client';\nimport { SazitoResponse, RequestOptions } from '../types';\nimport { GENERAL_API } from '../constants/endpoints';\nimport { transformGeneralInfoResponse } from '../utils/transformers';\n\nexport interface Region {\n id: number;\n name: string;\n latitude: number;\n longitude: number;\n}\n\nexport interface City {\n id: number;\n name: string;\n latitude: number;\n longitude: number;\n region: Region;\n}\n\nexport interface PremiumInfo {\n enabled: boolean;\n nextRenewal: string;\n subscriptionSubtype: string;\n}\n\nexport interface GoogleAnalyticsCode {\n code: string;\n enabled: boolean;\n}\n\nexport interface GoogleInfo {\n analyticsCode: GoogleAnalyticsCode;\n analyticsId: GoogleAnalyticsCode;\n tagManager: GoogleAnalyticsCode;\n}\n\nexport interface LogoInfo {\n favicon: string;\n main: string;\n}\n\nexport interface SocialInfo {\n facebook: string;\n instagram: string;\n phone1: string;\n phone2: string;\n telegram: string;\n twitter: string;\n whatsapp: string;\n}\n\nexport interface DomainInfo {\n url: string;\n}\n\nexport interface EnamadInfo {\n code: string;\n}\n\nexport interface ShopInfo {\n name: string;\n description: string;\n city: City | null;\n domain: DomainInfo;\n logo: LogoInfo;\n social: SocialInfo;\n}\n\nexport interface CheckoutConfig {\n addToCartAlert: boolean;\n dynamicForm: boolean;\n emailOptional: boolean;\n preventRedirect: boolean;\n minBasket: {\n enabled: boolean;\n minAmount: number;\n };\n miniCart: boolean;\n postalCodeMandatory: boolean;\n quickAddToCart: boolean;\n}\n\nexport interface TajrobeConfig {\n enabled: boolean;\n}\n\nexport interface WalletConfig {\n enabled: boolean;\n useWithDiscount: boolean;\n minAmount: number;\n minAmountRequired: boolean;\n}\n\n/**\n * Standardized feature shape:\n * - boolean feature switches as direct keys on the object\n * - premium details in `premium`\n */\nexport interface ShopFeatures {\n [featureName: string]: boolean | PremiumInfo | undefined;\n premium?: PremiumInfo;\n}\n\nexport interface ScriptsInfo {\n enamad: EnamadInfo;\n google: GoogleInfo;\n}\n\nexport interface SettingsInfo {\n checkout: CheckoutConfig;\n features: ShopFeatures;\n wallet: WalletConfig;\n tajrobe: TajrobeConfig;\n registerType: string;\n showProductStockNumber: boolean;\n}\n\n/**\n * Standardized General API response\n */\nexport interface GeneralInfo {\n shop: ShopInfo;\n settings: SettingsInfo;\n scripts: ScriptsInfo;\n}\n\ninterface RawGeneralInfo {\n general?: {\n name?: string;\n description?: string;\n city?: City;\n };\n shop?: {\n registerType?: string;\n showProductStockNumber?: { enabled?: boolean } | boolean;\n };\n checkout?: unknown;\n features?: Record<string, unknown>;\n wallet?: unknown;\n tajrobe?: unknown;\n domain?: DomainInfo;\n enamad?: EnamadInfo;\n google?: GoogleInfo;\n logo?: LogoInfo;\n social?: SocialInfo;\n}\n\nexport class GeneralAPI {\n constructor(private http: HttpClient) {}\n\n /**\n * Get normalized shop information including config and features.\n */\n async getInfo(options?: RequestOptions): Promise<SazitoResponse<GeneralInfo>> {\n const response = await this.http.get<RawGeneralInfo>(GENERAL_API, options);\n\n if (response.data) {\n return { data: transformGeneralInfoResponse(response.data) as GeneralInfo };\n }\n\n if (response.error) {\n return { error: response.error };\n }\n\n return {\n error: {\n type: 'api',\n message: 'No data returned from general info endpoint.'\n }\n };\n }\n\n /**\n * Get standardized shop feature flags only.\n */\n async getFeatures(options?: RequestOptions): Promise<SazitoResponse<ShopFeatures>> {\n const response = await this.getInfo(options);\n\n if (response.error) {\n return { error: response.error };\n }\n\n return { data: response.data?.settings?.features };\n }\n\n /**\n * Get standardized checkout config only.\n */\n async getCheckoutConfig(options?: RequestOptions): Promise<SazitoResponse<CheckoutConfig>> {\n const response = await this.getInfo(options);\n\n if (response.error) {\n return { error: response.error };\n }\n\n return { data: response.data?.settings?.checkout };\n }\n\n /**\n * Get standardized wallet config only.\n */\n async getWalletConfig(options?: RequestOptions): Promise<SazitoResponse<WalletConfig>> {\n const response = await this.getInfo(options);\n\n if (response.error) {\n return { error: response.error };\n }\n\n return { data: response.data?.settings?.wallet };\n }\n\n /**\n * Get standardized Tajrobe config only.\n */\n async getTajrobeConfig(options?: RequestOptions): Promise<SazitoResponse<TajrobeConfig>> {\n const response = await this.getInfo(options);\n\n if (response.error) {\n return { error: response.error };\n }\n\n return { data: response.data?.settings?.tajrobe };\n }\n}\n","/**\n * Main Sazito SDK Client\n */\n\nimport { SazitoConfig, mergeConfig } from './config';\nimport { HttpClient } from './http-client';\nimport { TokenStorage } from '../utils/token-storage';\nimport { CredentialsManager } from '../utils/credentials-manager';\n\n// API modules\nimport { ProductsAPI } from '../api/products';\nimport { CategoriesAPI } from '../api/categories';\nimport { CartAPI } from '../api/cart';\nimport { OrdersAPI } from '../api/orders';\nimport { InvoicesAPI } from '../api/invoices';\nimport { ShippingAPI } from '../api/shipping';\nimport { PaymentsAPI } from '../api/payments';\nimport { UsersAPI } from '../api/users';\nimport { SearchAPI, type SearchFilters } from '../api/search';\nimport { FeedbacksAPI } from '../api/feedbacks';\nimport { WalletAPI } from '../api/wallet';\nimport { CMSAPI } from '../api/cms';\nimport { ImagesAPI } from '../api/images';\nimport { VisitsAPI } from '../api/visits';\nimport { BookingAPI } from '../api/booking';\nimport { EntityRoutesAPI } from '../api/entity-routes';\nimport { MenuAPI } from '../api/menu';\nimport { GeneralAPI } from '../api/general';\nimport type { RequestOptions, SazitoResponse, SearchResponse } from '../types';\n\nexport class SazitoClient {\n private http: HttpClient;\n private tokenStorage: TokenStorage;\n private credentialsManager: CredentialsManager;\n\n // API modules (lazy-loaded)\n public readonly products: ProductsAPI;\n public readonly categories: CategoriesAPI;\n public readonly cart: CartAPI;\n public readonly orders: OrdersAPI;\n public readonly invoices: InvoicesAPI;\n public readonly shipping: ShippingAPI;\n public readonly payments: PaymentsAPI;\n public readonly users: UsersAPI;\n public readonly search: SearchAPI;\n public readonly feedbacks: FeedbacksAPI;\n public readonly wallet: WalletAPI;\n public readonly cms: CMSAPI;\n public readonly images: ImagesAPI;\n public readonly visits: VisitsAPI;\n public readonly booking: BookingAPI;\n public readonly entityRoutes: EntityRoutesAPI;\n public readonly menu: MenuAPI;\n public readonly general: GeneralAPI;\n\n constructor(config: SazitoConfig) {\n const mergedConfig = mergeConfig(config);\n\n // Initialize core components\n this.http = new HttpClient(mergedConfig);\n this.tokenStorage = this.http.getTokenStorage();\n this.credentialsManager = new CredentialsManager();\n\n // Initialize API modules\n this.products = new ProductsAPI(this.http);\n this.categories = new CategoriesAPI(this.http);\n this.cart = new CartAPI(this.http, this.credentialsManager);\n this.orders = new OrdersAPI(this.http);\n this.invoices = new InvoicesAPI(this.http, this.credentialsManager);\n this.shipping = new ShippingAPI(this.http, this.credentialsManager);\n this.payments = new PaymentsAPI(this.http, this.credentialsManager);\n this.users = new UsersAPI(this.http);\n this.search = new SearchAPI(this.http);\n this.feedbacks = new FeedbacksAPI(this.http);\n this.wallet = new WalletAPI(this.http);\n this.cms = new CMSAPI(this.http);\n this.images = new ImagesAPI(this.http);\n this.visits = new VisitsAPI(this.http);\n this.booking = new BookingAPI(this.http);\n this.entityRoutes = new EntityRoutesAPI(this.http);\n this.menu = new MenuAPI(this.http);\n this.general = new GeneralAPI(this.http);\n }\n\n /**\n * Set authentication token (stored in localStorage with cookie fallback)\n */\n setAuthToken(token: string): void {\n this.tokenStorage.set(token);\n }\n\n /**\n * Get authentication token from storage\n */\n getAuthToken(): string | null {\n return this.tokenStorage.get();\n }\n\n /**\n * Clear authentication token\n */\n clearAuth(): void {\n this.tokenStorage.remove();\n }\n\n /**\n * Check if user is authenticated\n */\n isAuthenticated(): boolean {\n return this.tokenStorage.get() !== null;\n }\n\n /**\n * Clear all cache\n */\n clearCache(): void {\n this.http.clearCache();\n }\n\n /**\n * Clear all guest credentials\n */\n clearCredentials(): void {\n this.credentialsManager.clearAll();\n }\n\n /**\n * Clear everything (auth + cache + credentials)\n */\n clearAll(): void {\n this.clearAuth();\n this.clearCache();\n this.clearCredentials();\n }\n\n /**\n * Search helper for `client.search.query(...)`.\n */\n async searchQuery(\n query: string,\n filters?: SearchFilters,\n options?: RequestOptions\n ): Promise<SazitoResponse<SearchResponse>> {\n return this.search.query(query, filters, options);\n }\n}\n\n/**\n * Create a new Sazito SDK client instance\n */\nexport function createSazitoClient(config: SazitoConfig): SazitoClient {\n return new SazitoClient(config);\n}\n","import { CredentialsManager } from '../utils/credentials-manager';\nimport type { SazitoConfig } from './config';\nimport { mergeConfig } from './config';\nimport { HttpClient } from './http-client';\n\nexport interface ModuleContext {\n http: HttpClient;\n credentials: CredentialsManager;\n}\n\n/**\n * Create a shared module context so multiple API modules can share\n * one HttpClient and one credential store.\n */\nexport function createModuleContext(config: SazitoConfig): ModuleContext {\n const mergedConfig = mergeConfig(config);\n\n return {\n http: new HttpClient(mergedConfig),\n credentials: new CredentialsManager()\n };\n}\n\nexport function isModuleContext(value: unknown): value is ModuleContext {\n if (!value || typeof value !== 'object') {\n return false;\n }\n\n const candidate = value as Partial<ModuleContext>;\n return candidate.http instanceof HttpClient && candidate.credentials instanceof CredentialsManager;\n}\n\nexport function ensureModuleContext(configOrContext: SazitoConfig | ModuleContext): ModuleContext {\n return isModuleContext(configOrContext)\n ? configOrContext\n : createModuleContext(configOrContext);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { ProductsAPI } from '../api/products';\n\nexport * from '../api/products';\n\nexport function createProductsAPI(configOrContext: SazitoConfig | ModuleContext): ProductsAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new ProductsAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { CategoriesAPI } from '../api/categories';\n\nexport * from '../api/categories';\n\nexport function createCategoriesAPI(configOrContext: SazitoConfig | ModuleContext): CategoriesAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new CategoriesAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { CartAPI } from '../api/cart';\n\nexport * from '../api/cart';\n\nexport function createCartAPI(configOrContext: SazitoConfig | ModuleContext): CartAPI {\n const { http, credentials } = ensureModuleContext(configOrContext);\n return new CartAPI(http, credentials);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { OrdersAPI } from '../api/orders';\n\nexport * from '../api/orders';\n\nexport function createOrdersAPI(configOrContext: SazitoConfig | ModuleContext): OrdersAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new OrdersAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { InvoicesAPI } from '../api/invoices';\n\nexport * from '../api/invoices';\n\nexport function createInvoicesAPI(configOrContext: SazitoConfig | ModuleContext): InvoicesAPI {\n const { http, credentials } = ensureModuleContext(configOrContext);\n return new InvoicesAPI(http, credentials);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { ShippingAPI } from '../api/shipping';\n\nexport * from '../api/shipping';\n\nexport function createShippingAPI(configOrContext: SazitoConfig | ModuleContext): ShippingAPI {\n const { http, credentials } = ensureModuleContext(configOrContext);\n return new ShippingAPI(http, credentials);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { PaymentsAPI } from '../api/payments';\n\nexport * from '../api/payments';\n\nexport function createPaymentsAPI(configOrContext: SazitoConfig | ModuleContext): PaymentsAPI {\n const { http, credentials } = ensureModuleContext(configOrContext);\n return new PaymentsAPI(http, credentials);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { UsersAPI } from '../api/users';\n\nexport * from '../api/users';\n\nexport function createUsersAPI(configOrContext: SazitoConfig | ModuleContext): UsersAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new UsersAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { SearchAPI } from '../api/search';\n\nexport * from '../api/search';\n\nexport function createSearchAPI(configOrContext: SazitoConfig | ModuleContext): SearchAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new SearchAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { FeedbacksAPI } from '../api/feedbacks';\n\nexport * from '../api/feedbacks';\n\nexport function createFeedbacksAPI(configOrContext: SazitoConfig | ModuleContext): FeedbacksAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new FeedbacksAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { WalletAPI } from '../api/wallet';\n\nexport * from '../api/wallet';\n\nexport function createWalletAPI(configOrContext: SazitoConfig | ModuleContext): WalletAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new WalletAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { CMSAPI } from '../api/cms';\n\nexport * from '../api/cms';\n\nexport function createCMSAPI(configOrContext: SazitoConfig | ModuleContext): CMSAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new CMSAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { ImagesAPI } from '../api/images';\n\nexport * from '../api/images';\n\nexport function createImagesAPI(configOrContext: SazitoConfig | ModuleContext): ImagesAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new ImagesAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { VisitsAPI } from '../api/visits';\n\nexport * from '../api/visits';\n\nexport function createVisitsAPI(configOrContext: SazitoConfig | ModuleContext): VisitsAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new VisitsAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { BookingAPI } from '../api/booking';\n\nexport * from '../api/booking';\n\nexport function createBookingAPI(configOrContext: SazitoConfig | ModuleContext): BookingAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new BookingAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { EntityRoutesAPI } from '../api/entity-routes';\n\nexport * from '../api/entity-routes';\n\nexport function createEntityRoutesAPI(configOrContext: SazitoConfig | ModuleContext): EntityRoutesAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new EntityRoutesAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { MenuAPI } from '../api/menu';\n\nexport * from '../api/menu';\n\nexport function createMenuAPI(configOrContext: SazitoConfig | ModuleContext): MenuAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new MenuAPI(http);\n}\n","import type { SazitoConfig } from '../core/config';\nimport { ensureModuleContext, type ModuleContext } from '../core/module-context';\nimport { GeneralAPI } from '../api/general';\n\nexport * from '../api/general';\n\nexport function createGeneralAPI(configOrContext: SazitoConfig | ModuleContext): GeneralAPI {\n const { http } = ensureModuleContext(configOrContext);\n return new GeneralAPI(http);\n}\n"],"names":["DEFAULT_CONFIG","timeout","retry","enabled","retries","retryDelay","cache","products","ttl","categories","cart","orders","search","cms","tags","entityRoutes","debug","mergeConfig","userConfig","customFetchApi","fetch","undefined","TokenStorage","constructor","this","tokenKey","get","window","document","storageToken","getFromLocalStorage","parseCookies","set","token","options","console","warn","setInLocalStorage","defaultOptions","secure","sameSite","maxAge","path","setCookie","remove","removeFromLocalStorage","localStorage","getItem","setItem","removeItem","cookie","split","reduce","acc","key","value","trim","decodeURIComponent","name","encodeURIComponent","domain","httpOnly","CacheManager","Map","entry","Date","now","timestamp","delete","data","deletePattern","pattern","regex","RegExp","keysToDelete","forEach","_","test","push","clear","generateKey","method","url","params","JSON","stringify","FIELD_NAME_MAP","no_of_items","single_item_price","total_items_price","items_total_raw_price","items_discount","customer_profit","customer_profit_percentage","total_amount","net_total","gross_total","final_total","discount_total","shipping_total","tax_total","unique_identifier","invoice_identifier","payment_identifier","shipping_address_identifier","first_name","last_name","mobile_phone","phone_number","postal_code","user_comment","product_id","variant_id","product_name","product_image","product_variant","product_variants","product_categories","product_attributes","product_type","title","short_description","stock_quantity","stock_number","sale_price","raw_price","has_max_order","max_no_of_order","min_order_count","sold_count","static_url","dynamic_form_id","event_entity_id","theme_config","image_id","is_stock_managed","commercial_files","sort_index","attribute_type","cart_products","cart_product_id","invoice_items","total_count","shipping_method_needed","shipping_method","shipping_address","shipping_items","delivery_time","min_delivery_days","max_delivery_days","payment_type","payment_types","reference_code","is_default","is_available","delete_coupon","form_attributes","booking_attributes","readable_form_attr","created_at","updated_at","page_number","page_size","total_count_raw","max_price","min_price","stock_alert_limit","sub_categories","order_number","sort_order","pinned_ids","region_id","city_id","parent_id","discount_code","entity_name","entity_id","other_props","shipping_methods","shipping_rates","grouped_shipping_rates","items_shipping_rate","shipping_rate","rate_id","invoice_item_id","invoice_item_ids","scheduler_booking_attributes","inventory_count","order_identifier","self_only","coupon","user_set_coordinates_before","alt","activate_add_to_cart_alert","activate_advanced_card_to_card","activate_ayria_payment_customization","activate_azki_payment_customization","activate_bazar_payment_customization","activate_blog","activate_card_to_card_payment","activate_checkout_dynamic_form","activate_different_register_customization","activate_digipay_payment","activate_digipay_payment_customization","activate_filter_products","activate_ghesta_payment_customization","activate_mega_footer","activate_mellat_payment_customization","activate_min_basket","activate_novapay_payment_customization","activate_ozon_payment_customization","activate_payment_in_place","activate_payping_payment","activate_pec_payment_customization","activate_sabin_payment_customization","activate_sadad_payment_customization","activate_search","activate_sep_payment_customization","activate_shop_vat","activate_snapppay_payment_customization","activate_tajrobe","activate_tara_payment_customization","activate_theme_config_settings","activate_toman_payment_customization","activate_torobpay_payment_customization","activate_up_payment_customization","activate_vandar_payment_customization","activate_wallet","activate_yourgate_payment_customization","activate_zarinpal_payment","activate_zarinplus_payment_customization","activate_zibal_payment_customization","activate_zify_payment_customization","disable_ordering","pwa","remove_front_basket","remove_front_taint","REVERSE_FIELD_NAME_MAP","Object","entries","snakeToCamel","str","replace","letter","toUpperCase","camelToSnake","toLowerCase","isPlainObject","Array","isArray","removeKeys","obj","keys","cleaned","transformResponseKeys","map","item","transformed","newKey","transformRequestKeys","transformApiResponse","response","result","length","transformGeneralInfoResponse","general","shop","checkout","features","wallet","tajrobe","enamad","google","logo","social","rest","mergedShop","registerType","showProductStockNumber","shopWithoutSettings","normalizedCheckout","checkoutCopy","preventRedirect","manual","scripts","normalizeGeneralShop","settings","normalizeGeneralFeatures","normalizeGeneralWallet","normalizeGeneralTajrobe","normalizeGeneralRegisterType","normalizeGeneralShowProductStockNumber","prototype","hasOwnProperty","call","normalizedShop","city","cityWithoutMeta","cleanedRegion","region","FEATURE_FLAG_NAME_MAP","addToCardAlert","addToCartAlert","advancedCardToCard","cardToCardPayment","checkoutDynamicForm","multiTypeRegister","productFilters","megaFooter","checkoutMinimumAmount","paymentInPlace","shopBlog","shopSearch","shopVat","themeConfigSettings","progressiveWebApp","disableOrdering","hideCheckout","sazitoBrandingRemoval","ayriaPaymentGateway","azkiPaymentGateway","bazarPaymentGateway","digipayPaymentGateway","ghestaPaymentGateway","mellatPaymentGateway","novapayPaymentGateway","ozonPaymentGateway","paypingPaymentGateway","pecPaymentGateway","sabinPaymentGateway","sadadPaymentGateway","sepPaymentGateway","snapppayPaymentGateway","taraPaymentGateway","tomanPaymentGateway","torobpayPaymentGateway","asanpardakhtPaymentGateway","vandarPaymentGateway","yourgatePaymentGateway","zarinpalPaymentGateway","zarinplusPaymentGateway","zibalPaymentGateway","zifyPaymentGateway","activateEditOrderCustomization","activateEditOrderCustomizationEnabled","FEATURE_FLAG_BLOCKLIST","Set","FEATURE_FLAG_NAME_BLOCKLIST","rawFlags","pushFlag","has","normalized","readBooleanish","flags","configurations","normalizedName","rawKey","camelKey","includes","mapped","withoutActivatePrefix","startsWith","charAt","slice","endsWith","normalizeFeatureFlagName","premium","source","toBoolean","useWithDiscount","minAmount","Number","isFinite","parsed","toNumber","walletMinAmount","minAmountRequired","walletMinStatus","transformCartResponse","items","product","variantId","variant","id","productId","image","attributes","hasMaxOrder","maxOrderQuantity","minOrderQuantity","transformInvoiceResponse","invoice","discount","originalPrice","unitPrice","cleanProduct","cleanedProduct","variants","category","images","cleanProductListItem","transformProductListResponse","total","page","pageSize","totalPages","Math","ceil","transformSearchResponse","blogPages","cmsPages","productCategories","productsCount","productsPageNumber","productsPageSize","cleanCmsPageListItem","blogPagesCount","blogPagesPageNumber","blogPagesPageSize","cmsPagesCount","cmsPagesPageNumber","cmsPagesPageSize","cat","cleanCategoryListItem","productCategoriesCount","productCategoriesPageNumber","productCategoriesPageSize","transformShippingAddressInput","input","transformAddToCartInput","quantity","formAttributes","count","transformCreateCartInput","productVariants","cleanCategory","cleanCmsPage","transformEntityRouteResponse","route","entity","entityType","cleanCategoryTreeNode","node","cleanedNode","children","transformCMSListResponse","pageNumber","transformCMSFilters","filters","cmsPageTypes","pageType","cleanMenuNode","entityId","cleanedEntity","details","child","transformMenuResponse","tree","treeStructure","nodes","HttpClient","config","baseUrl","tokenStorage","fetchApi","bind","globalThis","endpoint","buildUrl","cacheKey","apiName","getApiName","cacheConfig","cached","log","request","post","body","transformedBody","put","retryCount","controller","AbortController","signal","timeoutId","setTimeout","abort","headers","getHeaders","clearTimeout","maxRetries","ok","shouldRetry","status","delay","contentType","json","text","transformedResult","unwrapKeys","error","message","statusText","type","searchParams","URLSearchParams","append","String","toString","customHeaders","ms","Promise","resolve","getTokenStorage","clearCache","CredentialsManager","CART_KEY","INVOICE_KEY","SHIPPING_KEY","PAYMENT_KEY","DISCOUNT_KEY","getCartCredentials","setCartCredentials","credentials","clearCartCredentials","getInvoiceCredentials","setInvoiceCredentials","clearInvoiceCredentials","getShippingCredentials","setShippingCredentials","clearShippingCredentials","getPaymentCredentials","setPaymentCredentials","clearPaymentCredentials","getDiscountCode","setDiscountCode","code","clearDiscountCode","clearAll","parse","PRODUCT_CATEGORIES_API","SEARCH_API","CARTS_API","INVOICES_API","SHIPPING_ADDRESSES_API","PAYMENTS_API","ORDERS_API","USERS_API","SESSIONS_API","FEEDBACKS_API","CMS_PAGES_API","IMAGES_API","SCHEDULER_EVENTS_API","SCHEDULER_BOOKINGS_API","ENTITY_ROUTE_API","ProductsAPI","http","mapSortToApi","sort","newest","availability","sortOrder","price","transformFilters","filterArray","join","availableOnly","discountedOnly","similarTo","pinnedIds","priceMin","priceMax","slugOrPath","urlPart","url_part","list","query","search_direction","CategoriesAPI","idOrSlug","productCategory","transformCategoryResponse","transformCategoryListResponse","CartAPI","cartCreds","identifier","create","addItem","updateItem","cartProductId","clearCart","OrdersAPI","orderId","InvoicesAPI","invoiceCreds","cart_id","cart_identifier","refresh","addShippingAddress","shippingAddressId","shippingAddressIdentifier","shipping_address_id","addDiscountCode","assignShippingMethod","shippings","addDetails","comment","getApplicableShippingMethods","clearInvoice","ShippingAPI","createAddress","address","updateAddress","shippingCreds","getAddress","getMethods","clearAddress","PaymentsAPI","invoice_id","paymentTypeId","initialize","paymentCreds","processStep","clearPayment","UsersAPI","login","requestMobileOTP","verifyMobileOTP","requestEmailLogin","register","getCurrentUser","updateProfile","userId","requestMobilePhoneUpdate","verifyMobilePhoneUpdate","forgotPassword","revivePassword","mergeUser","SearchAPI","categoryId","category_id","minPrice","maxPrice","term","transformedFilters","FeedbacksAPI","feedbackId","WalletAPI","validateInvoiceId","invoiceId","getBalance","listTransactions","applyCredit","validation","removeCredit","CMSAPI","getPage","urlPath","cmsPageType","Error","listPages","transformedParams","getBlogPost","listBlogPosts","listAll","ImagesAPI","upload","file","formData","FormData","imageId","VisitsAPI","track","inputOrOptions","resolvedOptions","trackProduct","trackCategory","BookingAPI","listEvents","getEvent","eventId","createBooking","listBookings","cancelBooking","bookingId","EntityRoutesAPI","MenuAPI","getHeaderMenu","processedMenu","convertRawTreeToNavigation","findNodeTitle","findNodeUrl","shouldBeDropped","shouldDropNode","filter","_shouldBeDropped","isTitleDefault","GeneralAPI","getInfo","getFeatures","getCheckoutConfig","getWalletConfig","getTajrobeConfig","SazitoClient","mergedConfig","credentialsManager","invoices","shipping","payments","users","feedbacks","visits","booking","menu","setAuthToken","getAuthToken","clearAuth","isAuthenticated","clearCredentials","searchQuery","createSazitoClient","ensureModuleContext","configOrContext","candidate","isModuleContext","createModuleContext","createProductsAPI","createCategoriesAPI","createCartAPI","createOrdersAPI","createInvoicesAPI","createShippingAPI","createPaymentsAPI","createUsersAPI","createSearchAPI","createFeedbacksAPI","createWalletAPI","createCMSAPI","createImagesAPI","createVisitsAPI","createBookingAPI","createEntityRoutesAPI","createMenuAPI","createGeneralAPI"],"mappings":"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"}