@kasuvia/sdk 0.0.8 → 0.0.9

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 (176) hide show
  1. package/README.md +42 -15
  2. package/dist/AddressAutocomplete-CjcqPElD.d.mts +46 -0
  3. package/dist/AddressAutocomplete-CvJHuRkf.d.ts +46 -0
  4. package/dist/components/index.d.mts +497 -0
  5. package/dist/components/index.d.ts +497 -0
  6. package/dist/components/index.js +4217 -0
  7. package/dist/components/index.js.map +1 -0
  8. package/dist/components/index.mjs +4194 -0
  9. package/dist/components/index.mjs.map +1 -0
  10. package/dist/config/server.d.mts +26 -0
  11. package/dist/config/server.d.ts +26 -0
  12. package/dist/config/server.js +38 -0
  13. package/dist/config/server.js.map +1 -0
  14. package/dist/config/server.mjs +13 -0
  15. package/dist/config/server.mjs.map +1 -0
  16. package/dist/hooks/index.d.mts +393 -160
  17. package/dist/hooks/index.d.ts +393 -160
  18. package/dist/hooks/index.js +2792 -2137
  19. package/dist/hooks/index.js.map +1 -1
  20. package/dist/hooks/index.mjs +2734 -2121
  21. package/dist/hooks/index.mjs.map +1 -1
  22. package/dist/index-CNW_LINy.d.mts +578 -0
  23. package/dist/index-CNW_LINy.d.ts +578 -0
  24. package/dist/{index-C1chUA3P.d.mts → index-F7N6UItS.d.mts} +1 -1
  25. package/dist/{index-C1chUA3P.d.ts → index-F7N6UItS.d.ts} +1 -1
  26. package/dist/index-NkI10J_E.d.mts +40 -0
  27. package/dist/index-NkI10J_E.d.ts +40 -0
  28. package/dist/index.d.mts +20437 -103
  29. package/dist/index.d.ts +20437 -103
  30. package/dist/index.js +2111 -1802
  31. package/dist/index.js.map +1 -1
  32. package/dist/index.mjs +2006 -1786
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/media.service-Cx7dQjzX.d.mts +1393 -0
  35. package/dist/media.service-mrBFJ2UQ.d.ts +1393 -0
  36. package/dist/services/index.d.mts +908 -2
  37. package/dist/services/index.d.ts +908 -2
  38. package/dist/services/index.js +1492 -1686
  39. package/dist/services/index.js.map +1 -1
  40. package/dist/services/index.mjs +1431 -1670
  41. package/dist/services/index.mjs.map +1 -1
  42. package/package.json +46 -6
  43. package/src/components/bespoke/BespokeAvailabilityBadge.tsx +32 -0
  44. package/src/components/bespoke/BespokeProgressTracker.tsx +58 -0
  45. package/src/components/bespoke/index.ts +3 -0
  46. package/src/components/booking/SlotPicker.tsx +97 -0
  47. package/src/components/booking/index.ts +1 -0
  48. package/src/components/cart/CartItem.tsx +81 -0
  49. package/src/components/cart/CartSidebar.tsx +115 -0
  50. package/src/components/cart/CartTypeMismatchBanner.tsx +55 -0
  51. package/src/components/cart/index.ts +3 -0
  52. package/src/components/index.ts +8 -0
  53. package/src/components/orders/DeliverableReviewer.tsx +139 -0
  54. package/src/components/orders/index.ts +1 -0
  55. package/src/components/product/ProductCard.tsx +350 -0
  56. package/src/components/product/ProductGrid.tsx +84 -0
  57. package/src/components/product/index.ts +2 -0
  58. package/src/components/shared/AddressAutocomplete.tsx +212 -0
  59. package/src/components/shared/AnalyticsScripts.tsx +56 -0
  60. package/src/components/shared/CookieConsentBanner.tsx +98 -0
  61. package/src/components/shared/ImageEditorModal.tsx +1066 -0
  62. package/src/components/shared/ImageViewerModal.tsx +598 -0
  63. package/src/components/shared/LucideReactIcon.tsx +52 -0
  64. package/src/components/shared/MapPinDrop.tsx +101 -0
  65. package/src/components/shared/MultiSelectPicker.tsx +193 -0
  66. package/src/components/shared/OfflineBanner.tsx +46 -0
  67. package/src/components/shared/SearchableInput.tsx +153 -0
  68. package/src/components/shared/SearchablePopover.tsx +166 -0
  69. package/src/components/shared/SmartImage.tsx +311 -0
  70. package/src/components/shared/TruncatedValue.tsx +27 -0
  71. package/src/components/shared/UnsavedChangesGuard.tsx +138 -0
  72. package/src/components/shared/index.ts +15 -0
  73. package/src/components/skeletons/CardSkeleton.tsx +26 -0
  74. package/src/components/skeletons/CartItemSkeleton.tsx +26 -0
  75. package/src/components/skeletons/OrderItemSkeleton.tsx +26 -0
  76. package/src/components/skeletons/ProductCardSkeleton.tsx +26 -0
  77. package/src/components/skeletons/TableSkeleton.tsx +42 -0
  78. package/src/components/skeletons/index.ts +5 -0
  79. package/src/config/index.ts +22 -4
  80. package/src/config/server.ts +45 -0
  81. package/src/context/sdk-context.tsx +5 -2
  82. package/src/generated/auth-openapi.ts +2935 -0
  83. package/src/generated/cart-openapi.ts +652 -0
  84. package/src/generated/cms-openapi.ts +1668 -0
  85. package/src/generated/crm-openapi.ts +986 -0
  86. package/src/generated/graphql.ts +126 -0
  87. package/src/generated/index.ts +11 -0
  88. package/src/generated/media-openapi.ts +613 -0
  89. package/src/generated/notification-openapi.ts +862 -0
  90. package/src/generated/payment-openapi.ts +2713 -0
  91. package/src/generated/store-openapi.ts +9510 -0
  92. package/src/graphql/operations/collections.graphql +32 -0
  93. package/src/graphql/operations/products.graphql +197 -0
  94. package/src/graphql/operations/wishlist.graphql +25 -0
  95. package/src/hooks/index.ts +9 -2
  96. package/src/hooks/use-auth.ts +163 -69
  97. package/src/hooks/use-bespoke-availability.ts +39 -22
  98. package/src/hooks/use-business-config.ts +51 -0
  99. package/src/hooks/use-cart.ts +310 -238
  100. package/src/hooks/use-cms.ts +107 -127
  101. package/src/hooks/use-collections.ts +35 -55
  102. package/src/hooks/use-consultations.ts +9 -136
  103. package/src/hooks/use-countries.ts +19 -28
  104. package/src/hooks/use-currencies.ts +8 -20
  105. package/src/hooks/use-customer-address.ts +64 -0
  106. package/src/hooks/use-feedback.ts +34 -0
  107. package/src/hooks/use-languages.ts +26 -39
  108. package/src/hooks/use-media-upload.ts +23 -0
  109. package/src/hooks/use-notification-stream.ts +88 -0
  110. package/src/hooks/use-notifications.ts +163 -0
  111. package/src/hooks/use-order-stream.ts +29 -29
  112. package/src/hooks/use-orders.ts +91 -73
  113. package/src/hooks/use-payment.ts +116 -84
  114. package/src/hooks/use-products.ts +65 -269
  115. package/src/hooks/use-push-notifications.ts +122 -0
  116. package/src/hooks/use-reviews.ts +175 -0
  117. package/src/hooks/use-service-booking.ts +109 -132
  118. package/src/hooks/use-states.ts +16 -30
  119. package/src/hooks/use-wishlist.ts +44 -69
  120. package/src/index.ts +15 -11
  121. package/src/services/auth.service.ts +422 -132
  122. package/src/services/bespoke.service.ts +69 -10
  123. package/src/services/cart.service.ts +155 -186
  124. package/src/services/cms.service.ts +41 -50
  125. package/src/services/collection.service.ts +25 -63
  126. package/src/services/config.service.ts +10 -21
  127. package/src/services/consultation.service.ts +36 -93
  128. package/src/services/feedback.service.ts +76 -0
  129. package/src/services/index.ts +7 -1
  130. package/src/services/legal.service.ts +62 -0
  131. package/src/services/logistics.service.ts +235 -53
  132. package/src/services/media.service.ts +115 -0
  133. package/src/services/notifications.service.ts +204 -20
  134. package/src/services/order.service.ts +498 -127
  135. package/src/services/payment.service.ts +149 -100
  136. package/src/services/product.service.ts +157 -814
  137. package/src/services/review.service.ts +211 -0
  138. package/src/services/service-booking.service.ts +198 -99
  139. package/src/services/wishlist.service.ts +27 -74
  140. package/src/types/auth/index.ts +161 -18
  141. package/src/types/business/index.ts +9 -1
  142. package/src/types/cms/index.ts +91 -6
  143. package/src/types/cms/legal.ts +18 -0
  144. package/src/types/consultations/index.ts +60 -68
  145. package/src/types/index.ts +5 -3
  146. package/src/types/media/index.ts +35 -3
  147. package/src/types/payments/index.ts +80 -16
  148. package/src/types/reviews/index.ts +116 -0
  149. package/src/types/services/index.ts +113 -38
  150. package/src/types/store/checkout.ts +53 -0
  151. package/src/types/store/index.ts +273 -52
  152. package/src/types/store/invoice.ts +31 -0
  153. package/src/types/store/shipping.ts +84 -3
  154. package/src/types/ui/index.ts +1 -1
  155. package/src/utils/checkout.ts +19 -3
  156. package/src/utils/cookieConsent.ts +34 -0
  157. package/src/utils/format.ts +408 -0
  158. package/src/utils/geolocation.ts +134 -0
  159. package/src/utils/graphql-url.ts +47 -0
  160. package/src/utils/guest-session.ts +59 -0
  161. package/src/utils/http-client.ts +147 -0
  162. package/src/utils/index.ts +11 -4
  163. package/src/utils/status-colors.ts +79 -0
  164. package/src/utils/token-refresh.ts +115 -0
  165. package/src/utils/validators.ts +13 -0
  166. package/src/utils/youtube.ts +18 -0
  167. package/dist/index-C5YO9gTl.d.mts +0 -507
  168. package/dist/index-C5YO9gTl.d.ts +0 -507
  169. package/dist/index-CefG7_xq.d.mts +0 -793
  170. package/dist/index-DeHCf3zI.d.ts +0 -793
  171. package/src/graphql/collections.graphql.ts +0 -48
  172. package/src/graphql/index.ts +0 -7
  173. package/src/graphql/products.graphql.ts +0 -860
  174. package/src/graphql/wishlist.graphql.ts +0 -34
  175. package/src/hooks/use-consultation-stream.ts +0 -142
  176. package/src/types/bespoke/index.ts +0 -39
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * Notification Service
3
- *
4
- * Handles contact form submissions and email notifications.
3
+ *
4
+ * Handles contact form submissions, email notifications, and notification
5
+ * channel preferences (customer self-service + merchant-level policy).
5
6
  * Stateless - all configuration passed as parameters.
6
7
  */
7
8
  import type { SdkConfig } from '../config'
9
+ import type { NotificationPreferences } from '../types/auth'
10
+ import { apiRequest, storefrontHeaders, JSON_HEADERS } from '../utils/http-client'
8
11
 
9
12
  export interface ContactFormData {
10
13
  name: string
@@ -14,7 +17,10 @@ export interface ContactFormData {
14
17
  source?: string
15
18
  company_name?: string
16
19
  current_year?: number
17
- turnstile_token?: string
20
+ }
21
+
22
+ function bearerHeaders(accessToken: string): Record<string, string> {
23
+ return { Authorization: `Bearer ${accessToken}` }
18
24
  }
19
25
 
20
26
  /**
@@ -25,17 +31,12 @@ export async function sendContactEmail(
25
31
  config: SdkConfig,
26
32
  payload: ContactFormData
27
33
  ): Promise<{ detail: string }> {
28
- const response = await fetch(`${config.backendUrls.notifications}/contact/send-contact-email`, {
34
+ return apiRequest<{ detail: string }>(`${config.backendUrls.notifications}/contact/send-contact-email`, {
29
35
  method: 'POST',
30
- headers: {
31
- 'Content-Type': 'application/json',
32
- "X-Storefront-Key": config.storefrontApiKey,
33
- "X-Business-ID": config.businessId,
34
- },
36
+ headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
35
37
  body: JSON.stringify(payload),
38
+ fallbackErrorMessage: 'Failed to send contact email',
36
39
  })
37
- if (!response.ok) throw new Error('Failed to send contact email')
38
- return response.json()
39
40
  }
40
41
 
41
42
  /**
@@ -44,22 +45,205 @@ export async function sendContactEmail(
44
45
  */
45
46
  export async function sendContactConfirmation(
46
47
  config: SdkConfig,
47
- payload: Omit<ContactFormData, 'turnstile_token'>
48
+ payload: ContactFormData
48
49
  ): Promise<{ detail: string }> {
49
- const response = await fetch(`${config.backendUrls.notifications}/contact/send-contact-confirmation`, {
50
+ return apiRequest<{ detail: string }>(`${config.backendUrls.notifications}/contact/send-contact-confirmation`, {
50
51
  method: 'POST',
51
- headers: {
52
- 'Content-Type': 'application/json',
53
- "X-Storefront-Key": config.storefrontApiKey,
54
- "X-Business-ID": config.businessId,
55
- },
52
+ headers: { ...JSON_HEADERS, ...storefrontHeaders(config) },
53
+ body: JSON.stringify(payload),
54
+ fallbackErrorMessage: 'Failed to send contact confirmation',
55
+ })
56
+ }
57
+
58
+ /**
59
+ * Get the caller's own notification preferences (customer or business
60
+ * owner self-service — whoever's access token is passed).
61
+ * GET /notifications/preferences/
62
+ */
63
+ export async function getNotificationPreferences(
64
+ config: SdkConfig,
65
+ accessToken: string
66
+ ): Promise<NotificationPreferences> {
67
+ return apiRequest<NotificationPreferences>(`${config.backendUrls.notifications}/notifications/preferences/`, {
68
+ headers: bearerHeaders(accessToken),
69
+ fallbackErrorMessage: 'Failed to fetch notification preferences',
70
+ })
71
+ }
72
+
73
+ /**
74
+ * Update the caller's own notification preferences.
75
+ * PATCH /notifications/preferences/
76
+ */
77
+ export async function updateNotificationPreferences(
78
+ config: SdkConfig,
79
+ accessToken: string,
80
+ payload: Partial<NotificationPreferences>
81
+ ): Promise<NotificationPreferences> {
82
+ return apiRequest<NotificationPreferences>(`${config.backendUrls.notifications}/notifications/preferences/`, {
83
+ method: 'PATCH',
84
+ headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
56
85
  body: JSON.stringify(payload),
86
+ fallbackErrorMessage: 'Failed to update notification preferences',
87
+ })
88
+ }
89
+
90
+ // ── Push subscriptions ───────────────────────────────────────────────────
91
+ // REAL FEATURE WIRED (2026-09-21): kasuvia-notification-system-go's push.go
92
+ // (VAPID key, subscribe/unsubscribe, device list) already works correctly
93
+ // for both owner/staff and customer callers (role-branched server-side) but
94
+ // had zero SDK coverage. Auth here is JWT-bearer-only (AuthMiddleware —
95
+ // no X-Storefront-Key/X-Business-ID requirement), matching
96
+ // getNotificationPreferences above.
97
+
98
+ export interface VapidPublicKeyResponse {
99
+ public_key: string
100
+ subject: string
101
+ }
102
+
103
+ export interface PushSubscriptionKeys {
104
+ p256dh: string
105
+ auth: string
106
+ }
107
+
108
+ export interface SubscribeToPushParams {
109
+ subscription: {
110
+ endpoint: string
111
+ keys: PushSubscriptionKeys
112
+ }
113
+ user_agent: string
114
+ }
115
+
116
+ export async function getVapidPublicKey(config: SdkConfig): Promise<VapidPublicKeyResponse> {
117
+ return apiRequest<VapidPublicKeyResponse>(`${config.backendUrls.notifications}/push/vapid-public-key`, {
118
+ fallbackErrorMessage: 'Failed to fetch VAPID public key',
119
+ })
120
+ }
121
+
122
+ export async function subscribeToPush(
123
+ config: SdkConfig,
124
+ accessToken: string,
125
+ params: SubscribeToPushParams
126
+ ): Promise<{ status: string; subscription_id: string; vapid_key_version: number }> {
127
+ return apiRequest(`${config.backendUrls.notifications}/push/subscribe`, {
128
+ method: 'POST',
129
+ headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
130
+ body: JSON.stringify(params),
131
+ fallbackErrorMessage: 'Failed to subscribe to push notifications',
132
+ })
133
+ }
134
+
135
+ export async function unsubscribeFromPush(
136
+ config: SdkConfig,
137
+ accessToken: string,
138
+ endpoint: string
139
+ ): Promise<{ status: string }> {
140
+ return apiRequest(`${config.backendUrls.notifications}/push/subscribe`, {
141
+ method: 'DELETE',
142
+ headers: { ...JSON_HEADERS, ...bearerHeaders(accessToken) },
143
+ body: JSON.stringify({ endpoint }),
144
+ fallbackErrorMessage: 'Failed to unsubscribe from push notifications',
145
+ })
146
+ }
147
+
148
+ // ── Notification inbox ──────────────────────────────────────────────────
149
+ // REAL FEATURE WIRED (2026-09-21): kasuvia-notification-system-go's
150
+ // notification_inbox.go (list/mark-read/mark-all-read/click) — fixed
151
+ // alongside this to actually work for a customer caller (see that file's
152
+ // own doc comments: it used to always query/check by user_id, which a
153
+ // customer-facing notification never has set).
154
+
155
+ export type NotificationPriority = 'urgent' | 'normal' | 'low'
156
+
157
+ export interface NotificationInboxItem {
158
+ id: string
159
+ title: string
160
+ body: string
161
+ icon_url?: string | null
162
+ image_url?: string | null
163
+ priority: NotificationPriority
164
+ action_type?: string | null
165
+ action_url?: string | null
166
+ entity_id?: string | null
167
+ entity_type?: string | null
168
+ category: string
169
+ source_event_type: string
170
+ read: boolean
171
+ read_at?: string | null
172
+ clicked: boolean
173
+ clicked_at?: string | null
174
+ action_performed: boolean
175
+ created_at: string
176
+ expires_at?: string | null
177
+ }
178
+
179
+ export interface NotificationInboxResponse {
180
+ results: NotificationInboxItem[]
181
+ count: number
182
+ page: number
183
+ page_size: number
184
+ total_pages: number
185
+ }
186
+
187
+ export async function getNotificationInbox(
188
+ config: SdkConfig,
189
+ accessToken: string,
190
+ params?: { page?: number; limit?: number; unread_only?: boolean }
191
+ ): Promise<NotificationInboxResponse> {
192
+ const query = new URLSearchParams()
193
+ if (params?.page) query.set('page', String(params.page))
194
+ if (params?.limit) query.set('limit', String(params.limit))
195
+ if (params?.unread_only) query.set('unread_only', 'true')
196
+ return apiRequest<NotificationInboxResponse>(`${config.backendUrls.notifications}/notifications?${query.toString()}`, {
197
+ headers: bearerHeaders(accessToken),
198
+ fallbackErrorMessage: 'Failed to fetch notifications',
199
+ })
200
+ }
201
+
202
+ export async function markNotificationRead(
203
+ config: SdkConfig,
204
+ accessToken: string,
205
+ notificationId: string
206
+ ): Promise<{ status: string }> {
207
+ return apiRequest(`${config.backendUrls.notifications}/notifications/${notificationId}/read`, {
208
+ method: 'POST',
209
+ headers: bearerHeaders(accessToken),
210
+ fallbackErrorMessage: 'Failed to mark notification as read',
211
+ })
212
+ }
213
+
214
+ export async function markAllNotificationsRead(
215
+ config: SdkConfig,
216
+ accessToken: string
217
+ ): Promise<{ status: string }> {
218
+ return apiRequest(`${config.backendUrls.notifications}/notifications/mark-all-read`, {
219
+ method: 'POST',
220
+ headers: bearerHeaders(accessToken),
221
+ fallbackErrorMessage: 'Failed to mark all notifications as read',
222
+ })
223
+ }
224
+
225
+ export async function trackNotificationClick(
226
+ config: SdkConfig,
227
+ accessToken: string,
228
+ notificationId: string
229
+ ): Promise<{ status: string }> {
230
+ return apiRequest(`${config.backendUrls.notifications}/notifications/${notificationId}/click`, {
231
+ method: 'POST',
232
+ headers: bearerHeaders(accessToken),
233
+ fallbackErrorMessage: 'Failed to track notification click',
57
234
  })
58
- if (!response.ok) throw new Error('Failed to send contact confirmation')
59
- return response.json()
60
235
  }
61
236
 
62
237
  export const notificationsService = {
63
238
  sendContactEmail,
64
239
  sendContactConfirmation,
240
+ getNotificationPreferences,
241
+ updateNotificationPreferences,
242
+ getVapidPublicKey,
243
+ subscribeToPush,
244
+ unsubscribeFromPush,
245
+ getNotificationInbox,
246
+ markNotificationRead,
247
+ markAllNotificationsRead,
248
+ trackNotificationClick,
65
249
  } as const