@shoppexio/storefront 1.0.57 → 1.0.59

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +99 -0
  2. package/LICENSE +21 -0
  3. package/README.md +96 -180
  4. package/dist/chunk-ZVOFFURI.js +15364 -0
  5. package/dist/chunk-ZVOFFURI.js.map +1 -0
  6. package/dist/customer.cjs +16013 -1
  7. package/dist/customer.cjs.map +1 -1
  8. package/dist/{headless-customer.d.ts → customer.d.cts} +74 -61
  9. package/dist/customer.d.ts +336 -10
  10. package/dist/customer.js +726 -2
  11. package/dist/customer.js.map +1 -1
  12. package/dist/index.cjs +21533 -0
  13. package/dist/index.cjs.map +1 -0
  14. package/dist/index.d.cts +1979 -0
  15. package/dist/index.d.ts +1859 -49
  16. package/dist/index.js +6139 -0
  17. package/dist/index.js.map +1 -0
  18. package/package.json +18 -37
  19. package/dist/core/attribution.d.ts +0 -26
  20. package/dist/core/attribution.d.ts.map +0 -1
  21. package/dist/core/cache.d.ts +0 -26
  22. package/dist/core/cache.d.ts.map +0 -1
  23. package/dist/core/client.d.ts +0 -18
  24. package/dist/core/client.d.ts.map +0 -1
  25. package/dist/core/config.d.ts +0 -10
  26. package/dist/core/config.d.ts.map +0 -1
  27. package/dist/core/endpoint.d.ts +0 -2
  28. package/dist/core/endpoint.d.ts.map +0 -1
  29. package/dist/core/errors.d.ts +0 -34
  30. package/dist/core/errors.d.ts.map +0 -1
  31. package/dist/core/telemetry.d.ts +0 -20
  32. package/dist/core/telemetry.d.ts.map +0 -1
  33. package/dist/core/typed-client.d.ts +0 -15
  34. package/dist/core/typed-client.d.ts.map +0 -1
  35. package/dist/customer.d.ts.map +0 -1
  36. package/dist/headless-customer.d.ts.map +0 -1
  37. package/dist/index.d.ts.map +0 -1
  38. package/dist/modules/affiliates.d.ts +0 -15
  39. package/dist/modules/affiliates.d.ts.map +0 -1
  40. package/dist/modules/analytics.d.ts +0 -2
  41. package/dist/modules/analytics.d.ts.map +0 -1
  42. package/dist/modules/cart.d.ts +0 -62
  43. package/dist/modules/cart.d.ts.map +0 -1
  44. package/dist/modules/checkout.d.ts +0 -133
  45. package/dist/modules/checkout.d.ts.map +0 -1
  46. package/dist/modules/coupons.d.ts +0 -3
  47. package/dist/modules/coupons.d.ts.map +0 -1
  48. package/dist/modules/customer.d.ts +0 -147
  49. package/dist/modules/customer.d.ts.map +0 -1
  50. package/dist/modules/invoices.d.ts +0 -6
  51. package/dist/modules/invoices.d.ts.map +0 -1
  52. package/dist/modules/navigation.d.ts +0 -20
  53. package/dist/modules/navigation.d.ts.map +0 -1
  54. package/dist/modules/pages.d.ts +0 -10
  55. package/dist/modules/pages.d.ts.map +0 -1
  56. package/dist/modules/presence.d.ts +0 -12
  57. package/dist/modules/presence.d.ts.map +0 -1
  58. package/dist/modules/products.d.ts +0 -16
  59. package/dist/modules/products.d.ts.map +0 -1
  60. package/dist/modules/reviews.d.ts +0 -4
  61. package/dist/modules/reviews.d.ts.map +0 -1
  62. package/dist/modules/search.d.ts +0 -10
  63. package/dist/modules/search.d.ts.map +0 -1
  64. package/dist/modules/store.d.ts +0 -11
  65. package/dist/modules/store.d.ts.map +0 -1
  66. package/dist/modules/theme.d.ts +0 -27
  67. package/dist/modules/theme.d.ts.map +0 -1
  68. package/dist/shoppex.esm.js +0 -3
  69. package/dist/shoppex.esm.js.map +0 -1
  70. package/dist/shoppex.umd.js +0 -2
  71. package/dist/shoppex.umd.js.map +0 -1
  72. package/dist/types/api.d.ts +0 -757
  73. package/dist/types/api.d.ts.map +0 -1
  74. package/dist/types/cart.d.ts +0 -239
  75. package/dist/types/cart.d.ts.map +0 -1
  76. package/dist/types/config.d.ts +0 -18
  77. package/dist/types/config.d.ts.map +0 -1
  78. package/dist/types/index.d.ts +0 -7
  79. package/dist/types/index.d.ts.map +0 -1
  80. package/dist/types/theme-config.d.ts +0 -109
  81. package/dist/types/theme-config.d.ts.map +0 -1
  82. package/dist/utils/cart-line-id.d.ts +0 -5
  83. package/dist/utils/cart-line-id.d.ts.map +0 -1
  84. package/dist/utils/format.d.ts +0 -6
  85. package/dist/utils/format.d.ts.map +0 -1
  86. package/dist/utils/requested-currency.d.ts +0 -3
  87. package/dist/utils/requested-currency.d.ts.map +0 -1
  88. package/dist/utils/storage.d.ts +0 -10
  89. package/dist/utils/storage.d.ts.map +0 -1
  90. package/dist/utils/storefront-catalog.d.ts +0 -5
  91. package/dist/utils/storefront-catalog.d.ts.map +0 -1
  92. package/dist/utils/storefront-contact.d.ts +0 -32
  93. package/dist/utils/storefront-contact.d.ts.map +0 -1
  94. package/dist/utils/storefront-custom-fields.d.ts +0 -13
  95. package/dist/utils/storefront-custom-fields.d.ts.map +0 -1
  96. package/dist/utils/storefront-search.d.ts +0 -22
  97. package/dist/utils/storefront-search.d.ts.map +0 -1
  98. package/dist/utils/storefront-stock.d.ts +0 -14
  99. package/dist/utils/storefront-stock.d.ts.map +0 -1
@@ -0,0 +1,1979 @@
1
+ import { createApiClient, CustomerWarrantyClaimWire, CustomerPortalDashboardWire, CustomerPortalPaginatedInvoicesWire, CustomerPortalInvoiceDetailWire, CustomerLoyaltyWire, CustomerLoyaltyRedeemWire, CustomerWarrantyListWire } from '@shoppex/contracts';
2
+ import { NavigationMenuSlot } from '@shoppex/contracts/navigation';
3
+ export { NavigationMenuSlot } from '@shoppex/contracts/navigation';
4
+ import * as src from 'src';
5
+ export { CATALOG_UNIT_PRICE_DECIMAL_PLACES, CATALOG_UNIT_PRICE_FORMAT_OPTIONS, PAYABLE_AMOUNT_DECIMAL_PLACES, roundPayableAmount } from '@shoppex/contracts/catalog-unit-price';
6
+
7
+ /**
8
+ * SDK Configuration Types
9
+ */
10
+ interface ShoppexConfig {
11
+ storeSlug: string;
12
+ locale?: string;
13
+ currency?: string;
14
+ apiBaseUrl?: string;
15
+ checkoutBaseUrl?: string;
16
+ }
17
+ interface ShoppexInitOptions {
18
+ locale?: string;
19
+ currency?: string;
20
+ apiBaseUrl?: string;
21
+ checkoutBaseUrl?: string;
22
+ shopId?: string;
23
+ }
24
+
25
+ /**
26
+ * API Response Types
27
+ *
28
+ * Backend returns: { status: number, data: T, error: string | null }
29
+ * SDK maps to: { success: boolean, data?: T, message?: string }
30
+ */
31
+ interface ApiResponse<T> {
32
+ status: number;
33
+ data: T;
34
+ error: string | null;
35
+ message?: string | null;
36
+ /**
37
+ * Machine-readable refusal identifier (e.g. `errors.checkout.coupon_no_longer_valid`).
38
+ * Emitted by every localized backend error; the localized `error` sentence is
39
+ * for humans, this is what code branches on.
40
+ */
41
+ error_code?: string | null;
42
+ error_params?: Record<string, unknown> | null;
43
+ }
44
+ interface ApiChallenge {
45
+ provider: 'turnstile';
46
+ siteKey: string;
47
+ }
48
+ interface SDKResponse<T> {
49
+ success: boolean;
50
+ data?: T;
51
+ message?: string;
52
+ /**
53
+ * The backend's `error_code`, preserved verbatim on every failure the server
54
+ * answered — including non-2xx HTTP responses. `message` is localized display
55
+ * copy and must never be pattern-matched; branch on `code` instead.
56
+ * Absent when the failure never reached the server (transport, timeout) or
57
+ * when the endpoint emits no machine-readable code.
58
+ */
59
+ code?: string;
60
+ errorParams?: Record<string, unknown>;
61
+ /**
62
+ * HTTP status of the server's answer, when there was one.
63
+ *
64
+ * Needed to tell "not signed in" (401) apart from "the server broke" (5xx) or
65
+ * a transport failure, which are otherwise indistinguishable. Without it a
66
+ * client has to treat every failure as no-session and show a sign-in form to
67
+ * someone who is signed in — a silent downgrade of the very state it is
68
+ * trying to report.
69
+ *
70
+ * Absent when the request never reached the server.
71
+ */
72
+ status?: number;
73
+ /**
74
+ * Whether the request received an HTTP response from the server.
75
+ *
76
+ * `false` identifies an ambiguous transport failure: the browser cannot
77
+ * know whether a mutation committed before the connection was lost. Public
78
+ * mutation helpers use this signal to retain their idempotency key for the
79
+ * buyer's retry. Absent on successful responses and older SDK results.
80
+ */
81
+ responseReceived?: boolean;
82
+ /**
83
+ * True only when a parsed server refusal proves that the mutation did not
84
+ * commit (currently a JSON 4xx other than timeout). Mutation helpers may
85
+ * rotate an idempotency key on this signal. A response whose body is
86
+ * truncated, malformed, or a 5xx remains ambiguous even though headers were
87
+ * received.
88
+ */
89
+ responseDefinitive?: boolean;
90
+ /** A renewable human-verification challenge returned with a refusal. */
91
+ challenge?: ApiChallenge;
92
+ }
93
+ interface Shop {
94
+ id: string;
95
+ name: string;
96
+ slug: string;
97
+ domain?: string;
98
+ description?: string;
99
+ title?: string;
100
+ message?: string;
101
+ url?: string;
102
+ logo?: string;
103
+ banner?: string;
104
+ avatar?: string;
105
+ average_score?: number | null;
106
+ rating?: number | null;
107
+ products_sold_count?: number;
108
+ customers_count?: number;
109
+ hide_products_sold?: boolean;
110
+ currency: string;
111
+ tos_enabled?: boolean;
112
+ dark_mode?: boolean;
113
+ search_enabled?: boolean;
114
+ sort_enabled?: boolean;
115
+ cart_enabled?: boolean;
116
+ contact_form_enabled?: boolean;
117
+ require_invoice_for_contact?: boolean;
118
+ hide_out_of_stock?: boolean;
119
+ hide_stock_counter?: boolean;
120
+ center_product_titles?: boolean;
121
+ center_group_titles?: boolean;
122
+ default_sort?: string;
123
+ social?: Record<string, string | null>;
124
+ discord_link?: string | null;
125
+ twitter_link?: string | null;
126
+ instagram_link?: string | null;
127
+ facebook_link?: string | null;
128
+ telegram_link?: string | null;
129
+ youtube_link?: string | null;
130
+ reddit_link?: string | null;
131
+ tiktok_link?: string | null;
132
+ verified?: boolean;
133
+ on_hold?: boolean;
134
+ theme?: ShopTheme | null;
135
+ builder_settings?: Record<string, unknown> | null;
136
+ feedback?: ShopFeedback;
137
+ trusted_checks?: TrustedChecks | null;
138
+ available_gateways?: string[];
139
+ payment_gateways_fees?: unknown[];
140
+ reward_program_summary?: RewardProgramSummary | null;
141
+ }
142
+ interface RewardProgramTeaserItem {
143
+ trigger_type: RewardReason;
144
+ action_type: RewardActionType;
145
+ label: string;
146
+ }
147
+ interface RewardProgramSummary {
148
+ enabled: boolean;
149
+ headline: string;
150
+ items: RewardProgramTeaserItem[];
151
+ }
152
+ interface ShopTheme {
153
+ primary_color?: string;
154
+ secondary_color?: string;
155
+ font?: string;
156
+ logo?: string | null;
157
+ logo_cloudflare_image_id?: string | null;
158
+ background_image?: string | null;
159
+ background_image_cloudflare_image_id?: string | null;
160
+ cards_in_row?: number | string;
161
+ cards_align?: string;
162
+ card_animation?: string;
163
+ dark_color?: string;
164
+ light_color?: string;
165
+ border_color?: string;
166
+ button_color?: string;
167
+ }
168
+ interface ShopFeedback {
169
+ positive: number;
170
+ neutral: number;
171
+ negative: number;
172
+ total: number;
173
+ }
174
+ interface TrustedChecks {
175
+ identity_verified?: boolean;
176
+ feedback_score?: string | null;
177
+ trusted_score?: number;
178
+ sales_last14days_metric?: string;
179
+ }
180
+ interface ProductCategory {
181
+ uniqid: string;
182
+ title: string;
183
+ description?: string | null;
184
+ image_attachment?: string | null;
185
+ image_name?: string | null;
186
+ image_storage?: string | null;
187
+ cloudflare_image_id?: string | null;
188
+ cdn_image_url?: string | null;
189
+ }
190
+ interface ProductDescriptionTab {
191
+ title: string;
192
+ content: string;
193
+ }
194
+ interface Product {
195
+ id?: string;
196
+ uniqid: string;
197
+ title: string;
198
+ slug?: string | null;
199
+ description?: string | null;
200
+ /** Merchant-defined description tabs; present when the shop configured them. */
201
+ description_tabs?: ProductDescriptionTab[];
202
+ product_highlights?: string[];
203
+ /**
204
+ * Merchant-defined public key/value pairs, set in the dashboard and readable
205
+ * here without a theme rebuild. Always present on storefront catalog reads —
206
+ * `{}` when the merchant set nothing — and values are always strings.
207
+ *
208
+ * Optional on this type because the older bound/legacy product payloads do not
209
+ * carry it; read it as `product.metadata?.status` on those paths.
210
+ */
211
+ metadata?: Record<string, string>;
212
+ price: string;
213
+ price_display?: string;
214
+ price_discount?: number;
215
+ currency: string;
216
+ /**
217
+ * RAW local stock only. `-1` (or any negative value) means unlimited, `0` means
218
+ * no local units. This is NEVER on its own a purchasable cap: a supplier-backed
219
+ * product reports `stock: 0` by design and is still buyable. Gate buying on
220
+ * {@link Product.orderable}, and use `resolveDisplayStock` / `isProductInStock`
221
+ * rather than reading this field directly.
222
+ */
223
+ stock?: number;
224
+ /**
225
+ * Per-product override for the shop's stock-counter setting; `null` inherits.
226
+ * Consumers must resolve it against the shop default rather than reading it
227
+ * alone.
228
+ *
229
+ * Both spellings are declared because both are really sent: the storefront
230
+ * catalog (`getStorefront`) emits camelCase alongside its other product
231
+ * fields, while `getProducts`, `getProduct` and `getStorefrontProductsPage`
232
+ * go through transformStorefrontCatalogProduct, which emits snake_case, and
233
+ * nothing normalizes between them. Declaring only one would have left readers
234
+ * of the other silently seeing `undefined` and falling back to the shop
235
+ * setting — showing a count the merchant hid, or hiding one they wanted shown.
236
+ */
237
+ hideStockCounter?: boolean | null;
238
+ hide_stock_counter?: boolean | null;
239
+ /**
240
+ * Authoritative buyability predicate, mirrored from the backend's order-time
241
+ * gate: `local stock covers one unit OR an eligible supplier source can fulfil
242
+ * the line`. This — not `stock` — is what a storefront must gate the buy button,
243
+ * the quantity cap and the sold-out badge on.
244
+ *
245
+ * Absent on payloads that predate Dynamic Delivery. When absent, treat
246
+ * availability exactly as `stock` alone dictates; a missing field must never
247
+ * turn a genuinely sold-out product into a buyable one.
248
+ */
249
+ orderable?: boolean;
250
+ /**
251
+ * True when an enabled supplier source fulfils this product instead of local
252
+ * stock. `orderable` remains the buy/sold-out gate; this field decides the
253
+ * QUANTITY CAP: the supplier purchase — not the local counter — fulfils the line
254
+ * and the completion excludes it from the local decrement, so residual local
255
+ * units bound nothing and the cap is unlimited even at `stock: 1`. Absent on
256
+ * payloads that predate Dynamic Delivery; when absent, the cap stays exactly
257
+ * what `stock` alone dictates.
258
+ */
259
+ supplier_backed?: boolean;
260
+ quantity_min?: number;
261
+ quantity_max?: number;
262
+ min_quantity?: number;
263
+ max_quantity?: number;
264
+ on_hold?: boolean | number;
265
+ unlisted?: boolean | number;
266
+ private?: boolean | number;
267
+ bestseller?: boolean | number;
268
+ type?: string;
269
+ subtype?: string | null;
270
+ isSubscription?: boolean;
271
+ isGroup?: boolean;
272
+ images: ProductImage[];
273
+ image_name?: string | null;
274
+ image_storage?: string | null;
275
+ cloudflare_image_id?: string | null;
276
+ image_attachment?: string | null;
277
+ sold_count?: number;
278
+ soldCount?: number;
279
+ variants?: ProductVariant[];
280
+ addons?: ProductAddon[];
281
+ price_variants?: PriceVariant[];
282
+ volume_discounts?: unknown;
283
+ custom_fields?: string | unknown[] | null;
284
+ categories?: ProductCategory[];
285
+ bundles?: ProductBundle[];
286
+ faqs?: ProductFaq[];
287
+ subscription?: Subscription;
288
+ feedbacks?: Feedback[];
289
+ feedback?: ProductFeedback;
290
+ cdn_image_url?: string;
291
+ detail_image_url?: string | null;
292
+ recurring_interval?: string | null;
293
+ recurring_interval_count?: number | null;
294
+ trial_period?: number | null;
295
+ setup_cost?: string;
296
+ licensing_enabled?: boolean | number;
297
+ license_period?: string | number | null;
298
+ delivery_text?: string;
299
+ service_text?: string;
300
+ terms_of_service?: string | null;
301
+ warranty?: number;
302
+ warranty_text?: string | null;
303
+ sort_priority?: number;
304
+ pay_what_you_want?: boolean | number;
305
+ video_link?: string | null;
306
+ }
307
+ interface ProductFeedback {
308
+ total: number;
309
+ positive: number;
310
+ neutral: number;
311
+ negative: number;
312
+ numbers?: Record<number, number>;
313
+ list?: Array<{
314
+ score: number;
315
+ message: string | null;
316
+ reply: string | null;
317
+ created_at: string | null;
318
+ createdAt?: string | null;
319
+ updated_at: string | null;
320
+ updatedAt?: string | null;
321
+ is_automated?: boolean;
322
+ isAutomated?: boolean;
323
+ }>;
324
+ }
325
+ interface ProductImage {
326
+ id: string;
327
+ url: string;
328
+ cloudflare_image_id?: string;
329
+ alt?: string;
330
+ }
331
+ interface ProductVariant {
332
+ id: string;
333
+ title: string;
334
+ price?: number;
335
+ /**
336
+ * RAW local stock for this option only. `-1` (or any negative value) means
337
+ * unlimited, `0` means no local units — which a supplier-backed option reports
338
+ * by design. Never render this as a purchasable cap on its own; gate on
339
+ * {@link ProductVariant.orderable}.
340
+ */
341
+ stock?: number;
342
+ /**
343
+ * Authoritative buyability predicate for this option: `local stock covers one
344
+ * unit OR an eligible supplier source can fulfil the line`. The backend resolves
345
+ * a product-wide supplier mapping onto every variant's own flag, so this alone
346
+ * is authoritative for a selected variant.
347
+ *
348
+ * Absent on payloads that predate Dynamic Delivery; when absent, availability
349
+ * follows `stock` alone, exactly as before.
350
+ */
351
+ orderable?: boolean;
352
+ /**
353
+ * True when an enabled supplier source fulfils this option instead of local
354
+ * stock. `orderable` remains the buy/sold-out gate; this field decides the
355
+ * QUANTITY CAP — a supplier-backed row is unbounded even when it still holds a
356
+ * few local units, because the supplier purchase fulfils the line and the
357
+ * completion excludes it from the local decrement. Absent on payloads that
358
+ * predate Dynamic Delivery.
359
+ */
360
+ supplier_backed?: boolean;
361
+ quantity_min?: number;
362
+ quantity_max?: number;
363
+ quantityMin?: number;
364
+ quantityMax?: number;
365
+ image_id?: string | null;
366
+ imageId?: string | null;
367
+ cloudflare_image_id?: string | null;
368
+ cloudflareImageId?: string | null;
369
+ image_url?: string | null;
370
+ imageUrl?: string | null;
371
+ /** Merchant-selected storefront highlight. It does not affect selection or availability. */
372
+ is_featured?: boolean;
373
+ isFeatured?: boolean;
374
+ /** License validity in days for this option. Zero means lifetime. */
375
+ license_period?: number | null;
376
+ }
377
+ interface ProductAddon {
378
+ id: string;
379
+ name?: string;
380
+ title?: string;
381
+ price: number;
382
+ required?: boolean;
383
+ }
384
+ interface PriceVariant {
385
+ id: string;
386
+ label?: string;
387
+ title?: string;
388
+ price: number;
389
+ /**
390
+ * RAW local stock for this price variant only. `-1` (or any negative value)
391
+ * means unlimited, `0` means no local units — which a supplier-backed variant
392
+ * reports by design. Never render this as a purchasable cap on its own; gate on
393
+ * {@link PriceVariant.orderable}.
394
+ */
395
+ stock?: number;
396
+ /**
397
+ * Authoritative buyability predicate for this price variant: `local stock covers
398
+ * one unit OR an eligible supplier source can fulfil the line`. The backend
399
+ * resolves a product-wide supplier mapping onto every variant's own flag, so
400
+ * this alone is authoritative for a selected variant.
401
+ *
402
+ * Absent on payloads that predate Dynamic Delivery; when absent, availability
403
+ * follows `stock` alone, exactly as before.
404
+ */
405
+ orderable?: boolean;
406
+ /**
407
+ * True when an enabled supplier source fulfils this price variant instead of
408
+ * local stock. `orderable` remains the buy/sold-out gate; this field decides the
409
+ * QUANTITY CAP — a supplier-backed row is unbounded even when it still holds a
410
+ * few local units, because the supplier purchase fulfils the line and the
411
+ * completion excludes it from the local decrement. Absent on payloads that
412
+ * predate Dynamic Delivery.
413
+ */
414
+ supplier_backed?: boolean;
415
+ quantity_min?: number;
416
+ quantity_max?: number;
417
+ quantityMin?: number;
418
+ quantityMax?: number;
419
+ image_id?: string | null;
420
+ imageId?: string | null;
421
+ cloudflare_image_id?: string | null;
422
+ cloudflareImageId?: string | null;
423
+ image_url?: string | null;
424
+ imageUrl?: string | null;
425
+ /** Merchant-selected storefront highlight. It does not affect selection or availability. */
426
+ is_featured?: boolean;
427
+ isFeatured?: boolean;
428
+ /** License validity in days for this option. Zero means lifetime. */
429
+ license_period?: number | null;
430
+ }
431
+ interface CustomFieldDefinition {
432
+ id: string;
433
+ name: string;
434
+ type: 'text' | 'textarea' | 'select' | 'checkbox';
435
+ required?: boolean;
436
+ options?: string[];
437
+ }
438
+ interface Feedback {
439
+ id: string;
440
+ rating: number;
441
+ score?: number;
442
+ author?: string;
443
+ customer_name?: string;
444
+ comment?: string;
445
+ message?: string | null;
446
+ reply?: string | null;
447
+ is_automated?: boolean;
448
+ isAutomated?: boolean;
449
+ product_id?: string | null;
450
+ product_title?: string | null;
451
+ cloudflare_image_id?: string | null;
452
+ created_at: string;
453
+ updated_at?: string | number | null;
454
+ }
455
+ interface ShopReviewsSummary {
456
+ total: number;
457
+ positive: number;
458
+ neutral: number;
459
+ negative: number;
460
+ average_score: number | null;
461
+ }
462
+ interface ShopReviewsPage {
463
+ feedback: Feedback[];
464
+ pagination: CursorPagination;
465
+ summary: ShopReviewsSummary;
466
+ }
467
+ interface ProductBundle {
468
+ id?: string;
469
+ uniqid?: string;
470
+ title?: string;
471
+ discount_type?: 'PERCENTAGE' | 'FIXED';
472
+ discount_amount?: number;
473
+ products?: ProductBundleProduct[];
474
+ }
475
+ interface ProductBundleProduct {
476
+ id?: string;
477
+ uniqid: string;
478
+ title?: string | null;
479
+ default_variant_id?: string;
480
+ }
481
+ interface ProductFaq {
482
+ id?: string;
483
+ uniqid?: string;
484
+ question: string;
485
+ answer: string;
486
+ }
487
+ interface SubscriptionInterval {
488
+ unit?: string;
489
+ count?: number;
490
+ label?: string;
491
+ }
492
+ interface SubscriptionFlags {
493
+ cancel_anytime?: boolean;
494
+ }
495
+ interface Subscription {
496
+ id?: string;
497
+ name?: string;
498
+ description?: string;
499
+ badge?: string;
500
+ interval?: SubscriptionInterval;
501
+ flags?: SubscriptionFlags;
502
+ }
503
+ interface Invoice {
504
+ uniqid: string;
505
+ status: string;
506
+ total: number;
507
+ currency: string;
508
+ gateway?: string;
509
+ products: InvoiceProduct[];
510
+ created_at: string;
511
+ rewards?: BuyerRewards | null;
512
+ }
513
+ interface InvoiceProduct {
514
+ product_id: string;
515
+ title: string;
516
+ quantity: number;
517
+ price: number;
518
+ }
519
+ type RewardActionType = 'WALLET_CREDIT' | 'COUPON';
520
+ type RewardGrantStatus = 'PENDING' | 'FULFILLED' | 'FAILED' | 'REVOKED';
521
+ type RewardReason = 'ORDER_COMPLETED' | 'ORDER_COUNT_REACHED' | 'SPEND_AMOUNT_REACHED' | 'POSITIVE_REVIEW_LEFT' | 'FIRST_PURCHASE_COMPLETED';
522
+ interface BuyerRewardActivityItem {
523
+ id: string;
524
+ type: RewardActionType;
525
+ status: RewardGrantStatus;
526
+ amount: string | null;
527
+ currency: string | null;
528
+ coupon_code: string | null;
529
+ reason: RewardReason;
530
+ trigger_reference_type: string;
531
+ trigger_reference_id: string;
532
+ created_at: number;
533
+ fulfilled_at: number | null;
534
+ expires_at: number | null;
535
+ }
536
+ interface BuyerRewards {
537
+ summary: {
538
+ available: string;
539
+ pending: string;
540
+ lifetime_earned: string;
541
+ redeemed: string | null;
542
+ currency: string;
543
+ };
544
+ activity: BuyerRewardActivityItem[];
545
+ earned_after_invoice: BuyerRewardActivityItem[];
546
+ pending_after_invoice: BuyerRewardActivityItem[];
547
+ }
548
+ interface CouponValidation {
549
+ valid: boolean;
550
+ discount?: number;
551
+ discount_type?: 'percentage' | 'fixed';
552
+ first_order_only?: boolean;
553
+ source?: 'COUPON' | 'AFFILIATE';
554
+ product_restricted?: boolean;
555
+ variant_restricted?: boolean;
556
+ restriction_scope?: 'all' | 'products' | 'variants' | 'products_and_variants';
557
+ allowed_product_ids?: string[];
558
+ allowed_variant_ids?: string[];
559
+ message?: string;
560
+ }
561
+ interface CouponValidationOptions {
562
+ productId?: string;
563
+ variantId?: string;
564
+ }
565
+ interface AffiliateValidation {
566
+ valid: boolean;
567
+ program_enabled?: boolean;
568
+ affiliate_code: string | null;
569
+ discount_active: boolean;
570
+ discount_percent: number;
571
+ message?: string;
572
+ }
573
+ interface ProductGroup {
574
+ id?: string;
575
+ uniqid: string;
576
+ category_id?: string | null;
577
+ slug?: string | null;
578
+ name?: string | null;
579
+ title: string;
580
+ description?: string | null;
581
+ product_uniqids?: string[];
582
+ products_count?: number;
583
+ image_attachment?: string | null;
584
+ image_name?: string | null;
585
+ image_storage?: string | null;
586
+ cloudflare_image_id?: string | null;
587
+ cdn_image_url?: string | null;
588
+ sort_priority?: number | null;
589
+ }
590
+ interface Category {
591
+ uniqid: string;
592
+ title: string;
593
+ description?: string | null;
594
+ image_attachment?: string | null;
595
+ image_name?: string | null;
596
+ image_storage?: string | null;
597
+ cloudflare_image_id?: string | null;
598
+ cdn_image_url?: string | null;
599
+ product_uniqids?: string[];
600
+ products_bound?: Product[];
601
+ products_count?: number;
602
+ groups_bound?: ProductGroup[];
603
+ groups_count?: number;
604
+ }
605
+ interface CursorPagination {
606
+ next_cursor: string | null;
607
+ has_more: boolean;
608
+ }
609
+ interface StorefrontAnnouncementBarAddon {
610
+ id: string;
611
+ type: 'announcement_bar';
612
+ slot: string;
613
+ component: 'announcement_bar';
614
+ sort_order: number;
615
+ props: {
616
+ addon_id: string;
617
+ text: string;
618
+ link_label?: string | null;
619
+ link_url?: string | null;
620
+ dismissible: boolean;
621
+ display_mode: 'static' | 'marquee';
622
+ theme_preset: 'brand_blue' | 'emerald' | 'sunset' | 'rose' | 'charcoal' | 'custom';
623
+ animation_speed_seconds: number;
624
+ background_color: string;
625
+ text_color: string;
626
+ };
627
+ }
628
+ interface StorefrontCountdownBarAddon {
629
+ id: string;
630
+ type: 'countdown_bar';
631
+ slot: string;
632
+ component: 'countdown_bar';
633
+ sort_order: number;
634
+ props: {
635
+ addon_id: string;
636
+ text: string;
637
+ end_at: string;
638
+ link_label?: string | null;
639
+ link_url?: string | null;
640
+ dismissible: boolean;
641
+ theme_preset: 'brand_blue' | 'emerald' | 'sunset' | 'rose' | 'charcoal' | 'custom';
642
+ expired_behavior: 'hide' | 'message';
643
+ expired_message?: string | null;
644
+ density: 'compact' | 'comfortable';
645
+ cta_style: 'subtle' | 'outline' | 'solid';
646
+ timer_style: 'minimal' | 'boxed';
647
+ background_color: string;
648
+ text_color: string;
649
+ };
650
+ }
651
+ interface StorefrontPromoInfoCardAddon {
652
+ id: string;
653
+ type: 'promo_info_card';
654
+ slot: string;
655
+ component: 'promo_info_card';
656
+ sort_order: number;
657
+ props: {
658
+ addon_id: string;
659
+ eyebrow?: string | null;
660
+ title: string;
661
+ body: string;
662
+ link_label?: string | null;
663
+ link_url?: string | null;
664
+ theme_preset: 'indigo' | 'emerald' | 'amber' | 'rose' | 'slate' | 'custom';
665
+ layout_style: 'compact' | 'feature' | 'alert';
666
+ density: 'compact' | 'comfortable';
667
+ cta_style: 'subtle' | 'outline' | 'solid';
668
+ icon: 'sparkles' | 'megaphone' | 'gift' | 'truck' | 'shield' | 'support' | 'none';
669
+ icon_visibility: 'show' | 'hide';
670
+ background_color: string;
671
+ text_color: string;
672
+ accent_color: string;
673
+ };
674
+ }
675
+ interface StorefrontRecentPurchasePopupAddon {
676
+ id: string;
677
+ type: 'recent_purchase_popup';
678
+ slot: string;
679
+ component: 'recent_purchase_popup';
680
+ sort_order: number;
681
+ props: {
682
+ addon_id: string;
683
+ title: string;
684
+ cooldown_seconds: number;
685
+ items: Array<{
686
+ customer_label: string;
687
+ product_title: string;
688
+ created_at: string;
689
+ }>;
690
+ };
691
+ }
692
+ interface StorefrontCouponPopupModalAddon {
693
+ id: string;
694
+ type: 'coupon_popup_modal';
695
+ slot: string;
696
+ component: 'coupon_popup_modal';
697
+ sort_order: number;
698
+ props: {
699
+ addon_id: string;
700
+ eyebrow?: string | null;
701
+ title: string;
702
+ body: string;
703
+ coupon_code: string;
704
+ primary_button_label: string;
705
+ secondary_button_label: string;
706
+ disclaimer?: string | null;
707
+ theme_preset: 'midnight' | 'ocean' | 'ember' | 'forest' | 'custom';
708
+ trigger: 'delay' | 'exit_intent';
709
+ delay_seconds: number;
710
+ show_once_per_session: boolean;
711
+ reminder_hours: number;
712
+ background_color: string;
713
+ text_color: string;
714
+ accent_color: string;
715
+ hero_image_url?: string | null;
716
+ discount_display?: string | null;
717
+ expires_at?: string | null;
718
+ };
719
+ }
720
+ type StorefrontAddon = StorefrontAnnouncementBarAddon | StorefrontCountdownBarAddon | StorefrontPromoInfoCardAddon | StorefrontRecentPurchasePopupAddon | StorefrontCouponPopupModalAddon;
721
+ interface StorefrontAddonBootstrap {
722
+ items: StorefrontAddon[];
723
+ }
724
+ interface StorefrontOnlineUsers {
725
+ count: number;
726
+ window_seconds: number;
727
+ }
728
+ interface StorefrontRecentSaleEntry {
729
+ product_title: string;
730
+ seconds_ago: number;
731
+ }
732
+ interface StorefrontRecentSales {
733
+ items: StorefrontRecentSaleEntry[];
734
+ window_hours: number;
735
+ }
736
+ type StorefrontItem = {
737
+ item_type: 'PRODUCT' | 'GROUP';
738
+ uniqid: string;
739
+ sort_priority?: number | null;
740
+ title?: string | null;
741
+ };
742
+ interface StorefrontData {
743
+ shop: Shop;
744
+ products: Product[];
745
+ products_pagination?: CursorPagination | null;
746
+ groups: ProductGroup[];
747
+ items: StorefrontItem[];
748
+ categories: Category[];
749
+ addons: StorefrontAddonBootstrap;
750
+ }
751
+ interface Page {
752
+ id: string;
753
+ shop_id?: string;
754
+ slug: string;
755
+ name: string;
756
+ content: string | null;
757
+ template_type: string;
758
+ is_system: boolean;
759
+ settings: Record<string, unknown> | null;
760
+ visible_after: string | null;
761
+ created_at: number;
762
+ updated_at: number;
763
+ }
764
+ interface Menu {
765
+ id: string;
766
+ shop_id: string;
767
+ title: string;
768
+ slot?: NavigationMenuSlot | null;
769
+ item_count?: number | null;
770
+ items?: MenuItem[];
771
+ created_at: number;
772
+ updated_at: number;
773
+ }
774
+ interface MenuItem {
775
+ id: string;
776
+ shop_id?: string;
777
+ menu_id: string;
778
+ page_id: string | null;
779
+ title: string;
780
+ url?: string | null;
781
+ link_type?: 'LINK' | 'PAGE' | 'link' | 'page' | null;
782
+ target?: '_self' | '_blank' | null;
783
+ sort_order: number;
784
+ page_slug: string | null;
785
+ created_at: number;
786
+ updated_at: number;
787
+ children?: MenuItem[];
788
+ }
789
+
790
+ /**
791
+ * Cart Types
792
+ *
793
+ * Extended cart schema supporting Shoppex features:
794
+ * - Addons (express shipping, gift wrap, etc.)
795
+ * - Custom Fields (engraving, gift message, etc.)
796
+ * - Price Variants (different pricing tiers)
797
+ *
798
+ * All fields use snake_case to match API conventions.
799
+ */
800
+ interface CartAddon {
801
+ id: string;
802
+ quantity?: number;
803
+ }
804
+ /** Incoming basket rows may omit line_id; mergeBaskets derives it before deduping. */
805
+ type CartBasketMergeLine = Omit<CartItem, 'line_id'> & {
806
+ line_id?: string;
807
+ };
808
+ interface CartItem {
809
+ /** Stable identity for this configuration (product + variant + addons + custom_fields + price snapshot). */
810
+ line_id: string;
811
+ product_id: string;
812
+ variant_id: string;
813
+ quantity: number;
814
+ addons?: CartAddon[];
815
+ custom_fields?: Record<string, string>;
816
+ price_variant_id?: string;
817
+ price_data?: {
818
+ unit_price: number;
819
+ };
820
+ /** Buyer-selected unit price for a product explicitly configured as pay-what-you-want. */
821
+ pay_what_you_want_price?: number;
822
+ title?: string;
823
+ variant_title?: string;
824
+ image_url?: string;
825
+ addon_labels?: string[];
826
+ max_quantity?: number;
827
+ min_quantity?: number;
828
+ }
829
+ /**
830
+ * The patch `updateCartItem` accepts, with an explicit TRI-STATE for the two
831
+ * bounds — the same shape `checkout()`'s `affiliateCode` uses for "none":
832
+ *
833
+ * key absent leave the stored bound exactly as it is;
834
+ * `null` DELETE the stored bound (the merchant removed it);
835
+ * `number` set it.
836
+ *
837
+ * Without the `null` arm a bound could be raised and lowered forever but never
838
+ * REMOVED: an update carrying `undefined` is indistinguishable from one that
839
+ * never mentioned the field, so a `max_quantity: 5` the merchant deleted stuck
840
+ * to the line for the life of the cart, and every quote-driven heal that tried
841
+ * to clear it was a silent no-op.
842
+ */
843
+ type CartItemUpdate = Partial<Omit<CartItem, 'line_id' | 'product_id' | 'variant_id' | 'min_quantity' | 'max_quantity'>> & {
844
+ /** `null` clears the stored minimum. */
845
+ min_quantity?: number | null;
846
+ /** `null` clears the stored ceiling. */
847
+ max_quantity?: number | null;
848
+ };
849
+ interface CartAddOptions {
850
+ addons?: CartAddon[];
851
+ custom_fields?: Record<string, string>;
852
+ price_variant_id?: string;
853
+ price_data?: {
854
+ unit_price: number;
855
+ };
856
+ pay_what_you_want_price?: number;
857
+ title?: string;
858
+ variant_title?: string;
859
+ image_url?: string;
860
+ addon_labels?: string[];
861
+ max_quantity?: number;
862
+ min_quantity?: number;
863
+ replace_display_snapshot?: boolean;
864
+ }
865
+ interface CartPayload {
866
+ store_slug: string;
867
+ items: CartItem[];
868
+ coupon?: string;
869
+ }
870
+ type CartCodeSource = 'COUPON' | 'AFFILIATE';
871
+ interface CartAppliedDiscount {
872
+ source: 'PRODUCT_DISCOUNT' | 'VOLUME_DISCOUNT' | 'AUTOMATIC_PRODUCT_DEAL' | 'BUNDLE_DEAL' | 'STORE_PROMOTION' | 'COUPON' | 'AFFILIATE';
873
+ source_id: string | null;
874
+ source_uniqid: string | null;
875
+ label: string;
876
+ amount: string;
877
+ }
878
+ interface EligibleCartDeal {
879
+ source?: 'AUTOMATIC_PRODUCT_DEAL';
880
+ deal_id: string;
881
+ deal_uniqid: string;
882
+ product_id: string;
883
+ product_uniqid: string | null;
884
+ label: string;
885
+ missing_quantity: number;
886
+ required_quantity: number;
887
+ }
888
+ interface EligibleBundleDealProduct {
889
+ product_id: string;
890
+ product_uniqid: string;
891
+ title: string;
892
+ /** Units to add for this member — its own configured MINIMUM, never a blind 1. */
893
+ quantity: number;
894
+ price: string;
895
+ currency: string;
896
+ /**
897
+ * The option this member is sellable on. A deal is only offered when every member has one, so
898
+ * this is never the "first variant, whatever its stock" it used to be.
899
+ */
900
+ default_variant_id: string;
901
+ /**
902
+ * The member's order bounds on that option — the merchant's configured range narrowed by what
903
+ * is actually on the shelf. `max_quantity: -1` means nothing bounds the line.
904
+ *
905
+ * OPTIONAL because a server older than this field simply does not send them, and a client
906
+ * cannot invent them: an add against such a payload sends no bounds, exactly as it did before.
907
+ * That is a version gap, not a fallback — the gating that makes the offer safe happens on the
908
+ * server, and a client that guessed bounds here would be inventing the merchant's limits.
909
+ */
910
+ min_quantity?: number;
911
+ max_quantity?: number;
912
+ }
913
+ interface EligibleBundleDeal {
914
+ source: 'BUNDLE_DEAL';
915
+ bundle_id: string;
916
+ bundle_uniqid: string;
917
+ label: string;
918
+ discount_type: 'PERCENTAGE' | 'FIXED';
919
+ discount_amount: string;
920
+ missing_products: EligibleBundleDealProduct[];
921
+ products: EligibleBundleDealProduct[];
922
+ }
923
+ /**
924
+ * THE CART BOUNDS CONTRACT — one quoted line's effective order bounds and sellability.
925
+ *
926
+ * Cart lines carry bounds that were snapshotted when the item was ADDED, so they go stale the
927
+ * moment stock moves or the merchant edits the limits — and a line added before bounds existed
928
+ * carries none at all. The quote is the only thing that runs server-side on every cart change, so
929
+ * it restates them: each settled quote reports the bounds derived from the CURRENT product row and
930
+ * the CURRENT shelf, through the same resolution the checkout refuses with.
931
+ *
932
+ * FIELD CONTRACT:
933
+ * `product_id` the product identifier the cart sent, echoed exactly.
934
+ * `variant_id` the resolved option id, `null` for a product with no variants.
935
+ * `quantity` the quantity this line was quoted at.
936
+ * `min_quantity` ABSENT when it is 1. Present values are the stepper's floor.
937
+ * `max_quantity` ABSENT when nothing bounds the line — absence is the unbounded sentinel, and
938
+ * `-1` is never sent. Never coerce an absent key to 0.
939
+ * SHARED across duplicate lines: cart lines naming the same product and option
940
+ * draw from ONE shelf, and the invoice endpoint sums them and refuses the TOTAL.
941
+ * The value is therefore this line's SHARE — the option's ceiling minus what its
942
+ * sibling lines request. One line per option (the ordinary cart) sees the option
943
+ * ceiling unchanged, and duplicate lines with equal quantities always carry equal
944
+ * bounds. When the siblings have taken the whole ceiling that share is 0 or less,
945
+ * which no per-line bound can express (1 would license a unit that does not exist,
946
+ * 0 is not a quantity a line can hold, absence means unbounded): the line then
947
+ * carries the OPTION'S CEILING — the number the option as a whole must come down
948
+ * to — together with `sellable: false`.
949
+ * `sellable` FALSE when this line cannot be ordered as the cart stands — either no quantity
950
+ * of the option can be ordered at all (empty effective range, empty shelf, nothing
951
+ * to fulfil it), or the cart's lines of this option together request more units
952
+ * than the option's ceiling, which the invoice endpoint refuses on the SUM. The
953
+ * line is still priced and still counted in the totals: it is a line the buyer
954
+ * must resolve by reducing or removing, not one that vanishes. It answers for the
955
+ * OPTION and for the whole cart's demand on it, so every line of one option always
956
+ * reports the same value.
957
+ *
958
+ * CONSUMER DUTY: on every settled quote, REPLACE the stored line bounds with these (do not merge —
959
+ * an absent `max_quantity` means the ceiling was removed), disable `+` at `max_quantity`, hold `-`
960
+ * at `min_quantity`, show a sold-out state for `sellable: false`, and REFUSE THE HAND-OFF while any
961
+ * line is `sellable: false` — that cart is the one the invoice endpoint rejects.
962
+ *
963
+ * OPTIONAL on `CartQuote` because a server older than this field does not send it. A client that
964
+ * receives no `lines` keeps whatever bounds it already had — it must not invent them.
965
+ */
966
+ interface CartQuoteLine {
967
+ product_id: string;
968
+ variant_id: string | null;
969
+ quantity: number;
970
+ /** Absent when 1. */
971
+ min_quantity?: number;
972
+ /** Absent when unbounded. Never `-1`. */
973
+ max_quantity?: number;
974
+ sellable: boolean;
975
+ }
976
+ interface CartQuote {
977
+ subtotal: string;
978
+ discount: string;
979
+ total: string;
980
+ currency: string;
981
+ /**
982
+ * Opaque server-signed proof of this quote, valid ~15 minutes. `checkout()`
983
+ * submits the most recent one automatically, which is what stops the invoice
984
+ * from being priced above the total shown here. Null when the server has no
985
+ * signing secret configured; absent on older backends.
986
+ */
987
+ quote_token?: string | null;
988
+ coupon_applied: boolean;
989
+ coupon_source: CartCodeSource | null;
990
+ coupon_discount_order_type: 'TOTAL' | 'PAYMENT_FEES' | null;
991
+ /** Referral code priced into this quote (ambient `?ref=` or a typed referral code). */
992
+ affiliate_code: string | null;
993
+ applied_discounts: CartAppliedDiscount[];
994
+ automatic_product_deals: Array<Record<string, unknown>>;
995
+ bundle_deals: Array<Record<string, unknown>>;
996
+ eligible_deals: EligibleCartDeal[];
997
+ eligible_bundle_deals: EligibleBundleDeal[];
998
+ /** Per-line effective bounds and sellability — see CartQuoteLine. Absent on older backends. */
999
+ lines?: CartQuoteLine[];
1000
+ /**
1001
+ * TRUE when this cart already exceeds the shop's configured checkout maximum.
1002
+ *
1003
+ * Advisory: warn the buyer in the drawer instead of letting them hit the checkout button and
1004
+ * take an unexplained rejection. The server refuses authoritatively at checkout regardless, and
1005
+ * the flag is conservative — it excludes payment fees, so a cart without it can still be
1006
+ * refused. Absent when the cart is within the limit.
1007
+ */
1008
+ cart_max_exceeded?: true;
1009
+ /** The configured maximum in the quote's currency. Present only alongside `cart_max_exceeded`. */
1010
+ cart_maximum_checkout?: string;
1011
+ }
1012
+ interface CartMetadata {
1013
+ created_at: number;
1014
+ last_modified: number;
1015
+ version: number;
1016
+ checksum: string;
1017
+ }
1018
+ interface CartStats {
1019
+ item_count: number;
1020
+ total_quantity: number;
1021
+ last_modified: number;
1022
+ version: number;
1023
+ has_backup: boolean;
1024
+ integrity_valid: boolean;
1025
+ total_price: number;
1026
+ total_price_is_estimate: boolean;
1027
+ }
1028
+
1029
+ /**
1030
+ * SDK Configuration Management
1031
+ */
1032
+
1033
+ declare function getConfig(): ShoppexConfig;
1034
+ declare function isInitialized(): boolean;
1035
+
1036
+ /**
1037
+ * Typed OpenAPI client factory.
1038
+ *
1039
+ * Surfaces the generated `createApiClient` from `@shoppex/contracts` with the
1040
+ * SDK's configured `apiBaseUrl`. This lets consumers of `@shoppexio/storefront`
1041
+ * call any public Dev API endpoint with full end-to-end types without
1042
+ * rebuilding a client from scratch.
1043
+ *
1044
+ * Prefer the high-level modules (`shoppex.getProducts()` etc.) for common
1045
+ * read flows — they handle caching, pagination defaults, and storefront
1046
+ * scoping. Drop down to `shoppex.client()` only when you need an endpoint
1047
+ * the high-level API does not cover yet.
1048
+ */
1049
+
1050
+ type ApiClient = ReturnType<typeof createApiClient>;
1051
+ /**
1052
+ * Return a typed OpenAPI client bound to the SDK's configured API base URL.
1053
+ * The client is cached per base URL and recreated when the SDK is re-initialized
1054
+ * against a different host.
1055
+ */
1056
+ declare function getTypedClient(token?: string): ApiClient;
1057
+
1058
+ /**
1059
+ * SDK Error Classes
1060
+ */
1061
+ declare class ShoppexError extends Error {
1062
+ readonly code: string;
1063
+ readonly statusCode?: number;
1064
+ constructor(message: string, code: string, statusCode?: number);
1065
+ }
1066
+ declare class NotInitializedError extends ShoppexError {
1067
+ constructor();
1068
+ }
1069
+ declare class NetworkError extends ShoppexError {
1070
+ constructor(message: string, statusCode?: number);
1071
+ }
1072
+ /**
1073
+ * A refusal the SERVER made and named. `code` is the backend's `error_code`
1074
+ * (e.g. `errors.checkout.coupon_no_longer_valid`) — the branchable identity of
1075
+ * the refusal, stable across locales, unlike the localized `message`.
1076
+ *
1077
+ * Distinct from {@link NetworkError}, whose `code` is always `NETWORK_ERROR`:
1078
+ * that one means "the request did not produce a named answer".
1079
+ */
1080
+ declare class ApiError extends ShoppexError {
1081
+ readonly errorParams?: Record<string, unknown>;
1082
+ constructor(message: string, code: string, statusCode?: number, errorParams?: Record<string, unknown>);
1083
+ }
1084
+ declare class ValidationError extends ShoppexError {
1085
+ readonly invalidFields?: string[];
1086
+ constructor(message: string, invalidFields?: string[]);
1087
+ }
1088
+ declare class CartError extends ShoppexError {
1089
+ constructor(message: string);
1090
+ }
1091
+
1092
+ interface StorefrontCustomField {
1093
+ name: string;
1094
+ type: string;
1095
+ required: boolean;
1096
+ defaultValue: string;
1097
+ placeholder: string;
1098
+ regex?: string;
1099
+ }
1100
+ declare function normalizeStorefrontCustomFields(raw: unknown): StorefrontCustomField[];
1101
+ declare function isStorefrontCheckboxCustomFieldValueChecked(value: string | undefined): boolean;
1102
+ declare function validateStorefrontCustomFieldValue(field: StorefrontCustomField, value: string): string | null;
1103
+ declare function buildStorefrontCustomFieldPayload(fields: StorefrontCustomField[], values: Record<string, string>): Record<string, string>;
1104
+
1105
+ type VariantLike = Pick<ProductVariant, 'stock' | 'orderable' | 'supplier_backed'> | Pick<PriceVariant, 'stock' | 'orderable' | 'supplier_backed'>;
1106
+ type ProductLike = Pick<Product, 'type' | 'stock' | 'orderable' | 'supplier_backed' | 'on_hold' | 'price_variants' | 'variants'> & {
1107
+ onHold?: boolean | number | string | null;
1108
+ is_on_hold?: boolean | number | string | null;
1109
+ isOnHold?: boolean | number | string | null;
1110
+ };
1111
+ declare function resolveVariantStockValue(variant: VariantLike | null | undefined): number;
1112
+ declare function resolveDisplayStock(product: ProductLike | null | undefined): number;
1113
+ declare function isProductOutOfStock(product: ProductLike | null | undefined): boolean;
1114
+ declare function isProductInStock(product: ProductLike | null | undefined): boolean;
1115
+ declare function isVariantOutOfStock(variant: VariantLike | null | undefined): boolean;
1116
+
1117
+ declare function buildStorefrontProductLookup(products?: Product[]): Map<string, Product>;
1118
+ declare function getStorefrontGroupProducts(group: ProductGroup, productsOrLookup?: Product[] | Map<string, Product>): Product[];
1119
+ declare function getMergedStorefrontProducts(products?: Product[]): Product[];
1120
+
1121
+ interface StorefrontSearchFilterOptions {
1122
+ hideOutOfStock?: boolean;
1123
+ maxResults?: number;
1124
+ }
1125
+ type StorefrontCatalogSearchItem = {
1126
+ type: 'product';
1127
+ product: Product;
1128
+ } | {
1129
+ type: 'group';
1130
+ group: ProductGroup;
1131
+ products: Product[];
1132
+ };
1133
+ declare function stripHtmlFromText(value: string | null | undefined): string;
1134
+ declare function normalizeSearchQuery(query: string): string;
1135
+ declare function collectProductSearchHaystack(product: Product): string[];
1136
+ declare function productMatchesSearchQuery(product: Product, query: string): boolean;
1137
+ declare function groupMatchesSearchQuery(group: ProductGroup, query: string): boolean;
1138
+ declare function filterProductsBySearchQuery(products: Product[], query: string, options?: StorefrontSearchFilterOptions): Product[];
1139
+ declare function searchMergedStorefrontCatalogItems(products: Product[], groups: ProductGroup[], query: string, options?: StorefrontSearchFilterOptions): StorefrontCatalogSearchItem[];
1140
+ declare function searchMergedStorefrontCatalog(products: Product[], groups: ProductGroup[], query: string, options?: StorefrontSearchFilterOptions): Product[];
1141
+
1142
+ type StorefrontContactTicketInput = {
1143
+ shopSlug: string;
1144
+ email: string;
1145
+ message: string;
1146
+ title?: string;
1147
+ name?: string;
1148
+ invoiceId?: string;
1149
+ apiBaseUrl?: string;
1150
+ };
1151
+ type StorefrontContactTicketResult = {
1152
+ uniqid: string;
1153
+ };
1154
+ declare function resolveStorefrontApiBaseUrl(options?: {
1155
+ apiBaseUrl?: string;
1156
+ hostname?: string;
1157
+ }): string;
1158
+ declare function buildStorefrontContactMessage(input: {
1159
+ name?: string;
1160
+ message: string;
1161
+ maxLength?: number;
1162
+ }): string;
1163
+ declare function submitStorefrontContactTicket(input: StorefrontContactTicketInput): Promise<StorefrontContactTicketResult>;
1164
+ type StorefrontSocialLinks = {
1165
+ discord?: string | null;
1166
+ telegram?: string | null;
1167
+ };
1168
+ declare function resolveStorefrontSocialLinks(store: {
1169
+ discord_link?: string | null;
1170
+ telegram_link?: string | null;
1171
+ social?: Record<string, string | null | undefined> | null;
1172
+ } | null | undefined): StorefrontSocialLinks;
1173
+
1174
+ /**
1175
+ * Theme configuration types (framework agnostic)
1176
+ */
1177
+ type SettingFieldType = 'color' | 'text' | 'range' | 'select' | 'boolean' | 'image' | 'font' | 'richtext' | 'products' | 'images';
1178
+ interface BaseSettingField {
1179
+ type: SettingFieldType;
1180
+ label: string;
1181
+ description?: string;
1182
+ }
1183
+ interface ColorField extends BaseSettingField {
1184
+ type: 'color';
1185
+ default: string;
1186
+ }
1187
+ interface RangeField extends BaseSettingField {
1188
+ type: 'range';
1189
+ default: number;
1190
+ min: number;
1191
+ max: number;
1192
+ step?: number;
1193
+ unit?: string;
1194
+ }
1195
+ interface SelectField extends BaseSettingField {
1196
+ type: 'select';
1197
+ default: string;
1198
+ options: string[] | {
1199
+ value: string;
1200
+ label: string;
1201
+ }[];
1202
+ }
1203
+ interface BooleanField extends BaseSettingField {
1204
+ type: 'boolean';
1205
+ default: boolean;
1206
+ }
1207
+ interface TextField extends BaseSettingField {
1208
+ type: 'text';
1209
+ default: string;
1210
+ }
1211
+ interface ImageField extends BaseSettingField {
1212
+ type: 'image';
1213
+ default: string | null;
1214
+ }
1215
+ interface FontField extends BaseSettingField {
1216
+ type: 'font';
1217
+ default: string;
1218
+ options?: string[];
1219
+ }
1220
+ interface RichtextField extends BaseSettingField {
1221
+ type: 'richtext';
1222
+ default: string;
1223
+ }
1224
+ interface ProductsField extends BaseSettingField {
1225
+ type: 'products';
1226
+ default: string[];
1227
+ max?: number;
1228
+ }
1229
+ interface ImagesField extends BaseSettingField {
1230
+ type: 'images';
1231
+ default: string[];
1232
+ max?: number;
1233
+ }
1234
+ type SettingField = ColorField | RangeField | SelectField | BooleanField | TextField | ImageField | FontField | RichtextField | ProductsField | ImagesField;
1235
+ interface SectionDefinition {
1236
+ name: string;
1237
+ description?: string;
1238
+ icon?: string;
1239
+ settings: Record<string, SettingField>;
1240
+ }
1241
+ interface BlockDefinition {
1242
+ name: string;
1243
+ description?: string;
1244
+ icon?: string;
1245
+ settings: Record<string, SettingField>;
1246
+ allowedPages?: string[];
1247
+ maxPerPage?: number;
1248
+ }
1249
+ interface BlockInstance {
1250
+ id: string;
1251
+ type: string;
1252
+ visible?: boolean;
1253
+ settings?: Record<string, SettingValue>;
1254
+ }
1255
+ interface PageLayout {
1256
+ blocks: BlockInstance[];
1257
+ }
1258
+ interface ThemeBlockManifest {
1259
+ pages: string[];
1260
+ blocks: Record<string, BlockDefinition>;
1261
+ defaultLayouts?: Record<string, PageLayout>;
1262
+ }
1263
+ interface ThemeConfig {
1264
+ id: string;
1265
+ name: string;
1266
+ description?: string;
1267
+ version: string;
1268
+ author?: string;
1269
+ preview?: string;
1270
+ settings: Record<string, Record<string, SettingField>>;
1271
+ sections: Record<string, SectionDefinition>;
1272
+ blocks?: Record<string, BlockDefinition>;
1273
+ pageLayouts?: Record<string, PageLayout>;
1274
+ builder?: ThemeBlockManifest;
1275
+ }
1276
+ type SettingValue = string | number | boolean | null | string[] | Record<string, unknown>;
1277
+ type ResolvedThemeSettings = {
1278
+ [Category: string]: {
1279
+ [Key: string]: SettingValue;
1280
+ };
1281
+ };
1282
+
1283
+ type JsonRecord = Record<string, unknown>;
1284
+ interface PublishedBuilderSettings {
1285
+ version: number;
1286
+ revision: number;
1287
+ theme: {
1288
+ content: JsonRecord;
1289
+ layout: JsonRecord;
1290
+ style_slots: JsonRecord;
1291
+ pages?: unknown[];
1292
+ terms?: JsonRecord;
1293
+ [key: string]: unknown;
1294
+ };
1295
+ [key: string]: unknown;
1296
+ }
1297
+ interface PublishedThemeSettingsPayload {
1298
+ settings: ResolvedThemeSettings;
1299
+ builder_settings: PublishedBuilderSettings | null;
1300
+ content: JsonRecord;
1301
+ style_slots: JsonRecord;
1302
+ }
1303
+ declare function fetchPublishedBuilderSettings(shopSlug: string): Promise<PublishedThemeSettingsPayload | null>;
1304
+ declare function fetchPublishedThemeSettings(shopSlug: string): Promise<ResolvedThemeSettings | null>;
1305
+ declare function resolveDefaults(config: ThemeConfig): ResolvedThemeSettings;
1306
+ declare function mergeSettings(defaults: ResolvedThemeSettings, overrides: Partial<ResolvedThemeSettings>): ResolvedThemeSettings;
1307
+
1308
+ /**
1309
+ * Store Module
1310
+ *
1311
+ * API methods for store data.
1312
+ */
1313
+
1314
+ interface GetStorefrontOptions {
1315
+ productsLimit?: number;
1316
+ productsCursor?: string | null;
1317
+ }
1318
+ declare function getStore(): Promise<SDKResponse<Shop>>;
1319
+ declare function resolveStoreByDomain(domain?: string, apiBaseUrl?: string): Promise<SDKResponse<Shop>>;
1320
+ declare function getStorefront(options?: GetStorefrontOptions): Promise<SDKResponse<StorefrontData>>;
1321
+ declare function getStoreLogoUrl(): Promise<string | null>;
1322
+ declare function getStoreBannerUrl(): Promise<string | null>;
1323
+
1324
+ /**
1325
+ * Products Module
1326
+ *
1327
+ * API methods for product data.
1328
+ */
1329
+
1330
+ interface GetStorefrontProductsPageOptions {
1331
+ cursor?: string | null;
1332
+ limit?: number;
1333
+ sort?: 'featured' | 'newest' | 'price-asc' | 'price-desc' | string | null;
1334
+ category?: string | null;
1335
+ hideOutOfStock?: boolean;
1336
+ }
1337
+ declare function getProducts(): Promise<SDKResponse<Product[]>>;
1338
+ declare function getStorefrontProductsPage(options?: GetStorefrontProductsPageOptions): Promise<SDKResponse<{
1339
+ products: Product[];
1340
+ pagination: CursorPagination | null;
1341
+ }>>;
1342
+ declare function getProduct(idOrSlug: string): Promise<SDKResponse<Product>>;
1343
+ declare function getCategories(): Promise<SDKResponse<string[]>>;
1344
+
1345
+ declare function getCartCoupon(): string | null;
1346
+ declare function getCartCouponSource(): CartCodeSource | null;
1347
+ declare function setCartCoupon(coupon: string | null | undefined, source?: CartCodeSource): string | null;
1348
+ declare function clearCartCoupon(): void;
1349
+ declare function getCart(): CartItem[];
1350
+ /** Resolve a cart line_id for product+variant. When multiple configs exist, returns the first line. */
1351
+ declare function resolveCartLineId(productId: string, variantId: string, cart?: CartItem[]): string;
1352
+ declare function getCartItemCount(): number;
1353
+ declare function addToCart(productId: string, variantId: string, quantity?: number, options?: CartAddOptions): void;
1354
+ declare function setCartItem(productId: string, variantId: string, quantity?: number, options?: CartAddOptions): void;
1355
+ /**
1356
+ * Patch one cart line.
1357
+ *
1358
+ * TRI-STATE BOUNDS: `min_quantity`/`max_quantity` accept `null` to DELETE the
1359
+ * stored bound — see {@link CartItemUpdate}. `undefined` (or an absent key)
1360
+ * leaves it alone, which is why a removed ceiling needs its own spelling.
1361
+ *
1362
+ * NO-OP UPDATES DO NOT WRITE. An update that leaves the cart byte-identical
1363
+ * returns without touching storage: no metadata bump, no `version` increment,
1364
+ * and — because the storage write is what other tabs observe — no `storage`
1365
+ * event. Writing anyway made an ineffective heal indistinguishable from a real
1366
+ * cart change, and two tabs healing the same line could hand the event back and
1367
+ * forth indefinitely. Line-shape healing of a legacy stored row is NOT this
1368
+ * function's job: `normalizeCartItems` clamps and repairs on every READ, which
1369
+ * is the chokepoint every access already flows through.
1370
+ */
1371
+ declare function updateCartItem(lineId: string, updates: CartItemUpdate): void;
1372
+ declare function removeFromCart(lineId: string): void;
1373
+ /**
1374
+ * Discards the cart entirely — and with it the proof that describes it.
1375
+ *
1376
+ * PAYMENT PATH. `latestQuoteToken` is evidence about a specific cart, and this
1377
+ * is the one mutation after which that cart does not exist in any form. Held
1378
+ * across the clear, the proof outlives its subject: a caller that clears and
1379
+ * re-adds (Buy Now REPLACES the cart) hands `/from-cart` a token bound to the
1380
+ * previous cart's hash, which is refused as `quote_token_stale` — a hand-off
1381
+ * dead-ended by a proof nobody asked for. And with no re-quote in between there
1382
+ * is nothing to replace it with, so the retry is refused identically.
1383
+ *
1384
+ * Only this path clears it. Every OTHER mutation turns one cart into another
1385
+ * cart, where a proof that no longer matches is the server's to refuse: it
1386
+ * answers `quote_token_stale`, the surfaces re-quote, and the buyer approves the
1387
+ * new total. Dropping the proof there instead would silently remove the approved
1388
+ * -total ceiling from a checkout that raced the re-quote, which is the failure
1389
+ * the token exists to prevent.
1390
+ */
1391
+ declare function clearCart(): void;
1392
+ declare function createCartBackup(): void;
1393
+ declare function restoreCartFromBackup(): boolean;
1394
+ declare function mergeBaskets(items: CartBasketMergeLine[]): CartItem[];
1395
+ declare function moveBasketItem(fromProductId: string, fromVariantId: string, toProductId: string, toVariantId: string): void;
1396
+ declare function validateCartIntegrity(): boolean;
1397
+ declare function getCartStats(): CartStats;
1398
+ declare function quoteCart(coupon?: string, currency?: string): Promise<src.SDKResponse<CartQuote>>;
1399
+
1400
+ type CartLineIdentityInput = Pick<CartItem, 'product_id' | 'variant_id' | 'price_variant_id' | 'addons' | 'custom_fields' | 'price_data' | 'pay_what_you_want_price'>;
1401
+ declare function computeCartLineId(input: CartLineIdentityInput): string;
1402
+ declare function ensureCartLineId(item: CartItem): CartItem;
1403
+
1404
+ /**
1405
+ * Checkout Module
1406
+ *
1407
+ * Creates invoice via backend API and redirects to hosted checkout page.
1408
+ * All checkout flows go through: checkout.shoppex.io/invoice/{invoiceId}
1409
+ */
1410
+
1411
+ interface CheckoutOptions {
1412
+ autoRedirect?: boolean;
1413
+ locale?: string;
1414
+ email?: string;
1415
+ coupon?: string;
1416
+ currency?: string;
1417
+ /**
1418
+ * Absolute HTTPS URL used after a completed purchase when the product does
1419
+ * not define its own redirect. This is persisted on the invoice, so each
1420
+ * sales channel can provide its own return destination.
1421
+ */
1422
+ redirectUrl?: string;
1423
+ /**
1424
+ * A Cloudflare Turnstile proof for the `storefront_checkout` action.
1425
+ *
1426
+ * Normally omitted. A checkout surface may provide a renewed proof when a
1427
+ * legitimate shared network reaches the public invoice-create budget. The
1428
+ * widget must run on the same origin that calls this SDK, while the proof is
1429
+ * transport-only and does not change the checkout intent or its idempotency
1430
+ * key.
1431
+ */
1432
+ turnstileToken?: string;
1433
+ /**
1434
+ * Referral (affiliate) code to submit, as a tri-state:
1435
+ *
1436
+ * - `undefined` — the SDK resolves it from storage (cart-applied referral
1437
+ * code first, then the ambient `?ref=` attribution).
1438
+ * - `''` — explicitly none: submit no referral code and do NOT re-read
1439
+ * storage. This is how a caller pins "quoted WITHOUT a referral"; without
1440
+ * it a code captured between the quote and the submit would be applied to
1441
+ * a total the buyer never saw.
1442
+ * - non-empty — pinned: submit exactly this code.
1443
+ *
1444
+ * `referralCode` is an alias and follows the same rules; `affiliateCode`
1445
+ * wins when both are present.
1446
+ */
1447
+ affiliateCode?: string;
1448
+ /** Alias of {@link CheckoutOptions.affiliateCode}, same tri-state. */
1449
+ referralCode?: string;
1450
+ customerCheckoutPath?: '/dashboard/api/checkout';
1451
+ /**
1452
+ * The cart this hand-off was approved FOR, as `JSON.stringify(getCart())`.
1453
+ *
1454
+ * PAYMENT PATH. A caller that writes the cart and reads it back before
1455
+ * checking out (Buy Now, which replaces the cart, is the sharp case) verifies
1456
+ * a cart it read at one moment, while these functions read storage again on
1457
+ * their way into the request — and localStorage is shared with every other
1458
+ * tab on the domain. A write landing in that gap is billed without ever
1459
+ * having passed the caller's verification.
1460
+ *
1461
+ * The caller cannot close that itself: any check it makes is one more read
1462
+ * BEFORE this one. Pinning the expected bytes moves the comparison to the
1463
+ * only place it can be conclusive — against the exact cart the call is about
1464
+ * to POST. A mismatch refuses before anything is created or sent.
1465
+ *
1466
+ * Honoured identically by BOTH invoice-creating entry points, `checkout()`
1467
+ * and `buildCheckoutUrl()` — they hit the same endpoint and create the same
1468
+ * invoice, so a pin that held on one and not the other would be a promise
1469
+ * the caller could not rely on. Only the refusal shape differs, following
1470
+ * each function's own success shape: `checkout()` returns
1471
+ * `{ success: false }`, `buildCheckoutUrl()` throws.
1472
+ *
1473
+ * Optional and additive: omitted, nothing changes, and the server is not
1474
+ * involved either way.
1475
+ */
1476
+ expectedCart?: string;
1477
+ }
1478
+ interface CheckoutResult {
1479
+ success: boolean;
1480
+ redirectUrl?: string;
1481
+ invoiceId?: string;
1482
+ rewards?: BuyerRewards | null;
1483
+ message?: string;
1484
+ /**
1485
+ * The server's machine-readable refusal identifier when the checkout was
1486
+ * refused, e.g. `errors.checkout.price_increased_since_quote` or
1487
+ * `errors.checkout.affiliate_code_not_applicable`. Branch on this rather
1488
+ * than on `message`, which is localized display copy.
1489
+ *
1490
+ * The quote-proof family — `errors.checkout.quote_token_invalid`,
1491
+ * `errors.checkout.quote_token_expired`, `errors.checkout.quote_token_stale`
1492
+ * — says the proof this call submitted could not be honoured: not ours, past
1493
+ * its window, or priced for a cart/currency/codes that have since moved. The
1494
+ * server refuses rather than pricing without the ceiling, so the caller's
1495
+ * response is always the same: `quoteCart()` again, show the buyer the new
1496
+ * total, and only then retry. A retry with the same stale token is refused
1497
+ * identically.
1498
+ *
1499
+ * Absent for failures the server never named (transport, timeout, an empty
1500
+ * cart caught client-side).
1501
+ */
1502
+ code?: string;
1503
+ /**
1504
+ * Human-verification challenge returned when a legitimate shared network
1505
+ * reaches the invoice-create budget. Render the named provider on the same
1506
+ * origin that calls the SDK, then retry with its proof as `turnstileToken`.
1507
+ */
1508
+ challenge?: ApiChallenge;
1509
+ }
1510
+ /**
1511
+ * Typed refusal from {@link buildCheckoutUrl}. The function keeps its existing
1512
+ * throw-based contract while exposing a server-requested human-verification
1513
+ * challenge so callers can render it and retry with `turnstileToken`.
1514
+ */
1515
+ declare class CheckoutCreateError extends Error {
1516
+ readonly challenge?: ApiChallenge;
1517
+ readonly code?: string;
1518
+ readonly status?: number;
1519
+ constructor(message: string, options?: {
1520
+ challenge?: ApiChallenge;
1521
+ code?: string;
1522
+ status?: number;
1523
+ });
1524
+ }
1525
+ declare function checkout(couponOrOptions?: string | CheckoutOptions, options?: CheckoutOptions): Promise<CheckoutResult>;
1526
+ /**
1527
+ * Build checkout URL by creating invoice first.
1528
+ * Returns the checkout URL for the created invoice.
1529
+ *
1530
+ * PAYMENT PATH. "Build a URL" names what this returns, not a lighter way to
1531
+ * price a cart: it POSTs the same invoice-creating endpoint as `checkout()` and
1532
+ * bills whatever storage holds when it reads. It therefore honours
1533
+ * `CheckoutOptions.expectedCart` on exactly the same terms — a pinned cart that
1534
+ * moved is refused, not invoiced.
1535
+ *
1536
+ * A refusal throws, like every other refusal on this function: the success
1537
+ * shape is a URL string, so there is no in-band value that a caller could
1538
+ * mistake for one. The thrown message is the buyer-facing copy, identical to
1539
+ * the sentence `checkout()` returns, and callers that already handle the
1540
+ * `Cart is empty` throw handle this one unchanged.
1541
+ */
1542
+ declare function buildCheckoutUrl(couponOrOptions?: string | CheckoutOptions, options?: CheckoutOptions): Promise<string>;
1543
+ /**
1544
+ * @deprecated Use buildCheckoutUrl instead.
1545
+ * Sync version is no longer supported as invoice creation requires API call.
1546
+ */
1547
+ declare function buildCheckoutUrlSync(): never;
1548
+
1549
+ interface SearchOptions {
1550
+ hideOutOfStock?: boolean;
1551
+ maxResults?: number;
1552
+ }
1553
+
1554
+ declare function searchCatalogItems(query: string, options?: SearchOptions): Promise<SDKResponse<StorefrontCatalogSearchItem[]>>;
1555
+ declare function searchProducts(query: string, options?: SearchOptions): Promise<SDKResponse<Product[]>>;
1556
+
1557
+ declare function setAffiliateCode(code: string | null | undefined, ttlDays?: number): string | null;
1558
+ declare function clearAffiliateCode(): void;
1559
+ declare function getAffiliateCode(): string | null;
1560
+ declare function trackAffiliateEvent(eventType: 'add_to_cart' | 'checkout_started', options?: {
1561
+ /**
1562
+ * The code the surrounding call actually resolved and submitted (e.g.
1563
+ * checkout()'s tri-state result). `null` means the caller explicitly
1564
+ * submitted WITHOUT a referral — no event is recorded, so an ambient
1565
+ * stored code is never credited for a sale it did not get. Omit the
1566
+ * options object entirely to attribute to the stored ambient code.
1567
+ */
1568
+ code: string | null;
1569
+ /**
1570
+ * Overrides the per-browser-session dedupe key. checkout entry points
1571
+ * pass `inv:<invoiceId>` so every created invoice counts as exactly one
1572
+ * checkout — a session-wide key would drop the second checkout of a
1573
+ * buyer who orders twice in one session while both sales still count.
1574
+ */
1575
+ dedupeKey?: string;
1576
+ }): Promise<void>;
1577
+ declare function validateAffiliateCode(code: string): Promise<SDKResponse<AffiliateValidation>>;
1578
+ declare function applyAffiliateCode(code: string): Promise<SDKResponse<AffiliateValidation>>;
1579
+ /**
1580
+ * Capture an affiliate code from the current URL and store it for 30 days (last-click).
1581
+ *
1582
+ * Example:
1583
+ * - URL: https://mystore.com/product/abc?ref=deadbeef
1584
+ * - captureAffiliateFromUrl() stores "deadbeef" and returns it.
1585
+ */
1586
+ declare function captureAffiliateFromUrl(param?: string): Promise<string | null>;
1587
+
1588
+ /**
1589
+ * Coupons Module
1590
+ *
1591
+ * Coupon validation before checkout.
1592
+ */
1593
+
1594
+ declare function validateCoupon(code: string, productOrOptions?: string | CouponValidationOptions): Promise<SDKResponse<CouponValidation>>;
1595
+
1596
+ /**
1597
+ * Reviews Module
1598
+ *
1599
+ * Shop-level feedback/reviews.
1600
+ * Note: Shoppex has shop-level feedback, not product-level reviews.
1601
+ */
1602
+
1603
+ declare function getShopReviewsPage(cursor?: string | null): Promise<SDKResponse<ShopReviewsPage>>;
1604
+ declare function getShopReviews(): Promise<SDKResponse<Feedback[]>>;
1605
+
1606
+ /**
1607
+ * Customer Module
1608
+ *
1609
+ * Authenticated customer account calls for code-lane storefronts. The edge
1610
+ * worker owns the HttpOnly session cookie and derives the shop from the host.
1611
+ * This module therefore sends neither a session token nor shop identity.
1612
+ */
1613
+
1614
+ interface CustomerOrdersQuery {
1615
+ page?: number;
1616
+ limit?: number;
1617
+ /**
1618
+ * Invoice status filter, verbatim from the producer's enum. Anything else is
1619
+ * answered with a 400 rather than quietly ignored, so pass what the buyer
1620
+ * actually chose.
1621
+ */
1622
+ status?: string;
1623
+ /** Partial invoice-id search. The producer trims it to 64 characters. */
1624
+ search?: string;
1625
+ }
1626
+ interface CustomerTicketPayload {
1627
+ title?: string;
1628
+ message: string;
1629
+ invoice_id?: string;
1630
+ }
1631
+ interface CustomerProfilePatch {
1632
+ name: string;
1633
+ }
1634
+ interface CustomerSubscriptionCancelOptions {
1635
+ cancel_at_period_end?: boolean;
1636
+ reason?: string | null;
1637
+ }
1638
+ interface CustomerEmailPreferencesPatch {
1639
+ global_unsubscribed?: boolean;
1640
+ list_subscriptions?: Array<{
1641
+ list_id: string;
1642
+ subscribed: boolean;
1643
+ }>;
1644
+ }
1645
+ /** One basket line for a QUOTE. `variant_id` is omitted, never null, when a product has no variants. */
1646
+ interface ResellerOrderItem {
1647
+ product_id: string;
1648
+ variant_id?: string;
1649
+ quantity: number;
1650
+ }
1651
+ interface ResellerCatalogQuery {
1652
+ search?: string;
1653
+ page?: number;
1654
+ per_page?: number;
1655
+ }
1656
+ interface ResellerOrdersQuery {
1657
+ page?: number;
1658
+ per_page?: number;
1659
+ }
1660
+ declare function requestOtp(email: string): Promise<SDKResponse<unknown>>;
1661
+ /**
1662
+ * The wire field is `otp`, not `code` — `CustomerOtpVerifyBodySchema` in
1663
+ * `apps/backend-elysia/src/routes/v1/customer/schemas.ts` requires it under that
1664
+ * name, and a `code` body is rejected with 400.
1665
+ */
1666
+ declare function verifyOtp(email: string, otp: string): Promise<SDKResponse<unknown>>;
1667
+ declare function logout(): Promise<SDKResponse<unknown>>;
1668
+ declare function me(): Promise<SDKResponse<unknown>>;
1669
+ declare function dashboard(): Promise<SDKResponse<CustomerPortalDashboardWire>>;
1670
+ /**
1671
+ * Paginated order history.
1672
+ *
1673
+ * Page-based, matching the producer: `invoices.routes.ts` reads `page` and
1674
+ * `limit` and answers with a `has_more` envelope. A cursor parameter would be
1675
+ * ignored upstream and silently return page one forever.
1676
+ *
1677
+ * `status` and `search` are filtered SERVER-side, which is why they belong
1678
+ * here rather than in the caller: `/invoices` is paged, and a filter applied
1679
+ * to the page in hand would filter only the rows that page happens to hold.
1680
+ * The producer spells the search `q`.
1681
+ */
1682
+ declare function orders(options?: CustomerOrdersQuery): Promise<SDKResponse<CustomerPortalPaginatedInvoicesWire>>;
1683
+ declare function order(id: string): Promise<SDKResponse<CustomerPortalInvoiceDetailWire>>;
1684
+ declare function loyalty(): Promise<SDKResponse<CustomerLoyaltyWire>>;
1685
+ declare function redeemLoyaltyPoints(input: {
1686
+ points: number;
1687
+ idempotencyKey: string;
1688
+ }): Promise<SDKResponse<CustomerLoyaltyRedeemWire>>;
1689
+ /**
1690
+ * The warranties this buyer holds — all of them, or the ones on one order.
1691
+ *
1692
+ * `invoiceUniqid` becomes the producer's own `invoice=` filter, which matches
1693
+ * `invoices.uniqid`: the id an order carries everywhere a storefront shows one.
1694
+ * So an order detail asks for its own cover rather than reading every warranty
1695
+ * the buyer owns and discarding most of them.
1696
+ */
1697
+ declare function warranties(invoiceUniqid?: string): Promise<SDKResponse<CustomerWarrantyListWire>>;
1698
+ declare function claimWarranty(uniqid: string, message?: string): Promise<SDKResponse<CustomerWarrantyClaimWire>>;
1699
+ declare function resetLicenseHwid(uniqid: string): Promise<SDKResponse<unknown>>;
1700
+ declare function subscriptionBillingHistory(uniqid: string): Promise<SDKResponse<unknown>>;
1701
+ declare function cancelSubscription(uniqid: string, options?: CustomerSubscriptionCancelOptions): Promise<SDKResponse<unknown>>;
1702
+ declare function pauseSubscription(uniqid: string): Promise<SDKResponse<unknown>>;
1703
+ declare function resumeSubscription(uniqid: string): Promise<SDKResponse<unknown>>;
1704
+ declare function favorites(): Promise<SDKResponse<unknown>>;
1705
+ /** Idempotent upstream, and a PUT — `customer-favorites.ts` has no POST route. */
1706
+ declare function addFavorite(productUniqid: string): Promise<SDKResponse<unknown>>;
1707
+ declare function removeFavorite(productUniqid: string): Promise<SDKResponse<unknown>>;
1708
+ declare function affiliate(): Promise<SDKResponse<unknown>>;
1709
+ declare function affiliateStats(days?: number): Promise<SDKResponse<unknown>>;
1710
+ declare function createTicket(payload: CustomerTicketPayload): Promise<SDKResponse<unknown>>;
1711
+ declare function ticket(uniqid: string): Promise<SDKResponse<unknown>>;
1712
+ declare function replyToTicket(uniqid: string, message: string): Promise<SDKResponse<unknown>>;
1713
+ /**
1714
+ * The producer is `POST /v1/customer/profile`, not PATCH.
1715
+ *
1716
+ * There is no `GET /profile` to pair with it — the buyer's own record comes from
1717
+ * `/me` and `/dashboard`.
1718
+ */
1719
+ declare function updateProfile(patch: CustomerProfilePatch): Promise<SDKResponse<unknown>>;
1720
+ declare function updateAvatar(file: File): Promise<SDKResponse<unknown>>;
1721
+ declare function removeAvatar(): Promise<SDKResponse<unknown>>;
1722
+ declare function emailPreferences(): Promise<SDKResponse<unknown>>;
1723
+ declare function updateEmailPreferences(patch: CustomerEmailPreferencesPatch): Promise<SDKResponse<unknown>>;
1724
+ declare function sessions(): Promise<SDKResponse<unknown>>;
1725
+ declare function revokeSession(id: string): Promise<SDKResponse<unknown>>;
1726
+ /**
1727
+ * Ends every session except this one.
1728
+ *
1729
+ * `others=true` is required, not decorative: `RevokeOtherSessionsQuerySchema`
1730
+ * declares it as a literal, so the route answers 400 without it. The selector
1731
+ * is explicit on purpose — "revoke sessions" with no qualifier is one typo away
1732
+ * from signing the buyer out of the device they are holding.
1733
+ */
1734
+ declare function revokeAllSessions(): Promise<SDKResponse<unknown>>;
1735
+ /** The program's state and this buyer's place in it. Null reseller means not enrolled. */
1736
+ declare function reseller(): Promise<SDKResponse<unknown>>;
1737
+ /** `APPLICATION` mode. The note is optional unless the shop requires one. */
1738
+ declare function applyForReseller(note?: string): Promise<SDKResponse<unknown>>;
1739
+ /** `OPEN` mode: no application, the buyer is a reseller when they say so. */
1740
+ declare function enrollAsReseller(): Promise<SDKResponse<unknown>>;
1741
+ /** `MANUAL` mode: the merchant invited this buyer and gave them a token. */
1742
+ declare function acceptResellerInvite(token: string): Promise<SDKResponse<unknown>>;
1743
+ /** The buyer's own tier prices. Page-based, like the order history. */
1744
+ declare function resellerCatalog(options?: ResellerCatalogQuery): Promise<SDKResponse<unknown>>;
1745
+ /**
1746
+ * Prices a basket and writes nothing.
1747
+ *
1748
+ * The volume discount cannot be derived from the catalog — it only reports that
1749
+ * one exists — so a storefront that adds up unit prices itself shows a total
1750
+ * the shop will not charge. This is the number to display.
1751
+ */
1752
+ declare function quoteResellerOrder(items: ResellerOrderItem[]): Promise<SDKResponse<unknown>>;
1753
+ declare function resellerOrders(options?: ResellerOrdersQuery): Promise<SDKResponse<unknown>>;
1754
+ /** One order with its lines, delivery state and delivered serials. */
1755
+ declare function resellerOrder(uniqid: string): Promise<SDKResponse<unknown>>;
1756
+ /** The prepaid balance the wholesale orders are paid from. */
1757
+ declare function resellerWallet(): Promise<SDKResponse<unknown>>;
1758
+ declare function resellerApiKeys(): Promise<SDKResponse<unknown>>;
1759
+
1760
+ /**
1761
+ * Invoices Module
1762
+ *
1763
+ * Invoice status checking after payment.
1764
+ */
1765
+
1766
+ declare function getInvoice(invoiceId: string): Promise<SDKResponse<Invoice>>;
1767
+ declare function getInvoiceStatus(invoiceId: string): Promise<SDKResponse<{
1768
+ status: string;
1769
+ }>>;
1770
+
1771
+ /**
1772
+ * Pages Module
1773
+ *
1774
+ * API methods for public pages.
1775
+ */
1776
+
1777
+ /**
1778
+ * Get all public pages for the store
1779
+ */
1780
+ declare function getPages(): Promise<SDKResponse<Page[]>>;
1781
+ /**
1782
+ * Get a public page by slug
1783
+ */
1784
+ declare function getPage(slug: string): Promise<SDKResponse<Page>>;
1785
+
1786
+ /**
1787
+ * Navigation Module
1788
+ *
1789
+ * API methods for menus and navigation.
1790
+ */
1791
+
1792
+ /**
1793
+ * Get all menus for the store
1794
+ */
1795
+ declare function getMenus(): Promise<SDKResponse<Menu[]>>;
1796
+ /**
1797
+ * Get a menu by its exact title.
1798
+ */
1799
+ declare function getMenuByTitle(title: string): Promise<SDKResponse<Menu>>;
1800
+ /**
1801
+ * Get a menu by its exact title.
1802
+ */
1803
+ declare function getMenu(title: string): Promise<SDKResponse<Menu>>;
1804
+ /**
1805
+ * Get a menu by canonical slot. The backend resolves legacy menu titles too.
1806
+ */
1807
+ declare function getMenuBySlot(slot: NavigationMenuSlot): Promise<SDKResponse<Menu>>;
1808
+ declare function getMenuSlotTitles(slot: NavigationMenuSlot): string[];
1809
+
1810
+ declare function trackPageView(cartValue?: number, itemCount?: number): Promise<void>;
1811
+
1812
+ /**
1813
+ * Anonymized recent-sales feed for storefront social proof (product title +
1814
+ * relative age only — never buyer identity). Empty items when the shop has no
1815
+ * recent completed orders.
1816
+ */
1817
+ declare function getStorefrontRecentSales(): Promise<SDKResponse<StorefrontRecentSales>>;
1818
+ declare function getStorefrontOnlineUsers(): Promise<SDKResponse<StorefrontOnlineUsers>>;
1819
+ declare function touchStorefrontPresence(): Promise<SDKResponse<{
1820
+ pong: string;
1821
+ }>>;
1822
+
1823
+ /**
1824
+ * Formatting Utilities
1825
+ */
1826
+ declare function createFormatter(currency?: string, locale?: string): Intl.NumberFormat;
1827
+ declare function formatPrice(amount: number | string, currency?: string, locale?: string): string;
1828
+
1829
+ interface CacheStats {
1830
+ hits: number;
1831
+ misses: number;
1832
+ pendingRequests: number;
1833
+ entries: number;
1834
+ }
1835
+ declare function getCacheStats(): CacheStats;
1836
+ declare function clearCache(): void;
1837
+ declare function invalidateCache(prefixOrKey: string): void;
1838
+
1839
+ /**
1840
+ * Shoppex Storefront SDK
1841
+ *
1842
+ * Usage:
1843
+ * ```html
1844
+ * <script src="https://cdn.shoppex.io/sdk/v1.0/shoppex.umd.js"></script>
1845
+ * <script>
1846
+ * shoppex.init('my-store');
1847
+ *
1848
+ * shoppex.getStore().then(store => console.log(store));
1849
+ * shoppex.addToCart('product-id', 'variant-id', 2);
1850
+ * shoppex.checkout();
1851
+ * </script>
1852
+ * ```
1853
+ */
1854
+
1855
+ /**
1856
+ * Initialize the SDK with a store slug
1857
+ */
1858
+ declare function init(storeSlug: string, options?: ShoppexInitOptions): void;
1859
+ declare function init(options: ShoppexInitOptions & {
1860
+ storeId: string;
1861
+ }): void;
1862
+ /**
1863
+ * Shoppex SDK instance
1864
+ */
1865
+ declare const shoppex: {
1866
+ init: typeof init;
1867
+ isInitialized: typeof isInitialized;
1868
+ getConfig: typeof getConfig;
1869
+ client: typeof getTypedClient;
1870
+ getStore: typeof getStore;
1871
+ getStorefront: typeof getStorefront;
1872
+ getStoreLogoUrl: typeof getStoreLogoUrl;
1873
+ getStoreBannerUrl: typeof getStoreBannerUrl;
1874
+ resolveStoreByDomain: typeof resolveStoreByDomain;
1875
+ getProducts: typeof getProducts;
1876
+ getStorefrontProductsPage: typeof getStorefrontProductsPage;
1877
+ getProduct: typeof getProduct;
1878
+ getCategories: typeof getCategories;
1879
+ getCart: typeof getCart;
1880
+ getCartItemCount: typeof getCartItemCount;
1881
+ getCartCoupon: typeof getCartCoupon;
1882
+ getCartCouponSource: typeof getCartCouponSource;
1883
+ setCartCoupon: typeof setCartCoupon;
1884
+ clearCartCoupon: typeof clearCartCoupon;
1885
+ addToCart: typeof addToCart;
1886
+ setCartItem: typeof setCartItem;
1887
+ updateCartItem: typeof updateCartItem;
1888
+ removeFromCart: typeof removeFromCart;
1889
+ clearCart: typeof clearCart;
1890
+ createCartBackup: typeof createCartBackup;
1891
+ restoreCartFromBackup: typeof restoreCartFromBackup;
1892
+ mergeBaskets: typeof mergeBaskets;
1893
+ moveBasketItem: typeof moveBasketItem;
1894
+ getCartStats: typeof getCartStats;
1895
+ validateCartIntegrity: typeof validateCartIntegrity;
1896
+ quoteCart: typeof quoteCart;
1897
+ resolveCartLineId: typeof resolveCartLineId;
1898
+ checkout: typeof checkout;
1899
+ buildCheckoutUrl: typeof buildCheckoutUrl;
1900
+ buildCheckoutUrlSync: typeof buildCheckoutUrlSync;
1901
+ captureAffiliateFromUrl: typeof captureAffiliateFromUrl;
1902
+ validateAffiliateCode: typeof validateAffiliateCode;
1903
+ applyAffiliateCode: typeof applyAffiliateCode;
1904
+ getAffiliateCode: typeof getAffiliateCode;
1905
+ setAffiliateCode: typeof setAffiliateCode;
1906
+ clearAffiliateCode: typeof clearAffiliateCode;
1907
+ trackAffiliateEvent: typeof trackAffiliateEvent;
1908
+ validateCoupon: typeof validateCoupon;
1909
+ getShopReviews: typeof getShopReviews;
1910
+ getShopReviewsPage: typeof getShopReviewsPage;
1911
+ requestOtp: typeof requestOtp;
1912
+ verifyOtp: typeof verifyOtp;
1913
+ logout: typeof logout;
1914
+ me: typeof me;
1915
+ dashboard: typeof dashboard;
1916
+ orders: typeof orders;
1917
+ order: typeof order;
1918
+ loyalty: typeof loyalty;
1919
+ redeemLoyaltyPoints: typeof redeemLoyaltyPoints;
1920
+ warranties: typeof warranties;
1921
+ claimWarranty: typeof claimWarranty;
1922
+ resetLicenseHwid: typeof resetLicenseHwid;
1923
+ subscriptionBillingHistory: typeof subscriptionBillingHistory;
1924
+ cancelSubscription: typeof cancelSubscription;
1925
+ pauseSubscription: typeof pauseSubscription;
1926
+ resumeSubscription: typeof resumeSubscription;
1927
+ favorites: typeof favorites;
1928
+ addFavorite: typeof addFavorite;
1929
+ removeFavorite: typeof removeFavorite;
1930
+ affiliate: typeof affiliate;
1931
+ affiliateStats: typeof affiliateStats;
1932
+ createTicket: typeof createTicket;
1933
+ ticket: typeof ticket;
1934
+ replyToTicket: typeof replyToTicket;
1935
+ updateProfile: typeof updateProfile;
1936
+ updateAvatar: typeof updateAvatar;
1937
+ removeAvatar: typeof removeAvatar;
1938
+ emailPreferences: typeof emailPreferences;
1939
+ updateEmailPreferences: typeof updateEmailPreferences;
1940
+ sessions: typeof sessions;
1941
+ revokeSession: typeof revokeSession;
1942
+ revokeAllSessions: typeof revokeAllSessions;
1943
+ reseller: typeof reseller;
1944
+ applyForReseller: typeof applyForReseller;
1945
+ enrollAsReseller: typeof enrollAsReseller;
1946
+ acceptResellerInvite: typeof acceptResellerInvite;
1947
+ resellerCatalog: typeof resellerCatalog;
1948
+ quoteResellerOrder: typeof quoteResellerOrder;
1949
+ resellerOrders: typeof resellerOrders;
1950
+ resellerOrder: typeof resellerOrder;
1951
+ resellerWallet: typeof resellerWallet;
1952
+ resellerApiKeys: typeof resellerApiKeys;
1953
+ searchProducts: typeof searchProducts;
1954
+ searchCatalogItems: typeof searchCatalogItems;
1955
+ getInvoice: typeof getInvoice;
1956
+ getInvoiceStatus: typeof getInvoiceStatus;
1957
+ getPages: typeof getPages;
1958
+ getPage: typeof getPage;
1959
+ getMenus: typeof getMenus;
1960
+ getMenu: typeof getMenu;
1961
+ getMenuBySlot: typeof getMenuBySlot;
1962
+ getMenuByTitle: typeof getMenuByTitle;
1963
+ getMenuSlotTitles: typeof getMenuSlotTitles;
1964
+ trackPageView: typeof trackPageView;
1965
+ getStorefrontOnlineUsers: typeof getStorefrontOnlineUsers;
1966
+ getStorefrontRecentSales: typeof getStorefrontRecentSales;
1967
+ touchStorefrontPresence: typeof touchStorefrontPresence;
1968
+ createFormatter: typeof createFormatter;
1969
+ formatPrice: typeof formatPrice;
1970
+ clearCache: typeof clearCache;
1971
+ invalidateCache: typeof invalidateCache;
1972
+ getCacheStats: typeof getCacheStats;
1973
+ fetchPublishedBuilderSettings: typeof fetchPublishedBuilderSettings;
1974
+ fetchPublishedThemeSettings: typeof fetchPublishedThemeSettings;
1975
+ resolveDefaults: typeof resolveDefaults;
1976
+ mergeSettings: typeof mergeSettings;
1977
+ };
1978
+
1979
+ export { type AffiliateValidation, type ApiChallenge, ApiError, type ApiResponse, type BlockDefinition, type BlockInstance, type BuyerRewardActivityItem, type BuyerRewards, type CartAddOptions, type CartAddon, type CartAppliedDiscount, type CartBasketMergeLine, type CartCodeSource, CartError, type CartItem, type CartItemUpdate, type CartLineIdentityInput, type CartMetadata, type CartPayload, type CartQuote, type CartQuoteLine, type CartStats, type Category, CheckoutCreateError, type CheckoutOptions, type CheckoutResult, type CouponValidation, type CouponValidationOptions, type CursorPagination, type CustomFieldDefinition, type CustomerEmailPreferencesPatch, type CustomerProfilePatch, type CustomerSubscriptionCancelOptions, type CustomerTicketPayload, type EligibleBundleDeal, type EligibleBundleDealProduct, type EligibleCartDeal, type Feedback, type Invoice, type InvoiceProduct, type Menu, type MenuItem, NetworkError, NotInitializedError, type Page, type PageLayout, type PriceVariant, type Product, type ProductAddon, type ProductBundle, type ProductBundleProduct, type ProductCategory, type ProductDescriptionTab, type ProductFaq, type ProductFeedback, type ProductGroup, type ProductImage, type ProductVariant, type PublishedBuilderSettings, type PublishedThemeSettingsPayload, type ResellerCatalogQuery, type ResellerOrderItem, type ResellerOrdersQuery, type ResolvedThemeSettings, type RewardActionType, type RewardGrantStatus, type RewardProgramSummary, type RewardProgramTeaserItem, type RewardReason, type SDKResponse, type SearchOptions, type SectionDefinition, type SettingField, type Shop, type ShopFeedback, type ShopReviewsPage, type ShopReviewsSummary, type ShopTheme, type ShoppexConfig, ShoppexError, type ShoppexInitOptions, type StorefrontAddon, type StorefrontAddonBootstrap, type StorefrontAnnouncementBarAddon, type StorefrontCatalogSearchItem, type StorefrontContactTicketInput, type StorefrontContactTicketResult, type StorefrontCountdownBarAddon, type StorefrontCouponPopupModalAddon, type StorefrontCustomField, type StorefrontData, type StorefrontItem, type StorefrontOnlineUsers, type StorefrontPromoInfoCardAddon, type StorefrontRecentPurchasePopupAddon, type StorefrontRecentSaleEntry, type StorefrontRecentSales, type StorefrontSearchFilterOptions, type StorefrontSocialLinks, type Subscription, type SubscriptionFlags, type SubscriptionInterval, type ThemeBlockManifest, type ThemeConfig, type TrustedChecks, ValidationError, acceptResellerInvite, addFavorite, affiliate, affiliateStats, applyForReseller, buildStorefrontContactMessage, buildStorefrontCustomFieldPayload, buildStorefrontProductLookup, cancelSubscription, claimWarranty, collectProductSearchHaystack, computeCartLineId, createTicket, dashboard, shoppex as default, emailPreferences, enrollAsReseller, ensureCartLineId, favorites, fetchPublishedBuilderSettings, fetchPublishedThemeSettings, filterProductsBySearchQuery, getMenu, getMenuBySlot, getMenuByTitle, getMenuSlotTitles, getMenus, getMergedStorefrontProducts, getShopReviewsPage, getStorefrontGroupProducts, getStorefrontOnlineUsers, getStorefrontRecentSales, groupMatchesSearchQuery, isProductInStock, isProductOutOfStock, isStorefrontCheckboxCustomFieldValueChecked, isVariantOutOfStock, logout, loyalty, me, mergeSettings, normalizeSearchQuery, normalizeStorefrontCustomFields, order, orders, pauseSubscription, productMatchesSearchQuery, quoteResellerOrder, redeemLoyaltyPoints, removeAvatar, removeFavorite, replyToTicket, requestOtp, reseller, resellerApiKeys, resellerCatalog, resellerOrder, resellerOrders, resellerWallet, resetLicenseHwid, resolveDefaults, resolveDisplayStock, resolveStorefrontApiBaseUrl, resolveStorefrontSocialLinks, resolveVariantStockValue, resumeSubscription, revokeAllSessions, revokeSession, searchMergedStorefrontCatalog, searchMergedStorefrontCatalogItems, sessions, shoppex, stripHtmlFromText, submitStorefrontContactTicket, subscriptionBillingHistory, ticket, touchStorefrontPresence, trackPageView, updateAvatar, updateEmailPreferences, updateProfile, validateStorefrontCustomFieldValue, verifyOtp, warranties };