@kasuvia/sdk 0.0.1

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 (73) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +112 -0
  3. package/dist/index.d.mts +1891 -0
  4. package/dist/index.d.ts +1891 -0
  5. package/dist/index.js +3540 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +3314 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +59 -0
  10. package/src/client/authClient.ts +135 -0
  11. package/src/client/graphqlClient.ts +53 -0
  12. package/src/client/httpClient.ts +298 -0
  13. package/src/config/index.ts +102 -0
  14. package/src/graphql/collections.graphql.ts +56 -0
  15. package/src/graphql/index.ts +7 -0
  16. package/src/graphql/products.graphql.ts +710 -0
  17. package/src/graphql/wishlist.graphql.ts +33 -0
  18. package/src/hooks/index.ts +26 -0
  19. package/src/hooks/use-auth.ts +182 -0
  20. package/src/hooks/use-bespoke-availability.ts +20 -0
  21. package/src/hooks/use-cart.ts +207 -0
  22. package/src/hooks/use-cms.ts +165 -0
  23. package/src/hooks/use-collections.ts +40 -0
  24. package/src/hooks/use-consultation-stream.ts +141 -0
  25. package/src/hooks/use-consultations.ts +76 -0
  26. package/src/hooks/use-countries.ts +24 -0
  27. package/src/hooks/use-currencies.ts +27 -0
  28. package/src/hooks/use-google-translate.ts +164 -0
  29. package/src/hooks/use-is-mounted.ts +9 -0
  30. package/src/hooks/use-languages.ts +33 -0
  31. package/src/hooks/use-order-stream.ts +195 -0
  32. package/src/hooks/use-orders.ts +64 -0
  33. package/src/hooks/use-payment.ts +68 -0
  34. package/src/hooks/use-products.ts +113 -0
  35. package/src/hooks/use-service-booking.ts +118 -0
  36. package/src/hooks/use-states.ts +28 -0
  37. package/src/hooks/use-wishlist.ts +121 -0
  38. package/src/index.ts +65 -0
  39. package/src/services/app.service.ts +17 -0
  40. package/src/services/auth.service.ts +332 -0
  41. package/src/services/bespoke.service.ts +17 -0
  42. package/src/services/cart.service.ts +245 -0
  43. package/src/services/cms.service.ts +112 -0
  44. package/src/services/collection.service.ts +77 -0
  45. package/src/services/config.service.ts +42 -0
  46. package/src/services/consultation.service.ts +51 -0
  47. package/src/services/index.ts +21 -0
  48. package/src/services/logistics.service.ts +95 -0
  49. package/src/services/notifications.service.ts +50 -0
  50. package/src/services/order.service.ts +169 -0
  51. package/src/services/payment.service.ts +127 -0
  52. package/src/services/product.service.ts +678 -0
  53. package/src/services/service-booking.service.ts +86 -0
  54. package/src/services/wishlist.service.ts +84 -0
  55. package/src/types/auth/index.ts +126 -0
  56. package/src/types/bespoke/index.ts +39 -0
  57. package/src/types/business/index.ts +6 -0
  58. package/src/types/cms/index.ts +77 -0
  59. package/src/types/consultations/index.ts +79 -0
  60. package/src/types/index.ts +27 -0
  61. package/src/types/media/index.ts +41 -0
  62. package/src/types/payments/index.ts +120 -0
  63. package/src/types/services/index.ts +80 -0
  64. package/src/types/store/index.ts +282 -0
  65. package/src/types/store/shipping.ts +38 -0
  66. package/src/types/ui/index.ts +32 -0
  67. package/src/utils/cache.ts +33 -0
  68. package/src/utils/checkout.ts +39 -0
  69. package/src/utils/customer.ts +20 -0
  70. package/src/utils/error-handler.ts +14 -0
  71. package/src/utils/index.ts +10 -0
  72. package/src/utils/logger.ts +79 -0
  73. package/src/utils/sanitize-url.ts +55 -0
@@ -0,0 +1,1891 @@
1
+ import { AxiosInstance } from 'axios';
2
+ import { GraphQLClient } from 'graphql-request';
3
+ import React, { ReactNode } from 'react';
4
+ import * as _tanstack_react_query from '@tanstack/react-query';
5
+
6
+ /**
7
+ * Kasuvia SDK Configuration
8
+ *
9
+ * This module manages SDK initialization and runtime configuration.
10
+ * The SDK is client-based and runs in the browser.
11
+ * All backend URLs are bundled with the SDK.
12
+ *
13
+ * SECURITY NOTE: The storefront API key has limited permissions - it only provides
14
+ * customer-based resources from a business owner to customers, not full platform access.
15
+ * This key is safe to expose to the browser as a NEXT_PUBLIC_ environment variable.
16
+ */
17
+ interface SdkConfig {
18
+ businessId: string;
19
+ storefrontApiKey: string;
20
+ }
21
+ interface SdkRuntimeConfig {
22
+ businessId: string;
23
+ storefrontApiKey: string;
24
+ }
25
+ /**
26
+ * Initialize the SDK with runtime credentials
27
+ * This must be called before any SDK operations
28
+ *
29
+ * IMPORTANT: In Next.js, this should be called in layout.tsx (server component)
30
+ * using private environment variables (kasuvia_BUSINESS_ID, kasuvia_STOREFRONT_API_KEY).
31
+ * The config is stored in module scope and will be available to client components
32
+ * through the SDK's bundled code.
33
+ *
34
+ * @param config - SDK configuration including credentials
35
+ */
36
+ declare function initSdk(config: SdkConfig): void;
37
+ /**
38
+ * Get the current runtime configuration
39
+ * Throws if SDK is not initialized
40
+ */
41
+ declare function getRuntimeConfig(): SdkRuntimeConfig;
42
+ /**
43
+ * Get backend URL for a specific service
44
+ * Internal use only - never exposed to storefront
45
+ */
46
+ declare function getBackendUrl(service: 'auth' | 'store' | 'payment' | 'notifications' | 'cms'): string;
47
+ /**
48
+ * Check if SDK is initialized
49
+ */
50
+ declare function isInitialized(): boolean;
51
+ /**
52
+ * Reset SDK configuration (mainly for testing)
53
+ */
54
+ declare function resetConfig(): void;
55
+
56
+ /**
57
+ * HTTP Client - Pre-configured Axios instances
58
+ *
59
+ * Each Axios instance is created with a default baseURL based on the static
60
+ * service URL. The baseURLs are complete URLs including the API version,
61
+ * selected based on the configured environment (development/production).
62
+ */
63
+
64
+ declare function getOrCreateGuestSessionId(): string;
65
+ declare function getGuestSessionId(): string | null;
66
+ declare function clearGuestSessionId(): void;
67
+ declare const storeManagementAxios: AxiosInstance;
68
+ declare const publicStoreAxios: AxiosInstance;
69
+ declare const authAxios: AxiosInstance;
70
+ declare const paymentAxios: AxiosInstance;
71
+ declare const cmsAxios: AxiosInstance;
72
+ /**
73
+ * configureHttpClients()
74
+ * Updates the baseURL of all Axios instances to match the configured environment.
75
+ * This must be called after initSdk() to ensure the correct environment URLs are used.
76
+ */
77
+ declare function configureHttpClients(): void;
78
+
79
+ declare const tokenStore: {
80
+ readonly getAccessToken: () => string | null;
81
+ readonly setAccessToken: (token: string | null) => void;
82
+ readonly getRefreshToken: () => string | null;
83
+ readonly setRefreshToken: (token: string | null, remember?: boolean) => void;
84
+ readonly clearAll: () => void;
85
+ readonly hasSession: () => boolean;
86
+ readonly isPersistent: () => boolean;
87
+ };
88
+ /**
89
+ * Perform token refresh with queue-coalescing to avoid parallel refresh races.
90
+ */
91
+ declare function refreshToken(): Promise<string>;
92
+
93
+ /**
94
+ * GraphQL Client
95
+ *
96
+ * Provides a GraphQL client with tenant and auth headers for product queries.
97
+ * The endpoint URL is derived from the static BACKEND_URLS constant (eager,
98
+ * module-load safe). Auth headers are injected fresh on each request via a
99
+ * factory so the token is always current.
100
+ */
101
+
102
+ /**
103
+ * Returns a GraphQL client instance with up-to-date auth headers.
104
+ * A new client is created on each call so token/config changes take effect
105
+ * immediately without requiring an explicit reset.
106
+ */
107
+ declare function getGraphQLClient(): GraphQLClient;
108
+ /**
109
+ * No-op — kept for backward compatibility.
110
+ * Clients are now stateless (created fresh on each call), so there is no
111
+ * cached instance to reset.
112
+ */
113
+ declare function resetGraphQLClient(): void;
114
+
115
+ /**
116
+ * Simplified customer auth types for luxe-storefront.
117
+ * Customers only need enough to track their orders — no RBAC, MFA, or complex profiles.
118
+ */
119
+ /**
120
+ * Media System response object for avatar/profile picture.
121
+ * Stored as JSON in the backend Profile model.
122
+ */
123
+ interface AvatarObject {
124
+ id: string;
125
+ alt: string;
126
+ url: string;
127
+ }
128
+ interface CustomerProfileFields {
129
+ firstname: string;
130
+ lastname: string;
131
+ phone: string;
132
+ }
133
+ interface CustomerUser {
134
+ id: string;
135
+ email: string;
136
+ firstname?: string;
137
+ lastname?: string;
138
+ phone?: string;
139
+ /** Derived display name — prefer firstname + lastname when available */
140
+ full_name?: string;
141
+ avatar: string | null;
142
+ provider: 'google' | 'facebook' | 'email';
143
+ }
144
+ /** GET/PUT /auth/profile/ — matches luxe-auth UserSerializer */
145
+ interface AuthUserResponse {
146
+ id: string;
147
+ email: string;
148
+ is_google_auth_enabled?: boolean;
149
+ is_facebook_auth_enabled?: boolean;
150
+ profile?: {
151
+ firstname?: string;
152
+ lastname?: string;
153
+ phone?: string;
154
+ profile_picture?: string | null;
155
+ };
156
+ }
157
+ interface UpdateProfilePayload {
158
+ firstname?: string;
159
+ lastname?: string;
160
+ phone?: string;
161
+ }
162
+ interface BusinessContext {
163
+ id: string;
164
+ business_id: string;
165
+ name: string;
166
+ logo_picture?: string | null;
167
+ display_currency?: string;
168
+ }
169
+ interface CustomerAuthResponse {
170
+ access: string;
171
+ refresh: string;
172
+ user: CustomerUser;
173
+ business: BusinessContext;
174
+ is_new?: boolean;
175
+ }
176
+ interface RefreshTokenResponse {
177
+ access: string;
178
+ refresh?: string;
179
+ }
180
+ /** POST /auth/login/customer/ — field name is `tenant_id` (the business_id) */
181
+ interface CustomerLoginPayload {
182
+ tenant_id: string;
183
+ email: string;
184
+ password: string;
185
+ }
186
+ /** POST /auth/register/customer/ */
187
+ interface CustomerRegisterPayload {
188
+ tenant_id: string;
189
+ /** Full name — backend splits this into firstname and lastname on the Profile */
190
+ full_name: string;
191
+ email: string;
192
+ password: string;
193
+ }
194
+ /** POST /auth/verify-otp/ */
195
+ interface OTPVerifyPayload {
196
+ email: string;
197
+ code: string;
198
+ purpose?: 'verify' | 'password_reset';
199
+ }
200
+ /** POST /auth/resend-otp/ */
201
+ interface ResendOTPPayload {
202
+ email: string;
203
+ }
204
+ /** POST /auth/logout/ */
205
+ interface LogoutPayload {
206
+ refresh?: string;
207
+ }
208
+ interface AuthContextValue {
209
+ customer: CustomerUser | null;
210
+ isLoading: boolean;
211
+ isModalOpen: boolean;
212
+ openModal: () => void;
213
+ closeModal: () => void;
214
+ setCustomer: (user: CustomerUser | null) => void;
215
+ logout: () => Promise<void>;
216
+ }
217
+
218
+ /**
219
+ * Shipping and delivery types for the storefront
220
+ */
221
+ interface ShippingRate {
222
+ id: string;
223
+ carrier_name: string;
224
+ carrier_logo: string;
225
+ carrier_rate_description: string;
226
+ carrier_slug: string;
227
+ amount: number;
228
+ currency: string;
229
+ delivery_time: string;
230
+ delivery_eta: number;
231
+ pickup_time: string;
232
+ pickup_eta: number;
233
+ pickup_available: boolean;
234
+ dropoff_available?: boolean;
235
+ dropoff_required?: boolean;
236
+ }
237
+ interface ShippingRatesResponse {
238
+ status: boolean;
239
+ message: string;
240
+ data: ShippingRate[];
241
+ }
242
+ interface DeliveryAddress {
243
+ first_name: string;
244
+ last_name: string;
245
+ phone: string;
246
+ street: string;
247
+ city: string;
248
+ state: string;
249
+ lga: string;
250
+ country: string;
251
+ postal: string;
252
+ }
253
+
254
+ type ProductType = "physical" | "digital" | "service" | "bespoke";
255
+
256
+ interface Address {
257
+ street: string;
258
+ city: string;
259
+ state: string;
260
+ country: string;
261
+ zip?: string;
262
+ }
263
+ interface Collection {
264
+ id: string;
265
+ business_id?: string;
266
+ name: string;
267
+ slug: string;
268
+ description?: string;
269
+ image?: {
270
+ url: string;
271
+ alt?: string;
272
+ id?: string;
273
+ };
274
+ collection_type?: string;
275
+ rules?: Record<string, unknown>;
276
+ status?: string;
277
+ sort_order?: number;
278
+ created_at: string;
279
+ updated_at: string;
280
+ }
281
+ interface Inventory {
282
+ id: string;
283
+ product_id: string;
284
+ variant_id?: string;
285
+ quantity: number;
286
+ reserved: number;
287
+ reorder_point: number;
288
+ reorder_quantity: number;
289
+ track_quantity: boolean;
290
+ allow_backorder: boolean;
291
+ available: number;
292
+ is_in_stock: boolean;
293
+ is_low_stock: boolean;
294
+ updated_at: string;
295
+ }
296
+ interface ProductVariant {
297
+ id: string;
298
+ product_id: string;
299
+ sku?: string;
300
+ attributes: Record<string, string>;
301
+ price?: number;
302
+ images: Array<{
303
+ url: string;
304
+ alt?: string;
305
+ id?: string;
306
+ }>;
307
+ weight_kg?: number;
308
+ is_active: boolean;
309
+ inventory?: Inventory;
310
+ created_at: string;
311
+ updated_at: string;
312
+ }
313
+ interface CustomField {
314
+ label: string;
315
+ unit?: string;
316
+ required: boolean;
317
+ type?: string;
318
+ key?: string;
319
+ placeholder?: string;
320
+ }
321
+ interface Product {
322
+ id: string;
323
+ business_id: string;
324
+ name: string;
325
+ slug: string;
326
+ description?: string;
327
+ brand?: string;
328
+ product_type: ProductType;
329
+ requires_shipping: boolean;
330
+ is_consumable: boolean;
331
+ is_bespoke: boolean;
332
+ base_price: number;
333
+ currency: string;
334
+ images: Array<{
335
+ url: string;
336
+ alt?: string;
337
+ id?: string;
338
+ }>;
339
+ tags: string[];
340
+ custom_fields: CustomField[];
341
+ is_published: boolean;
342
+ is_featured: boolean;
343
+ is_popular: boolean;
344
+ is_new: boolean;
345
+ is_temporary: boolean;
346
+ digital_file_key?: string;
347
+ download_limit?: number;
348
+ download_expires_at?: string;
349
+ weight_kg: number;
350
+ length_cm?: number;
351
+ width_cm?: number;
352
+ height_cm?: number;
353
+ created_at: string;
354
+ updated_at: string;
355
+ variants: ProductVariant[];
356
+ collections: Collection[];
357
+ }
358
+ interface ListParams {
359
+ page?: number;
360
+ pageSize?: number;
361
+ search?: string;
362
+ ordering?: string;
363
+ collectionSlug?: string;
364
+ excludeProductId?: string;
365
+ }
366
+ interface PaginatedResponse<T> {
367
+ items: T[];
368
+ total: number;
369
+ page: number;
370
+ page_size: number;
371
+ total_pages: number;
372
+ }
373
+ interface CartItem {
374
+ id: string;
375
+ product_id: string;
376
+ product_slug: string;
377
+ product_name: string;
378
+ image?: string;
379
+ variant_id?: string;
380
+ variant_attributes?: string | Record<string, string>;
381
+ unit_price: number;
382
+ quantity: number;
383
+ custom_measurements?: string;
384
+ is_bespoke: boolean;
385
+ created_at: string;
386
+ updated_at: string;
387
+ }
388
+ interface CartResponse {
389
+ items: CartItem[];
390
+ subtotal: number;
391
+ total: number;
392
+ item_count: number;
393
+ product_type?: string;
394
+ }
395
+ interface WishlistItem {
396
+ id: string;
397
+ product_id: string;
398
+ notes?: string;
399
+ created_at: string;
400
+ product_name?: string;
401
+ product_slug?: string;
402
+ product_price?: number;
403
+ product_image?: string;
404
+ }
405
+ interface WishlistListResponse {
406
+ items: WishlistItem[];
407
+ total: number;
408
+ page: number;
409
+ page_size: number;
410
+ total_pages: number;
411
+ }
412
+ interface WishlistCheckResponse {
413
+ in_wishlist: boolean;
414
+ }
415
+ type OrderStatus = 'pending' | 'confirmed' | 'processing' | 'packed' | 'picked_up' | 'in_transit' | 'shipped' | 'delivered' | 'voided' | 'refunded' | 'failed';
416
+ type BespokeStageKey = "received" | "development" | "finished" | "dispatched";
417
+ interface OrderItem {
418
+ id: string;
419
+ productName: string;
420
+ image: string;
421
+ quantity: number;
422
+ price: number;
423
+ }
424
+ interface Order {
425
+ id: string;
426
+ display_id?: string;
427
+ items: OrderItem[];
428
+ total: number;
429
+ status: OrderStatus;
430
+ customerEmail: string;
431
+ customerName: string;
432
+ createdAt: number;
433
+ updatedAt: number;
434
+ deliveryMethod?: string;
435
+ trackingNumber?: string;
436
+ deliveryAddress?: string;
437
+ shippingAddress?: DeliveryAddress;
438
+ cancellationReason?: string;
439
+ hasBespoke?: boolean;
440
+ bespokeStage?: BespokeStageKey;
441
+ bespokeBrief?: string;
442
+ deliveryStatus?: string;
443
+ carrierName?: string;
444
+ terminalShipmentId?: string;
445
+ guestToken?: string;
446
+ guestEmail?: string;
447
+ guestPhone?: string;
448
+ guestName?: string;
449
+ }
450
+ interface CheckoutCustomer {
451
+ first_name: string;
452
+ last_name: string;
453
+ email: string;
454
+ phone: string;
455
+ }
456
+ interface ShippingLocation {
457
+ street: string;
458
+ city: string;
459
+ state: string;
460
+ lga: string;
461
+ country: string;
462
+ postal: string;
463
+ }
464
+ interface FindOrderParams {
465
+ email: string;
466
+ order_id: string;
467
+ }
468
+ interface CreateOrderParams {
469
+ customer_id?: string | null;
470
+ status?: string;
471
+ shipping_address?: DeliveryAddress;
472
+ checkout_session_id?: string;
473
+ items: Array<{
474
+ product_id: string;
475
+ product_name: string;
476
+ quantity: number;
477
+ unit_price: number;
478
+ variant_id?: string;
479
+ variant_details?: Record<string, unknown>;
480
+ custom_measurements?: Record<string, unknown>;
481
+ }>;
482
+ delivery_method?: string;
483
+ delivery_address?: string;
484
+ total?: number;
485
+ payment_method?: string;
486
+ shipping_rate_id?: string;
487
+ guest_token?: string;
488
+ guest_email?: string;
489
+ guest_phone?: string;
490
+ guest_name?: string;
491
+ product_type?: string;
492
+ bespoke_brief?: string;
493
+ bespoke_reference_images?: string[];
494
+ bespoke_measurements?: Record<string, string>;
495
+ bespoke_preferred_timeline?: string;
496
+ bespoke_special_instructions?: string;
497
+ }
498
+
499
+ /**
500
+ * @file types/payments/index.ts
501
+ * @description All customer-facing payment types for the Luxe Payment System.
502
+ *
503
+ * Auth model:
504
+ * - X-Storefront-Key → identifies the business storefront
505
+ * - X-Business-ID → tenant context
506
+ * No business-owner JWT used here — these are CUSTOMER-facing types.
507
+ *
508
+ * Payment flow:
509
+ * Customer → Business Owner : Monnify (NGN) | Flutterwave (non-NGN)
510
+ * Business Owner → Luxe : Subscription (separate, JWT-auth)
511
+ * Luxe → Business Owner : Payout (separate, JWT-auth)
512
+ */
513
+ interface Currency {
514
+ code: string;
515
+ name: string;
516
+ symbol: string;
517
+ decimals: number;
518
+ is_active: boolean;
519
+ }
520
+ interface SupportedCurrenciesResponse {
521
+ currencies: Currency[];
522
+ }
523
+ interface BackendLanguage {
524
+ code: string;
525
+ label: string;
526
+ flag: string;
527
+ }
528
+ interface SupportedLang {
529
+ code: string;
530
+ appCode: string;
531
+ label: string;
532
+ native: string;
533
+ flag: string;
534
+ }
535
+ interface SupportedLanguagesResponse {
536
+ languages: BackendLanguage[];
537
+ }
538
+ interface DVACreateRequest {
539
+ order_id?: string;
540
+ amount: number;
541
+ customer_email: string;
542
+ customer_name?: string;
543
+ /** Defaults to NGN — DVA is Monnify-only */
544
+ currency?: string;
545
+ /** Idempotency key to prevent duplicate DVA creation */
546
+ idempotency_key?: string;
547
+ }
548
+ interface PaymentInitiateRequest {
549
+ amount: number;
550
+ currency: string;
551
+ customer_email: string;
552
+ customer_name?: string;
553
+ order_id?: string;
554
+ quote_id?: string;
555
+ /** Window origin of the storefront — used as gateway redirect base URL */
556
+ storefront_origin?: string;
557
+ metadata?: Record<string, string | number | boolean>;
558
+ /** Idempotency key to prevent duplicate payment initiation */
559
+ idempotency_key?: string;
560
+ }
561
+ interface ConversionQuote {
562
+ id: string;
563
+ business_id: string;
564
+ from_currency: string;
565
+ to_currency: string;
566
+ rate: number;
567
+ original_amount: number;
568
+ converted_amount: number;
569
+ is_used: boolean;
570
+ expires_at: string;
571
+ created_at: string;
572
+ }
573
+ interface DVADetails {
574
+ account_number: string;
575
+ bank_name: string;
576
+ account_name: string;
577
+ reference: string;
578
+ amount: number;
579
+ transaction_id: string;
580
+ expires_at: string;
581
+ }
582
+ interface PaymentInitiateResponse {
583
+ id: string;
584
+ gateway_ref: string;
585
+ gateway: string;
586
+ status: string;
587
+ /** Normalised top-level checkout URL for gateway redirect */
588
+ checkout_url: string;
589
+ }
590
+ interface TransactionVerifyResponse {
591
+ id: string;
592
+ status: string;
593
+ amount: number;
594
+ currency: string;
595
+ gateway_ref: string;
596
+ gateway?: string;
597
+ order_id?: string;
598
+ escrow_status?: string;
599
+ escrow_release_date?: string;
600
+ metadata_json?: Record<string, unknown>;
601
+ }
602
+
603
+ /**
604
+ * Consultation types for customer-facing storefront
605
+ */
606
+ type ConsultationStatus = "pending" | "quoted" | "negotiating" | "deposit_pending" | "deposit_paid" | "converting" | "converted" | "rejected";
607
+ type ConsultationProductType = "bespoke" | "service";
608
+ interface ConsultationMessage {
609
+ id: string;
610
+ consultation_id: string;
611
+ sender_id: string;
612
+ sender_role: "customer" | "merchant" | "system";
613
+ message: string;
614
+ attachments: string[];
615
+ is_read: boolean;
616
+ created_at: string;
617
+ }
618
+ interface Consultation {
619
+ id: string;
620
+ business_id: string;
621
+ customer_id: string;
622
+ product_id: string | null;
623
+ title: string;
624
+ status: ConsultationStatus;
625
+ product_type: ConsultationProductType;
626
+ quote_amount: number | null;
627
+ agreed_price: number | null;
628
+ deposit_amount: number | null;
629
+ deposit_required: boolean;
630
+ is_physical_delivery: boolean;
631
+ expected_delivery_type: string | null;
632
+ structured_details: Record<string, unknown>;
633
+ rejection_reason: string | null;
634
+ converted_order_id: string | null;
635
+ slot_booking_id: string | null;
636
+ capacity_config_id: string | null;
637
+ created_at: string;
638
+ updated_at: string;
639
+ messages: ConsultationMessage[];
640
+ }
641
+ interface ConsultationCreatePayload {
642
+ product_id?: string;
643
+ title: string;
644
+ description: string;
645
+ reference_images?: string[];
646
+ custom_measurements?: Record<string, string | number>;
647
+ preferred_timeline?: string;
648
+ special_instructions?: string;
649
+ product_type?: ConsultationProductType;
650
+ }
651
+ interface ConsultationMessagePayload {
652
+ message: string;
653
+ attachments?: string[];
654
+ }
655
+ interface ConsultationQuoteAcceptPayload {
656
+ agreed_price: number;
657
+ }
658
+ interface BespokeAvailability {
659
+ available_slots: number;
660
+ next_available_date: string | null;
661
+ period_end: string;
662
+ blocked_dates: string[];
663
+ production_days: number;
664
+ is_available: boolean;
665
+ }
666
+
667
+ /**
668
+ * Service booking types for customer-facing storefront
669
+ */
670
+ type ServiceLocationType = "remote" | "physical" | "both";
671
+ type ServiceType = "appointment" | "project" | "recurring";
672
+ type AppointmentStatus = "pending" | "confirmed" | "in_progress" | "completed" | "voided" | "no_show";
673
+ interface AvailableSlot {
674
+ date: string;
675
+ start_time: string;
676
+ end_time: string;
677
+ slots_remaining: number;
678
+ }
679
+ interface ServiceAppointment {
680
+ id: string;
681
+ product_id: string;
682
+ customer_id: string;
683
+ order_id: string | null;
684
+ status: AppointmentStatus;
685
+ appointment_date: string;
686
+ start_time: string;
687
+ end_time: string;
688
+ location_type: ServiceLocationType;
689
+ customer_address: Record<string, unknown> | null;
690
+ meeting_link: string | null;
691
+ customer_notes: string | null;
692
+ price: number;
693
+ created_at: string;
694
+ updated_at: string;
695
+ completed_at: string | null;
696
+ voided_at: string | null;
697
+ cancellation_reason: string | null;
698
+ }
699
+ interface ServiceAppointmentCreatePayload {
700
+ product_id: string;
701
+ scheduled_date: string;
702
+ scheduled_time: string;
703
+ location_type?: ServiceLocationType;
704
+ customer_address?: Record<string, unknown>;
705
+ customer_notes?: string;
706
+ }
707
+ interface DeliverableStatus {
708
+ pending: "pending";
709
+ in_progress: "in_progress";
710
+ review: "review";
711
+ approved: "approved";
712
+ rejected: "rejected";
713
+ }
714
+ type DeliverableStatusType = DeliverableStatus[keyof DeliverableStatus];
715
+ interface ServiceDeliverable {
716
+ id: string;
717
+ order_id: string;
718
+ title: string;
719
+ description: string;
720
+ status: DeliverableStatusType;
721
+ due_date: string | null;
722
+ submitted_at: string | null;
723
+ attachments: string[];
724
+ customer_feedback: string | null;
725
+ created_at: string;
726
+ updated_at: string;
727
+ }
728
+ interface DeliverableApprovalPayload {
729
+ approved: boolean;
730
+ feedback?: string;
731
+ }
732
+
733
+ /**
734
+ * Bespoke slot booking types for customer-facing storefront
735
+ */
736
+ type SlotBookingStatus = "reserved" | "confirmed" | "completed" | "voided";
737
+ interface BespokeSlotBooking {
738
+ id: string;
739
+ product_id: string;
740
+ capacity_config_id: string | null;
741
+ consultation_id: string | null;
742
+ order_id: string | null;
743
+ customer_id: string;
744
+ status: SlotBookingStatus;
745
+ preferred_start_date: string | null;
746
+ preferred_end_date: string | null;
747
+ estimated_completion_date: string | null;
748
+ notes: string | null;
749
+ created_at: string;
750
+ updated_at: string;
751
+ }
752
+ interface BespokeCapacityConfig {
753
+ id: string;
754
+ business_id: string;
755
+ product_id: string;
756
+ slot_period: "weekly" | "monthly" | "yearly";
757
+ total_slots: number;
758
+ slots_used: number;
759
+ period_start_date: string;
760
+ period_end_date: string;
761
+ production_days_per_order: number;
762
+ buffer_days_between_orders: number;
763
+ blocked_dates: string[];
764
+ auto_reset: boolean;
765
+ is_active: boolean;
766
+ created_at: string;
767
+ updated_at: string;
768
+ }
769
+
770
+ /**
771
+ * CMS Types
772
+ *
773
+ * Types for kasuvia-cms integration - dynamic content models and entries
774
+ */
775
+ interface CmsField {
776
+ name: string;
777
+ label: string;
778
+ type: string;
779
+ required: boolean;
780
+ config: Record<string, any>;
781
+ sub_fields?: CmsField[];
782
+ }
783
+ interface CmsModelPermissions {
784
+ read: boolean;
785
+ create: boolean;
786
+ update: boolean;
787
+ delete: boolean;
788
+ }
789
+ interface CmsModelPublicApiPermissions {
790
+ public_api: CmsModelPermissions;
791
+ }
792
+ interface CmsModel {
793
+ id: string;
794
+ business_id: string;
795
+ model_slug: string;
796
+ display_name: string;
797
+ description: string | null;
798
+ fields: CmsField[];
799
+ permissions: CmsModelPublicApiPermissions;
800
+ }
801
+ interface CmsEntry {
802
+ id: string;
803
+ business_id: string;
804
+ model_slug: string;
805
+ data: Record<string, any>;
806
+ created_at: string;
807
+ updated_at: string;
808
+ created_by: string | null;
809
+ }
810
+ interface CmsEntryListResponse {
811
+ entries: CmsEntry[];
812
+ total: number;
813
+ page: number;
814
+ page_size: number;
815
+ }
816
+ interface CmsIcon {
817
+ id: string;
818
+ name: string;
819
+ category: string;
820
+ tags: string[];
821
+ }
822
+ interface CmsIconListResponse {
823
+ icons: CmsIcon[];
824
+ total: number;
825
+ }
826
+ interface ListCmsEntriesParams {
827
+ page?: number;
828
+ page_size?: number;
829
+ }
830
+ interface CreateCmsEntryParams {
831
+ data: Record<string, any>;
832
+ }
833
+ interface UpdateCmsEntryParams {
834
+ data: Record<string, any>;
835
+ }
836
+
837
+ /**
838
+ * Media types for the storefront
839
+ */
840
+ interface MediaAsset {
841
+ id: string;
842
+ url: string;
843
+ filename: string;
844
+ content_type: string;
845
+ size: number;
846
+ business_id: string;
847
+ affiliation: string;
848
+ created_at: string;
849
+ alt?: string;
850
+ description?: string;
851
+ }
852
+ interface MediaUploadParams {
853
+ business_id?: string;
854
+ owner_id?: string;
855
+ uploaded_by_name?: string;
856
+ affiliation?: string;
857
+ context: string;
858
+ entity_id: string;
859
+ alt?: string;
860
+ description?: string;
861
+ idempotency_key?: string;
862
+ }
863
+ interface MediaAssetUpdatePayload {
864
+ alt?: string;
865
+ description?: string;
866
+ affiliation?: string;
867
+ }
868
+ interface StorageStats {
869
+ total_bytes: number;
870
+ used_bytes: number;
871
+ available_bytes: number;
872
+ asset_count: number;
873
+ }
874
+
875
+ interface BusinessConfig {
876
+ business_id: string;
877
+ store_name: string;
878
+ store_currency: string;
879
+ is_active: boolean;
880
+ }
881
+
882
+ type Theme = "light" | "dark";
883
+ type LangCode = "en" | "ha" | "yo" | "ig" | "fr";
884
+ interface AppState {
885
+ theme: Theme;
886
+ lang: LangCode;
887
+ currency: string;
888
+ }
889
+ interface AppContextValue extends AppState {
890
+ setTheme: (t: Theme) => void;
891
+ setLang: (l: LangCode) => void;
892
+ setCurrency: (c: string) => void;
893
+ formatPrice: (amount: number, fromCurrency?: string) => string;
894
+ resetAppState: () => void;
895
+ t: (text: string) => string;
896
+ translate: (text: string) => Promise<string>;
897
+ }
898
+ interface Country {
899
+ name: string;
900
+ code: string;
901
+ dial_code: string;
902
+ min_age: number;
903
+ }
904
+ interface State {
905
+ name: string;
906
+ code: string;
907
+ full_iso_code: string;
908
+ type: string;
909
+ }
910
+
911
+ /**
912
+ * Fetch guest cart from backend (Redis-backed).
913
+ */
914
+ declare function getGuestCart(): Promise<CartItem[]>;
915
+ /**
916
+ * Add item to guest cart (Redis-backed).
917
+ */
918
+ declare function addToGuestCart(item: CartItem): Promise<CartItem[]>;
919
+ /**
920
+ * Update quantity of a guest cart item.
921
+ */
922
+ declare function updateGuestCartItemQuantity(itemId: string, quantity: number): Promise<CartItem[]>;
923
+ /**
924
+ * Remove an item from the guest cart.
925
+ */
926
+ declare function removeFromGuestCart(itemId: string): Promise<CartItem[]>;
927
+ /**
928
+ * Clear the entire guest cart.
929
+ */
930
+ declare function clearGuestCart(): Promise<void>;
931
+ /**
932
+ * Fetch authenticated user's cart from backend.
933
+ */
934
+ declare function getCart(): Promise<CartResponse>;
935
+ /**
936
+ * Add item to authenticated user's cart.
937
+ */
938
+ declare function addToCart(item: {
939
+ product_id: string;
940
+ product_slug: string;
941
+ product_name: string;
942
+ image?: string;
943
+ variant_id?: string;
944
+ variant_attributes?: string;
945
+ unit_price: number;
946
+ quantity: number;
947
+ custom_measurements?: string;
948
+ is_bespoke: boolean;
949
+ }): Promise<CartResponse>;
950
+ /**
951
+ * Update item quantity in authenticated user's cart.
952
+ */
953
+ declare function updateCartItem(itemId: string, quantity: number): Promise<CartResponse>;
954
+ /**
955
+ * Remove item from authenticated user's cart.
956
+ */
957
+ declare function removeFromCart(itemId: string): Promise<CartResponse>;
958
+ /**
959
+ * Clear authenticated user's cart.
960
+ */
961
+ declare function clearCart(): Promise<void>;
962
+ /**
963
+ * Merge guest cart (from Redis) into authenticated user's DB cart.
964
+ */
965
+ declare function mergeGuestCart(): Promise<CartResponse>;
966
+ /**
967
+ * Convenience wrapper: merge guest cart if it has items (called post-login).
968
+ */
969
+ declare function mergeGuestCartIfPresent(): Promise<void>;
970
+ /**
971
+ * Returns 0 — count is now server-driven. Use the hook instead.
972
+ * Kept for backward compatibility.
973
+ */
974
+ declare function getGuestCartCount(): number;
975
+ /**
976
+ * Returns 0 — subtotal is now server-driven.
977
+ * Kept for backward compatibility.
978
+ */
979
+ declare function getGuestCartSubtotal(): number;
980
+ /**
981
+ * Derive product type from items (guest cart, no backend lookup needed).
982
+ */
983
+ declare function getGuestCartProductType(): "physical" | "digital" | "bespoke";
984
+
985
+ declare function createOrder(payload: CreateOrderParams): Promise<Order>;
986
+ declare function findOrder(params: FindOrderParams): Promise<Order>;
987
+ declare function findOrderByToken(token: string): Promise<Order>;
988
+ declare function getOrders(params?: {
989
+ email?: string;
990
+ page?: number;
991
+ page_size?: number;
992
+ }): Promise<Order[]>;
993
+ declare function cancelOrder(orderId: string, reason: string): Promise<Order>;
994
+ declare function trackOrder(orderId: string, token?: string): Promise<Order>;
995
+
996
+ /**
997
+ * POST /auth/login/customer/
998
+ * The `tenant_id` is automatically filled from config.api.storefrontBusinessId.
999
+ */
1000
+ declare function loginCustomer(payload: Omit<CustomerLoginPayload, 'tenant_id'>): Promise<CustomerAuthResponse>;
1001
+ /**
1002
+ * POST /auth/register/customer/
1003
+ * The `tenant_id` is automatically filled from config.api.storefrontBusinessId.
1004
+ */
1005
+ declare function registerCustomer(payload: Omit<CustomerRegisterPayload, 'tenant_id'>): Promise<CustomerAuthResponse>;
1006
+ /** POST /auth/logout/ — revokes the server-side session. Always clears local tokens. */
1007
+ declare function logout(): Promise<void>;
1008
+ /**
1009
+ * Verify a social provider id_token (or access_token for Facebook) with the backend.
1010
+ * The backend validates the token with the provider and creates/finds the customer.
1011
+ *
1012
+ * Industry-standard "ID Token Exchange" pattern:
1013
+ * 1. Customer completes Google/Facebook sign-in on the storefront
1014
+ * 2. Storefront receives an id_token / access_token from the provider
1015
+ * 3. This function sends it to the backend for server-side verification
1016
+ * 4. Backend returns our JWT tokens
1017
+ */
1018
+ declare function verifySocialToken(provider: 'google' | 'facebook', token: string): Promise<CustomerAuthResponse>;
1019
+ /** Map luxe-auth UserSerializer response to storefront CustomerUser. */
1020
+ declare function mapAuthUserToCustomer(data: AuthUserResponse, provider?: CustomerUser['provider']): CustomerUser;
1021
+ /** GET /auth/profile/ */
1022
+ declare function getMe(): Promise<CustomerUser>;
1023
+ /** GET /auth/profile/ - alias for getMe for backward compatibility */
1024
+ declare function getAuthUser(): Promise<AuthUserResponse>;
1025
+ /** PUT /auth/profile/ — update firstname, lastname, phone */
1026
+ declare function updateProfile(payload: UpdateProfilePayload): Promise<CustomerUser>;
1027
+ /**
1028
+ * Silently refresh the access token on app boot.
1029
+ * Builds CustomerUser from JWT claims — no additional profile API call needed.
1030
+ * Returns null if no refresh token exists or if the refresh fails.
1031
+ * Includes a concurrent lock to prevent React Strict Mode from double-firing and blacklisting the token.
1032
+ *
1033
+ * Network error resilience:
1034
+ * - Classifies errors as network vs auth
1035
+ * - Retries transient network errors with exponential backoff
1036
+ * - Immediately fails on auth errors (401/403) to avoid infinite loops
1037
+ * - Clears auth state on any failure to ensure consistent logout behavior
1038
+ */
1039
+ declare function silentRefresh(): Promise<{
1040
+ user: CustomerUser;
1041
+ provider: CustomerUser['provider'];
1042
+ } | null>;
1043
+ /** Store tokens after OAuth callback or login/register response. */
1044
+ declare function storeTokens(access: string, refresh: string, remember?: boolean): void;
1045
+
1046
+ /**
1047
+ * Fetch all active products for the storefront.
1048
+ */
1049
+ declare function getStorefrontProducts(params?: ListParams): Promise<PaginatedResponse<Product>>;
1050
+ /**
1051
+ * Fetch a single product by slug for the storefront.
1052
+ */
1053
+ declare function getStorefrontProductBySlug(slug: string): Promise<Product>;
1054
+ /**
1055
+ * Fetch latest products for the storefront.
1056
+ */
1057
+ declare function getLatestProducts(params?: ListParams): Promise<PaginatedResponse<Product>>;
1058
+ /**
1059
+ * Fetch popular products for the storefront.
1060
+ */
1061
+ declare function getPopularProducts(params?: ListParams): Promise<PaginatedResponse<Product>>;
1062
+ /**
1063
+ * Fetch featured products for the storefront.
1064
+ */
1065
+ declare function getFeaturedProducts(params?: ListParams): Promise<PaginatedResponse<Product>>;
1066
+ /**
1067
+ * Fetch new products for the storefront.
1068
+ */
1069
+ declare function getNewProducts(params?: ListParams): Promise<PaginatedResponse<Product>>;
1070
+ /**
1071
+ * Fetch recommended products for the storefront.
1072
+ * Returns featured, popular, and new products.
1073
+ * Optionally excludes a specific product ID.
1074
+ */
1075
+ declare function getRecommendedProducts(params?: ListParams & {
1076
+ excludeProductId?: string;
1077
+ }): Promise<PaginatedResponse<Product>>;
1078
+
1079
+ /**
1080
+ * Fetch paginated active collections for the storefront.
1081
+ */
1082
+ declare function getStorefrontCollections(params?: ListParams): Promise<PaginatedResponse<Collection>>;
1083
+ /**
1084
+ * Fetch a single collection by its slug.
1085
+ */
1086
+ declare function getStorefrontCollectionBySlug(slug: string): Promise<Collection>;
1087
+
1088
+ /**
1089
+ * Fetch the customer's wishlist for the current business.
1090
+ */
1091
+ declare function getWishlist(params?: {
1092
+ page?: number;
1093
+ pageSize?: number;
1094
+ }): Promise<WishlistListResponse>;
1095
+ /**
1096
+ * Check if a product is in the customer's wishlist.
1097
+ */
1098
+ declare function checkInWishlist(productId: string): Promise<WishlistCheckResponse>;
1099
+ /**
1100
+ * Add a product to the customer's wishlist.
1101
+ */
1102
+ declare function addToWishlist(productId: string, notes?: string): Promise<WishlistItem>;
1103
+ /**
1104
+ * Remove an item from the customer's wishlist by item ID.
1105
+ */
1106
+ declare function removeFromWishlist(itemId: string): Promise<void>;
1107
+ /**
1108
+ * Remove a product from the customer's wishlist by product ID.
1109
+ */
1110
+ declare function removeProductFromWishlist(productId: string): Promise<void>;
1111
+
1112
+ /**
1113
+ * Create a Monnify Dedicated Virtual Account so the customer can pay via
1114
+ * bank transfer. Note: Monnify DVA only supports NGN currency - the backend
1115
+ * will reject non-NGN requests for this payment method.
1116
+ */
1117
+ declare function createDedicatedAccount(request: DVACreateRequest): Promise<DVADetails>;
1118
+ /**
1119
+ * Initiate a card payment (customer → business owner).
1120
+ * Routes to Monnify (NGN) or Flutterwave (non-NGN) on the backend.
1121
+ * Returns a checkout_url to redirect the customer to the gateway.
1122
+ */
1123
+ declare function initiatePayment(request: PaymentInitiateRequest): Promise<PaymentInitiateResponse>;
1124
+ /**
1125
+ * Request a 15-minute rate-locked conversion quote for non-NGN transactions.
1126
+ */
1127
+ declare function requestQuote(amount: number): Promise<ConversionQuote>;
1128
+ /**
1129
+ * Verify a payment after the gateway redirects back to /checkout/verify.
1130
+ */
1131
+ declare function verifyTransaction(reference: string): Promise<TransactionVerifyResponse>;
1132
+ /**
1133
+ * Poll transaction status by internal transaction ID.
1134
+ */
1135
+ declare function getTransactionStatus(transactionId: string): Promise<TransactionVerifyResponse>;
1136
+ declare const paymentService: {
1137
+ readonly createDedicatedAccount: typeof createDedicatedAccount;
1138
+ readonly initiatePayment: typeof initiatePayment;
1139
+ readonly requestQuote: typeof requestQuote;
1140
+ readonly verifyTransaction: typeof verifyTransaction;
1141
+ readonly getTransactionStatus: typeof getTransactionStatus;
1142
+ };
1143
+
1144
+ declare function createConsultation(payload: ConsultationCreatePayload): Promise<Consultation>;
1145
+ declare function getConsultations(): Promise<Consultation[]>;
1146
+ declare function getConsultation(id: string): Promise<Consultation>;
1147
+ declare function sendMessage(id: string, payload: ConsultationMessagePayload): Promise<void>;
1148
+ declare function acceptQuote(id: string, payload: ConsultationQuoteAcceptPayload): Promise<Consultation>;
1149
+ declare function rejectQuote(id: string, reason?: string): Promise<Consultation>;
1150
+ declare const consultationService: {
1151
+ createConsultation: typeof createConsultation;
1152
+ getConsultations: typeof getConsultations;
1153
+ getConsultation: typeof getConsultation;
1154
+ sendMessage: typeof sendMessage;
1155
+ acceptQuote: typeof acceptQuote;
1156
+ rejectQuote: typeof rejectQuote;
1157
+ };
1158
+
1159
+ interface CartItemPayload {
1160
+ product: {
1161
+ name: string;
1162
+ price: number;
1163
+ weight: number;
1164
+ };
1165
+ variant: ProductVariant | null;
1166
+ quantity: number;
1167
+ }
1168
+ interface RateAddress {
1169
+ city: string;
1170
+ state: string;
1171
+ country: string;
1172
+ }
1173
+ interface ShippingRatesRequest {
1174
+ cart_items: CartItemPayload[];
1175
+ origin_address: RateAddress;
1176
+ destination_address: RateAddress;
1177
+ currency?: string;
1178
+ }
1179
+ /**
1180
+ * Fetch shipping rates for a cart.
1181
+ */
1182
+ declare function getShippingRates(payload: ShippingRatesRequest): Promise<ShippingRatesResponse>;
1183
+ /**
1184
+ * Fetch the seller's registered shipping address.
1185
+ */
1186
+ declare function getSellerShippingAddress(): Promise<{
1187
+ terminal_address_id: string | null;
1188
+ address_details: {
1189
+ city: string;
1190
+ state: string;
1191
+ country: string;
1192
+ line1: string;
1193
+ line2: string;
1194
+ zip: string;
1195
+ } | null;
1196
+ business_id: string;
1197
+ message: string;
1198
+ }>;
1199
+ /**
1200
+ * Validate a shipping address.
1201
+ */
1202
+ declare function validateShippingAddress(payload: {
1203
+ first_name: string;
1204
+ last_name: string;
1205
+ phone: string;
1206
+ address_line1: string;
1207
+ address_line2?: string;
1208
+ city: string;
1209
+ state: string;
1210
+ country: string;
1211
+ postal_code?: string;
1212
+ }): Promise<{
1213
+ valid: boolean;
1214
+ message?: string;
1215
+ data?: Array<{
1216
+ name: string;
1217
+ city_id: string;
1218
+ stateCode: string;
1219
+ countryCode: string;
1220
+ }>;
1221
+ }>;
1222
+ declare const logisticsService: {
1223
+ getShippingRates: typeof getShippingRates;
1224
+ getSellerShippingAddress: typeof getSellerShippingAddress;
1225
+ validateShippingAddress: typeof validateShippingAddress;
1226
+ };
1227
+
1228
+ declare function checkAvailability(product_id: string): Promise<BespokeAvailability>;
1229
+ declare const bespokeService: {
1230
+ checkAvailability: typeof checkAvailability;
1231
+ };
1232
+
1233
+ declare function getAvailableSlots(product_id: string, date_from: string, date_to: string): Promise<AvailableSlot[]>;
1234
+ declare function bookAppointment(payload: ServiceAppointmentCreatePayload): Promise<ServiceAppointment>;
1235
+ declare function getAppointments(): Promise<ServiceAppointment[]>;
1236
+ declare function getAppointment(id: string): Promise<ServiceAppointment>;
1237
+ declare function cancelAppointment(id: string): Promise<void>;
1238
+ declare function getDeliverables(order_id: string): Promise<ServiceDeliverable[]>;
1239
+ declare function approveDeliverable(order_id: string, deliverable_id: string): Promise<ServiceDeliverable>;
1240
+ declare function requestRevision(order_id: string, deliverable_id: string, feedback: string): Promise<ServiceDeliverable>;
1241
+ declare const serviceBookingService: {
1242
+ getAvailableSlots: typeof getAvailableSlots;
1243
+ bookAppointment: typeof bookAppointment;
1244
+ getAppointments: typeof getAppointments;
1245
+ getAppointment: typeof getAppointment;
1246
+ cancelAppointment: typeof cancelAppointment;
1247
+ getDeliverables: typeof getDeliverables;
1248
+ approveDeliverable: typeof approveDeliverable;
1249
+ requestRevision: typeof requestRevision;
1250
+ };
1251
+
1252
+ interface ContactFormData {
1253
+ name: string;
1254
+ email: string;
1255
+ subject: string;
1256
+ message: string;
1257
+ source?: string;
1258
+ company_name?: string;
1259
+ current_year?: number;
1260
+ turnstile_token?: string;
1261
+ }
1262
+ /**
1263
+ * Send contact email to Luxe team.
1264
+ * POST /contact/send-contact-email
1265
+ */
1266
+ declare function sendContactEmail(payload: ContactFormData): Promise<{
1267
+ detail: string;
1268
+ }>;
1269
+ /**
1270
+ * Send confirmation email to user.
1271
+ * POST /contact/send-contact-confirmation
1272
+ */
1273
+ declare function sendContactConfirmation(payload: Omit<ContactFormData, 'turnstile_token'>): Promise<{
1274
+ detail: string;
1275
+ }>;
1276
+ declare const notificationsService: {
1277
+ readonly sendContactEmail: typeof sendContactEmail;
1278
+ readonly sendContactConfirmation: typeof sendContactConfirmation;
1279
+ };
1280
+
1281
+ /**
1282
+ * App Service
1283
+ *
1284
+ * Handles translation and other app-level utilities.
1285
+ */
1286
+ declare function googleTranslate(text: string, target: string, source?: string): Promise<string>;
1287
+
1288
+ /**
1289
+ * Fetch supported languages from the payment system.
1290
+ * Resolves to: {luxePaymentBackendUrl}/config/supported-languages
1291
+ */
1292
+ declare function getSupportedLanguages(): Promise<SupportedLanguagesResponse>;
1293
+ /**
1294
+ * Fetch supported currencies from the payment system.
1295
+ * Resolves to: {luxePaymentBackendUrl}/config/supported-currencies
1296
+ */
1297
+ declare function getSupportedCurrencies(): Promise<SupportedCurrenciesResponse>;
1298
+ /**
1299
+ * Fetch the business's public configuration, including store_currency.
1300
+ * Uses publicStoreAxios (X-Storefront-Key + X-Business-ID — no user JWT required).
1301
+ * Resolves to: {luxeStoreBackendUrl}/business/profile
1302
+ */
1303
+ declare function getBusinessConfig(): Promise<BusinessConfig>;
1304
+ declare const configService: {
1305
+ readonly getSupportedLanguages: typeof getSupportedLanguages;
1306
+ readonly getSupportedCurrencies: typeof getSupportedCurrencies;
1307
+ readonly getBusinessConfig: typeof getBusinessConfig;
1308
+ };
1309
+
1310
+ /**
1311
+ * List CMS entries for a specific model.
1312
+ * Requires public_api.read permission on the model.
1313
+ */
1314
+ declare function listCmsEntries(modelSlug: string, params?: ListCmsEntriesParams): Promise<CmsEntryListResponse>;
1315
+ /**
1316
+ * Get a single CMS entry by ID.
1317
+ * Requires public_api.read permission on the model.
1318
+ */
1319
+ declare function getCmsEntry(modelSlug: string, entryId: string): Promise<CmsEntry>;
1320
+ /**
1321
+ * Create a new CMS entry.
1322
+ * Requires public_api.create permission on the model.
1323
+ */
1324
+ declare function createCmsEntry(modelSlug: string, params: CreateCmsEntryParams): Promise<CmsEntry>;
1325
+ /**
1326
+ * Update an existing CMS entry.
1327
+ * Requires public_api.update permission on the model.
1328
+ */
1329
+ declare function updateCmsEntry(modelSlug: string, entryId: string, params: UpdateCmsEntryParams): Promise<CmsEntry>;
1330
+ /**
1331
+ * Delete a CMS entry.
1332
+ * Requires public_api.delete permission on the model.
1333
+ */
1334
+ declare function deleteCmsEntry(modelSlug: string, entryId: string): Promise<void>;
1335
+
1336
+ /**
1337
+ * Cart Hook & Context Provider
1338
+ *
1339
+ * React Query hooks for cart operations with unified drawer state sharing.
1340
+ */
1341
+
1342
+ interface UseCartReturn {
1343
+ cart: CartResponse | undefined;
1344
+ items: CartItem[];
1345
+ count: number;
1346
+ isOpen: boolean;
1347
+ setOpen: (open: boolean) => void;
1348
+ isLoading: boolean;
1349
+ error: Error | null;
1350
+ addToCart: (item: {
1351
+ product_id: string;
1352
+ product_slug: string;
1353
+ product_name: string;
1354
+ image?: string;
1355
+ variant_id?: string;
1356
+ variant_attributes?: string;
1357
+ unit_price: number;
1358
+ quantity: number;
1359
+ custom_measurements?: string;
1360
+ is_bespoke: boolean;
1361
+ }) => void;
1362
+ updateCartItem: (variables: {
1363
+ itemId: string;
1364
+ quantity: number;
1365
+ }) => void;
1366
+ removeFromCart: (itemId: string) => void;
1367
+ clearCart: () => void;
1368
+ clear: () => void;
1369
+ mergeGuestCart: () => void;
1370
+ addItem: (product: Product, variantId?: string, quantity?: number, customMeasurements?: Record<string, string>) => void;
1371
+ updateQty: (itemId: string, quantity: number) => void;
1372
+ removeItem: (itemId: string) => void;
1373
+ subtotal: number;
1374
+ productTypeMismatch: {
1375
+ message: string;
1376
+ existing_type: string;
1377
+ new_type: string;
1378
+ } | null;
1379
+ handleClearCartAndAdd: () => void;
1380
+ handleKeepCurrentCart: () => void;
1381
+ }
1382
+ interface CartContextValue {
1383
+ isOpen: boolean;
1384
+ setOpen: (open: boolean) => void;
1385
+ }
1386
+ declare const CartCtx: React.Context<CartContextValue | null> | null;
1387
+ declare function CartProvider({ children }: {
1388
+ children: ReactNode;
1389
+ }): string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.FunctionComponentElement<React.ProviderProps<CartContextValue | null>> | null | undefined;
1390
+ declare function useCart(): UseCartReturn;
1391
+
1392
+ declare function useOrders(params?: {
1393
+ email?: string;
1394
+ page?: number;
1395
+ page_size?: number;
1396
+ }): _tanstack_react_query.UseQueryResult<NoInfer<Order[]>, Error>;
1397
+ declare function useOrdersList(params?: {
1398
+ email?: string;
1399
+ page?: number;
1400
+ page_size?: number;
1401
+ }): _tanstack_react_query.UseQueryResult<NoInfer<Order[]>, Error>;
1402
+ declare function useFindOrder(params: FindOrderParams): _tanstack_react_query.UseQueryResult<NoInfer<Order>, Error>;
1403
+ declare function useOrder(params: FindOrderParams): _tanstack_react_query.UseQueryResult<NoInfer<Order>, Error>;
1404
+ declare function useOrderTracking(orderId: string, token?: string): _tanstack_react_query.UseQueryResult<NoInfer<Order>, Error>;
1405
+ declare function useCreateOrder(): _tanstack_react_query.UseMutationResult<Order, Error, CreateOrderParams, unknown>;
1406
+ declare function useCancelOrder(): _tanstack_react_query.UseMutationResult<Order, Error, {
1407
+ orderId: string;
1408
+ reason: string;
1409
+ }, unknown>;
1410
+
1411
+ declare const AuthCtx: React.Context<AuthContextValue | null> | null;
1412
+ declare function AuthProvider({ children }: {
1413
+ children: ReactNode;
1414
+ }): string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.FunctionComponentElement<React.ProviderProps<AuthContextValue | null>> | null | undefined;
1415
+ declare function useAuthUser(): _tanstack_react_query.UseQueryResult<NoInfer<AuthUserResponse>, Error>;
1416
+ declare function useLogin(): _tanstack_react_query.UseMutationResult<CustomerAuthResponse, Error, Omit<CustomerLoginPayload, "tenant_id">, unknown>;
1417
+ declare function useRegister(): _tanstack_react_query.UseMutationResult<CustomerAuthResponse, Error, Omit<CustomerRegisterPayload, "tenant_id">, unknown>;
1418
+ declare function useUpdateProfile(): _tanstack_react_query.UseMutationResult<CustomerUser, Error, UpdateProfilePayload, unknown>;
1419
+ declare function useLogout(): _tanstack_react_query.UseMutationResult<void, Error, void, unknown>;
1420
+ /**
1421
+ * useAuth()
1422
+ * Consumes the AuthCtx provider value. Falls back to local hook query if no provider exists.
1423
+ */
1424
+ declare function useAuth(): AuthContextValue;
1425
+
1426
+ declare function getCountries(): Promise<Country[]>;
1427
+ declare function useCountries(): _tanstack_react_query.UseQueryResult<NoInfer<Country[]>, Error>;
1428
+
1429
+ declare function getStates(countryIso: string): Promise<State[]>;
1430
+ declare function useStates(countryIso: string): _tanstack_react_query.UseQueryResult<NoInfer<State[]>, Error>;
1431
+
1432
+ declare function getSupportedLanguagesList(): Promise<SupportedLang[]>;
1433
+ declare function useSupportedLanguages(): _tanstack_react_query.UseQueryResult<NoInfer<SupportedLang[]>, Error>;
1434
+
1435
+ declare function getSupportedCurrenciesList(): Promise<Currency[]>;
1436
+ declare function useCurrencies(): _tanstack_react_query.UseQueryResult<NoInfer<Currency[]>, Error>;
1437
+
1438
+ /**
1439
+ * Get bespoke availability for a product
1440
+ */
1441
+ declare function useBespokeAvailability(product_id: string): _tanstack_react_query.UseQueryResult<NoInfer<BespokeAvailability>, Error>;
1442
+
1443
+ declare const collectionKeys: {
1444
+ all: readonly ["core", "collections"];
1445
+ list: (params?: ListParams) => readonly ["core", "collections", "list", ListParams];
1446
+ slug: (slug: string) => readonly ["core", "collections", "slug", string];
1447
+ };
1448
+ /**
1449
+ * Hook to fetch paginated collections for the storefront.
1450
+ */
1451
+ declare function useStorefrontCollections(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Collection>>, Error>;
1452
+ /**
1453
+ * Hook to fetch a single collection by slug for the storefront.
1454
+ */
1455
+ declare function useStorefrontCollection(slug: string): _tanstack_react_query.UseQueryResult<NoInfer<Collection>, Error>;
1456
+
1457
+ declare const productKeys: {
1458
+ all: readonly ["products"];
1459
+ list: (params?: ListParams) => readonly ["products", "list", ListParams | undefined];
1460
+ detail: (slug: string) => readonly ["products", "detail", string];
1461
+ recommended: (params?: ListParams) => readonly ["products", "recommended", ListParams | undefined];
1462
+ latest: (params?: ListParams) => readonly ["products", "latest", ListParams | undefined];
1463
+ popular: (params?: ListParams) => readonly ["products", "popular", ListParams | undefined];
1464
+ featured: (params?: ListParams) => readonly ["products", "featured", ListParams | undefined];
1465
+ new: (params?: ListParams) => readonly ["products", "new", ListParams | undefined];
1466
+ };
1467
+ /**
1468
+ * Hook for fetching latest products.
1469
+ */
1470
+ declare function useLatestProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1471
+ /**
1472
+ * Hook for fetching popular products.
1473
+ */
1474
+ declare function usePopularProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1475
+ /**
1476
+ * Hook for fetching featured products.
1477
+ */
1478
+ declare function useFeaturedProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1479
+ /**
1480
+ * Hook for fetching new products.
1481
+ */
1482
+ declare function useNewProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1483
+ /**
1484
+ * Hook for fetching all active storefront products.
1485
+ */
1486
+ declare function useStorefrontProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1487
+ /**
1488
+ * Hook for fetching a single product by slug.
1489
+ */
1490
+ declare function useProduct(slug: string): _tanstack_react_query.UseQueryResult<NoInfer<Product>, Error>;
1491
+ /**
1492
+ * Hook for fetching recommended products.
1493
+ */
1494
+ declare function useRecommendedProducts(params?: ListParams): _tanstack_react_query.UseQueryResult<NoInfer<PaginatedResponse<Product>>, Error>;
1495
+
1496
+ declare const wishlistKeys: {
1497
+ all: readonly ["wishlist"];
1498
+ list: () => readonly ["wishlist", "list"];
1499
+ check: (productId: string) => readonly ["wishlist", "check", string];
1500
+ };
1501
+ /**
1502
+ * Hook for fetching the customer's wishlist.
1503
+ * Authentication-gated only - returns empty for unauthenticated users.
1504
+ */
1505
+ declare function useWishlist(params?: {
1506
+ page?: number;
1507
+ pageSize?: number;
1508
+ }): _tanstack_react_query.UseQueryResult<NoInfer<WishlistListResponse>, Error>;
1509
+ /**
1510
+ * Hook for checking if a product is in the wishlist.
1511
+ * Authentication-gated only - returns false for unauthenticated users.
1512
+ */
1513
+ declare function useCheckInWishlist(productId: string): _tanstack_react_query.UseQueryResult<NoInfer<WishlistCheckResponse>, Error>;
1514
+ /**
1515
+ * Hook for adding a product to the wishlist.
1516
+ * Authentication-gated only - triggers login modal for unauthenticated users.
1517
+ */
1518
+ declare function useAddToWishlist(): _tanstack_react_query.UseMutationResult<WishlistItem, Error, {
1519
+ productId: string;
1520
+ notes?: string;
1521
+ }, unknown>;
1522
+ /**
1523
+ * Hook for removing an item from the wishlist by item ID.
1524
+ */
1525
+ declare function useRemoveFromWishlist(): _tanstack_react_query.UseMutationResult<void, Error, string, unknown>;
1526
+ /**
1527
+ * Hook for removing a product from the wishlist by product ID.
1528
+ */
1529
+ declare function useRemoveProductFromWishlist(): _tanstack_react_query.UseMutationResult<void, Error, string, unknown>;
1530
+ /**
1531
+ * Hook for getting wishlist count.
1532
+ * Authentication-gated only - returns 0 for unauthenticated users.
1533
+ */
1534
+ declare function useWishlistCount(): _tanstack_react_query.UseQueryResult<number, Error>;
1535
+
1536
+ /**
1537
+ * Get available slots for a service product
1538
+ */
1539
+ declare function useAvailableSlots(product_id: string, date_from: string, date_to: string): _tanstack_react_query.UseQueryResult<NoInfer<AvailableSlot[]>, Error>;
1540
+ /**
1541
+ * Book a service appointment
1542
+ */
1543
+ declare function useBookAppointment(): _tanstack_react_query.UseMutationResult<ServiceAppointment, Error, ServiceAppointmentCreatePayload, unknown>;
1544
+ /**
1545
+ * Get all appointments for the current user
1546
+ */
1547
+ declare function useAppointments(): _tanstack_react_query.UseQueryResult<NoInfer<ServiceAppointment[]>, Error>;
1548
+ /**
1549
+ * Get a single appointment by ID
1550
+ */
1551
+ declare function useAppointment(id: string): _tanstack_react_query.UseQueryResult<NoInfer<ServiceAppointment>, Error>;
1552
+ /**
1553
+ * Cancel an appointment
1554
+ */
1555
+ declare function useCancelAppointment(): _tanstack_react_query.UseMutationResult<void, Error, string, unknown>;
1556
+ /**
1557
+ * Get deliverables for a project-based service order
1558
+ */
1559
+ declare function useDeliverables(order_id: string): _tanstack_react_query.UseQueryResult<NoInfer<ServiceDeliverable[]>, Error>;
1560
+ /**
1561
+ * Approve a deliverable
1562
+ */
1563
+ declare function useApproveDeliverable(order_id: string, deliverable_id: string): _tanstack_react_query.UseMutationResult<ServiceDeliverable, Error, void, unknown>;
1564
+ /**
1565
+ * Request revision for a deliverable
1566
+ */
1567
+ declare function useRequestRevision(order_id: string, deliverable_id: string): _tanstack_react_query.UseMutationResult<ServiceDeliverable, Error, string, unknown>;
1568
+
1569
+ declare function useConsultations(): _tanstack_react_query.UseQueryResult<NoInfer<Consultation[]>, Error>;
1570
+ declare function useConsultation(id: string): _tanstack_react_query.UseQueryResult<NoInfer<Consultation>, Error>;
1571
+ declare function useCreateConsultation(): _tanstack_react_query.UseMutationResult<Consultation, Error, ConsultationCreatePayload, unknown>;
1572
+ declare function useSendMessage(consultationId: string): _tanstack_react_query.UseMutationResult<void, Error, ConsultationMessagePayload, unknown>;
1573
+ declare function useAcceptQuote(consultationId: string): _tanstack_react_query.UseMutationResult<Consultation, Error, ConsultationQuoteAcceptPayload, unknown>;
1574
+ declare function useRejectQuote(consultationId: string): _tanstack_react_query.UseMutationResult<Consultation, Error, string | undefined, unknown>;
1575
+
1576
+ interface ConsultationMessageData {
1577
+ event: string;
1578
+ data: {
1579
+ consultation_id: string;
1580
+ message_id: string;
1581
+ sender_id: string;
1582
+ sender_role: string;
1583
+ message: string;
1584
+ attachments?: Array<{
1585
+ url: string;
1586
+ type: string;
1587
+ name: string;
1588
+ }>;
1589
+ created_at: string;
1590
+ };
1591
+ }
1592
+ interface ConsultationQuoteData {
1593
+ event: string;
1594
+ data: {
1595
+ consultation_id: string;
1596
+ quote_amount: number;
1597
+ deposit_amount?: number;
1598
+ merchant_notes?: string;
1599
+ updated_at: string;
1600
+ };
1601
+ }
1602
+ interface ConsultationStatusData {
1603
+ event: string;
1604
+ data: {
1605
+ consultation_id: string;
1606
+ status: string;
1607
+ updated_at: string;
1608
+ };
1609
+ }
1610
+ interface UseConsultationStreamOptions {
1611
+ consultationId: string;
1612
+ onMessage?: (data: ConsultationMessageData) => void;
1613
+ onQuote?: (data: ConsultationQuoteData) => void;
1614
+ onStatusChange?: (data: ConsultationStatusData) => void;
1615
+ onError?: (error: Error) => void;
1616
+ }
1617
+ declare function useConsultationStream({ consultationId, onMessage, onQuote, onStatusChange, onError, }: UseConsultationStreamOptions): {
1618
+ isConnected: boolean;
1619
+ lastEvent: any;
1620
+ };
1621
+
1622
+ interface PaymentSuccessData {
1623
+ event: string;
1624
+ data: {
1625
+ transaction_id: string;
1626
+ order_id: string;
1627
+ amount: number;
1628
+ currency: string;
1629
+ status: string;
1630
+ };
1631
+ }
1632
+ interface DigitalReadyData {
1633
+ event: string;
1634
+ data: {
1635
+ order_id: string;
1636
+ business_id: string;
1637
+ customer_id: string;
1638
+ download_links: Array<{
1639
+ item_id: string;
1640
+ product_name: string;
1641
+ url: string;
1642
+ token: string;
1643
+ expires_at: string;
1644
+ max_downloads: number;
1645
+ }>;
1646
+ fulfilled_at: string;
1647
+ };
1648
+ }
1649
+ interface BespokeUpdateData {
1650
+ event: string;
1651
+ data: {
1652
+ order_id: string;
1653
+ business_id: string;
1654
+ update_type: string;
1655
+ message: string;
1656
+ stage?: string;
1657
+ updated_at: string;
1658
+ };
1659
+ }
1660
+ interface ConsultationUpdateData {
1661
+ event: string;
1662
+ data: {
1663
+ consultation_id: string;
1664
+ business_id: string;
1665
+ customer_id: string;
1666
+ status: string;
1667
+ message?: string;
1668
+ updated_at: string;
1669
+ };
1670
+ }
1671
+ interface ServiceBookingUpdateData {
1672
+ event: string;
1673
+ data: {
1674
+ booking_id: string;
1675
+ order_id: string;
1676
+ business_id: string;
1677
+ customer_id: string;
1678
+ status: string;
1679
+ appointment_date?: string;
1680
+ updated_at: string;
1681
+ };
1682
+ }
1683
+ interface UseOrderStreamOptions {
1684
+ orderId: string;
1685
+ onPaymentComplete?: (data: PaymentSuccessData) => void;
1686
+ onDigitalReady?: (data: DigitalReadyData) => void;
1687
+ onBespokeUpdate?: (data: BespokeUpdateData) => void;
1688
+ onConsultationUpdate?: (data: ConsultationUpdateData) => void;
1689
+ onServiceBookingUpdate?: (data: ServiceBookingUpdateData) => void;
1690
+ onError?: (error: Error) => void;
1691
+ }
1692
+ declare function useOrderStream({ orderId, onPaymentComplete, onDigitalReady, onBespokeUpdate, onConsultationUpdate, onServiceBookingUpdate, onError }: UseOrderStreamOptions): null;
1693
+
1694
+ declare function useIsMounted(): boolean;
1695
+
1696
+ interface GoogleTranslateOptions {
1697
+ pageLanguage: string;
1698
+ includedLanguages?: string;
1699
+ autoDisplay?: boolean;
1700
+ layout?: number;
1701
+ }
1702
+ interface GoogleTranslateElement {
1703
+ new (options: GoogleTranslateOptions, elementId: string): void;
1704
+ }
1705
+ interface GoogleNamespace {
1706
+ translate?: {
1707
+ TranslateElement: GoogleTranslateElement;
1708
+ };
1709
+ }
1710
+ declare global {
1711
+ interface Window {
1712
+ googleTranslateElementInit?: () => void;
1713
+ google?: GoogleNamespace;
1714
+ }
1715
+ }
1716
+ declare function useGoogleTranslate(appLang: string): {
1717
+ isLoaded: boolean;
1718
+ };
1719
+
1720
+ /**
1721
+ * Hook for creating a Dedicated Virtual Account (DVA)
1722
+ */
1723
+ declare function useCreateDVA(): _tanstack_react_query.UseMutationResult<DVADetails, Error, DVACreateRequest, unknown>;
1724
+ /**
1725
+ * Hook for initiating card payment
1726
+ */
1727
+ declare function useInitiatePayment(): _tanstack_react_query.UseMutationResult<PaymentInitiateResponse, Error, PaymentInitiateRequest, unknown>;
1728
+ /**
1729
+ * Hook for verifying a transaction
1730
+ */
1731
+ declare function useVerifyTransaction(): _tanstack_react_query.UseMutationResult<TransactionVerifyResponse, Error, string, unknown>;
1732
+ /**
1733
+ * Hook for getting transaction status
1734
+ */
1735
+ declare function useTransactionStatus(transactionId: string, enabled?: boolean): _tanstack_react_query.UseQueryResult<NoInfer<TransactionVerifyResponse>, Error>;
1736
+ /**
1737
+ * Hook for checking transaction status with automatic polling
1738
+ */
1739
+ declare function usePollTransactionStatus(reference: string, enabled?: boolean): _tanstack_react_query.UseQueryResult<NoInfer<TransactionVerifyResponse>, Error>;
1740
+
1741
+ interface UseCmsEntriesReturn {
1742
+ entries: CmsEntry[];
1743
+ total: number;
1744
+ page: number;
1745
+ page_size: number;
1746
+ isLoading: boolean;
1747
+ error: Error | null;
1748
+ refetch: () => void;
1749
+ }
1750
+ /**
1751
+ * Hook to list CMS entries for a specific model.
1752
+ */
1753
+ declare function useCmsEntries(modelSlug: string, params?: ListCmsEntriesParams): UseCmsEntriesReturn;
1754
+ interface UseCmsEntryReturn {
1755
+ entry: CmsEntry | undefined;
1756
+ isLoading: boolean;
1757
+ error: Error | null;
1758
+ refetch: () => void;
1759
+ }
1760
+ /**
1761
+ * Hook to get a single CMS entry by ID.
1762
+ */
1763
+ declare function useCmsEntry(modelSlug: string, entryId: string): UseCmsEntryReturn;
1764
+ interface UseCreateCmsEntryReturn {
1765
+ createEntry: (params: CreateCmsEntryParams) => void;
1766
+ isLoading: boolean;
1767
+ error: Error | null;
1768
+ }
1769
+ /**
1770
+ * Hook to create a new CMS entry.
1771
+ */
1772
+ declare function useCreateCmsEntry(modelSlug: string): UseCreateCmsEntryReturn;
1773
+ interface UseUpdateCmsEntryReturn {
1774
+ updateEntry: (entryId: string, params: UpdateCmsEntryParams) => void;
1775
+ isLoading: boolean;
1776
+ error: Error | null;
1777
+ }
1778
+ /**
1779
+ * Hook to update an existing CMS entry.
1780
+ */
1781
+ declare function useUpdateCmsEntry(modelSlug: string): UseUpdateCmsEntryReturn;
1782
+ interface UseDeleteCmsEntryReturn {
1783
+ deleteEntry: (entryId: string) => void;
1784
+ isLoading: boolean;
1785
+ error: Error | null;
1786
+ }
1787
+ /**
1788
+ * Hook to delete a CMS entry.
1789
+ */
1790
+ declare function useDeleteCmsEntry(modelSlug: string): UseDeleteCmsEntryReturn;
1791
+
1792
+ /**
1793
+ * Cache Tiers Utility
1794
+ *
1795
+ * Provides cache configuration for React Query based on environment.
1796
+ */
1797
+ declare const CACHE_TIERS: {
1798
+ readonly none: {
1799
+ readonly staleTime: 0;
1800
+ readonly gcTime: 0;
1801
+ };
1802
+ readonly infinity: {
1803
+ readonly staleTime: number;
1804
+ readonly gcTime: 0;
1805
+ };
1806
+ readonly low: {
1807
+ readonly staleTime: number;
1808
+ readonly gcTime: number;
1809
+ };
1810
+ readonly medium: {
1811
+ readonly staleTime: number;
1812
+ readonly gcTime: number;
1813
+ };
1814
+ readonly high: {
1815
+ readonly staleTime: number;
1816
+ readonly gcTime: number;
1817
+ };
1818
+ };
1819
+ type CacheTier = keyof typeof CACHE_TIERS;
1820
+ /**
1821
+ * Set the environment mode for cache configuration
1822
+ */
1823
+ declare function setEnvironmentMode(development: boolean): void;
1824
+ /**
1825
+ * Get cache configuration for a given tier
1826
+ * In development, returns 'none' tier to disable caching
1827
+ */
1828
+ declare const getCacheTier: (tier: CacheTier) => {
1829
+ readonly staleTime: number;
1830
+ readonly gcTime: number;
1831
+ };
1832
+
1833
+ /**
1834
+ * Logger Utility
1835
+ *
1836
+ * Environment-gated logger that suppresses output in production.
1837
+ */
1838
+ /**
1839
+ * Set the environment mode for logging
1840
+ */
1841
+ declare function setLoggerEnvironmentMode(development: boolean): void;
1842
+ declare const logger: {
1843
+ log: (...args: unknown[]) => void;
1844
+ warn: (...args: unknown[]) => void;
1845
+ /**
1846
+ * Logs a warning to the console in development only.
1847
+ * Alias for warn() for Python logging compatibility.
1848
+ * In production, this is a no-op.
1849
+ */
1850
+ warning: (...args: unknown[]) => void;
1851
+ error: (...args: unknown[]) => void;
1852
+ info: (...args: unknown[]) => void;
1853
+ createScope: (scope: string) => {
1854
+ log: (...args: unknown[]) => void;
1855
+ warn: (...args: unknown[]) => void;
1856
+ warning: (...args: unknown[]) => void;
1857
+ error: (...args: unknown[]) => void;
1858
+ info: (...args: unknown[]) => void;
1859
+ };
1860
+ };
1861
+
1862
+ declare class InvalidBaseURLError extends Error {
1863
+ constructor(message: string);
1864
+ }
1865
+ /**
1866
+ * Normalizes a URL by trimming whitespace and stripping trailing slashes.
1867
+ */
1868
+ declare function sanitizeBaseUrl(url: string | undefined | null, name?: string): string;
1869
+
1870
+ declare function buildFullName(firstname?: string, lastname?: string): string | undefined;
1871
+ declare function splitFullName(fullName?: string): {
1872
+ firstname: string;
1873
+ lastname: string;
1874
+ };
1875
+ declare function getCustomerDisplayName(user: CustomerUser): string;
1876
+
1877
+ declare function buildDeliveryAddress(customer: CheckoutCustomer, location: ShippingLocation): DeliveryAddress;
1878
+ declare function getCheckoutCustomerName(customer: CheckoutCustomer): string;
1879
+ declare function enrichCompletedOrder(order: Order, options: {
1880
+ customer: CheckoutCustomer;
1881
+ location?: ShippingLocation;
1882
+ bespokeBrief?: string;
1883
+ productType?: "physical" | "digital" | "bespoke" | null;
1884
+ }): Order;
1885
+
1886
+ /**
1887
+ * Type-safe way to extract an error message from an API error.
1888
+ */
1889
+ declare function getErrorMessage(error: unknown, fallback?: string): string;
1890
+
1891
+ export { type Address, type AppContextValue, type AppState, type AppointmentStatus, type AuthContextValue, AuthCtx, AuthProvider, type AuthUserResponse, type AvailableSlot, type AvatarObject, type BackendLanguage, type BespokeAvailability, type BespokeCapacityConfig, type BespokeSlotBooking, type BespokeStageKey, type BusinessConfig, type BusinessContext, type CartContextValue, CartCtx, type CartItem, type CartItemPayload, CartProvider, type CartResponse, type CheckoutCustomer, type CmsEntry, type CmsEntryListResponse, type CmsField, type CmsIcon, type CmsIconListResponse, type CmsModel, type CmsModelPermissions, type CmsModelPublicApiPermissions, type Collection, type Consultation, type ConsultationCreatePayload, type ConsultationMessage, type ConsultationMessagePayload, type ConsultationProductType, type ConsultationQuoteAcceptPayload, type ConsultationStatus, type ContactFormData, type ConversionQuote, type Country, type CreateCmsEntryParams, type CreateOrderParams, type Currency, type CustomField, type CustomerAuthResponse, type CustomerLoginPayload, type CustomerProfileFields, type CustomerRegisterPayload, type CustomerUser, type DVACreateRequest, type DVADetails, type DeliverableApprovalPayload, type DeliverableStatus, type DeliverableStatusType, type DeliveryAddress, type FindOrderParams, InvalidBaseURLError, type Inventory, type LangCode, type ListCmsEntriesParams, type ListParams, type LogoutPayload, type MediaAsset, type MediaAssetUpdatePayload, type MediaUploadParams, type OTPVerifyPayload, type Order, type OrderItem, type OrderStatus, type PaginatedResponse, type PaymentInitiateRequest, type PaymentInitiateResponse, type Product, type ProductType, type ProductVariant, type RateAddress, type RefreshTokenResponse, type ResendOTPPayload, type SdkConfig, type ServiceAppointment, type ServiceAppointmentCreatePayload, type ServiceDeliverable, type ServiceLocationType, type ServiceType, type ShippingLocation, type ShippingRatesRequest, type SlotBookingStatus, type State, type StorageStats, type SupportedCurrenciesResponse, type SupportedLang, type SupportedLanguagesResponse, type Theme, type TransactionVerifyResponse, type UpdateCmsEntryParams, type UpdateProfilePayload, type UseCartReturn, type UseCmsEntriesReturn, type UseCmsEntryReturn, type UseCreateCmsEntryReturn, type UseDeleteCmsEntryReturn, type UseUpdateCmsEntryReturn, type WishlistCheckResponse, type WishlistItem, type WishlistListResponse, acceptQuote, addToCart, addToGuestCart, addToWishlist, approveDeliverable, authAxios, bespokeService, bookAppointment, buildDeliveryAddress, buildFullName, cancelAppointment, cancelOrder, checkAvailability, checkInWishlist, clearCart, clearGuestCart, clearGuestSessionId, cmsAxios, collectionKeys, configService, configureHttpClients, consultationService, createCmsEntry, createConsultation, createDedicatedAccount, createOrder, deleteCmsEntry, enrichCompletedOrder, findOrder, findOrderByToken, getAppointment, getAppointments, getAuthUser, getAvailableSlots, getBackendUrl, getBusinessConfig, getCacheTier, getCart, getCheckoutCustomerName, getCmsEntry, getConsultation, getConsultations, getCountries, getCustomerDisplayName, getDeliverables, getErrorMessage, getFeaturedProducts, getGraphQLClient, getGuestCart, getGuestCartCount, getGuestCartProductType, getGuestCartSubtotal, getGuestSessionId, getLatestProducts, getMe, getNewProducts, getOrCreateGuestSessionId, getOrders, getPopularProducts, getRecommendedProducts, getRuntimeConfig, getSellerShippingAddress, getShippingRates, getStates, getStorefrontCollectionBySlug, getStorefrontCollections, getStorefrontProductBySlug, getStorefrontProducts, getSupportedCurrencies, getSupportedCurrenciesList, getSupportedLanguages, getSupportedLanguagesList, getTransactionStatus, getWishlist, googleTranslate, initSdk, initiatePayment, isInitialized, listCmsEntries, logger, loginCustomer, logisticsService, logout, mapAuthUserToCustomer, mergeGuestCart, mergeGuestCartIfPresent, notificationsService, paymentAxios, paymentService, productKeys, publicStoreAxios, refreshToken, registerCustomer, rejectQuote, removeFromCart, removeFromGuestCart, removeFromWishlist, removeProductFromWishlist, requestQuote, requestRevision, resetConfig, resetGraphQLClient, sanitizeBaseUrl, sendContactConfirmation, sendContactEmail, sendMessage, serviceBookingService, setEnvironmentMode, setLoggerEnvironmentMode, silentRefresh, splitFullName, storeManagementAxios, storeTokens, tokenStore, trackOrder, updateCartItem, updateCmsEntry, updateGuestCartItemQuantity, updateProfile, useAcceptQuote, useAddToWishlist, useAppointment, useAppointments, useApproveDeliverable, useAuth, useAuthUser, useAvailableSlots, useBespokeAvailability, useBookAppointment, useCancelAppointment, useCancelOrder, useCart, useCheckInWishlist, useCmsEntries, useCmsEntry, useConsultation, useConsultationStream, useConsultations, useCountries, useCreateCmsEntry, useCreateConsultation, useCreateDVA, useCreateOrder, useCurrencies, useDeleteCmsEntry, useDeliverables, useFeaturedProducts, useFindOrder, useGoogleTranslate, useInitiatePayment, useIsMounted, useLatestProducts, useLogin, useLogout, useNewProducts, useOrder, useOrderStream, useOrderTracking, useOrders, useOrdersList, usePollTransactionStatus, usePopularProducts, useProduct, useRecommendedProducts, useRegister, useRejectQuote, useRemoveFromWishlist, useRemoveProductFromWishlist, useRequestRevision, useSendMessage, useStates, useStorefrontCollection, useStorefrontCollections, useStorefrontProducts, useSupportedLanguages, useTransactionStatus, useUpdateCmsEntry, useUpdateProfile, useVerifyTransaction, useWishlist, useWishlistCount, validateShippingAddress, verifySocialToken, verifyTransaction, wishlistKeys };