@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.
- package/README.md +42 -15
- package/dist/AddressAutocomplete-CjcqPElD.d.mts +46 -0
- package/dist/AddressAutocomplete-CvJHuRkf.d.ts +46 -0
- package/dist/components/index.d.mts +497 -0
- package/dist/components/index.d.ts +497 -0
- package/dist/components/index.js +4217 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/index.mjs +4194 -0
- package/dist/components/index.mjs.map +1 -0
- package/dist/config/server.d.mts +26 -0
- package/dist/config/server.d.ts +26 -0
- package/dist/config/server.js +38 -0
- package/dist/config/server.js.map +1 -0
- package/dist/config/server.mjs +13 -0
- package/dist/config/server.mjs.map +1 -0
- package/dist/hooks/index.d.mts +393 -160
- package/dist/hooks/index.d.ts +393 -160
- package/dist/hooks/index.js +2792 -2137
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/index.mjs +2734 -2121
- package/dist/hooks/index.mjs.map +1 -1
- package/dist/index-CNW_LINy.d.mts +578 -0
- package/dist/index-CNW_LINy.d.ts +578 -0
- package/dist/{index-C1chUA3P.d.mts → index-F7N6UItS.d.mts} +1 -1
- package/dist/{index-C1chUA3P.d.ts → index-F7N6UItS.d.ts} +1 -1
- package/dist/index-NkI10J_E.d.mts +40 -0
- package/dist/index-NkI10J_E.d.ts +40 -0
- package/dist/index.d.mts +20437 -103
- package/dist/index.d.ts +20437 -103
- package/dist/index.js +2111 -1802
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2006 -1786
- package/dist/index.mjs.map +1 -1
- package/dist/media.service-Cx7dQjzX.d.mts +1393 -0
- package/dist/media.service-mrBFJ2UQ.d.ts +1393 -0
- package/dist/services/index.d.mts +908 -2
- package/dist/services/index.d.ts +908 -2
- package/dist/services/index.js +1492 -1686
- package/dist/services/index.js.map +1 -1
- package/dist/services/index.mjs +1431 -1670
- package/dist/services/index.mjs.map +1 -1
- package/package.json +46 -6
- package/src/components/bespoke/BespokeAvailabilityBadge.tsx +32 -0
- package/src/components/bespoke/BespokeProgressTracker.tsx +58 -0
- package/src/components/bespoke/index.ts +3 -0
- package/src/components/booking/SlotPicker.tsx +97 -0
- package/src/components/booking/index.ts +1 -0
- package/src/components/cart/CartItem.tsx +81 -0
- package/src/components/cart/CartSidebar.tsx +115 -0
- package/src/components/cart/CartTypeMismatchBanner.tsx +55 -0
- package/src/components/cart/index.ts +3 -0
- package/src/components/index.ts +8 -0
- package/src/components/orders/DeliverableReviewer.tsx +139 -0
- package/src/components/orders/index.ts +1 -0
- package/src/components/product/ProductCard.tsx +350 -0
- package/src/components/product/ProductGrid.tsx +84 -0
- package/src/components/product/index.ts +2 -0
- package/src/components/shared/AddressAutocomplete.tsx +212 -0
- package/src/components/shared/AnalyticsScripts.tsx +56 -0
- package/src/components/shared/CookieConsentBanner.tsx +98 -0
- package/src/components/shared/ImageEditorModal.tsx +1066 -0
- package/src/components/shared/ImageViewerModal.tsx +598 -0
- package/src/components/shared/LucideReactIcon.tsx +52 -0
- package/src/components/shared/MapPinDrop.tsx +101 -0
- package/src/components/shared/MultiSelectPicker.tsx +193 -0
- package/src/components/shared/OfflineBanner.tsx +46 -0
- package/src/components/shared/SearchableInput.tsx +153 -0
- package/src/components/shared/SearchablePopover.tsx +166 -0
- package/src/components/shared/SmartImage.tsx +311 -0
- package/src/components/shared/TruncatedValue.tsx +27 -0
- package/src/components/shared/UnsavedChangesGuard.tsx +138 -0
- package/src/components/shared/index.ts +15 -0
- package/src/components/skeletons/CardSkeleton.tsx +26 -0
- package/src/components/skeletons/CartItemSkeleton.tsx +26 -0
- package/src/components/skeletons/OrderItemSkeleton.tsx +26 -0
- package/src/components/skeletons/ProductCardSkeleton.tsx +26 -0
- package/src/components/skeletons/TableSkeleton.tsx +42 -0
- package/src/components/skeletons/index.ts +5 -0
- package/src/config/index.ts +22 -4
- package/src/config/server.ts +45 -0
- package/src/context/sdk-context.tsx +5 -2
- package/src/generated/auth-openapi.ts +2935 -0
- package/src/generated/cart-openapi.ts +652 -0
- package/src/generated/cms-openapi.ts +1668 -0
- package/src/generated/crm-openapi.ts +986 -0
- package/src/generated/graphql.ts +126 -0
- package/src/generated/index.ts +11 -0
- package/src/generated/media-openapi.ts +613 -0
- package/src/generated/notification-openapi.ts +862 -0
- package/src/generated/payment-openapi.ts +2713 -0
- package/src/generated/store-openapi.ts +9510 -0
- package/src/graphql/operations/collections.graphql +32 -0
- package/src/graphql/operations/products.graphql +197 -0
- package/src/graphql/operations/wishlist.graphql +25 -0
- package/src/hooks/index.ts +9 -2
- package/src/hooks/use-auth.ts +163 -69
- package/src/hooks/use-bespoke-availability.ts +39 -22
- package/src/hooks/use-business-config.ts +51 -0
- package/src/hooks/use-cart.ts +310 -238
- package/src/hooks/use-cms.ts +107 -127
- package/src/hooks/use-collections.ts +35 -55
- package/src/hooks/use-consultations.ts +9 -136
- package/src/hooks/use-countries.ts +19 -28
- package/src/hooks/use-currencies.ts +8 -20
- package/src/hooks/use-customer-address.ts +64 -0
- package/src/hooks/use-feedback.ts +34 -0
- package/src/hooks/use-languages.ts +26 -39
- package/src/hooks/use-media-upload.ts +23 -0
- package/src/hooks/use-notification-stream.ts +88 -0
- package/src/hooks/use-notifications.ts +163 -0
- package/src/hooks/use-order-stream.ts +29 -29
- package/src/hooks/use-orders.ts +91 -73
- package/src/hooks/use-payment.ts +116 -84
- package/src/hooks/use-products.ts +65 -269
- package/src/hooks/use-push-notifications.ts +122 -0
- package/src/hooks/use-reviews.ts +175 -0
- package/src/hooks/use-service-booking.ts +109 -132
- package/src/hooks/use-states.ts +16 -30
- package/src/hooks/use-wishlist.ts +44 -69
- package/src/index.ts +15 -11
- package/src/services/auth.service.ts +422 -132
- package/src/services/bespoke.service.ts +69 -10
- package/src/services/cart.service.ts +155 -186
- package/src/services/cms.service.ts +41 -50
- package/src/services/collection.service.ts +25 -63
- package/src/services/config.service.ts +10 -21
- package/src/services/consultation.service.ts +36 -93
- package/src/services/feedback.service.ts +76 -0
- package/src/services/index.ts +7 -1
- package/src/services/legal.service.ts +62 -0
- package/src/services/logistics.service.ts +235 -53
- package/src/services/media.service.ts +115 -0
- package/src/services/notifications.service.ts +204 -20
- package/src/services/order.service.ts +498 -127
- package/src/services/payment.service.ts +149 -100
- package/src/services/product.service.ts +157 -814
- package/src/services/review.service.ts +211 -0
- package/src/services/service-booking.service.ts +198 -99
- package/src/services/wishlist.service.ts +27 -74
- package/src/types/auth/index.ts +161 -18
- package/src/types/business/index.ts +9 -1
- package/src/types/cms/index.ts +91 -6
- package/src/types/cms/legal.ts +18 -0
- package/src/types/consultations/index.ts +60 -68
- package/src/types/index.ts +5 -3
- package/src/types/media/index.ts +35 -3
- package/src/types/payments/index.ts +80 -16
- package/src/types/reviews/index.ts +116 -0
- package/src/types/services/index.ts +113 -38
- package/src/types/store/checkout.ts +53 -0
- package/src/types/store/index.ts +273 -52
- package/src/types/store/invoice.ts +31 -0
- package/src/types/store/shipping.ts +84 -3
- package/src/types/ui/index.ts +1 -1
- package/src/utils/checkout.ts +19 -3
- package/src/utils/cookieConsent.ts +34 -0
- package/src/utils/format.ts +408 -0
- package/src/utils/geolocation.ts +134 -0
- package/src/utils/graphql-url.ts +47 -0
- package/src/utils/guest-session.ts +59 -0
- package/src/utils/http-client.ts +147 -0
- package/src/utils/index.ts +11 -4
- package/src/utils/status-colors.ts +79 -0
- package/src/utils/token-refresh.ts +115 -0
- package/src/utils/validators.ts +13 -0
- package/src/utils/youtube.ts +18 -0
- package/dist/index-C5YO9gTl.d.mts +0 -507
- package/dist/index-C5YO9gTl.d.ts +0 -507
- package/dist/index-CefG7_xq.d.mts +0 -793
- package/dist/index-DeHCf3zI.d.ts +0 -793
- package/src/graphql/collections.graphql.ts +0 -48
- package/src/graphql/index.ts +0 -7
- package/src/graphql/products.graphql.ts +0 -860
- package/src/graphql/wishlist.graphql.ts +0 -34
- package/src/hooks/use-consultation-stream.ts +0 -142
- package/src/types/bespoke/index.ts +0 -39
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Notification Service
|
|
3
|
-
*
|
|
4
|
-
* Handles contact form submissions
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
48
|
+
payload: ContactFormData
|
|
48
49
|
): Promise<{ detail: string }> {
|
|
49
|
-
|
|
50
|
+
return apiRequest<{ detail: string }>(`${config.backendUrls.notifications}/contact/send-contact-confirmation`, {
|
|
50
51
|
method: 'POST',
|
|
51
|
-
headers: {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|