@kasuvia/sdk 0.0.2 → 0.0.4
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/dist/hooks/index.d.mts +429 -0
- package/dist/hooks/index.d.ts +429 -0
- package/dist/hooks/index.js +3073 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +2962 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/index.d.mts +250 -1161
- package/dist/index.d.ts +250 -1161
- package/dist/index.js +1544 -2359
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1527 -2258
- package/dist/index.mjs.map +1 -1
- package/dist/sdk-context-Cy51kEKT.d.mts +565 -0
- package/dist/sdk-context-Cy51kEKT.d.ts +565 -0
- package/package.json +6 -2
- package/src/config/index.ts +10 -91
- package/src/constants.ts +13 -0
- package/src/context/sdk-context.tsx +70 -0
- package/src/graphql/collections.graphql.ts +2 -10
- package/src/graphql/products.graphql.ts +215 -65
- package/src/graphql/wishlist.graphql.ts +7 -6
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-auth.ts +82 -158
- package/src/hooks/use-bespoke-availability.ts +25 -8
- package/src/hooks/use-cart.ts +222 -119
- package/src/hooks/use-cms.ts +179 -86
- package/src/hooks/use-collections.ts +52 -15
- package/src/hooks/use-consultation-stream.ts +4 -3
- package/src/hooks/use-consultations.ts +120 -51
- package/src/hooks/use-countries.ts +35 -13
- package/src/hooks/use-currencies.ts +26 -13
- package/src/hooks/use-google-translate.ts +22 -8
- package/src/hooks/use-languages.ts +40 -20
- package/src/hooks/use-mobile.ts +23 -0
- package/src/hooks/use-order-stream.ts +9 -5
- package/src/hooks/use-orders.ts +99 -44
- package/src/hooks/use-payment.ts +108 -40
- package/src/hooks/use-products.ts +251 -53
- package/src/hooks/use-service-booking.ts +152 -90
- package/src/hooks/use-states.ts +35 -15
- package/src/hooks/use-wishlist.ts +92 -91
- package/src/index.ts +26 -30
- package/src/services/auth.service.ts +209 -167
- package/src/services/bespoke.service.ts +12 -4
- package/src/services/cart.service.ts +172 -70
- package/src/services/cms.service.ts +70 -35
- package/src/services/collection.service.ts +22 -5
- package/src/services/config.service.ts +34 -14
- package/src/services/consultation.service.ts +72 -18
- package/src/services/logistics.service.ts +35 -11
- package/src/services/notifications.service.ts +27 -12
- package/src/services/order.service.ts +74 -15
- package/src/services/payment.service.ts +86 -31
- package/src/services/product.service.ts +279 -39
- package/src/services/service-booking.service.ts +98 -26
- package/src/services/wishlist.service.ts +69 -25
- package/src/types/auth/index.ts +6 -4
- package/src/types/business/index.ts +7 -2
- package/src/types/payments/index.ts +3 -3
- package/src/types/services/index.ts +2 -5
- package/src/types/store/index.ts +38 -3
- package/src/utils/error-handler.ts +10 -5
- package/src/utils/storage.ts +48 -26
- package/src/utils/validators.ts +85 -0
- package/src/client/authClient.ts +0 -135
- package/src/client/graphqlClient.ts +0 -53
- package/src/client/httpClient.ts +0 -298
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
* Cart Service
|
|
3
3
|
*
|
|
4
4
|
* Handles cart operations for both guest and authenticated users.
|
|
5
|
+
* Stateless - all configuration passed as parameters.
|
|
5
6
|
*/
|
|
6
|
-
import {
|
|
7
|
+
import type { SdkConfig } from '../config'
|
|
7
8
|
import type { CartItem, CartResponse } from '../types/store'
|
|
8
9
|
|
|
9
|
-
const GUEST_SESSION_COOKIE = "luxe_guest_sid"
|
|
10
|
-
const GUEST_CART_TTL_DAYS = 7
|
|
11
|
-
|
|
12
10
|
function parseItems(items: CartItem[]): CartItem[] {
|
|
13
11
|
return items.map((item) => ({
|
|
14
12
|
...item,
|
|
@@ -22,14 +20,19 @@ function parseItems(items: CartItem[]): CartItem[] {
|
|
|
22
20
|
/**
|
|
23
21
|
* Fetch guest cart from backend (Redis-backed).
|
|
24
22
|
*/
|
|
25
|
-
export async function getGuestCart(): Promise<CartItem[]> {
|
|
26
|
-
|
|
27
|
-
if (!sid) return []
|
|
23
|
+
export async function getGuestCart(config: SdkConfig, guestSessionId: string): Promise<CartItem[]> {
|
|
24
|
+
if (!guestSessionId) return []
|
|
28
25
|
|
|
29
26
|
try {
|
|
30
|
-
const
|
|
31
|
-
headers: {
|
|
27
|
+
const response = await fetch(`${config.backendUrls.store}/cart/`, {
|
|
28
|
+
headers: {
|
|
29
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
30
|
+
"X-Business-ID": config.businessId,
|
|
31
|
+
"X-Guest-Session": guestSessionId
|
|
32
|
+
},
|
|
32
33
|
})
|
|
34
|
+
if (!response.ok) return []
|
|
35
|
+
const data = await response.json()
|
|
33
36
|
return parseItems(data.items || [])
|
|
34
37
|
} catch {
|
|
35
38
|
return []
|
|
@@ -39,9 +42,8 @@ export async function getGuestCart(): Promise<CartItem[]> {
|
|
|
39
42
|
/**
|
|
40
43
|
* Add item to guest cart (Redis-backed).
|
|
41
44
|
*/
|
|
42
|
-
export async function addToGuestCart(item: CartItem): Promise<CartItem[]> {
|
|
43
|
-
|
|
44
|
-
if (!sid) return []
|
|
45
|
+
export async function addToGuestCart(config: SdkConfig, guestSessionId: string, item: CartItem): Promise<CartItem[]> {
|
|
46
|
+
if (!guestSessionId) return []
|
|
45
47
|
|
|
46
48
|
const payload = {
|
|
47
49
|
product_id: item.product_id,
|
|
@@ -59,9 +61,18 @@ export async function addToGuestCart(item: CartItem): Promise<CartItem[]> {
|
|
|
59
61
|
is_bespoke: item.is_bespoke,
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
+
const response = await fetch(`${config.backendUrls.store}/cart/`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
headers: {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
69
|
+
"X-Business-ID": config.businessId,
|
|
70
|
+
"X-Guest-Session": guestSessionId
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify(payload),
|
|
64
73
|
})
|
|
74
|
+
if (!response.ok) return []
|
|
75
|
+
const data = await response.json()
|
|
65
76
|
return parseItems(data.items || [])
|
|
66
77
|
}
|
|
67
78
|
|
|
@@ -69,51 +80,82 @@ export async function addToGuestCart(item: CartItem): Promise<CartItem[]> {
|
|
|
69
80
|
* Update quantity of a guest cart item.
|
|
70
81
|
*/
|
|
71
82
|
export async function updateGuestCartItemQuantity(
|
|
83
|
+
config: SdkConfig,
|
|
84
|
+
guestSessionId: string,
|
|
72
85
|
itemId: string,
|
|
73
86
|
quantity: number
|
|
74
87
|
): Promise<CartItem[]> {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
if (!guestSessionId) return []
|
|
89
|
+
|
|
90
|
+
const response = await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
|
|
91
|
+
method: 'PATCH',
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/json',
|
|
94
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
95
|
+
"X-Business-ID": config.businessId,
|
|
96
|
+
"X-Guest-Session": guestSessionId
|
|
97
|
+
},
|
|
98
|
+
body: JSON.stringify({ quantity }),
|
|
99
|
+
})
|
|
100
|
+
if (!response.ok) return []
|
|
101
|
+
const data = await response.json()
|
|
83
102
|
return parseItems(data.items || [])
|
|
84
103
|
}
|
|
85
104
|
|
|
86
105
|
/**
|
|
87
106
|
* Remove an item from the guest cart.
|
|
88
107
|
*/
|
|
89
|
-
export async function removeFromGuestCart(
|
|
90
|
-
|
|
91
|
-
|
|
108
|
+
export async function removeFromGuestCart(
|
|
109
|
+
config: SdkConfig,
|
|
110
|
+
guestSessionId: string,
|
|
111
|
+
itemId: string
|
|
112
|
+
): Promise<CartItem[]> {
|
|
113
|
+
if (!guestSessionId) return []
|
|
92
114
|
|
|
93
|
-
await
|
|
94
|
-
|
|
115
|
+
await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
|
|
116
|
+
method: 'DELETE',
|
|
117
|
+
headers: {
|
|
118
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
119
|
+
"X-Business-ID": config.businessId,
|
|
120
|
+
"X-Guest-Session": guestSessionId
|
|
121
|
+
},
|
|
95
122
|
})
|
|
96
123
|
|
|
97
|
-
return getGuestCart()
|
|
124
|
+
return getGuestCart(config, guestSessionId)
|
|
98
125
|
}
|
|
99
126
|
|
|
100
127
|
/**
|
|
101
128
|
* Clear the entire guest cart.
|
|
102
129
|
*/
|
|
103
|
-
export async function clearGuestCart(): Promise<void> {
|
|
104
|
-
|
|
105
|
-
if (!sid) return
|
|
130
|
+
export async function clearGuestCart(config: SdkConfig, guestSessionId: string): Promise<void> {
|
|
131
|
+
if (!guestSessionId) return
|
|
106
132
|
|
|
107
|
-
await
|
|
108
|
-
|
|
133
|
+
await fetch(`${config.backendUrls.store}/cart/clear`, {
|
|
134
|
+
method: 'DELETE',
|
|
135
|
+
headers: {
|
|
136
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
137
|
+
"X-Business-ID": config.businessId,
|
|
138
|
+
"X-Guest-Session": guestSessionId
|
|
139
|
+
},
|
|
109
140
|
})
|
|
110
141
|
}
|
|
111
142
|
|
|
112
143
|
/**
|
|
113
144
|
* Fetch authenticated user's cart from backend.
|
|
114
145
|
*/
|
|
115
|
-
export async function getCart(): Promise<CartResponse> {
|
|
116
|
-
|
|
146
|
+
export async function getCart(config: SdkConfig, accessToken?: string | null): Promise<CartResponse> {
|
|
147
|
+
if (!accessToken) {
|
|
148
|
+
return { id: '', items: [], subtotal: 0, total: 0, product_type: 'physical' } as any;
|
|
149
|
+
}
|
|
150
|
+
const response = await fetch(`${config.backendUrls.store}/cart/`, {
|
|
151
|
+
headers: {
|
|
152
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
153
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
154
|
+
"X-Business-ID": config.businessId,
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
if (!response.ok) throw new Error('Failed to fetch cart')
|
|
158
|
+
const data = await response.json()
|
|
117
159
|
const parsedItems = parseItems(data.items || [])
|
|
118
160
|
return { ...data, items: parsedItems }
|
|
119
161
|
}
|
|
@@ -121,19 +163,34 @@ export async function getCart(): Promise<CartResponse> {
|
|
|
121
163
|
/**
|
|
122
164
|
* Add item to authenticated user's cart.
|
|
123
165
|
*/
|
|
124
|
-
export async function addToCart(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
166
|
+
export async function addToCart(
|
|
167
|
+
config: SdkConfig,
|
|
168
|
+
accessToken: string,
|
|
169
|
+
item: {
|
|
170
|
+
product_id: string
|
|
171
|
+
product_slug: string
|
|
172
|
+
product_name: string
|
|
173
|
+
image?: string
|
|
174
|
+
variant_id?: string
|
|
175
|
+
variant_attributes?: string
|
|
176
|
+
unit_price: number
|
|
177
|
+
quantity: number
|
|
178
|
+
custom_measurements?: string
|
|
179
|
+
is_bespoke: boolean
|
|
180
|
+
}
|
|
181
|
+
): Promise<CartResponse> {
|
|
182
|
+
const response = await fetch(`${config.backendUrls.store}/cart/`, {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
headers: {
|
|
185
|
+
'Content-Type': 'application/json',
|
|
186
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
187
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
188
|
+
"X-Business-ID": config.businessId,
|
|
189
|
+
},
|
|
190
|
+
body: JSON.stringify(item),
|
|
191
|
+
})
|
|
192
|
+
if (!response.ok) throw new Error('Failed to add to cart')
|
|
193
|
+
const data = await response.json()
|
|
137
194
|
const parsedItems = parseItems(data.items || [])
|
|
138
195
|
return { ...data, items: parsedItems }
|
|
139
196
|
}
|
|
@@ -142,13 +199,23 @@ export async function addToCart(item: {
|
|
|
142
199
|
* Update item quantity in authenticated user's cart.
|
|
143
200
|
*/
|
|
144
201
|
export async function updateCartItem(
|
|
202
|
+
config: SdkConfig,
|
|
203
|
+
accessToken: string,
|
|
145
204
|
itemId: string,
|
|
146
205
|
quantity: number
|
|
147
206
|
): Promise<CartResponse> {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
{
|
|
151
|
-
|
|
207
|
+
const response = await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
|
|
208
|
+
method: 'PATCH',
|
|
209
|
+
headers: {
|
|
210
|
+
'Content-Type': 'application/json',
|
|
211
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
212
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
213
|
+
"X-Business-ID": config.businessId,
|
|
214
|
+
},
|
|
215
|
+
body: JSON.stringify({ quantity }),
|
|
216
|
+
})
|
|
217
|
+
if (!response.ok) throw new Error('Failed to update cart item')
|
|
218
|
+
const data = await response.json()
|
|
152
219
|
const parsedItems = parseItems(data.items || [])
|
|
153
220
|
return { ...data, items: parsedItems }
|
|
154
221
|
}
|
|
@@ -156,27 +223,48 @@ export async function updateCartItem(
|
|
|
156
223
|
/**
|
|
157
224
|
* Remove item from authenticated user's cart.
|
|
158
225
|
*/
|
|
159
|
-
export async function removeFromCart(
|
|
160
|
-
|
|
161
|
-
|
|
226
|
+
export async function removeFromCart(
|
|
227
|
+
config: SdkConfig,
|
|
228
|
+
accessToken: string,
|
|
229
|
+
itemId: string
|
|
230
|
+
): Promise<CartResponse> {
|
|
231
|
+
await fetch(`${config.backendUrls.store}/cart/${itemId}`, {
|
|
232
|
+
method: 'DELETE',
|
|
233
|
+
headers: {
|
|
234
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
235
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
236
|
+
"X-Business-ID": config.businessId,
|
|
237
|
+
},
|
|
238
|
+
})
|
|
239
|
+
return getCart(config, accessToken)
|
|
162
240
|
}
|
|
163
241
|
|
|
164
242
|
/**
|
|
165
243
|
* Clear authenticated user's cart.
|
|
166
244
|
*/
|
|
167
|
-
export async function clearCart(): Promise<void> {
|
|
168
|
-
await
|
|
245
|
+
export async function clearCart(config: SdkConfig, accessToken: string): Promise<void> {
|
|
246
|
+
await fetch(`${config.backendUrls.store}/cart/clear`, {
|
|
247
|
+
method: 'DELETE',
|
|
248
|
+
headers: {
|
|
249
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
250
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
251
|
+
"X-Business-ID": config.businessId,
|
|
252
|
+
},
|
|
253
|
+
})
|
|
169
254
|
}
|
|
170
255
|
|
|
171
256
|
/**
|
|
172
257
|
* Merge guest cart (from Redis) into authenticated user's DB cart.
|
|
173
258
|
*/
|
|
174
|
-
export async function mergeGuestCart(
|
|
175
|
-
|
|
176
|
-
|
|
259
|
+
export async function mergeGuestCart(
|
|
260
|
+
config: SdkConfig,
|
|
261
|
+
accessToken: string,
|
|
262
|
+
guestSessionId: string
|
|
263
|
+
): Promise<CartResponse> {
|
|
264
|
+
const guestItems = guestSessionId ? await getGuestCart(config, guestSessionId) : []
|
|
177
265
|
|
|
178
266
|
if (guestItems.length === 0) {
|
|
179
|
-
return getCart()
|
|
267
|
+
return getCart(config, accessToken)
|
|
180
268
|
}
|
|
181
269
|
|
|
182
270
|
const payloadItems = guestItems.map((item) => ({
|
|
@@ -198,24 +286,38 @@ export async function mergeGuestCart(): Promise<CartResponse> {
|
|
|
198
286
|
is_bespoke: item.is_bespoke,
|
|
199
287
|
}))
|
|
200
288
|
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
289
|
+
const headers: Record<string, string> = {
|
|
290
|
+
'Content-Type': 'application/json',
|
|
291
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
292
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
293
|
+
"X-Business-ID": config.businessId,
|
|
294
|
+
}
|
|
295
|
+
if (guestSessionId) {
|
|
296
|
+
headers["X-Guest-Session"] = guestSessionId
|
|
297
|
+
}
|
|
206
298
|
|
|
207
|
-
|
|
299
|
+
const response = await fetch(`${config.backendUrls.store}/cart/merge`, {
|
|
300
|
+
method: 'POST',
|
|
301
|
+
headers,
|
|
302
|
+
body: JSON.stringify({ items: payloadItems }),
|
|
303
|
+
})
|
|
304
|
+
if (!response.ok) throw new Error('Failed to merge guest cart')
|
|
305
|
+
const data = await response.json()
|
|
208
306
|
return { ...data, items: parseItems(data.items || []) }
|
|
209
307
|
}
|
|
210
308
|
|
|
211
309
|
/**
|
|
212
310
|
* Convenience wrapper: merge guest cart if it has items (called post-login).
|
|
213
311
|
*/
|
|
214
|
-
export async function mergeGuestCartIfPresent(
|
|
312
|
+
export async function mergeGuestCartIfPresent(
|
|
313
|
+
config: SdkConfig,
|
|
314
|
+
accessToken: string,
|
|
315
|
+
guestSessionId: string
|
|
316
|
+
): Promise<void> {
|
|
215
317
|
try {
|
|
216
|
-
const guestItems = await getGuestCart()
|
|
318
|
+
const guestItems = await getGuestCart(config, guestSessionId)
|
|
217
319
|
if (guestItems.length === 0) return
|
|
218
|
-
await mergeGuestCart()
|
|
320
|
+
await mergeGuestCart(config, accessToken, guestSessionId)
|
|
219
321
|
} catch (error) {
|
|
220
322
|
console.warn("[Cart] Failed to merge guest cart:", error)
|
|
221
323
|
}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Handles CMS model and entry operations using the kasuvia-cms SDK endpoints.
|
|
5
5
|
* Protected by X-Storefront-Key and X-Business-ID headers.
|
|
6
|
+
* Stateless - all configuration passed as parameters.
|
|
6
7
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import { getRuntimeConfig } from '../config'
|
|
8
|
+
import type { SdkConfig } from '../config'
|
|
9
9
|
import type {
|
|
10
10
|
CmsEntry,
|
|
11
11
|
CmsEntryListResponse,
|
|
@@ -19,23 +19,26 @@ import type {
|
|
|
19
19
|
* Requires public_api.read permission on the model.
|
|
20
20
|
*/
|
|
21
21
|
export async function listCmsEntries(
|
|
22
|
+
config: SdkConfig,
|
|
22
23
|
modelSlug: string,
|
|
23
24
|
params?: ListCmsEntriesParams
|
|
24
25
|
): Promise<CmsEntryListResponse> {
|
|
25
|
-
const
|
|
26
|
-
|
|
26
|
+
const queryParams = new URLSearchParams()
|
|
27
|
+
queryParams.set('page', (params?.page || 1).toString())
|
|
28
|
+
queryParams.set('page_size', (params?.page_size || 50).toString())
|
|
27
29
|
|
|
28
|
-
const response = await
|
|
29
|
-
|
|
30
|
+
const response = await fetch(
|
|
31
|
+
`${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries?${queryParams.toString()}`,
|
|
30
32
|
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
headers: {
|
|
34
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
35
|
+
"X-Business-ID": config.businessId,
|
|
34
36
|
},
|
|
35
37
|
}
|
|
36
38
|
)
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
if (!response.ok) throw new Error('Failed to list CMS entries')
|
|
41
|
+
return response.json()
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/**
|
|
@@ -43,17 +46,22 @@ export async function listCmsEntries(
|
|
|
43
46
|
* Requires public_api.read permission on the model.
|
|
44
47
|
*/
|
|
45
48
|
export async function getCmsEntry(
|
|
49
|
+
config: SdkConfig,
|
|
46
50
|
modelSlug: string,
|
|
47
51
|
entryId: string
|
|
48
52
|
): Promise<CmsEntry> {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
const response = await fetch(
|
|
54
|
+
`${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
|
|
55
|
+
{
|
|
56
|
+
headers: {
|
|
57
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
58
|
+
"X-Business-ID": config.businessId,
|
|
59
|
+
},
|
|
60
|
+
}
|
|
54
61
|
)
|
|
55
62
|
|
|
56
|
-
|
|
63
|
+
if (!response.ok) throw new Error('Failed to get CMS entry')
|
|
64
|
+
return response.json()
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
/**
|
|
@@ -61,18 +69,27 @@ export async function getCmsEntry(
|
|
|
61
69
|
* Requires public_api.create permission on the model.
|
|
62
70
|
*/
|
|
63
71
|
export async function createCmsEntry(
|
|
72
|
+
config: SdkConfig,
|
|
73
|
+
accessToken: string,
|
|
64
74
|
modelSlug: string,
|
|
65
75
|
params: CreateCmsEntryParams
|
|
66
76
|
): Promise<CmsEntry> {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
77
|
+
const response = await fetch(
|
|
78
|
+
`${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries`,
|
|
79
|
+
{
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
84
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
85
|
+
"X-Business-ID": config.businessId,
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify(params),
|
|
88
|
+
}
|
|
73
89
|
)
|
|
74
90
|
|
|
75
|
-
|
|
91
|
+
if (!response.ok) throw new Error('Failed to create CMS entry')
|
|
92
|
+
return response.json()
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
/**
|
|
@@ -80,19 +97,28 @@ export async function createCmsEntry(
|
|
|
80
97
|
* Requires public_api.update permission on the model.
|
|
81
98
|
*/
|
|
82
99
|
export async function updateCmsEntry(
|
|
100
|
+
config: SdkConfig,
|
|
101
|
+
accessToken: string,
|
|
83
102
|
modelSlug: string,
|
|
84
103
|
entryId: string,
|
|
85
104
|
params: UpdateCmsEntryParams
|
|
86
105
|
): Promise<CmsEntry> {
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
106
|
+
const response = await fetch(
|
|
107
|
+
`${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
|
|
108
|
+
{
|
|
109
|
+
method: 'PUT',
|
|
110
|
+
headers: {
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
113
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
114
|
+
"X-Business-ID": config.businessId,
|
|
115
|
+
},
|
|
116
|
+
body: JSON.stringify(params),
|
|
117
|
+
}
|
|
93
118
|
)
|
|
94
119
|
|
|
95
|
-
|
|
120
|
+
if (!response.ok) throw new Error('Failed to update CMS entry')
|
|
121
|
+
return response.json()
|
|
96
122
|
}
|
|
97
123
|
|
|
98
124
|
/**
|
|
@@ -100,13 +126,22 @@ export async function updateCmsEntry(
|
|
|
100
126
|
* Requires public_api.delete permission on the model.
|
|
101
127
|
*/
|
|
102
128
|
export async function deleteCmsEntry(
|
|
129
|
+
config: SdkConfig,
|
|
130
|
+
accessToken: string,
|
|
103
131
|
modelSlug: string,
|
|
104
132
|
entryId: string
|
|
105
133
|
): Promise<void> {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
134
|
+
const response = await fetch(
|
|
135
|
+
`${config.backendUrls.cms}/sdk/${config.businessId}/${modelSlug}/entries/${entryId}`,
|
|
136
|
+
{
|
|
137
|
+
method: 'DELETE',
|
|
138
|
+
headers: {
|
|
139
|
+
"Authorization": `Bearer ${accessToken}`,
|
|
140
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
141
|
+
"X-Business-ID": config.businessId,
|
|
142
|
+
},
|
|
143
|
+
}
|
|
111
144
|
)
|
|
145
|
+
|
|
146
|
+
if (!response.ok) throw new Error('Failed to delete CMS entry')
|
|
112
147
|
}
|
|
@@ -2,9 +2,11 @@
|
|
|
2
2
|
* Collection Service
|
|
3
3
|
*
|
|
4
4
|
* Handles collection operations using GraphQL.
|
|
5
|
+
* Stateless - all configuration passed as parameters.
|
|
5
6
|
*/
|
|
6
|
-
import {
|
|
7
|
+
import { GraphQLClient } from 'graphql-request'
|
|
7
8
|
import type { Collection, PaginatedResponse, ListParams } from '../types/store'
|
|
9
|
+
import type { SdkConfig } from '../config'
|
|
8
10
|
|
|
9
11
|
const GET_STOREFRONT_COLLECTIONS = `
|
|
10
12
|
query GetStorefrontCollections($page: Int!, $pageSize: Int!) {
|
|
@@ -15,7 +17,7 @@ const GET_STOREFRONT_COLLECTIONS = `
|
|
|
15
17
|
name
|
|
16
18
|
slug
|
|
17
19
|
description
|
|
18
|
-
image
|
|
20
|
+
image
|
|
19
21
|
collection_type
|
|
20
22
|
rules
|
|
21
23
|
status
|
|
@@ -39,7 +41,7 @@ const GET_STOREFRONT_COLLECTION_BY_SLUG = `
|
|
|
39
41
|
name
|
|
40
42
|
slug
|
|
41
43
|
description
|
|
42
|
-
image
|
|
44
|
+
image
|
|
43
45
|
collection_type
|
|
44
46
|
rules
|
|
45
47
|
status
|
|
@@ -50,13 +52,27 @@ const GET_STOREFRONT_COLLECTION_BY_SLUG = `
|
|
|
50
52
|
}
|
|
51
53
|
`
|
|
52
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Create GraphQL client with provided config
|
|
57
|
+
*/
|
|
58
|
+
function createGraphQLClient(config: SdkConfig): GraphQLClient {
|
|
59
|
+
const headers: Record<string, string> = {
|
|
60
|
+
'Content-Type': 'application/json',
|
|
61
|
+
'Accept': 'application/json',
|
|
62
|
+
'X-Storefront-Key': config.storefrontApiKey,
|
|
63
|
+
'X-Business-ID': config.businessId,
|
|
64
|
+
}
|
|
65
|
+
return new GraphQLClient(`${config.backendUrls.store}/graphql`, { headers })
|
|
66
|
+
}
|
|
67
|
+
|
|
53
68
|
/**
|
|
54
69
|
* Fetch paginated active collections for the storefront.
|
|
55
70
|
*/
|
|
56
71
|
export async function getStorefrontCollections(
|
|
72
|
+
config: SdkConfig,
|
|
57
73
|
params?: ListParams
|
|
58
74
|
): Promise<PaginatedResponse<Collection>> {
|
|
59
|
-
const client =
|
|
75
|
+
const client = createGraphQLClient(config)
|
|
60
76
|
const variables = {
|
|
61
77
|
page: params?.page || 1,
|
|
62
78
|
pageSize: params?.pageSize || 20,
|
|
@@ -69,9 +85,10 @@ export async function getStorefrontCollections(
|
|
|
69
85
|
* Fetch a single collection by its slug.
|
|
70
86
|
*/
|
|
71
87
|
export async function getStorefrontCollectionBySlug(
|
|
88
|
+
config: SdkConfig,
|
|
72
89
|
slug: string
|
|
73
90
|
): Promise<Collection> {
|
|
74
|
-
const client =
|
|
91
|
+
const client = createGraphQLClient(config)
|
|
75
92
|
const data = await client.request(GET_STOREFRONT_COLLECTION_BY_SLUG, { slug })
|
|
76
93
|
return data.storefront_collection_by_slug
|
|
77
94
|
}
|
|
@@ -2,37 +2,57 @@
|
|
|
2
2
|
* Config Service
|
|
3
3
|
*
|
|
4
4
|
* Handles configuration endpoints (languages, currencies, locales, business config).
|
|
5
|
+
* Stateless - all configuration passed as parameters.
|
|
5
6
|
*/
|
|
6
|
-
import {
|
|
7
|
+
import type { SdkConfig } from '../config'
|
|
7
8
|
import type { BackendLanguage, SupportedLanguagesResponse, SupportedCurrenciesResponse } from '../types/payments'
|
|
8
9
|
import type { BusinessConfig } from '../types/business'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Fetch supported languages from the payment system.
|
|
12
|
-
* Resolves to: {
|
|
13
|
+
* Resolves to: {kasuviaPaymentBackendUrl}/config/supported-languages
|
|
13
14
|
*/
|
|
14
|
-
export async function getSupportedLanguages(): Promise<SupportedLanguagesResponse> {
|
|
15
|
-
const
|
|
16
|
-
|
|
15
|
+
export async function getSupportedLanguages(config: SdkConfig): Promise<SupportedLanguagesResponse> {
|
|
16
|
+
const response = await fetch(`${config.backendUrls.payment}/config/supported-languages`, {
|
|
17
|
+
headers: {
|
|
18
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
19
|
+
"X-Business-ID": config.businessId,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
if (!response.ok) throw new Error('Failed to get supported languages')
|
|
23
|
+
return response.json()
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
/**
|
|
20
27
|
* Fetch supported currencies from the payment system.
|
|
21
|
-
* Resolves to: {
|
|
28
|
+
* Resolves to: {kasuviaPaymentBackendUrl}/config/supported-currencies
|
|
22
29
|
*/
|
|
23
|
-
export async function getSupportedCurrencies(): Promise<SupportedCurrenciesResponse> {
|
|
24
|
-
const
|
|
25
|
-
|
|
30
|
+
export async function getSupportedCurrencies(config: SdkConfig): Promise<SupportedCurrenciesResponse> {
|
|
31
|
+
const response = await fetch(`${config.backendUrls.payment}/config/supported-currencies`, {
|
|
32
|
+
headers: {
|
|
33
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
34
|
+
"X-Business-ID": config.businessId,
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
if (!response.ok) throw new Error('Failed to get supported currencies')
|
|
38
|
+
return response.json()
|
|
26
39
|
}
|
|
27
40
|
|
|
28
41
|
/**
|
|
29
42
|
* Fetch the business's public configuration, including store_currency.
|
|
30
|
-
* Uses
|
|
31
|
-
* Resolves to: {
|
|
43
|
+
* Uses storefront API key header (X-Storefront-Key).
|
|
44
|
+
* Resolves to: {kasuviaAuthBackendUrl}/internal/businesses/{business_id}/
|
|
45
|
+
* This endpoint is designed for storefronts to fetch business config using their storefront API key.
|
|
32
46
|
*/
|
|
33
|
-
export async function getBusinessConfig(): Promise<BusinessConfig> {
|
|
34
|
-
const
|
|
35
|
-
|
|
47
|
+
export async function getBusinessConfig(config: SdkConfig): Promise<BusinessConfig> {
|
|
48
|
+
const response = await fetch(`${config.backendUrls.auth}/internal/businesses/${config.businessId}/`, {
|
|
49
|
+
headers: {
|
|
50
|
+
"X-Storefront-Key": config.storefrontApiKey,
|
|
51
|
+
"X-Business-ID": config.businessId,
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
if (!response.ok) throw new Error('Failed to get business config')
|
|
55
|
+
return response.json()
|
|
36
56
|
}
|
|
37
57
|
|
|
38
58
|
export const configService = {
|