arky-sdk 0.1.0 → 0.1.2

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