arky-sdk 0.1.0 → 0.1.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 (104) hide show
  1. package/dist/config-CPkOgumU.d.cts +16 -0
  2. package/dist/config-CPkOgumU.d.ts +16 -0
  3. package/dist/index.cjs +1517 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +268 -0
  6. package/dist/index.d.ts +268 -26
  7. package/dist/index.js +1457 -56
  8. package/dist/index.js.map +1 -0
  9. package/dist/stores.cjs +2148 -0
  10. package/dist/stores.cjs.map +1 -0
  11. package/dist/stores.d.cts +218 -0
  12. package/dist/stores.d.ts +218 -0
  13. package/dist/stores.js +2111 -0
  14. package/dist/stores.js.map +1 -0
  15. package/dist/types.cjs +13 -0
  16. package/dist/types.cjs.map +1 -0
  17. package/dist/{types/index.d.ts → types.d.cts} +25 -24
  18. package/dist/types.d.ts +245 -0
  19. package/dist/types.js +11 -0
  20. package/dist/types.js.map +1 -0
  21. package/dist/utils.cjs +725 -0
  22. package/dist/utils.cjs.map +1 -0
  23. package/dist/utils.d.cts +9 -0
  24. package/dist/utils.d.ts +9 -0
  25. package/dist/utils.js +680 -0
  26. package/dist/utils.js.map +1 -0
  27. package/dist/validation-C9UAYKke.d.cts +245 -0
  28. package/dist/validation-DIvAzYjG.d.ts +245 -0
  29. package/package.json +17 -11
  30. package/dist/api/cms.d.ts +0 -19
  31. package/dist/api/cms.d.ts.map +0 -1
  32. package/dist/api/cms.js +0 -41
  33. package/dist/api/eshop.d.ts +0 -89
  34. package/dist/api/eshop.d.ts.map +0 -1
  35. package/dist/api/eshop.js +0 -183
  36. package/dist/api/index.d.ts +0 -6
  37. package/dist/api/index.d.ts.map +0 -1
  38. package/dist/api/index.js +0 -5
  39. package/dist/api/newsletter.d.ts +0 -32
  40. package/dist/api/newsletter.d.ts.map +0 -1
  41. package/dist/api/newsletter.js +0 -70
  42. package/dist/api/reservation.d.ts +0 -84
  43. package/dist/api/reservation.d.ts.map +0 -1
  44. package/dist/api/reservation.js +0 -239
  45. package/dist/config.d.ts +0 -15
  46. package/dist/config.d.ts.map +0 -1
  47. package/dist/config.js +0 -20
  48. package/dist/index.d.ts.map +0 -1
  49. package/dist/services/auth.d.ts +0 -17
  50. package/dist/services/auth.d.ts.map +0 -1
  51. package/dist/services/auth.js +0 -62
  52. package/dist/services/http.d.ts +0 -20
  53. package/dist/services/http.d.ts.map +0 -1
  54. package/dist/services/http.js +0 -73
  55. package/dist/stores/business.d.ts +0 -28
  56. package/dist/stores/business.d.ts.map +0 -1
  57. package/dist/stores/business.js +0 -122
  58. package/dist/stores/cart.d.ts +0 -8
  59. package/dist/stores/cart.d.ts.map +0 -1
  60. package/dist/stores/cart.js +0 -20
  61. package/dist/stores/eshop.d.ts +0 -121
  62. package/dist/stores/eshop.d.ts.map +0 -1
  63. package/dist/stores/eshop.js +0 -377
  64. package/dist/stores/index.d.ts +0 -7
  65. package/dist/stores/index.d.ts.map +0 -1
  66. package/dist/stores/index.js +0 -19
  67. package/dist/stores/reservation.d.ts +0 -237
  68. package/dist/stores/reservation.d.ts.map +0 -1
  69. package/dist/stores/reservation.js +0 -853
  70. package/dist/types/index.d.ts.map +0 -1
  71. package/dist/types/index.js +0 -8
  72. package/dist/utils/blocks.d.ts +0 -30
  73. package/dist/utils/blocks.d.ts.map +0 -1
  74. package/dist/utils/blocks.js +0 -237
  75. package/dist/utils/currency.d.ts +0 -9
  76. package/dist/utils/currency.d.ts.map +0 -1
  77. package/dist/utils/currency.js +0 -99
  78. package/dist/utils/errors.d.ts +0 -121
  79. package/dist/utils/errors.d.ts.map +0 -1
  80. package/dist/utils/errors.js +0 -114
  81. package/dist/utils/i18n.d.ts +0 -5
  82. package/dist/utils/i18n.d.ts.map +0 -1
  83. package/dist/utils/i18n.js +0 -37
  84. package/dist/utils/index.d.ts +0 -9
  85. package/dist/utils/index.d.ts.map +0 -1
  86. package/dist/utils/index.js +0 -10
  87. package/dist/utils/price.d.ts +0 -33
  88. package/dist/utils/price.d.ts.map +0 -1
  89. package/dist/utils/price.js +0 -141
  90. package/dist/utils/queryParams.d.ts +0 -21
  91. package/dist/utils/queryParams.d.ts.map +0 -1
  92. package/dist/utils/queryParams.js +0 -47
  93. package/dist/utils/svg.d.ts +0 -17
  94. package/dist/utils/svg.d.ts.map +0 -1
  95. package/dist/utils/svg.js +0 -62
  96. package/dist/utils/text.d.ts +0 -26
  97. package/dist/utils/text.d.ts.map +0 -1
  98. package/dist/utils/text.js +0 -64
  99. package/dist/utils/timezone.d.ts +0 -9
  100. package/dist/utils/timezone.d.ts.map +0 -1
  101. package/dist/utils/timezone.js +0 -49
  102. package/dist/utils/validation.d.ts +0 -9
  103. package/dist/utils/validation.d.ts.map +0 -1
  104. package/dist/utils/validation.js +0 -44
package/dist/index.js CHANGED
@@ -1,57 +1,1458 @@
1
- // Main export file for @arky/sdk
2
- // Configuration
3
- export * from './config';
4
- // Types
5
- export * from './types';
6
- // APIs
7
- export * from './api';
8
- // Services
9
- export * from './services/auth';
10
- export { default as httpClient } from './services/http';
11
- // NOTE: Stores are exported via separate entry point: @arky/sdk/stores
12
- // This keeps the main bundle small for API-only users
13
- // Utilities
14
- export * from './utils/blocks';
15
- export * from './utils/errors';
16
- export * from './utils/price';
17
- export * from './utils/svg';
18
- export * from './utils/text';
19
- export * from './utils/timezone';
20
- export * from './utils/validation';
21
- // Re-export commonly used functions for convenience
22
- export {
23
- // Validation utilities
24
- validatePhoneNumber, validateEmail, validateVerificationCode, validateRequired } from './utils/validation';
25
- export {
26
- // Block utilities
27
- getBlockLabel, getBlockTextValue, getBlockValue, getBlockValues, getImageUrl, thumbnailUrl } from './utils/blocks';
28
- export {
29
- // Auth utilities
30
- getGuestToken, updateProfilePhone, verifyPhoneCode, getBusinessConfig } from './services/auth';
31
- export {
32
- // SVG utilities
33
- fetchSvgContent, getSvgContentForAstro, injectSvgIntoElement } from './utils/svg';
34
- export {
35
- // Text utilities
36
- slugify, humanize, categorify, formatDate } from './utils/text';
37
- export {
38
- // Timezone utilities
39
- findTimeZone, tzGroups } from './utils/timezone';
40
- export {
41
- // Error utilities
42
- getErrorMessage, isErrorCode, ERROR_CODES, ERROR_CONSTANTS } from './utils/errors';
43
- // SDK Version
44
- export const SDK_VERSION = '0.1.0';
45
- export const SUPPORTED_FRAMEWORKS = ['astro', 'react', 'vue', 'svelte', 'vanilla'];
46
- // SDK initialization function
47
- import { setGlobalConfig } from './config';
48
- export function initArky(config) {
49
- if (!config.apiUrl) {
50
- throw new Error('apiUrl is required');
51
- }
52
- if (!config.businessId) {
53
- throw new Error('businessId is required');
54
- }
55
- setGlobalConfig(config);
56
- return config;
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/config.ts
12
+ var config_exports = {};
13
+ __export(config_exports, {
14
+ API_URL: () => API_URL,
15
+ BUSINESS_ID: () => BUSINESS_ID,
16
+ STORAGE_URL: () => STORAGE_URL,
17
+ getGlobalConfig: () => getGlobalConfig,
18
+ setGlobalConfig: () => setGlobalConfig
19
+ });
20
+ function setGlobalConfig(config) {
21
+ globalConfig = config;
22
+ API_URL = config.apiUrl;
23
+ BUSINESS_ID = config.businessId;
24
+ STORAGE_URL = config.storageUrl || "";
57
25
  }
26
+ function getGlobalConfig() {
27
+ if (!globalConfig) {
28
+ throw new Error(
29
+ "Arky SDK not initialized. Call initArky() or create an ArkyClient instance."
30
+ );
31
+ }
32
+ return globalConfig;
33
+ }
34
+ var globalConfig, API_URL, BUSINESS_ID, STORAGE_URL;
35
+ var init_config = __esm({
36
+ "src/config.ts"() {
37
+ globalConfig = null;
38
+ API_URL = "";
39
+ BUSINESS_ID = "";
40
+ STORAGE_URL = "";
41
+ }
42
+ });
43
+
44
+ // src/index.ts
45
+ init_config();
46
+
47
+ // src/types/index.ts
48
+ var PaymentMethod = /* @__PURE__ */ ((PaymentMethod2) => {
49
+ PaymentMethod2["Cash"] = "CASH";
50
+ PaymentMethod2["CreditCard"] = "CREDIT_CARD";
51
+ PaymentMethod2["Free"] = "FREE";
52
+ return PaymentMethod2;
53
+ })(PaymentMethod || {});
54
+
55
+ // src/api/cms.ts
56
+ init_config();
57
+
58
+ // src/utils/queryParams.ts
59
+ function buildQueryString(params) {
60
+ const queryParts = [];
61
+ Object.entries(params).forEach(([key, value]) => {
62
+ if (value === null || value === void 0) {
63
+ return;
64
+ }
65
+ if (Array.isArray(value)) {
66
+ const jsonString = JSON.stringify(value);
67
+ queryParts.push(`${key}=${encodeURIComponent(jsonString)}`);
68
+ } else if (typeof value === "string") {
69
+ queryParts.push(`${key}=${encodeURIComponent(value)}`);
70
+ } else if (typeof value === "number" || typeof value === "boolean") {
71
+ queryParts.push(`${key}=${value}`);
72
+ } else if (typeof value === "object") {
73
+ const jsonString = JSON.stringify(value);
74
+ queryParts.push(`${key}=${encodeURIComponent(jsonString)}`);
75
+ }
76
+ });
77
+ return queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
78
+ }
79
+ function appendQueryString(url, params) {
80
+ const queryString = buildQueryString(params);
81
+ return queryString ? `${url}${queryString}` : url;
82
+ }
83
+
84
+ // src/services/http.ts
85
+ async function get(url, options) {
86
+ try {
87
+ const finalUrl = options?.params ? appendQueryString(url, options.params) : url;
88
+ const response = await fetch(finalUrl);
89
+ if (!response.ok) {
90
+ throw new Error(`HTTP error! status: ${response.status}`);
91
+ }
92
+ const data = await response.json();
93
+ return {
94
+ value: data,
95
+ success: true
96
+ };
97
+ } catch (error) {
98
+ const errorMsg = error instanceof Error ? error.message : "Unknown error occurred";
99
+ return {
100
+ value: null,
101
+ success: false,
102
+ error: errorMsg
103
+ };
104
+ }
105
+ }
106
+ async function post(url, data, options) {
107
+ try {
108
+ const response = await fetch(url, {
109
+ method: "POST",
110
+ headers: {
111
+ "Content-Type": "application/json"
112
+ },
113
+ body: JSON.stringify(data)
114
+ });
115
+ if (!response.ok) {
116
+ throw new Error(`HTTP error! status: ${response.status}`);
117
+ }
118
+ const responseData = await response.json();
119
+ return {
120
+ value: responseData,
121
+ success: true
122
+ };
123
+ } catch (error) {
124
+ const errorMsg = error instanceof Error ? error.message : "Unknown error occurred";
125
+ return {
126
+ value: null,
127
+ success: false,
128
+ error: errorMsg
129
+ };
130
+ }
131
+ }
132
+ var httpClient = {
133
+ get,
134
+ post
135
+ };
136
+ var http_default = httpClient;
137
+
138
+ // src/api/cms.ts
139
+ var getCollection = async (id) => {
140
+ const url = `${API_URL}/v1/businesses/${BUSINESS_ID}/collections/${id}`;
141
+ const { value } = await http_default.get(url);
142
+ return value;
143
+ };
144
+ var getCollections = async ({ name = null, ids = null }) => {
145
+ const url = `${API_URL}/v1/businesses/${BUSINESS_ID}/collections`;
146
+ const response = await http_default.get(url, {
147
+ params: { name, ids }
148
+ });
149
+ return response.value;
150
+ };
151
+ var getCollectionEntries = async ({
152
+ collectionId,
153
+ limit,
154
+ cursor,
155
+ ids = null
156
+ }) => {
157
+ const url = `${API_URL}/v1/businesses/${BUSINESS_ID}/collections/${collectionId}/entries`;
158
+ const response = await http_default.get(url, {
159
+ params: { limit, cursor, ids }
160
+ });
161
+ return response.value;
162
+ };
163
+ var createCollectionEntry = async (collectionEntryData) => {
164
+ const url = `${API_URL}/v1/businesses/${BUSINESS_ID}/collections/${collectionEntryData.collectionId}/entries`;
165
+ const result = await http_default.post(url, collectionEntryData, {
166
+ successMessage: "Created successfully",
167
+ errorMessage: "Failed to create collection"
168
+ });
169
+ return result;
170
+ };
171
+ var getCollectionEntry = async ({ collectionId, id }) => {
172
+ const url = `${API_URL}/v1/businesses/${BUSINESS_ID}/collections/${collectionId}/entries/${id}`;
173
+ const response = await http_default.get(url);
174
+ return response;
175
+ };
176
+ var cmsApi = {
177
+ getCollection,
178
+ getCollections,
179
+ getCollectionEntries,
180
+ getCollectionEntry,
181
+ createCollectionEntry
182
+ };
183
+
184
+ // src/api/eshop.ts
185
+ init_config();
186
+
187
+ // src/api/reservation.ts
188
+ init_config();
189
+ var reservationApi = {
190
+ // Get quote for reservation parts
191
+ async getQuote({
192
+ token,
193
+ businessId,
194
+ market,
195
+ currency,
196
+ userId,
197
+ parts,
198
+ paymentMethod = "CASH",
199
+ promoCode
200
+ }) {
201
+ try {
202
+ const lines = parts.map((part) => ({
203
+ type: "SERVICE",
204
+ serviceId: part.serviceId,
205
+ quantity: 1
206
+ }));
207
+ const payload = {
208
+ businessId,
209
+ market,
210
+ currency,
211
+ userId,
212
+ paymentMethod,
213
+ lines,
214
+ promoCode: promoCode || void 0,
215
+ shippingMethodId: null
216
+ };
217
+ const res = await fetch(`${API_URL}/v1/payments/quote`, {
218
+ method: "POST",
219
+ headers: {
220
+ "Content-Type": "application/json",
221
+ "Authorization": `Bearer ${token}`
222
+ },
223
+ body: JSON.stringify(payload)
224
+ });
225
+ const text = await res.text();
226
+ if (!res.ok) {
227
+ try {
228
+ const json = JSON.parse(text);
229
+ return { success: false, error: json.reason || json.error || "Failed to fetch quote", code: json.code };
230
+ } catch {
231
+ return { success: false, error: text || "Failed to fetch quote" };
232
+ }
233
+ }
234
+ const quote = text ? JSON.parse(text) : null;
235
+ return { success: true, data: quote };
236
+ } catch (e) {
237
+ return {
238
+ success: false,
239
+ error: e.message || "Failed to fetch quote"
240
+ };
241
+ }
242
+ },
243
+ // Get available slots for a service
244
+ async getAvailableSlots({
245
+ businessId,
246
+ serviceId,
247
+ from,
248
+ to,
249
+ limit = 1e3,
250
+ providerId = null
251
+ }) {
252
+ const url = `${API_URL}/v1/businesses/${businessId}/services/${serviceId}/available-slots`;
253
+ const response = await http_default.get(url, {
254
+ params: {
255
+ from,
256
+ to,
257
+ limit,
258
+ providerId
259
+ }
260
+ });
261
+ if (response.success) {
262
+ const json = response.value;
263
+ return {
264
+ success: true,
265
+ data: json.data?.items || json.items || []
266
+ };
267
+ } else {
268
+ console.error("Error fetching available slots:", response.error);
269
+ return {
270
+ success: false,
271
+ error: response.error,
272
+ data: []
273
+ };
274
+ }
275
+ },
276
+ // Get all providers for a service
277
+ async getProviders({ businessId, serviceId, limit = 50 }) {
278
+ const url = `${API_URL}/v1/businesses/${businessId}/providers`;
279
+ const response = await http_default.get(url, {
280
+ params: {
281
+ serviceId,
282
+ limit
283
+ }
284
+ });
285
+ if (response.success) {
286
+ const json = response.value;
287
+ return {
288
+ success: true,
289
+ data: json.items || []
290
+ };
291
+ } else {
292
+ console.error("Error loading providers:", response.error);
293
+ return {
294
+ success: false,
295
+ error: response.error,
296
+ data: []
297
+ };
298
+ }
299
+ },
300
+ // Get guest token or create a new one
301
+ async getGuestToken() {
302
+ try {
303
+ const res = await fetch(`${API_URL}/v1/users/login`, {
304
+ method: "POST",
305
+ headers: { "Content-Type": "application/json" },
306
+ body: JSON.stringify({ provider: "GUEST" })
307
+ });
308
+ if (!res.ok) throw new Error("Guest login failed");
309
+ const json = await res.json();
310
+ return {
311
+ success: true,
312
+ data: { token: json.accessToken }
313
+ };
314
+ } catch (e) {
315
+ return {
316
+ success: false,
317
+ error: e.message
318
+ };
319
+ }
320
+ },
321
+ // Update user's phone number
322
+ async updateProfilePhone({ token, phoneNumber }) {
323
+ try {
324
+ const res = await fetch(`${API_URL}/v1/users/update`, {
325
+ method: "PUT",
326
+ headers: {
327
+ "Content-Type": "application/json",
328
+ Authorization: `Bearer ${token}`
329
+ },
330
+ body: JSON.stringify({
331
+ phoneNumber,
332
+ phoneNumbers: [],
333
+ addresses: []
334
+ })
335
+ });
336
+ if (!res.ok) {
337
+ const error = await res.text() || res.statusText;
338
+ return {
339
+ success: false,
340
+ error
341
+ };
342
+ }
343
+ return {
344
+ success: true
345
+ };
346
+ } catch (e) {
347
+ return {
348
+ success: false,
349
+ error: e.message
350
+ };
351
+ }
352
+ },
353
+ // Verify phone number with code
354
+ async verifyPhoneCode({ token, phoneNumber, code }) {
355
+ try {
356
+ const res = await fetch(`${API_URL}/v1/users/confirm/phone-number`, {
357
+ method: "PUT",
358
+ headers: {
359
+ "Content-Type": "application/json",
360
+ Authorization: `Bearer ${token}`
361
+ },
362
+ body: JSON.stringify({
363
+ phoneNumber,
364
+ code
365
+ })
366
+ });
367
+ if (!res.ok) {
368
+ const error = await res.text() || res.statusText;
369
+ return {
370
+ success: false,
371
+ error
372
+ };
373
+ }
374
+ return {
375
+ success: true
376
+ };
377
+ } catch (e) {
378
+ return {
379
+ success: false,
380
+ error: e.message
381
+ };
382
+ }
383
+ },
384
+ // Complete reservation checkout - Backend calculates currency from market
385
+ async checkout({
386
+ token,
387
+ businessId,
388
+ parts,
389
+ paymentMethod = "CASH",
390
+ blocks = [],
391
+ market = "US",
392
+ promoCode
393
+ }) {
394
+ try {
395
+ const payload = {
396
+ businessId,
397
+ blocks,
398
+ market,
399
+ parts: parts.map((p) => ({
400
+ serviceId: p.serviceId,
401
+ from: p.from,
402
+ to: p.to,
403
+ blocks: p.blocks,
404
+ reservationMethod: p.reservationMethod,
405
+ providerId: p.providerId
406
+ }))
407
+ };
408
+ if (paymentMethod !== void 0) {
409
+ payload.paymentMethod = paymentMethod;
410
+ }
411
+ if (promoCode) {
412
+ payload.promoCode = promoCode;
413
+ }
414
+ const res = await fetch(`${API_URL}/v1/reservations/checkout`, {
415
+ method: "POST",
416
+ headers: {
417
+ "Content-Type": "application/json",
418
+ Authorization: `Bearer ${token}`
419
+ },
420
+ body: JSON.stringify(payload)
421
+ });
422
+ if (!res.ok) {
423
+ const error = await res.text() || res.statusText;
424
+ throw new Error(error);
425
+ }
426
+ const json = await res.json();
427
+ return {
428
+ success: true,
429
+ data: json
430
+ // Should include reservationId and clientSecret for payments
431
+ };
432
+ } catch (e) {
433
+ return {
434
+ success: false,
435
+ error: e.message
436
+ };
437
+ }
438
+ }
439
+ };
440
+
441
+ // src/api/eshop.ts
442
+ var eshopApi = {
443
+ // Get products
444
+ async getProducts({
445
+ businessId,
446
+ categoryIds = null,
447
+ status = "ACTIVE",
448
+ limit = 20,
449
+ cursor = null
450
+ }) {
451
+ const url = `${API_URL}/v1/businesses/${encodeURIComponent(businessId)}/products`;
452
+ const response = await http_default.get(url, {
453
+ params: {
454
+ categoryIds: categoryIds && categoryIds.length > 0 ? categoryIds : void 0,
455
+ status,
456
+ limit,
457
+ cursor
458
+ }
459
+ });
460
+ if (response.success) {
461
+ const json = response.value;
462
+ return {
463
+ success: true,
464
+ data: json.items || [],
465
+ cursor: json.cursor,
466
+ total: json.total || 0
467
+ };
468
+ } else {
469
+ console.error("Error fetching products:", response.error);
470
+ return {
471
+ success: false,
472
+ error: response.error,
473
+ data: []
474
+ };
475
+ }
476
+ },
477
+ // Get product by slug
478
+ async getProductBySlug({ businessId, slug }) {
479
+ try {
480
+ const url = `${API_URL}/v1/businesses/${encodeURIComponent(businessId)}/products/slug/${encodeURIComponent(businessId)}/${encodeURIComponent(slug)}`;
481
+ const res = await fetch(url);
482
+ if (!res.ok) throw new Error("Product not found");
483
+ const json = await res.json();
484
+ return {
485
+ success: true,
486
+ data: json
487
+ };
488
+ } catch (e) {
489
+ console.error("Error fetching product:", e);
490
+ return {
491
+ success: false,
492
+ error: e.message,
493
+ data: null
494
+ };
495
+ }
496
+ },
497
+ // Get quote for cart (pricing with promo codes, shipping, taxes)
498
+ async getQuote({
499
+ token,
500
+ businessId,
501
+ items,
502
+ market,
503
+ currency,
504
+ userId,
505
+ paymentMethod,
506
+ shippingMethodId,
507
+ promoCode
508
+ }) {
509
+ try {
510
+ const lines = items.map((item) => ({
511
+ type: "PRODUCT_VARIANT",
512
+ productId: item.productId,
513
+ variantId: item.variantId,
514
+ quantity: item.quantity
515
+ }));
516
+ const payload = {
517
+ businessId,
518
+ market,
519
+ currency,
520
+ userId,
521
+ paymentMethod,
522
+ lines,
523
+ ...shippingMethodId && { shippingMethodId },
524
+ ...promoCode && { promoCode }
525
+ };
526
+ const res = await fetch(`${API_URL}/v1/payments/quote`, {
527
+ method: "POST",
528
+ headers: {
529
+ "Content-Type": "application/json",
530
+ Authorization: `Bearer ${token}`
531
+ },
532
+ body: JSON.stringify(payload)
533
+ });
534
+ const text = await res.text();
535
+ if (!res.ok) {
536
+ try {
537
+ const json = JSON.parse(text);
538
+ return { success: false, error: json.reason || json.error || res.statusText, code: json.code };
539
+ } catch {
540
+ return { success: false, error: text || res.statusText };
541
+ }
542
+ }
543
+ const quote = text ? JSON.parse(text) : null;
544
+ return { success: true, data: quote };
545
+ } catch (e) {
546
+ console.error("Quote fetch failed:", e);
547
+ return {
548
+ success: false,
549
+ error: e.message
550
+ };
551
+ }
552
+ },
553
+ // Checkout - Backend calculates currency from market
554
+ async checkout({
555
+ token,
556
+ businessId,
557
+ items,
558
+ paymentMethod,
559
+ blocks,
560
+ market = "US",
561
+ shippingMethodId,
562
+ promoCode,
563
+ paymentIntentId = null
564
+ }) {
565
+ try {
566
+ const payload = {
567
+ businessId,
568
+ items,
569
+ paymentMethod,
570
+ blocks,
571
+ market,
572
+ ...shippingMethodId && { shippingMethodId },
573
+ ...promoCode && { promoCode },
574
+ ...paymentIntentId && { paymentIntentId }
575
+ };
576
+ const res = await fetch(`${API_URL}/v1/businesses/${encodeURIComponent(businessId)}/orders/checkout`, {
577
+ method: "POST",
578
+ headers: {
579
+ "Content-Type": "application/json",
580
+ Authorization: `Bearer ${token}`
581
+ },
582
+ body: JSON.stringify(payload)
583
+ });
584
+ const text = await res.text();
585
+ if (!res.ok) {
586
+ try {
587
+ const json2 = JSON.parse(text);
588
+ return { success: false, error: json2.reason || json2.error || res.statusText, code: json2.code };
589
+ } catch {
590
+ return { success: false, error: text || res.statusText };
591
+ }
592
+ }
593
+ const json = text ? JSON.parse(text) : null;
594
+ return { success: true, data: json };
595
+ } catch (e) {
596
+ return {
597
+ success: false,
598
+ error: e.message
599
+ };
600
+ }
601
+ },
602
+ // Create payment intent for Stripe
603
+ async createPaymentIntent({ amount, currency, businessId }) {
604
+ try {
605
+ const tokenResponse = await reservationApi.getGuestToken();
606
+ if (!tokenResponse.success || !tokenResponse.data) {
607
+ throw new Error("Failed to get guest token");
608
+ }
609
+ const token = tokenResponse.data.token;
610
+ const res = await fetch(`${API_URL}/v1/businesses/${encodeURIComponent(businessId)}/payment/create-intent`, {
611
+ method: "POST",
612
+ headers: {
613
+ "Content-Type": "application/json",
614
+ Authorization: `Bearer ${token}`
615
+ },
616
+ body: JSON.stringify({
617
+ amount,
618
+ currency,
619
+ businessId
620
+ })
621
+ });
622
+ if (!res.ok) {
623
+ const error = await res.text() || res.statusText;
624
+ throw new Error(error);
625
+ }
626
+ const json = await res.json();
627
+ return {
628
+ success: true,
629
+ data: json
630
+ };
631
+ } catch (e) {
632
+ console.error("Payment intent creation failed:", e);
633
+ return {
634
+ success: false,
635
+ error: e.message
636
+ };
637
+ }
638
+ }
639
+ };
640
+
641
+ // src/api/newsletter.ts
642
+ var newsletterApi = {
643
+ async find(payload) {
644
+ const params = new URLSearchParams({
645
+ businessId: payload.business_id
646
+ });
647
+ const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
648
+ const url = `${API_URL2}/v1/newsletters?${params.toString()}`;
649
+ const response = await fetch(url);
650
+ if (!response.ok) {
651
+ throw new Error(`HTTP error! status: ${response.status}`);
652
+ }
653
+ const backendResponse = await response.json();
654
+ return {
655
+ data: backendResponse.items || [],
656
+ meta: {
657
+ total: backendResponse.items?.length || 0,
658
+ page: 1,
659
+ per_page: backendResponse.items?.length || 0
660
+ }
661
+ };
662
+ },
663
+ async get(id) {
664
+ const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
665
+ const url = `${API_URL2}/v1/newsletters/${id}`;
666
+ const response = await fetch(url);
667
+ if (!response.ok) {
668
+ throw new Error(`HTTP error! status: ${response.status}`);
669
+ }
670
+ return await response.json();
671
+ },
672
+ async subscribe(payload) {
673
+ try {
674
+ const { API_URL: API_URL2 } = await Promise.resolve().then(() => (init_config(), config_exports));
675
+ const url = `${API_URL2}/v1/newsletters/${payload.newsletterId}/subscribe`;
676
+ const response = await fetch(url, {
677
+ method: "POST",
678
+ headers: {
679
+ "Content-Type": "application/json"
680
+ },
681
+ body: JSON.stringify({
682
+ newsletterId: payload.newsletterId,
683
+ email: payload.email,
684
+ market: "US",
685
+ // Backend resolves currency from market
686
+ ...payload.customerId && { customerId: payload.customerId },
687
+ ...payload.payment && { payment: payload.payment }
688
+ })
689
+ });
690
+ if (!response.ok) {
691
+ const errorData = await response.json().catch(() => ({}));
692
+ throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
693
+ }
694
+ const data = await response.json();
695
+ return {
696
+ success: true,
697
+ data
698
+ };
699
+ } catch (error) {
700
+ console.error("Newsletter subscription error:", error);
701
+ return {
702
+ success: false,
703
+ error: error instanceof Error ? error.message : "Failed to subscribe to newsletter"
704
+ };
705
+ }
706
+ }
707
+ };
708
+
709
+ // src/services/auth.ts
710
+ init_config();
711
+ async function getGuestToken(currentToken = null) {
712
+ if (currentToken) return currentToken;
713
+ const response = await reservationApi.getGuestToken();
714
+ if (response.success && response.data) {
715
+ return response.data.token;
716
+ }
717
+ throw new Error("Failed to get guest token");
718
+ }
719
+ async function updateProfilePhone(token, phoneNumber) {
720
+ if (!phoneNumber) {
721
+ throw new Error("Phone number is required");
722
+ }
723
+ const response = await reservationApi.updateProfilePhone({ token, phoneNumber });
724
+ if (response.success) {
725
+ return { success: true };
726
+ } else {
727
+ throw new Error(response.error || "Failed to send verification code");
728
+ }
729
+ }
730
+ async function verifyPhoneCode(token, phoneNumber, code) {
731
+ if (!code) {
732
+ throw new Error("Verification code is required");
733
+ }
734
+ const response = await reservationApi.verifyPhoneCode({ token, phoneNumber, code });
735
+ if (response.success) {
736
+ return { success: true };
737
+ } else {
738
+ throw new Error(response.error || "Invalid verification code");
739
+ }
740
+ }
741
+ async function getBusinessConfig(businessId) {
742
+ try {
743
+ const response = await fetch(`${API_URL}/v1/businesses/${businessId}`, {
744
+ method: "GET",
745
+ headers: {
746
+ "Content-Type": "application/json"
747
+ }
748
+ });
749
+ if (!response.ok) {
750
+ throw new Error(`Failed to fetch business config: ${response.status}`);
751
+ }
752
+ const business = await response.json();
753
+ return {
754
+ success: true,
755
+ data: business
756
+ };
757
+ } catch (error) {
758
+ return {
759
+ success: false,
760
+ error: error.message
761
+ };
762
+ }
763
+ }
764
+
765
+ // src/utils/blocks.ts
766
+ init_config();
767
+ function getBlockLabel(block, locale = "en") {
768
+ if (!block) return "";
769
+ if (block.properties?.label) {
770
+ if (typeof block.properties.label === "object") {
771
+ return block.properties.label[locale] || block.properties.label.en || Object.values(block.properties.label)[0] || "";
772
+ }
773
+ if (typeof block.properties.label === "string") {
774
+ return block.properties.label;
775
+ }
776
+ }
777
+ return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) || "";
778
+ }
779
+ function formatBlockValue(block) {
780
+ if (!block || block.value === null || block.value === void 0) {
781
+ return "";
782
+ }
783
+ switch (block.type) {
784
+ case "BOOLEAN":
785
+ return block.value ? "Yes" : "No";
786
+ case "NUMBER":
787
+ if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
788
+ try {
789
+ return new Date(block.value).toLocaleDateString();
790
+ } catch (e) {
791
+ return String(block.value);
792
+ }
793
+ }
794
+ return String(block.value);
795
+ case "RELATIONSHIP":
796
+ if (Array.isArray(block.value) && block.value.length > 0) {
797
+ const firstValue = block.value[0];
798
+ if (firstValue && firstValue.mimeType) {
799
+ return firstValue.name || firstValue.id || "Media";
800
+ }
801
+ return firstValue.title || firstValue.name || firstValue.id || "Entry";
802
+ }
803
+ return String(block.value);
804
+ default:
805
+ return String(block.value);
806
+ }
807
+ }
808
+ function prepareBlocksForSubmission(formData) {
809
+ const preparedBlocks = [];
810
+ Object.keys(formData).forEach((key) => {
811
+ if (formData[key] !== null && formData[key] !== void 0) {
812
+ preparedBlocks.push({
813
+ key,
814
+ value: [formData[key]]
815
+ });
816
+ }
817
+ });
818
+ return preparedBlocks;
819
+ }
820
+ function extractBlockValues(blocks) {
821
+ const values = {};
822
+ blocks.forEach((block) => {
823
+ if (block.value && block.value.length > 0) {
824
+ values[block.key] = block.value[0];
825
+ } else {
826
+ values[block.key] = null;
827
+ }
828
+ });
829
+ return values;
830
+ }
831
+ function getBlockTextValue(block, locale = "en") {
832
+ if (!block || !block.value || block.value.length === 0) return "";
833
+ const firstValue = block.value[0];
834
+ if (typeof firstValue === "object" && firstValue !== null) {
835
+ if (firstValue[locale]) return firstValue[locale];
836
+ if (firstValue.en) return firstValue.en;
837
+ const values = Object.values(firstValue);
838
+ return String(values[0] || "");
839
+ }
840
+ return String(firstValue);
841
+ }
842
+ var getBlockValue = (entry, blockKey) => {
843
+ if (!entry || !entry.blocks) return null;
844
+ const block = entry.blocks.find((f) => f.key === blockKey);
845
+ if (!block || !block.value || block.value.length === 0) return null;
846
+ return block.value[0];
847
+ };
848
+ var getBlockValues = (entry, blockKey) => {
849
+ if (!entry || !entry.blocks) return null;
850
+ const block = entry.blocks.find((f) => f.key === blockKey);
851
+ if (!block || !block.value || block.value.length === 0) return null;
852
+ return block.value;
853
+ };
854
+ function unwrapBlock(block, locale) {
855
+ if (!block?.type || block.value === void 0) return block;
856
+ if (block.type === "BLOCK") {
857
+ return block.value.map((obj) => {
858
+ const parsed = {};
859
+ for (const [k, v] of Object.entries(obj)) {
860
+ parsed[k] = unwrapBlock(v, locale);
861
+ }
862
+ return parsed;
863
+ });
864
+ }
865
+ const isLocalized = block.type === "TEXT";
866
+ const isList = block.properties?.ui === "list" || (block.properties?.maxValues ?? 1) > 1 || block.value.length > 1;
867
+ if (isList) {
868
+ return isLocalized ? block.value.map((v) => v[locale] || v["en"]) : [...block.value];
869
+ }
870
+ return isLocalized ? block.value[0][locale] || block.value[0]["en"] : block.value[0];
871
+ }
872
+ var getBlockObjectValues = (entry, blockKey, locale = "en") => {
873
+ if (!entry) {
874
+ return [];
875
+ }
876
+ const values = getBlockValues(entry, blockKey);
877
+ const parsed = values.map((obj) => {
878
+ const res = obj.value.reduce((acc, current) => {
879
+ acc[current.key] = unwrapBlock(current, locale);
880
+ return acc;
881
+ }, {});
882
+ return res;
883
+ });
884
+ return parsed;
885
+ };
886
+ var getBlockFromArray = (entry, blockKey, locale = "en") => {
887
+ if (!entry) {
888
+ return [];
889
+ }
890
+ const values = getBlockValues(entry, blockKey);
891
+ return values.reduce((acc, current) => {
892
+ acc[current.key] = unwrapBlock(current, locale);
893
+ return acc;
894
+ });
895
+ };
896
+ var getImageUrl = (imageBlock, isBlock = true) => {
897
+ if (!imageBlock) return null;
898
+ const storageUrl = "https://storage.arky.io/dev";
899
+ const isExternalUrl = (url) => {
900
+ return url.startsWith("http://") || url.startsWith("https://");
901
+ };
902
+ if (imageBlock.type === "RELATIONSHIP" && Array.isArray(imageBlock.value)) {
903
+ const mediaValue = imageBlock.value[0];
904
+ if (mediaValue && mediaValue.mimeType) {
905
+ if (mediaValue.resolutions && mediaValue.resolutions.original && mediaValue.resolutions.original.url) {
906
+ const url = mediaValue.resolutions.original.url;
907
+ return isExternalUrl(url) ? url : `${storageUrl}/${url}`;
908
+ }
909
+ if (mediaValue.url) {
910
+ return isExternalUrl(mediaValue.url) ? mediaValue.url : `${storageUrl}/${mediaValue.url}`;
911
+ }
912
+ }
913
+ return null;
914
+ }
915
+ if (isBlock) {
916
+ if (typeof imageBlock === "string") {
917
+ if (isExternalUrl(imageBlock)) {
918
+ return imageBlock;
919
+ }
920
+ return `${storageUrl}/${imageBlock}`;
921
+ }
922
+ if (imageBlock.url) {
923
+ if (isExternalUrl(imageBlock.url)) {
924
+ return imageBlock.url;
925
+ }
926
+ return `${storageUrl}/${imageBlock.url}`;
927
+ }
928
+ }
929
+ if (imageBlock.resolutions && imageBlock.resolutions.original && imageBlock.resolutions.original.url) {
930
+ const url = imageBlock.resolutions.original.url;
931
+ if (isExternalUrl(url)) {
932
+ return url;
933
+ }
934
+ return `${storageUrl}/${url}`;
935
+ }
936
+ return null;
937
+ };
938
+ function getGalleryThumbnail(gallery) {
939
+ if (!gallery?.length) return null;
940
+ const item = gallery.find((g) => g.settings.isThumbnail) || gallery[0];
941
+ const res = item.media.resolutions.thumbnail || item.media.resolutions.original;
942
+ return res?.url || null;
943
+ }
944
+ function thumbnailUrl(service) {
945
+ const storageUrl = STORAGE_URL || "";
946
+ const path = getGalleryThumbnail(service.gallery);
947
+ return path ? `${storageUrl}/${path}` : null;
948
+ }
949
+ var translateMap = (labels, lang, fallback = "unknown") => {
950
+ let parsedLang = "en";
951
+ if (lang === "sr") {
952
+ parsedLang = "bih";
953
+ }
954
+ if (!labels) {
955
+ return fallback;
956
+ }
957
+ const label = labels[parsedLang];
958
+ if (!label) {
959
+ return fallback;
960
+ }
961
+ return label;
962
+ };
963
+
964
+ // src/utils/errors.ts
965
+ var ERROR_CODES = {
966
+ // General errors
967
+ "GENERAL.001": "GENERAL.BAD_REQUEST",
968
+ "GENERAL.002": "GENERAL.VALIDATION_ERROR",
969
+ "GENERAL.003": "GENERAL.FORBIDDEN_ERROR",
970
+ "GENERAL.004": "GENERAL.INTERNAL_SERVER_ERROR",
971
+ "GENERAL.005": "GENERAL.UNAUTHORIZED",
972
+ "GENERAL.006": "GENERAL.UNAUTHENTICATED",
973
+ // Google/OAuth errors
974
+ "GOOGLE.001": "GOOGLE.INVALID_ORIGIN_URI",
975
+ "GOOGLE.002": "GOOGLE.INVALID_REDIRECT_URI",
976
+ "GOOGLE.003": "GOOGLE.FAILED_TO_CALL_API",
977
+ "GOOGLE.004": "GOOGLE.FAILED_LOGIN",
978
+ "GOOGLE.005": "GOOGLE.FAILED_LOGOUT",
979
+ "GOOGLE.006": "GOOGLE.FAILED_REFRESH_TOKEN",
980
+ "GOOGLE.007": "GOOGLE.INVALID_PROVIDER_PASSED",
981
+ // User errors
982
+ "USER.001": "USER.NOT_FOUND",
983
+ "USER.002": "USER.FAILED_TO_CREATE",
984
+ "USER.003": "USER.FAILED_TO_UPDATE",
985
+ "USER.004": "USER.FAILED_TO_DELETE",
986
+ "USER.005": "USER.EMAIL_EXISTS",
987
+ "USER.006": "USER.FAILED_TO_GET_UPLOAD_URL",
988
+ // Business errors
989
+ "BUSINESS.001": "BUSINESS.NOT_FOUND",
990
+ "BUSINESS.002": "BUSINESS.FAILED_TO_CREATE",
991
+ "BUSINESS.003": "BUSINESS.FAILED_TO_UPDATE",
992
+ "BUSINESS.004": "BUSINESS.FAILED_TO_DELETE",
993
+ "BUSINESS.005": "BUSINESS.FAILED_TO_GET_UPLOAD_URL",
994
+ "BUSINESS.006": "BUSINESS.NAME_REQUIRED",
995
+ "BUSINESS.007": "BUSINESS.BUSINESS_ID_REQUIRED",
996
+ "BUSINESS.010": "BUSINESS.DESCRIPTION_REQUIRED",
997
+ "BUSINESS.011": "BUSINESS.SLUG_INVALID",
998
+ // Provider errors
999
+ "PROVIDER.001": "PROVIDER.NOT_FOUND",
1000
+ "PROVIDER.002": "PROVIDER.FAILED_TO_CREATE",
1001
+ "PROVIDER.003": "PROVIDER.FAILED_TO_UPDATE",
1002
+ "PROVIDER.004": "PROVIDER.FAILED_TO_DELETE",
1003
+ "PROVIDER.005": "PROVIDER.FAILED_TO_GET_UPLOAD_URL",
1004
+ "PROVIDER.006": "PROVIDER.NAME_REQUIRED",
1005
+ "PROVIDER.007": "PROVIDER.BUSINESS_ID_REQUIRED",
1006
+ "PROVIDER.008": "PROVIDER.DESCRIPTION_REQUIRED"
1007
+ };
1008
+ var ERROR_CONSTANTS = {
1009
+ GENERAL: {
1010
+ BAD_REQUEST: "GENERAL.BAD_REQUEST",
1011
+ VALIDATION_ERROR: "GENERAL.VALIDATION_ERROR",
1012
+ FORBIDDEN_ERROR: "GENERAL.FORBIDDEN_ERROR",
1013
+ INTERNAL_SERVER_ERROR: "GENERAL.INTERNAL_SERVER_ERROR",
1014
+ UNAUTHORIZED: "GENERAL.UNAUTHORIZED",
1015
+ UNAUTHENTICATED: "GENERAL.UNAUTHENTICATED"
1016
+ },
1017
+ USER: {
1018
+ NOT_FOUND: "USER.NOT_FOUND",
1019
+ FAILED_TO_CREATE: "USER.FAILED_TO_CREATE",
1020
+ FAILED_TO_UPDATE: "USER.FAILED_TO_UPDATE",
1021
+ FAILED_TO_DELETE: "USER.FAILED_TO_DELETE",
1022
+ EMAIL_EXISTS: "USER.EMAIL_EXISTS",
1023
+ FAILED_TO_GET_UPLOAD_URL: "USER.FAILED_TO_GET_UPLOAD_URL"
1024
+ },
1025
+ BUSINESS: {
1026
+ NOT_FOUND: "BUSINESS.NOT_FOUND",
1027
+ FAILED_TO_CREATE: "BUSINESS.FAILED_TO_CREATE",
1028
+ FAILED_TO_UPDATE: "BUSINESS.FAILED_TO_UPDATE",
1029
+ FAILED_TO_DELETE: "BUSINESS.FAILED_TO_DELETE",
1030
+ FAILED_TO_GET_UPLOAD_URL: "BUSINESS.FAILED_TO_GET_UPLOAD_URL",
1031
+ NAME_REQUIRED: "BUSINESS.NAME_REQUIRED",
1032
+ BUSINESS_ID_REQUIRED: "BUSINESS.BUSINESS_ID_REQUIRED",
1033
+ DESCRIPTION_REQUIRED: "BUSINESS.DESCRIPTION_REQUIRED",
1034
+ SLUG_INVALID: "BUSINESS.SLUG_INVALID"
1035
+ }
1036
+ };
1037
+ function getErrorMessage(code) {
1038
+ return ERROR_CODES[code] || code;
1039
+ }
1040
+ function isErrorCode(code) {
1041
+ return code in ERROR_CODES;
1042
+ }
1043
+ var transformErrors = (zodError) => {
1044
+ const customErrors = [];
1045
+ if (!zodError.issues) return customErrors;
1046
+ zodError.issues.forEach((issue) => {
1047
+ const field = issue.path.join(".");
1048
+ const message = issue.message;
1049
+ if (!customErrors.some(
1050
+ (customError) => customError.field === field && customError.message === message
1051
+ )) {
1052
+ customErrors.push({ field, message });
1053
+ }
1054
+ });
1055
+ return customErrors;
1056
+ };
1057
+ var convertServerErrorToRequestError = (serverError, renameRules) => {
1058
+ return {
1059
+ ...serverError,
1060
+ validationErrors: serverError.validationErrors.map((validationError) => {
1061
+ const field = renameRules && renameRules[validationError.field] ? renameRules[validationError.field] : validationError.field;
1062
+ return {
1063
+ field,
1064
+ message: ERROR_CODES[validationError.code] || "Unknown error"
1065
+ };
1066
+ })
1067
+ };
1068
+ };
1069
+ var errors = ERROR_CONSTANTS;
1070
+
1071
+ // src/utils/currency.ts
1072
+ function getCurrencySymbol(currency) {
1073
+ const currencySymbols = {
1074
+ USD: "$",
1075
+ EUR: "\u20AC",
1076
+ GBP: "\xA3",
1077
+ CAD: "C$",
1078
+ AUD: "A$",
1079
+ JPY: "\xA5",
1080
+ CHF: "CHF",
1081
+ SEK: "kr",
1082
+ NOK: "kr",
1083
+ DKK: "kr",
1084
+ PLN: "z\u0142",
1085
+ CZK: "K\u010D",
1086
+ HUF: "Ft",
1087
+ RON: "lei",
1088
+ BGN: "\u043B\u0432",
1089
+ HRK: "kn",
1090
+ RSD: "\u0434\u0438\u043D",
1091
+ BAM: "KM",
1092
+ MKD: "\u0434\u0435\u043D",
1093
+ ALL: "L",
1094
+ TRY: "\u20BA",
1095
+ RUB: "\u20BD",
1096
+ UAH: "\u20B4",
1097
+ BYN: "Br",
1098
+ CNY: "\xA5",
1099
+ INR: "\u20B9",
1100
+ KRW: "\u20A9",
1101
+ THB: "\u0E3F",
1102
+ VND: "\u20AB",
1103
+ SGD: "S$",
1104
+ MYR: "RM",
1105
+ IDR: "Rp",
1106
+ PHP: "\u20B1",
1107
+ BRL: "R$",
1108
+ ARS: "$",
1109
+ CLP: "$",
1110
+ COP: "$",
1111
+ PEN: "S/",
1112
+ MXN: "$",
1113
+ ZAR: "R",
1114
+ EGP: "E\xA3",
1115
+ NGN: "\u20A6",
1116
+ KES: "KSh",
1117
+ GHS: "\u20B5",
1118
+ MAD: "DH",
1119
+ TND: "\u062F.\u062A",
1120
+ DZD: "\u062F.\u062C",
1121
+ LYD: "\u0644.\u062F",
1122
+ AED: "\u062F.\u0625",
1123
+ SAR: "\u0631.\u0633",
1124
+ QAR: "\u0631.\u0642",
1125
+ KWD: "\u062F.\u0643",
1126
+ BHD: "\u0628.\u062F",
1127
+ OMR: "\u0631.\u0639",
1128
+ JOD: "\u062F.\u0623",
1129
+ LBP: "\u0644.\u0644",
1130
+ SYP: "\u0644.\u0633",
1131
+ IQD: "\u0639.\u062F",
1132
+ IRR: "\uFDFC",
1133
+ AFN: "\u060B",
1134
+ PKR: "\u20A8",
1135
+ LKR: "\u20A8",
1136
+ NPR: "\u20A8",
1137
+ BDT: "\u09F3",
1138
+ MMK: "K",
1139
+ LAK: "\u20AD",
1140
+ KHR: "\u17DB",
1141
+ MNT: "\u20AE",
1142
+ KZT: "\u20B8",
1143
+ UZS: "\u043B\u0432",
1144
+ KGS: "\u043B\u0432",
1145
+ TJS: "SM",
1146
+ TMT: "T",
1147
+ AZN: "\u20BC",
1148
+ GEL: "\u20BE",
1149
+ AMD: "\u058F",
1150
+ BYR: "p.",
1151
+ MDL: "L"
1152
+ };
1153
+ return currencySymbols[currency.toUpperCase()] || currency;
1154
+ }
1155
+
1156
+ // src/utils/price.ts
1157
+ var CURRENCY_SYMBOLS = {
1158
+ "USD": "$",
1159
+ "EUR": "\u20AC",
1160
+ "GBP": "\xA3",
1161
+ "CAD": "C$",
1162
+ "AUD": "A$"
1163
+ };
1164
+ var MARKET_CURRENCIES = {
1165
+ "US": "USD",
1166
+ "EU": "EUR",
1167
+ "UK": "GBP",
1168
+ "CA": "CAD",
1169
+ "AU": "AUD"
1170
+ };
1171
+ function convertToMajor(minorAmount) {
1172
+ return (minorAmount ?? 0) / 100;
1173
+ }
1174
+ function convertToMinor(majorAmount) {
1175
+ return Math.round((majorAmount ?? 0) * 100);
1176
+ }
1177
+ function getSymbol(currency) {
1178
+ return CURRENCY_SYMBOLS[currency] || "$";
1179
+ }
1180
+ function getCurrencyFromMarket(marketId) {
1181
+ return MARKET_CURRENCIES[marketId] || "USD";
1182
+ }
1183
+ function formatCurrencyAmount(amount, currency, options = {}) {
1184
+ const { showSymbols = true, decimalPlaces = 2, customSymbol } = options;
1185
+ const roundedAmount = amount.toFixed(decimalPlaces);
1186
+ if (!showSymbols) {
1187
+ return `${roundedAmount} ${currency}`;
1188
+ }
1189
+ const symbol = customSymbol || getSymbol(currency);
1190
+ return `${symbol}${roundedAmount}`;
1191
+ }
1192
+ function formatMinor(amountMinor, currency, options = {}) {
1193
+ const major = convertToMajor(amountMinor);
1194
+ return formatCurrencyAmount(major, currency, options);
1195
+ }
1196
+ function formatPayment(payment, options = {}) {
1197
+ if (!payment) return "";
1198
+ const { showSymbols = true, decimalPlaces = 2, showBreakdown = false } = options;
1199
+ if (showBreakdown) {
1200
+ const subtotal = formatMinor(payment.subtotal, payment.currency, { showSymbols, decimalPlaces });
1201
+ const discount = (payment.discount ?? 0) > 0 ? formatMinor(payment.discount, payment.currency, { showSymbols, decimalPlaces }) : null;
1202
+ const tax = (payment.tax ?? 0) > 0 ? formatMinor(payment.tax, payment.currency, { showSymbols, decimalPlaces }) : null;
1203
+ const total = formatMinor(payment.total, payment.currency, { showSymbols, decimalPlaces });
1204
+ let result = `Subtotal: ${subtotal}`;
1205
+ if (discount) result += `, Discount: -${discount}`;
1206
+ if (tax) result += `, Tax: ${tax}`;
1207
+ result += `, Total: ${total}`;
1208
+ return result;
1209
+ }
1210
+ return formatMinor(payment.total, payment.currency, { showSymbols, decimalPlaces });
1211
+ }
1212
+ function getMarketPrice(prices, marketId, businessMarkets, options = {}) {
1213
+ if (!prices || prices.length === 0) return "";
1214
+ const {
1215
+ showSymbols = true,
1216
+ decimalPlaces = 2,
1217
+ showCompareAt = true,
1218
+ fallbackMarket = "US"
1219
+ } = options;
1220
+ let price = prices.find((p) => p.market === marketId);
1221
+ if (!price) {
1222
+ price = prices.find((p) => p.market === fallbackMarket) || prices[0];
1223
+ }
1224
+ if (!price) return "";
1225
+ let currency;
1226
+ let symbol;
1227
+ if (businessMarkets) {
1228
+ const marketData = businessMarkets.find((m) => m.id === price.market || m.code === price.market);
1229
+ if (marketData?.currency) {
1230
+ currency = marketData.currency;
1231
+ symbol = getCurrencySymbol(currency);
1232
+ } else {
1233
+ currency = getCurrencyFromMarket(price.market);
1234
+ symbol = getSymbol(currency);
1235
+ }
1236
+ } else {
1237
+ currency = getCurrencyFromMarket(price.market);
1238
+ symbol = getSymbol(currency);
1239
+ }
1240
+ const formattedPrice = formatMinor(price.amount ?? 0, currency, {
1241
+ showSymbols,
1242
+ decimalPlaces,
1243
+ customSymbol: symbol
1244
+ });
1245
+ if (showCompareAt && price.compareAt && price.compareAt > (price.amount ?? 0)) {
1246
+ const formattedCompareAt = formatMinor(price.compareAt, currency, {
1247
+ showSymbols,
1248
+ decimalPlaces,
1249
+ customSymbol: symbol
1250
+ });
1251
+ return `${formattedPrice} was ${formattedCompareAt}`;
1252
+ }
1253
+ return formattedPrice;
1254
+ }
1255
+ function getPriceAmount(prices, marketId, fallbackMarket = "US") {
1256
+ if (!prices || prices.length === 0) return 0;
1257
+ const price = prices.find((p) => p.market === marketId) || prices.find((p) => p.market === fallbackMarket) || prices[0];
1258
+ return price?.amount || 0;
1259
+ }
1260
+ function createPaymentForCheckout(subtotalMinor, marketId, currency, paymentMethod, options = {}) {
1261
+ const { discount = 0, tax = 0, promoCodeId } = options;
1262
+ const total = subtotalMinor - discount + tax;
1263
+ return {
1264
+ currency,
1265
+ market: marketId,
1266
+ subtotal: subtotalMinor,
1267
+ shipping: 0,
1268
+ discount,
1269
+ tax,
1270
+ total,
1271
+ promoCodeId,
1272
+ method: paymentMethod
1273
+ };
1274
+ }
1275
+
1276
+ // src/utils/svg.ts
1277
+ async function fetchSvgContent(mediaObject) {
1278
+ if (!mediaObject) return null;
1279
+ const svgUrl = getImageUrl(mediaObject, false);
1280
+ try {
1281
+ const response = await fetch(svgUrl);
1282
+ if (!response.ok) {
1283
+ console.error(`Failed to fetch SVG: ${response.status} ${response.statusText}`);
1284
+ return null;
1285
+ }
1286
+ const svgContent = await response.text();
1287
+ return svgContent;
1288
+ } catch (error) {
1289
+ console.error("Error fetching SVG:", error);
1290
+ return null;
1291
+ }
1292
+ }
1293
+ async function getSvgContentForAstro(mediaObject) {
1294
+ try {
1295
+ const svgContent = await fetchSvgContent(mediaObject);
1296
+ return svgContent || "";
1297
+ } catch (error) {
1298
+ console.error("Error getting SVG content for Astro:", error);
1299
+ return "";
1300
+ }
1301
+ }
1302
+ async function injectSvgIntoElement(mediaObject, targetElement, className) {
1303
+ if (!targetElement) return;
1304
+ try {
1305
+ const svgContent = await fetchSvgContent(mediaObject);
1306
+ if (svgContent) {
1307
+ targetElement.innerHTML = svgContent;
1308
+ if (className) {
1309
+ const svgElement = targetElement.querySelector("svg");
1310
+ if (svgElement) {
1311
+ svgElement.classList.add(...className.split(" "));
1312
+ }
1313
+ }
1314
+ }
1315
+ } catch (error) {
1316
+ console.error("Error injecting SVG:", error);
1317
+ }
1318
+ }
1319
+
1320
+ // src/utils/text.ts
1321
+ var locales = ["en", "sr-latn"];
1322
+ var localeMap = {
1323
+ "en": "en-US",
1324
+ "sr-latn": "sr-RS"
1325
+ };
1326
+ function slugify(text) {
1327
+ return text.toString().toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
1328
+ }
1329
+ function humanize(text) {
1330
+ const slugifiedText = slugify(text);
1331
+ return slugifiedText.replace(/-/g, " ").replace(
1332
+ // upper case first letter of every word, and lower case the rest
1333
+ /\w\S*/g,
1334
+ (w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()
1335
+ );
1336
+ }
1337
+ function categorify(text) {
1338
+ const slugifiedText = slugify(text);
1339
+ return slugifiedText.replace(/-/g, " ").toUpperCase();
1340
+ }
1341
+ function formatDate(date, locale) {
1342
+ let localeString = "en-US";
1343
+ if (locales.includes(locale)) {
1344
+ localeString = localeMap[locale];
1345
+ }
1346
+ return new Date(date).toLocaleDateString(localeString, {
1347
+ timeZone: "UTC",
1348
+ year: "numeric",
1349
+ month: "short",
1350
+ day: "numeric"
1351
+ });
1352
+ }
1353
+
1354
+ // src/utils/timezone.ts
1355
+ var tzGroups = [
1356
+ {
1357
+ label: "US",
1358
+ zones: [
1359
+ { label: "Eastern Time", value: "America/New_York" },
1360
+ { label: "Central Time", value: "America/Chicago" },
1361
+ { label: "Mountain Time", value: "America/Denver" },
1362
+ { label: "Pacific Time", value: "America/Los_Angeles" }
1363
+ ]
1364
+ },
1365
+ {
1366
+ label: "Europe",
1367
+ zones: [
1368
+ { label: "London", value: "Europe/London" },
1369
+ { label: "Paris", value: "Europe/Paris" },
1370
+ { label: "Berlin", value: "Europe/Berlin" },
1371
+ { label: "Rome", value: "Europe/Rome" }
1372
+ ]
1373
+ },
1374
+ {
1375
+ label: "Asia",
1376
+ zones: [
1377
+ { label: "Tokyo", value: "Asia/Tokyo" },
1378
+ { label: "Shanghai", value: "Asia/Shanghai" },
1379
+ { label: "Mumbai", value: "Asia/Kolkata" },
1380
+ { label: "Dubai", value: "Asia/Dubai" }
1381
+ ]
1382
+ }
1383
+ ];
1384
+ function findTimeZone(groups) {
1385
+ try {
1386
+ const detected = Intl.DateTimeFormat().resolvedOptions().timeZone;
1387
+ for (const group of groups) {
1388
+ for (const zone of group.zones) {
1389
+ if (zone.value === detected) {
1390
+ return detected;
1391
+ }
1392
+ }
1393
+ }
1394
+ return "UTC";
1395
+ } catch (e) {
1396
+ return "UTC";
1397
+ }
1398
+ }
1399
+
1400
+ // src/utils/validation.ts
1401
+ function validatePhoneNumber(phone) {
1402
+ if (!phone) {
1403
+ return { isValid: false, error: "Phone number is required" };
1404
+ }
1405
+ const cleaned = phone.replace(/\D/g, "");
1406
+ if (cleaned.length < 8) {
1407
+ return { isValid: false, error: "Phone number is too short" };
1408
+ }
1409
+ if (cleaned.length > 15) {
1410
+ return { isValid: false, error: "Phone number is too long" };
1411
+ }
1412
+ return { isValid: true };
1413
+ }
1414
+ function validateEmail(email) {
1415
+ if (!email) {
1416
+ return { isValid: false, error: "Email is required" };
1417
+ }
1418
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1419
+ if (!emailRegex.test(email)) {
1420
+ return { isValid: false, error: "Please enter a valid email address" };
1421
+ }
1422
+ return { isValid: true };
1423
+ }
1424
+ function validateVerificationCode(code) {
1425
+ if (!code) {
1426
+ return { isValid: false, error: "Verification code is required" };
1427
+ }
1428
+ const cleaned = code.replace(/\D/g, "");
1429
+ if (cleaned.length !== 4) {
1430
+ return { isValid: false, error: "Please enter a 4-digit verification code" };
1431
+ }
1432
+ return { isValid: true };
1433
+ }
1434
+ function validateRequired(value, fieldName = "This field") {
1435
+ if (value === null || value === void 0 || value === "") {
1436
+ return { isValid: false, error: `${fieldName} is required` };
1437
+ }
1438
+ return { isValid: true };
1439
+ }
1440
+
1441
+ // src/index.ts
1442
+ init_config();
1443
+ var SDK_VERSION = "0.1.0";
1444
+ var SUPPORTED_FRAMEWORKS = ["astro", "react", "vue", "svelte", "vanilla"];
1445
+ function initArky(config) {
1446
+ if (!config.apiUrl) {
1447
+ throw new Error("apiUrl is required");
1448
+ }
1449
+ if (!config.businessId) {
1450
+ throw new Error("businessId is required");
1451
+ }
1452
+ setGlobalConfig(config);
1453
+ return config;
1454
+ }
1455
+
1456
+ export { API_URL, BUSINESS_ID, ERROR_CODES, ERROR_CONSTANTS, PaymentMethod, SDK_VERSION, STORAGE_URL, SUPPORTED_FRAMEWORKS, categorify, cmsApi, convertServerErrorToRequestError, convertToMajor, convertToMinor, createPaymentForCheckout, errors, eshopApi, extractBlockValues, fetchSvgContent, findTimeZone, formatBlockValue, formatCurrencyAmount, formatDate, formatMinor, formatPayment, getBlockFromArray, getBlockLabel, getBlockObjectValues, getBlockTextValue, getBlockValue, getBlockValues, getBusinessConfig, getCurrencyFromMarket, getErrorMessage, getGalleryThumbnail, getGlobalConfig, getGuestToken, getImageUrl, getMarketPrice, getPriceAmount, getSvgContentForAstro, getSymbol, http_default as httpClient, humanize, initArky, injectSvgIntoElement, isErrorCode, newsletterApi, prepareBlocksForSubmission, reservationApi, setGlobalConfig, slugify, thumbnailUrl, transformErrors, translateMap, tzGroups, updateProfilePhone, validateEmail, validatePhoneNumber, validateRequired, validateVerificationCode, verifyPhoneCode };
1457
+ //# sourceMappingURL=index.js.map
1458
+ //# sourceMappingURL=index.js.map