arky-sdk 0.9.0 → 0.9.11

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 (43) hide show
  1. package/README.md +113 -194
  2. package/dist/admin-BKXmDIVk.d.ts +1396 -0
  3. package/dist/admin-CAwQrMOX.d.cts +1396 -0
  4. package/dist/admin.cjs +1239 -455
  5. package/dist/admin.cjs.map +1 -1
  6. package/dist/admin.d.cts +3 -3
  7. package/dist/admin.d.ts +3 -3
  8. package/dist/admin.js +1239 -455
  9. package/dist/admin.js.map +1 -1
  10. package/dist/api-DJI3S6XA.d.cts +4204 -0
  11. package/dist/api-DJI3S6XA.d.ts +4204 -0
  12. package/dist/{index-C5gikdBg.d.cts → index-BaSBPLdF.d.ts} +1 -1
  13. package/dist/{index-MFMjlIfS.d.ts → index-u-gjHnKs.d.cts} +1 -1
  14. package/dist/index.cjs +1360 -610
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -3
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +1360 -610
  19. package/dist/index.js.map +1 -1
  20. package/dist/storefront.cjs +590 -382
  21. package/dist/storefront.cjs.map +1 -1
  22. package/dist/storefront.d.cts +182 -156
  23. package/dist/storefront.d.ts +182 -156
  24. package/dist/storefront.js +588 -381
  25. package/dist/storefront.js.map +1 -1
  26. package/dist/types.cjs.map +1 -1
  27. package/dist/types.d.cts +1 -2666
  28. package/dist/types.d.ts +1 -2666
  29. package/dist/types.js.map +1 -1
  30. package/dist/utils.d.cts +2 -2
  31. package/dist/utils.d.ts +2 -2
  32. package/package.json +9 -11
  33. package/scripts/contract-admin.mjs +137 -0
  34. package/scripts/contract-storefront.mjs +296 -0
  35. package/dist/admin-CfHen7c5.d.cts +0 -1036
  36. package/dist/admin-ru7pX5bd.d.ts +0 -1036
  37. package/dist/storefront-store.cjs +0 -2794
  38. package/dist/storefront-store.cjs.map +0 -1
  39. package/dist/storefront-store.d.cts +0 -5
  40. package/dist/storefront-store.d.ts +0 -5
  41. package/dist/storefront-store.js +0 -2792
  42. package/dist/storefront-store.js.map +0 -1
  43. package/scripts/smoke-store.mjs +0 -41
@@ -2,132 +2,6 @@
2
2
 
3
3
  var nanostores = require('nanostores');
4
4
 
5
- // src/utils/blocks.ts
6
- function getBlockLabel(block) {
7
- if (!block) return "";
8
- return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) ?? "";
9
- }
10
- function formatBlockValue(block) {
11
- if (!block || block.value === null || block.value === void 0) return "";
12
- const value = block.value;
13
- switch (block.type) {
14
- case "boolean":
15
- return value ? "Yes" : "No";
16
- case "number":
17
- if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
18
- return new Date(value).toLocaleDateString();
19
- }
20
- return String(value);
21
- case "relationship_entry":
22
- case "relationship_media":
23
- if (value && typeof value === "object") {
24
- return value.mime_type ? value.name || value.id : value.title || value.name || value.id;
25
- }
26
- return String(value);
27
- default:
28
- return String(value);
29
- }
30
- }
31
- function prepareBlocksForSubmission(formData, blockTypes) {
32
- return Object.keys(formData).filter((key) => formData[key] !== null && formData[key] !== void 0).map((key) => ({
33
- key,
34
- value: blockTypes?.[key] === "list" && !Array.isArray(formData[key]) ? [formData[key]] : formData[key]
35
- }));
36
- }
37
- function extractBlockValues(blocks) {
38
- const values = {};
39
- blocks.forEach((block) => {
40
- values[block.key] = block.value ?? null;
41
- });
42
- return values;
43
- }
44
- var getBlockValue = (entry, blockKey) => {
45
- const block = entry?.blocks?.find((f) => f.key === blockKey);
46
- return block?.value ?? null;
47
- };
48
- var getBlockTextValue = (block, locale = "en") => {
49
- if (!block || block.value === null || block.value === void 0) return "";
50
- if (block.type === "localized_text" || block.type === "markdown") {
51
- if (typeof block.value === "object" && block.value !== null) {
52
- return block.value[locale] ?? block.value["en"] ?? "";
53
- }
54
- }
55
- if (typeof block.value === "string") return block.value;
56
- return String(block.value ?? "");
57
- };
58
- var getBlockValues = (entry, blockKey) => {
59
- const block = entry?.blocks?.find((f) => f.key === blockKey);
60
- if (!block) return [];
61
- if (block.type === "list" && Array.isArray(block.value)) {
62
- return block.value;
63
- }
64
- return [];
65
- };
66
- function unwrapBlock(block, locale) {
67
- if (!block?.type || block.value === void 0) return block;
68
- if (block.type === "list") {
69
- return block.value.map((obj) => {
70
- const parsed = {};
71
- for (const [k, v] of Object.entries(obj)) {
72
- parsed[k] = unwrapBlock(v, locale);
73
- }
74
- return parsed;
75
- });
76
- }
77
- if (block.type === "map") {
78
- const parsed = {};
79
- for (const [k, v] of Object.entries(block.value || {})) {
80
- parsed[k] = unwrapBlock(v, locale);
81
- }
82
- return parsed;
83
- }
84
- if (block.type === "localized_text" || block.type === "markdown") {
85
- return block.value?.[locale];
86
- }
87
- return block.value;
88
- }
89
- var getBlockObjectValues = (entry, blockKey, locale = "en") => {
90
- const block = entry?.blocks?.find((f) => f.key === blockKey);
91
- if (!block || block.type !== "list" || !Array.isArray(block.value)) return [];
92
- return block.value.map((obj) => {
93
- if (!obj?.value || !Array.isArray(obj.value)) return {};
94
- return obj.value.reduce((acc, current) => {
95
- acc[current.key] = unwrapBlock(current, locale);
96
- return acc;
97
- }, {});
98
- });
99
- };
100
- var getBlockFromArray = (entry, blockKey, locale = "en") => {
101
- const block = entry?.blocks?.find((f) => f.key === blockKey);
102
- if (!block) return {};
103
- if (block.type === "list" && Array.isArray(block.value)) {
104
- return block.value.reduce((acc, current) => {
105
- acc[current.key] = unwrapBlock(current, locale);
106
- return acc;
107
- }, {});
108
- }
109
- if (block.type === "map" && block.value && typeof block.value === "object") {
110
- const result = {};
111
- for (const [k, v] of Object.entries(block.value)) {
112
- result[k] = unwrapBlock(v, locale);
113
- }
114
- return result;
115
- }
116
- return { [block.key]: unwrapBlock(block, locale) };
117
- };
118
- var getImageUrl = (imageBlock, isBlock = true) => {
119
- if (!imageBlock) return null;
120
- if (imageBlock.type === "relationship_media") {
121
- const mediaValue = imageBlock.value;
122
- return mediaValue?.resolutions?.original?.url || mediaValue?.url || null;
123
- }
124
- if (isBlock) {
125
- if (typeof imageBlock === "string") return imageBlock;
126
- if (imageBlock.url) return imageBlock.url;
127
- }
128
- return imageBlock.resolutions?.original?.url || null;
129
- };
130
-
131
5
  // src/utils/orderItems.ts
132
6
  function normalizeOrderCheckoutItems(items) {
133
7
  return items.map((item) => {
@@ -148,36 +22,36 @@ function normalizePublicCheckoutItems(items) {
148
22
  }
149
23
 
150
24
  // src/api/storefront.ts
151
- var COMMON_ACTIVITY_TYPES = [
152
- "page_view",
153
- "product_view",
154
- "service_view",
155
- "provider_view",
156
- "cart_added",
157
- "cart_removed",
158
- "checkout_started",
159
- "purchase",
160
- "order_created",
25
+ var COMMON_ACTION_KEYS = [
26
+ "page.view",
27
+ "product.view",
28
+ "service.view",
29
+ "provider.view",
30
+ "cart.added",
31
+ "cart.removed",
32
+ "checkout.started",
33
+ "order.created",
161
34
  "signin",
162
35
  "signup",
163
- "verified_email",
36
+ "verified.email",
164
37
  "search",
165
38
  "share",
166
- "wishlist_added"
39
+ "wishlist.added"
167
40
  ];
168
- var createActivityApi = (apiConfig) => ({
169
- COMMON_ACTIVITY_TYPES,
41
+ var createActionApi = (apiConfig) => ({
42
+ COMMON_ACTION_KEYS,
170
43
  async track(params) {
171
44
  try {
45
+ const key = "key" in params && params.key ? params.key : params.type;
172
46
  await apiConfig.httpClient.post(
173
- `/v1/storefront/${apiConfig.storeId}/activities/track`,
174
- { type: params.type, payload: params.payload }
47
+ `/v1/storefront/${apiConfig.storeId}/actions/track`,
48
+ { key, payload: params.payload }
175
49
  );
176
50
  } catch {
177
51
  }
178
52
  }
179
53
  });
180
- var createStorefrontApi = (apiConfig, updateCustomerSession) => {
54
+ var createStorefrontApi = (apiConfig, updateContactSession) => {
181
55
  const base = (storeId = apiConfig.storeId) => `/v1/storefront/${storeId}`;
182
56
  return {
183
57
  store: {
@@ -211,47 +85,32 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
211
85
  }
212
86
  },
213
87
  cms: {
214
- node: {
215
- async get(params, options) {
88
+ collection: {
89
+ get(params, options) {
216
90
  const store_id = params.store_id || apiConfig.storeId;
217
- let identifier;
218
- if (params.id) {
219
- identifier = params.id;
220
- } else if (params.slug) {
221
- identifier = `${store_id}:${apiConfig.locale}:${params.slug}`;
222
- } else if (params.key) {
223
- identifier = `${store_id}:${params.key}`;
224
- } else {
225
- throw new Error("GetNodeParams requires id, slug, or key");
91
+ if (!params.id) {
92
+ throw new Error("GetCollectionParams requires id");
226
93
  }
227
- const response = await apiConfig.httpClient.get(
228
- `${base(store_id)}/nodes/${identifier}`,
94
+ return apiConfig.httpClient.get(
95
+ `${base(store_id)}/collections/${params.id}`,
96
+ options
97
+ );
98
+ }
99
+ },
100
+ entry: {
101
+ get(params, options) {
102
+ const store_id = params.store_id || apiConfig.storeId;
103
+ if (!params.id) {
104
+ throw new Error("GetEntryParams requires id");
105
+ }
106
+ return apiConfig.httpClient.get(
107
+ `${base(store_id)}/entries/${params.id}`,
229
108
  options
230
109
  );
231
- return {
232
- ...response,
233
- getBlock(key) {
234
- return getBlockFromArray(response, key, apiConfig.locale);
235
- },
236
- getBlockValues(key) {
237
- return getBlockObjectValues(response, key, apiConfig.locale);
238
- },
239
- getImage(key) {
240
- const block = getBlockFromArray(response, key, apiConfig.locale);
241
- return getImageUrl(block, true);
242
- }
243
- };
244
110
  },
245
111
  find(params, options) {
246
112
  const { store_id, ...queryParams } = params;
247
- return apiConfig.httpClient.get(`${base(store_id)}/nodes`, {
248
- ...options,
249
- params: queryParams
250
- });
251
- },
252
- getChildren(params, options) {
253
- const { id, store_id, ...queryParams } = params;
254
- return apiConfig.httpClient.get(`${base(store_id)}/nodes/${id}/children`, {
113
+ return apiConfig.httpClient.get(`${base(store_id)}/entries`, {
255
114
  ...options,
256
115
  params: queryParams
257
116
  });
@@ -411,7 +270,9 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
411
270
  {
412
271
  id: params.id,
413
272
  store_id,
414
- payment_method_id: params.payment_method_id
273
+ payment_method_key: params.payment_method_key,
274
+ confirmation_token_id: params.confirmation_token_id,
275
+ return_url: params.return_url
415
276
  },
416
277
  options
417
278
  );
@@ -431,6 +292,14 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
431
292
  ...options,
432
293
  params: queryParams
433
294
  });
295
+ },
296
+ downloadDigitalAccess(params, options) {
297
+ const store_id = params.store_id || apiConfig.storeId;
298
+ return apiConfig.httpClient.post(
299
+ `${base(store_id)}/orders/${params.id}/digital-access/${params.grant_id}/download`,
300
+ {},
301
+ options
302
+ );
434
303
  }
435
304
  },
436
305
  service: {
@@ -498,11 +367,11 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
498
367
  }
499
368
  },
500
369
  crm: {
501
- customer: {
370
+ contact: {
502
371
  async identify(params, options) {
503
372
  const store_id = apiConfig.storeId;
504
373
  const result = await apiConfig.httpClient.post(
505
- `${base(store_id)}/customers/identify`,
374
+ `${base(store_id)}/account/identify`,
506
375
  {
507
376
  store_id,
508
377
  market: params?.market || apiConfig.market || null,
@@ -512,9 +381,9 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
512
381
  options
513
382
  );
514
383
  if (result?.token?.token) {
515
- updateCustomerSession(() => ({
384
+ updateContactSession(() => ({
516
385
  access_token: result.token.token,
517
- customer: result.customer,
386
+ contact: result.contact,
518
387
  store: result.store,
519
388
  market: result.market
520
389
  }));
@@ -524,12 +393,12 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
524
393
  async verify(params, options) {
525
394
  const store_id = apiConfig.storeId;
526
395
  const result = await apiConfig.httpClient.post(
527
- `${base(store_id)}/customers/verify`,
396
+ `${base(store_id)}/account/verify`,
528
397
  { store_id, code: params.code },
529
398
  options
530
399
  );
531
400
  if (result?.token) {
532
- updateCustomerSession(
401
+ updateContactSession(
533
402
  (prev) => prev ? { ...prev, access_token: result.token } : null
534
403
  );
535
404
  }
@@ -539,131 +408,74 @@ var createStorefrontApi = (apiConfig, updateCustomerSession) => {
539
408
  const store_id = apiConfig.storeId;
540
409
  try {
541
410
  await apiConfig.httpClient.post(
542
- `${base(store_id)}/customers/logout`,
411
+ `${base(store_id)}/account/logout`,
543
412
  {},
544
413
  options
545
414
  );
546
415
  } finally {
547
- updateCustomerSession(() => null);
416
+ updateContactSession(() => null);
548
417
  }
549
418
  },
550
419
  getMe(options) {
551
- return apiConfig.httpClient.get(`${base()}/customers/me`, options);
420
+ return apiConfig.httpClient.get(`${base()}/account/me`, options);
552
421
  }
553
422
  },
554
- audience: {
423
+ contactList: {
555
424
  get(params, options) {
556
- let identifier;
557
- if (params.id) {
558
- identifier = params.id;
559
- } else if (params.key) {
560
- identifier = `${apiConfig.storeId}:${params.key}`;
561
- } else {
562
- throw new Error("GetAudienceParams requires id or key");
563
- }
425
+ const store_id = params.store_id || apiConfig.storeId;
564
426
  return apiConfig.httpClient.get(
565
- `${base(apiConfig.storeId)}/audiences/${identifier}`,
427
+ `${base(store_id)}/contact-lists/${params.id}`,
566
428
  options
567
429
  );
568
430
  },
569
431
  find(params, options) {
570
- return apiConfig.httpClient.get(`${base()}/audiences`, {
432
+ const { store_id, ...queryParams } = params || {};
433
+ return apiConfig.httpClient.get(`${base(store_id)}/contact-lists`, {
571
434
  ...options,
572
- params
435
+ params: queryParams
573
436
  });
574
437
  },
575
438
  subscribe(params, options) {
439
+ const { store_id, id, ...payload } = params;
576
440
  return apiConfig.httpClient.post(
577
- `${base()}/audiences/${params.id}/subscribe`,
578
- {
579
- customer_id: params.customer_id,
580
- price_id: params.price_id,
581
- success_url: params.success_url,
582
- cancel_url: params.cancel_url,
583
- confirm_url: params.confirm_url
584
- },
441
+ `${base(store_id)}/contact-lists/${id}/subscribe`,
442
+ payload,
585
443
  options
586
444
  );
587
445
  },
588
446
  checkAccess(params, options) {
589
- return apiConfig.httpClient.get(
590
- `${base()}/audiences/${params.id}/access`,
591
- options
592
- );
593
- },
594
- unsubscribe(token, options) {
595
- return apiConfig.httpClient.get(`${base()}/audiences/unsubscribe`, {
596
- ...options,
597
- params: { token }
598
- });
599
- },
600
- confirm(token, options) {
601
- return apiConfig.httpClient.get(`${base()}/audiences/confirm`, {
602
- ...options,
603
- params: { token }
604
- });
605
- }
606
- }
607
- },
608
- activity: createActivityApi(apiConfig),
609
- automation: {
610
- agent: {
611
- getAgents(params, options) {
612
- const store_id = params?.store_id || apiConfig.storeId;
613
- const queryParams = { ...params || {} };
614
- delete queryParams.store_id;
615
- return apiConfig.httpClient.get(`${base(store_id)}/agents`, {
616
- ...options,
617
- params: Object.keys(queryParams).length > 0 ? queryParams : void 0
618
- });
619
- },
620
- getAgent(params, options) {
621
447
  const store_id = params.store_id || apiConfig.storeId;
622
448
  return apiConfig.httpClient.get(
623
- `${base(store_id)}/agents/${params.id}`,
449
+ `${base(store_id)}/contact-lists/${params.id}/access`,
624
450
  options
625
451
  );
626
452
  },
627
- sendMessage(params, options) {
628
- const store_id = params.store_id || apiConfig.storeId;
629
- const body = { message: params.message };
630
- if (params.chat_id) body.chat_id = params.chat_id;
453
+ unsubscribe(token, options) {
631
454
  return apiConfig.httpClient.post(
632
- `${base(store_id)}/agents/${params.id}/chats/messages`,
633
- body,
634
- options
635
- );
636
- },
637
- getChat(params, options) {
638
- const store_id = params.store_id || apiConfig.storeId;
639
- return apiConfig.httpClient.get(
640
- `${base(store_id)}/agents/${params.id}/chats/${params.chat_id}`,
455
+ `${base()}/contact-lists/unsubscribe`,
456
+ { token },
641
457
  options
642
458
  );
643
459
  },
644
- getChatMessages(params, options) {
645
- const store_id = params.store_id || apiConfig.storeId;
646
- const queryParams = {};
647
- if (params.limit) queryParams.limit = String(params.limit);
648
- return apiConfig.httpClient.get(
649
- `${base(store_id)}/agents/${params.id}/chats/${params.chat_id}/messages`,
650
- {
651
- ...options,
652
- params: Object.keys(queryParams).length > 0 ? queryParams : void 0
653
- }
654
- );
655
- },
656
- rateChat(params, options) {
657
- const store_id = params.store_id || apiConfig.storeId;
658
- const body = { rating: params.rating };
659
- if (params.comment) body.comment = params.comment;
460
+ confirm(token, options) {
660
461
  return apiConfig.httpClient.post(
661
- `${base(store_id)}/agents/${params.id}/chats/${params.chat_id}/rate`,
662
- body,
462
+ `${base()}/contact-lists/confirm`,
463
+ { token },
663
464
  options
664
465
  );
665
466
  }
666
467
  }
468
+ },
469
+ action: createActionApi(apiConfig),
470
+ experiments: {
471
+ use(params, options) {
472
+ const store_id = params.store_id || apiConfig.storeId;
473
+ return apiConfig.httpClient.post(
474
+ `${base(store_id)}/experiments/use`,
475
+ { key: params.key },
476
+ options
477
+ );
478
+ }
667
479
  }
668
480
  };
669
481
  };
@@ -889,7 +701,7 @@ function createHttpClient(cfg) {
889
701
  headers["Authorization"] = `Bearer ${tokens.access_token}`;
890
702
  }
891
703
  const finalPath = options?.params ? path + buildQueryString(options.params) : path;
892
- const fetchOpts = { method, headers };
704
+ const fetchOpts = { method, headers, signal: options?.signal };
893
705
  if (!["GET", "DELETE"].includes(method) && body !== void 0) {
894
706
  fetchOpts.body = JSON.stringify(body);
895
707
  }
@@ -900,13 +712,15 @@ function createHttpClient(cfg) {
900
712
  try {
901
713
  res = await fetch(fullUrl, fetchOpts);
902
714
  } catch (error) {
715
+ const aborted = options?.signal?.aborted || error instanceof Error && error.name === "AbortError";
903
716
  const err = new Error(error instanceof Error ? error.message : "Network request failed");
904
- err.name = "NetworkError";
717
+ err.name = aborted ? "AbortError" : "NetworkError";
905
718
  err.method = method;
906
719
  err.url = fullUrl;
720
+ err.aborted = aborted;
907
721
  if (options?.onError && method !== "GET") {
908
722
  Promise.resolve(
909
- options.onError({ error: err, method, url: fullUrl, aborted: false })
723
+ options.onError({ error: err, method, url: fullUrl, aborted })
910
724
  ).catch(() => {
911
725
  });
912
726
  }
@@ -999,6 +813,168 @@ function createHttpClient(cfg) {
999
813
  };
1000
814
  }
1001
815
 
816
+ // src/api/support.ts
817
+ function supportConversationQuery(params) {
818
+ const qs = new URLSearchParams({ store_id: params.store_id });
819
+ if (params.message_limit) qs.set("message_limit", String(params.message_limit));
820
+ if (typeof params.after_created_at === "number") qs.set("after_created_at", String(params.after_created_at));
821
+ if (params.after_id) qs.set("after_id", params.after_id);
822
+ return qs.toString();
823
+ }
824
+ function createStorefrontSupportApi(config) {
825
+ const { httpClient, storeId } = config;
826
+ return {
827
+ async startConversation(params = {}, opts) {
828
+ return httpClient.post(
829
+ `/v1/storefront/${storeId}/support/conversations`,
830
+ { store_id: storeId, ...params },
831
+ opts
832
+ );
833
+ },
834
+ async sendMessage(params, opts) {
835
+ return httpClient.post(
836
+ `/v1/storefront/${storeId}/support/conversations/${params.conversation_id}/messages`,
837
+ { store_id: storeId, ...params },
838
+ opts
839
+ );
840
+ },
841
+ async getConversation(params, opts) {
842
+ const qs = supportConversationQuery({ store_id: storeId, ...params });
843
+ return httpClient.get(
844
+ `/v1/storefront/${storeId}/support/conversations/${params.conversation_id}?${qs}`,
845
+ opts
846
+ );
847
+ }
848
+ };
849
+ }
850
+
851
+ // src/utils/blocks.ts
852
+ function getBlockLabel(block) {
853
+ if (!block) return "";
854
+ return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) ?? "";
855
+ }
856
+ function formatBlockValue(block) {
857
+ if (!block || block.value === null || block.value === void 0) return "";
858
+ const value = block.value;
859
+ switch (block.type) {
860
+ case "boolean":
861
+ return value ? "Yes" : "No";
862
+ case "number":
863
+ if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
864
+ return new Date(value).toLocaleDateString();
865
+ }
866
+ return String(value);
867
+ case "media":
868
+ if (value && typeof value === "object") {
869
+ return value.mime_type ? value.name || value.id : value.title || value.name || value.id;
870
+ }
871
+ return String(value);
872
+ default:
873
+ return String(value);
874
+ }
875
+ }
876
+ function prepareBlocksForSubmission(formData, blockTypes) {
877
+ return Object.keys(formData).filter((key) => formData[key] !== null && formData[key] !== void 0).map((key) => ({
878
+ key,
879
+ value: (blockTypes?.[key] || "text") === "array" && !Array.isArray(formData[key]) ? [formData[key]] : formData[key]
880
+ }));
881
+ }
882
+ function extractBlockValues(blocks) {
883
+ const values = {};
884
+ blocks.forEach((block) => {
885
+ values[block.key] = block.value ?? null;
886
+ });
887
+ return values;
888
+ }
889
+ var getBlockValue = (entry, blockKey) => {
890
+ const block = entry?.blocks?.find((f) => f.key === blockKey);
891
+ return block?.value ?? null;
892
+ };
893
+ var getBlockTextValue = (block, locale = "en") => {
894
+ if (!block || block.value === null || block.value === void 0) return "";
895
+ const blockType = block.type;
896
+ if (blockType === "localized_text" || blockType === "markdown") {
897
+ if (typeof block.value === "object" && block.value !== null) {
898
+ return block.value[locale] ?? block.value["en"] ?? "";
899
+ }
900
+ }
901
+ if (typeof block.value === "string") return block.value;
902
+ return String(block.value ?? "");
903
+ };
904
+ var getBlockValues = (entry, blockKey) => {
905
+ const block = entry?.blocks?.find((f) => f.key === blockKey);
906
+ if (!block) return [];
907
+ if (block.type === "array" && Array.isArray(block.value)) {
908
+ return block.value;
909
+ }
910
+ return [];
911
+ };
912
+ function unwrapBlock(block, locale) {
913
+ if (!block?.type || block.value === void 0) return block;
914
+ const blockType = block.type;
915
+ if (blockType === "array") {
916
+ return block.value.map((obj) => {
917
+ const parsed = {};
918
+ for (const [k, v] of Object.entries(obj)) {
919
+ parsed[k] = unwrapBlock(v, locale);
920
+ }
921
+ return parsed;
922
+ });
923
+ }
924
+ if (blockType === "object") {
925
+ const parsed = {};
926
+ for (const [k, v] of Object.entries(block.value || {})) {
927
+ parsed[k] = unwrapBlock(v, locale);
928
+ }
929
+ return parsed;
930
+ }
931
+ if (blockType === "localized_text" || blockType === "markdown") {
932
+ return block.value?.[locale];
933
+ }
934
+ return block.value;
935
+ }
936
+ var getBlockObjectValues = (entry, blockKey, locale = "en") => {
937
+ const block = entry?.blocks?.find((f) => f.key === blockKey);
938
+ if (!block || block.type !== "array" || !Array.isArray(block.value)) return [];
939
+ return block.value.map((obj) => {
940
+ if (!obj?.value || !Array.isArray(obj.value)) return {};
941
+ return obj.value.reduce((acc, current) => {
942
+ acc[current.key] = unwrapBlock(current, locale);
943
+ return acc;
944
+ }, {});
945
+ });
946
+ };
947
+ var getBlockFromArray = (entry, blockKey, locale = "en") => {
948
+ const block = entry?.blocks?.find((f) => f.key === blockKey);
949
+ if (!block) return {};
950
+ if (block.type === "array" && Array.isArray(block.value)) {
951
+ return block.value.reduce((acc, current) => {
952
+ acc[current.key] = unwrapBlock(current, locale);
953
+ return acc;
954
+ }, {});
955
+ }
956
+ if (block.type === "object" && block.value && typeof block.value === "object") {
957
+ const result = {};
958
+ for (const [k, v] of Object.entries(block.value)) {
959
+ result[k] = unwrapBlock(v, locale);
960
+ }
961
+ return result;
962
+ }
963
+ return { [block.key]: unwrapBlock(block, locale) };
964
+ };
965
+ var getImageUrl = (imageBlock, isBlock = true) => {
966
+ if (!imageBlock) return null;
967
+ if (imageBlock.type === "media") {
968
+ const mediaValue = imageBlock.value;
969
+ return mediaValue?.resolutions?.original?.url || mediaValue?.url || null;
970
+ }
971
+ if (isBlock) {
972
+ if (typeof imageBlock === "string") return imageBlock;
973
+ if (imageBlock.url) return imageBlock.url;
974
+ }
975
+ return imageBlock.resolutions?.original?.url || null;
976
+ };
977
+
1002
978
  // src/utils/price.ts
1003
979
  function formatCurrency(amount, currencyCode, locale = "en") {
1004
980
  if (!currencyCode) return "";
@@ -1288,22 +1264,22 @@ function createUtilitySurface(apiConfig) {
1288
1264
  getFirstAvailableFCId
1289
1265
  };
1290
1266
  }
1291
- var CUSTOMER_STORAGE_KEY = "arky_customer_session";
1292
- function readCustomerSession() {
1267
+ var CONTACT_STORAGE_KEY = "arky_contact_session";
1268
+ function readContactSession() {
1293
1269
  if (typeof window === "undefined") return null;
1294
1270
  try {
1295
- const raw = localStorage.getItem(CUSTOMER_STORAGE_KEY);
1271
+ const raw = localStorage.getItem(CONTACT_STORAGE_KEY);
1296
1272
  return raw ? JSON.parse(raw) : null;
1297
1273
  } catch {
1298
1274
  return null;
1299
1275
  }
1300
1276
  }
1301
- function writeCustomerSession(s) {
1277
+ function writeContactSession(s) {
1302
1278
  if (typeof window === "undefined") return;
1303
1279
  if (s) {
1304
- localStorage.setItem(CUSTOMER_STORAGE_KEY, JSON.stringify(s));
1280
+ localStorage.setItem(CONTACT_STORAGE_KEY, JSON.stringify(s));
1305
1281
  } else {
1306
- localStorage.removeItem(CUSTOMER_STORAGE_KEY);
1282
+ localStorage.removeItem(CONTACT_STORAGE_KEY);
1307
1283
  }
1308
1284
  }
1309
1285
  function createStorefront(config) {
@@ -1312,10 +1288,10 @@ function createStorefront(config) {
1312
1288
  const listeners = /* @__PURE__ */ new Set();
1313
1289
  let bareIdentifyPromise = null;
1314
1290
  function toPublic(s) {
1315
- return s ? { customer: s.customer, store: s.store, market: s.market } : null;
1291
+ return s ? { contact: s.contact, store: s.store, market: s.market } : null;
1316
1292
  }
1317
1293
  function emit() {
1318
- const pub = toPublic(readCustomerSession());
1294
+ const pub = toPublic(readContactSession());
1319
1295
  for (const l of listeners) {
1320
1296
  Promise.resolve().then(() => l(pub)).catch(() => {
1321
1297
  });
@@ -1323,9 +1299,9 @@ function createStorefront(config) {
1323
1299
  }
1324
1300
  const updateSession = (updater) => {
1325
1301
  if (config.apiToken) return;
1326
- const prev = readCustomerSession();
1302
+ const prev = readContactSession();
1327
1303
  const next = updater(prev);
1328
- writeCustomerSession(next);
1304
+ writeContactSession(next);
1329
1305
  emit();
1330
1306
  };
1331
1307
  const authStorage = config.apiToken ? {
@@ -1336,7 +1312,7 @@ function createStorefront(config) {
1336
1312
  }
1337
1313
  } : {
1338
1314
  getTokens() {
1339
- const s = readCustomerSession();
1315
+ const s = readContactSession();
1340
1316
  return s ? { access_token: s.access_token } : null;
1341
1317
  },
1342
1318
  onTokensRefreshed() {
@@ -1363,20 +1339,20 @@ function createStorefront(config) {
1363
1339
  authStorage
1364
1340
  };
1365
1341
  const storefrontApi = createStorefrontApi(apiConfig, updateSession);
1366
- const customerApi = storefrontApi.crm.customer;
1342
+ const contactApi = storefrontApi.crm.contact;
1367
1343
  function identify(params) {
1368
1344
  if (params?.market !== void 0) apiConfig.market = params.market;
1369
1345
  const isBareCall = !params?.email && !params?.verify;
1370
1346
  if (isBareCall && bareIdentifyPromise) return bareIdentifyPromise;
1371
1347
  const promise = (async () => {
1372
1348
  try {
1373
- const result = await customerApi.identify({
1349
+ const result = await contactApi.identify({
1374
1350
  market: apiConfig.market,
1375
1351
  email: params?.email,
1376
1352
  verify: params?.verify
1377
1353
  });
1378
1354
  return {
1379
- customer: result.customer,
1355
+ contact: result.contact,
1380
1356
  store: result.store,
1381
1357
  market: result.market
1382
1358
  };
@@ -1385,9 +1361,11 @@ function createStorefront(config) {
1385
1361
  const status = e?.statusCode || e?.status || e?.response?.status;
1386
1362
  if (isBareCall && status === 401) {
1387
1363
  updateSession(() => null);
1388
- const result = await customerApi.identify({ market: apiConfig.market });
1364
+ const result = await contactApi.identify({
1365
+ market: apiConfig.market
1366
+ });
1389
1367
  return {
1390
- customer: result.customer,
1368
+ contact: result.contact,
1391
1369
  store: result.store,
1392
1370
  market: result.market
1393
1371
  };
@@ -1402,7 +1380,7 @@ function createStorefront(config) {
1402
1380
  return promise;
1403
1381
  }
1404
1382
  async function verify(params) {
1405
- const result = await customerApi.verify(params);
1383
+ const result = await contactApi.verify(params);
1406
1384
  bareIdentifyPromise = null;
1407
1385
  return result;
1408
1386
  }
@@ -1410,7 +1388,7 @@ function createStorefront(config) {
1410
1388
  if (config.apiToken) return;
1411
1389
  bareIdentifyPromise = null;
1412
1390
  try {
1413
- await customerApi.logout();
1391
+ await contactApi.logout();
1414
1392
  } catch {
1415
1393
  updateSession(() => null);
1416
1394
  }
@@ -1419,19 +1397,19 @@ function createStorefront(config) {
1419
1397
  identify,
1420
1398
  verify,
1421
1399
  logout,
1422
- me: () => customerApi.getMe(),
1400
+ me: () => contactApi.getMe(),
1423
1401
  get session() {
1424
1402
  if (config.apiToken) return null;
1425
- return toPublic(readCustomerSession());
1403
+ return toPublic(readContactSession());
1426
1404
  },
1427
1405
  get isAuthenticated() {
1428
1406
  if (config.apiToken) return true;
1429
- const s = readCustomerSession();
1407
+ const s = readContactSession();
1430
1408
  return s !== null && !!s.access_token;
1431
1409
  },
1432
1410
  onAuthStateChanged(listener) {
1433
1411
  listeners.add(listener);
1434
- const current = toPublic(readCustomerSession());
1412
+ const current = toPublic(readContactSession());
1435
1413
  if (current) {
1436
1414
  Promise.resolve().then(() => listener(current)).catch(() => {
1437
1415
  });
@@ -1445,8 +1423,9 @@ function createStorefront(config) {
1445
1423
  cms: storefrontApi.cms,
1446
1424
  eshop: storefrontApi.eshop,
1447
1425
  crm: storefrontApi.crm,
1448
- activity: storefrontApi.activity,
1449
- automation: storefrontApi.automation,
1426
+ action: storefrontApi.action,
1427
+ experiments: storefrontApi.experiments,
1428
+ support: createStorefrontSupportApi(apiConfig),
1450
1429
  setStoreId: (storeId) => {
1451
1430
  apiConfig.storeId = storeId;
1452
1431
  bareIdentifyPromise = null;
@@ -1461,11 +1440,81 @@ function createStorefront(config) {
1461
1440
  apiConfig.locale = l;
1462
1441
  },
1463
1442
  getLocale: () => apiConfig.locale,
1464
- extractBlockValues,
1465
1443
  utils: createUtilitySurface(apiConfig)
1466
1444
  };
1467
1445
  }
1468
1446
 
1447
+ // src/payments/stripe.ts
1448
+ function normalizeCurrency(currency) {
1449
+ return currency.trim().toLowerCase();
1450
+ }
1451
+ async function createStripeConfirmationTokenController(config) {
1452
+ const { loadStripe } = await import('@stripe/stripe-js');
1453
+ const stripe = await loadStripe(config.publishableKey);
1454
+ if (!stripe) throw new Error("Stripe failed to initialize");
1455
+ let elements = createElements(stripe, config);
1456
+ let paymentElement = elements.create("payment", {
1457
+ layout: "tabs"
1458
+ });
1459
+ return {
1460
+ mount(target) {
1461
+ if (!paymentElement) {
1462
+ paymentElement = elements.create("payment", { layout: "tabs" });
1463
+ }
1464
+ paymentElement.mount(target);
1465
+ },
1466
+ update(input) {
1467
+ elements.update({
1468
+ ...input.amount !== void 0 ? { amount: input.amount } : {},
1469
+ ...input.currency ? { currency: normalizeCurrency(input.currency) } : {}
1470
+ });
1471
+ },
1472
+ async createConfirmationToken(options = {}) {
1473
+ const submitResult = await elements.submit();
1474
+ if (submitResult.error) {
1475
+ throw new Error(submitResult.error.message || "Payment details are incomplete");
1476
+ }
1477
+ const tokenInput = {
1478
+ elements,
1479
+ params: {
1480
+ ...options.return_url ? { return_url: options.return_url } : {},
1481
+ ...options.billing_details ? { payment_method_data: { billing_details: options.billing_details } } : {}
1482
+ }
1483
+ };
1484
+ const result = await stripe.createConfirmationToken(tokenInput);
1485
+ if (result.error) {
1486
+ throw new Error(result.error.message || "Payment confirmation token failed");
1487
+ }
1488
+ if (!result.confirmationToken?.id) {
1489
+ throw new Error("Stripe did not return a confirmation token");
1490
+ }
1491
+ return {
1492
+ confirmation_token_id: result.confirmationToken.id,
1493
+ return_url: options.return_url
1494
+ };
1495
+ },
1496
+ async handleNextAction(clientSecret) {
1497
+ const result = await stripe.handleNextAction({ clientSecret });
1498
+ if (result.error) {
1499
+ throw new Error(result.error.message || "Payment authentication failed");
1500
+ }
1501
+ },
1502
+ destroy() {
1503
+ paymentElement?.destroy();
1504
+ paymentElement = null;
1505
+ }
1506
+ };
1507
+ }
1508
+ function createElements(stripe, config) {
1509
+ return stripe.elements({
1510
+ mode: "payment",
1511
+ amount: config.amount,
1512
+ currency: normalizeCurrency(config.currency),
1513
+ paymentMethodCreation: "manual",
1514
+ ...config.appearance ? { appearance: config.appearance } : {}
1515
+ });
1516
+ }
1517
+
1469
1518
  // src/storefrontStore/utils.ts
1470
1519
  function readErrorMessage(error, fallback) {
1471
1520
  if (error instanceof Error && error.message) return error.message;
@@ -1517,7 +1566,7 @@ function priceForMarket(prices, market, fallbackCurrency) {
1517
1566
  market: price?.market || market,
1518
1567
  currency: price?.currency || fallbackCurrency || "",
1519
1568
  compare_at: price?.compare_at,
1520
- audience_id: price?.audience_id
1569
+ contact_list_id: price?.contact_list_id
1521
1570
  };
1522
1571
  }
1523
1572
  function availableStock(client, variant) {
@@ -1681,8 +1730,11 @@ function normalizeTimezoneGroups(groups) {
1681
1730
  return normalized;
1682
1731
  }
1683
1732
 
1684
- // src/storefrontStore/createArkyStore.ts
1685
- function createArkyStore(config) {
1733
+ // src/storefrontStore/initialize.ts
1734
+ function firstFiniteNumber(...values) {
1735
+ return values.find((value) => typeof value === "number" && Number.isFinite(value));
1736
+ }
1737
+ function initialize(config) {
1686
1738
  const client = createStorefront(config);
1687
1739
  const session = nanostores.atom(client.session);
1688
1740
  const locale = nanostores.atom(config.locale || client.getLocale());
@@ -1693,7 +1745,7 @@ function createArkyStore(config) {
1693
1745
  const payment_config = nanostores.computed(session, (value) => {
1694
1746
  const store = value?.store;
1695
1747
  const methods = value?.market?.payment_methods || [];
1696
- const hasCreditCard = methods.some((method) => method.id === "credit_card");
1748
+ const hasCreditCard = methods.some((method) => method.type === "credit_card");
1697
1749
  return { provider: store?.payment || null, enabled: hasCreditCard && !!store?.payment };
1698
1750
  });
1699
1751
  const cart = nanostores.atom(null);
@@ -1702,6 +1754,8 @@ function createArkyStore(config) {
1702
1754
  const quote = nanostores.atom(null);
1703
1755
  const promo_code = nanostores.atom(null);
1704
1756
  const last_order = nanostores.atom(null);
1757
+ const payment_controller = nanostores.atom(null);
1758
+ const payment_ready = nanostores.computed(payment_controller, (value) => value !== null);
1705
1759
  const cart_status = nanostores.map({
1706
1760
  loading: false,
1707
1761
  syncing: false,
@@ -1712,20 +1766,48 @@ function createArkyStore(config) {
1712
1766
  selected_shipping_method_id: null,
1713
1767
  user_token: null
1714
1768
  });
1769
+ function rawProductItemCount(value) {
1770
+ return (value?.items || []).reduce((total, item) => {
1771
+ if (item.type !== "product") return total;
1772
+ return total + (item.quantity || 0);
1773
+ }, 0);
1774
+ }
1775
+ function rawServiceItemCount(value) {
1776
+ return (value?.items || []).reduce((total, item) => {
1777
+ if (item.type !== "service") return total;
1778
+ return total + Math.max(1, item.slots?.length || 0);
1779
+ }, 0);
1780
+ }
1715
1781
  const product_item_count = nanostores.computed(
1716
- product_items,
1717
- (items) => items.reduce((total, item) => total + (item.quantity || 0), 0)
1782
+ [cart, product_items],
1783
+ (cartValue, items) => Math.max(
1784
+ rawProductItemCount(cartValue),
1785
+ items.reduce((total, item) => total + (item.quantity || 0), 0)
1786
+ )
1787
+ );
1788
+ const service_item_count = nanostores.computed(
1789
+ [cart, service_items],
1790
+ (cartValue, items) => Math.max(rawServiceItemCount(cartValue), items.length)
1791
+ );
1792
+ const item_count = nanostores.computed(
1793
+ [cart, product_item_count, service_item_count],
1794
+ (cartValue, products, services) => Math.max(cartValue?.item_count || 0, products + services)
1718
1795
  );
1719
- const service_item_count = nanostores.computed(service_items, (items) => items.length);
1720
- const item_count = nanostores.computed([product_item_count, service_item_count], (products, services) => products + services);
1721
1796
  const snapshot = nanostores.computed([cart, product_items, service_items, item_count], (cartValue, products, services, count) => ({
1722
1797
  cart: cartValue,
1723
1798
  product_items: products,
1724
1799
  service_items: services,
1725
1800
  item_count: count
1726
1801
  }));
1802
+ let cartWriteRevision = 0;
1803
+ let sessionRequest = null;
1804
+ let cartRequest = null;
1805
+ function nextCartWriteRevision() {
1806
+ cartWriteRevision += 1;
1807
+ return cartWriteRevision;
1808
+ }
1727
1809
  const cms_state = nanostores.map({
1728
- nodes: {},
1810
+ entries: {},
1729
1811
  forms: {},
1730
1812
  loading: false,
1731
1813
  error: null
@@ -1764,6 +1846,51 @@ function createArkyStore(config) {
1764
1846
  function currentCurrency() {
1765
1847
  return currency.get() || market.get()?.currency || null;
1766
1848
  }
1849
+ function currentStripePublishableKey() {
1850
+ const provider = payment_config.get()?.provider;
1851
+ return provider?.publishable_key || provider?.publishableKey || provider?.publicKey || null;
1852
+ }
1853
+ function currentPaymentAmount() {
1854
+ return Math.max(
1855
+ 0,
1856
+ firstFiniteNumber(
1857
+ quote.get()?.charge_amount,
1858
+ quote.get()?.payment?.total,
1859
+ cart.get()?.quote_snapshot?.charge_amount,
1860
+ cart.get()?.quote_snapshot?.payment?.total,
1861
+ cart.get()?.quote_snapshot?.total
1862
+ ) ?? 0
1863
+ );
1864
+ }
1865
+ function setPaymentController(controller) {
1866
+ const current = payment_controller.get();
1867
+ if (current && current !== controller) {
1868
+ current.destroy();
1869
+ }
1870
+ payment_controller.set(controller);
1871
+ return controller;
1872
+ }
1873
+ function destroyPaymentController() {
1874
+ setPaymentController(null);
1875
+ }
1876
+ async function mountStripePayment(target, options = {}) {
1877
+ const publishableKey = options.publishableKey || currentStripePublishableKey();
1878
+ if (!publishableKey) {
1879
+ throw new Error("Stripe publishable key is required to mount card payment");
1880
+ }
1881
+ const controller = await createStripeConfirmationTokenController({
1882
+ publishableKey,
1883
+ amount: Math.max(0, options.amount ?? currentPaymentAmount()),
1884
+ currency: options.currency || currentCurrency() || "usd",
1885
+ ...options.appearance ? { appearance: options.appearance } : {}
1886
+ });
1887
+ controller.mount(target);
1888
+ setPaymentController(controller);
1889
+ return controller;
1890
+ }
1891
+ function updatePaymentController(input) {
1892
+ payment_controller.get()?.update(input);
1893
+ }
1767
1894
  function marketForLocale(value) {
1768
1895
  return config.marketForLocale?.(value) || null;
1769
1896
  }
@@ -1771,7 +1898,12 @@ function createArkyStore(config) {
1771
1898
  const current = session.get();
1772
1899
  const marketKey = currentMarketKey();
1773
1900
  if (current && (!marketKey || current.market?.key === marketKey)) return current;
1774
- return identify({ market: marketKey });
1901
+ if (!sessionRequest) {
1902
+ sessionRequest = identify({ market: marketKey }).finally(() => {
1903
+ sessionRequest = null;
1904
+ });
1905
+ }
1906
+ return sessionRequest;
1775
1907
  }
1776
1908
  async function identify(params = {}) {
1777
1909
  if (params.market) setMarket(params.market);
@@ -1797,21 +1929,27 @@ function createArkyStore(config) {
1797
1929
  if (context.market) setMarket(context.market);
1798
1930
  }
1799
1931
  async function ensureCart() {
1932
+ if (cartRequest) return cartRequest;
1800
1933
  cart_status.setKey("loading", true);
1801
1934
  cart_status.setKey("error", null);
1802
- try {
1935
+ const refreshRevision = cartWriteRevision;
1936
+ cartRequest = (async () => {
1803
1937
  await ensureSession();
1804
1938
  const response = await client.cart.refresh({ market: currentMarketKey() });
1805
- await hydrateCart(response);
1939
+ await applyCartResponse(response, { ifRevision: refreshRevision });
1806
1940
  return response;
1941
+ })();
1942
+ try {
1943
+ return await cartRequest;
1807
1944
  } catch (error) {
1808
1945
  cart_status.setKey("error", readErrorMessage(error, "Failed to load cart."));
1809
1946
  throw error;
1810
1947
  } finally {
1948
+ cartRequest = null;
1811
1949
  cart_status.setKey("loading", false);
1812
1950
  }
1813
1951
  }
1814
- async function hydrateProductItem(item, source) {
1952
+ async function buildProductCartItem(item, source) {
1815
1953
  try {
1816
1954
  const product = await client.eshop.product.get({ id: item.product_id });
1817
1955
  const variant = product.variants.find((candidate) => candidate.id === item.variant_id);
@@ -1823,6 +1961,7 @@ function createArkyStore(config) {
1823
1961
  product_name: productName(product, currentLocale()),
1824
1962
  product_slug: entitySlug(product, currentLocale()),
1825
1963
  variant_attributes: variant.attributes,
1964
+ requires_shipping: variant.requires_shipping !== false,
1826
1965
  price: priceForMarket(variant.prices, currentMarketKey(), currentCurrency()),
1827
1966
  quantity: item.quantity,
1828
1967
  added_at: source.created_at ? source.created_at * 1e3 : Date.now(),
@@ -1832,7 +1971,7 @@ function createArkyStore(config) {
1832
1971
  return null;
1833
1972
  }
1834
1973
  }
1835
- async function hydrateServiceItems(items) {
1974
+ async function buildServiceCartItems(items) {
1836
1975
  const rows = [];
1837
1976
  for (const item of items) {
1838
1977
  let service = null;
@@ -1860,7 +1999,10 @@ function createArkyStore(config) {
1860
1999
  }
1861
2000
  return rows;
1862
2001
  }
1863
- async function hydrateCart(response) {
2002
+ async function applyCartResponse(response, options = {}) {
2003
+ if (options.ifRevision !== void 0 && options.ifRevision !== cartWriteRevision) {
2004
+ return cart.get() || response;
2005
+ }
1864
2006
  cart.set(response);
1865
2007
  cart_status.setKey("user_token", response.token || null);
1866
2008
  cart_status.setKey("selected_shipping_method_id", response.shipping_method_id || null);
@@ -1868,9 +2010,9 @@ function createArkyStore(config) {
1868
2010
  quote.set(response.quote_snapshot || null);
1869
2011
  const items = response.items || [];
1870
2012
  const products = await Promise.all(
1871
- items.filter((item) => item.type === "product").map((item) => hydrateProductItem(item, response))
2013
+ items.filter((item) => item.type === "product").map((item) => buildProductCartItem(item, response))
1872
2014
  );
1873
- const services = await hydrateServiceItems(
2015
+ const services = await buildServiceCartItems(
1874
2016
  items.filter((item) => item.type === "service")
1875
2017
  );
1876
2018
  product_items.set(products.filter((item) => item !== null));
@@ -1883,7 +2025,7 @@ function createArkyStore(config) {
1883
2025
  ...toServiceCheckoutItems(input.service_items || service_items.get())
1884
2026
  ];
1885
2027
  }
1886
- async function syncCart(input = {}) {
2028
+ async function syncCart(input = {}, writeRevision = nextCartWriteRevision()) {
1887
2029
  cart_status.setKey("syncing", true);
1888
2030
  cart_status.setKey("error", null);
1889
2031
  try {
@@ -1896,14 +2038,14 @@ function createArkyStore(config) {
1896
2038
  billing_address: input.billing_address || void 0,
1897
2039
  forms: normalizeForms(input.forms),
1898
2040
  promo_code: input.promo_code === void 0 ? promo_code.get() || void 0 : input.promo_code || void 0,
1899
- payment_method_id: input.payment_method_id || void 0,
2041
+ payment_method_key: input.payment_method_key || void 0,
1900
2042
  shipping_method_id: input.shipping_method_id || cart_status.get().selected_shipping_method_id || void 0
1901
2043
  });
1902
2044
  if (input.promo_code !== void 0) promo_code.set(input.promo_code);
1903
2045
  if (input.shipping_method_id !== void 0) {
1904
2046
  cart_status.setKey("selected_shipping_method_id", input.shipping_method_id);
1905
2047
  }
1906
- await hydrateCart(response);
2048
+ await applyCartResponse(response, { ifRevision: writeRevision });
1907
2049
  return response;
1908
2050
  } catch (error) {
1909
2051
  cart_status.setKey("error", readErrorMessage(error, "Failed to sync cart."));
@@ -1914,6 +2056,7 @@ function createArkyStore(config) {
1914
2056
  }
1915
2057
  async function addProduct(product, variant, quantity = 1) {
1916
2058
  cart_status.setKey("error", null);
2059
+ const writeRevision = nextCartWriteRevision();
1917
2060
  try {
1918
2061
  const current = cart.get() || await ensureCart();
1919
2062
  const response = await client.cart.addItem({
@@ -1925,8 +2068,7 @@ function createArkyStore(config) {
1925
2068
  quantity
1926
2069
  }
1927
2070
  });
1928
- await hydrateCart(response);
1929
- await client.activity.track({ type: "cart_added", payload: { product_id: product.id, variant_id: variant.id, quantity } });
2071
+ await applyCartResponse(response, { ifRevision: writeRevision });
1930
2072
  return response;
1931
2073
  } catch (error) {
1932
2074
  cart_status.setKey("error", readErrorMessage(error, "Failed to add product to cart."));
@@ -1934,15 +2076,17 @@ function createArkyStore(config) {
1934
2076
  }
1935
2077
  }
1936
2078
  async function setProductQuantity(itemId, quantity) {
2079
+ const writeRevision = nextCartWriteRevision();
1937
2080
  const next = product_items.get().map((item) => {
1938
2081
  if (item.id !== itemId) return item;
1939
2082
  const bounded = item.max_stock ? Math.min(Math.max(1, quantity), item.max_stock) : Math.max(1, quantity);
1940
2083
  return { ...item, quantity: bounded };
1941
2084
  });
1942
2085
  product_items.set(next);
1943
- return syncCart({ product_items: next });
2086
+ return syncCart({ product_items: next }, writeRevision);
1944
2087
  }
1945
2088
  async function removeProduct(itemId) {
2089
+ const writeRevision = nextCartWriteRevision();
1946
2090
  const item = product_items.get().find((candidate) => candidate.id === itemId);
1947
2091
  product_items.set(product_items.get().filter((candidate) => candidate.id !== itemId));
1948
2092
  const current = cart.get();
@@ -1953,31 +2097,37 @@ function createArkyStore(config) {
1953
2097
  product_id: item.product_id,
1954
2098
  variant_id: item.variant_id
1955
2099
  });
1956
- await hydrateCart(response);
1957
- await client.activity.track({ type: "cart_removed", payload: { product_id: item.product_id, variant_id: item.variant_id } });
2100
+ await applyCartResponse(response, { ifRevision: writeRevision });
1958
2101
  return response;
1959
2102
  }
1960
2103
  async function addServiceItem(item) {
2104
+ const writeRevision = nextCartWriteRevision();
1961
2105
  const next = [...service_items.get(), item];
1962
2106
  service_items.set(next);
1963
- return syncCart({ service_items: next });
2107
+ return syncCart({ service_items: next }, writeRevision);
1964
2108
  }
1965
2109
  async function removeServiceItem(itemId) {
2110
+ const writeRevision = nextCartWriteRevision();
1966
2111
  const next = service_items.get().filter((item) => item.id !== itemId);
1967
2112
  service_items.set(next);
1968
- return syncCart({ service_items: next });
2113
+ return syncCart({ service_items: next }, writeRevision);
1969
2114
  }
1970
2115
  async function clearCart() {
2116
+ const writeRevision = nextCartWriteRevision();
2117
+ const current = cart.get();
2118
+ clearLocalCart();
2119
+ if (!current) return null;
2120
+ const response = await client.cart.clear({ id: current.id });
2121
+ await applyCartResponse(response, { ifRevision: writeRevision });
2122
+ return response;
2123
+ }
2124
+ function clearLocalCart() {
1971
2125
  product_items.set([]);
1972
2126
  service_items.set([]);
2127
+ cart.set(null);
1973
2128
  quote.set(null);
1974
2129
  promo_code.set(null);
1975
2130
  cart_status.setKey("selected_shipping_method_id", null);
1976
- const current = cart.get();
1977
- if (!current) return null;
1978
- const response = await client.cart.clear({ id: current.id });
1979
- await hydrateCart(response);
1980
- return response;
1981
2131
  }
1982
2132
  async function fetchQuote(input = {}) {
1983
2133
  if (checkoutItems(input).length === 0) {
@@ -2005,16 +2155,51 @@ function createArkyStore(config) {
2005
2155
  cart_status.setKey("error", null);
2006
2156
  try {
2007
2157
  const current = await syncCart(input);
2008
- await client.activity.track({ type: "checkout_started", payload: { cart_id: current.id } });
2158
+ const quoteValue = quote.get();
2159
+ const paymentMethodKey = input.payment_method_key || current.payment_method_key || quoteValue?.payment?.payment_method_key || void 0;
2160
+ let chargeAmount = firstFiniteNumber(
2161
+ quoteValue?.charge_amount,
2162
+ quoteValue?.payment?.total,
2163
+ current.quote_snapshot?.charge_amount,
2164
+ current.quote_snapshot?.payment?.total
2165
+ );
2166
+ if (paymentMethodKey === "credit_card" && chargeAmount === void 0) {
2167
+ const latestQuote = await client.cart.quote({ id: current.id });
2168
+ quote.set(latestQuote);
2169
+ chargeAmount = firstFiniteNumber(
2170
+ latestQuote.charge_amount,
2171
+ latestQuote.payment?.total,
2172
+ latestQuote.total
2173
+ );
2174
+ }
2175
+ const needsConfirmationToken = paymentMethodKey === "credit_card" && (chargeAmount === void 0 || chargeAmount > 0);
2176
+ let confirmationTokenId;
2177
+ let returnUrl = input.return_url;
2178
+ const paymentController = input.payment ?? payment_controller.get();
2179
+ if (needsConfirmationToken) {
2180
+ if (!paymentController) throw new Error("Payment controller is required for card checkout");
2181
+ returnUrl = returnUrl || (typeof window !== "undefined" ? window.location.href : void 0);
2182
+ const token = await paymentController.createConfirmationToken({
2183
+ return_url: returnUrl,
2184
+ billing_details: input.billing_details
2185
+ });
2186
+ confirmationTokenId = token.confirmation_token_id;
2187
+ returnUrl = token.return_url || returnUrl;
2188
+ }
2009
2189
  const response = await client.cart.checkout({
2010
2190
  id: current.id,
2011
- payment_method_id: input.payment_method_id || void 0
2191
+ payment_method_key: paymentMethodKey,
2192
+ confirmation_token_id: confirmationTokenId,
2193
+ return_url: returnUrl
2012
2194
  });
2013
- const quoteValue = quote.get();
2195
+ if (response.payment_action.type === "handle_next_action") {
2196
+ if (!paymentController) throw new Error("Payment controller is required for card authentication");
2197
+ await paymentController.handleNextAction(response.payment_action.client_secret);
2198
+ }
2014
2199
  const stored = {
2015
2200
  order_id: response.order_id,
2016
2201
  number: response.number,
2017
- client_secret: response.client_secret,
2202
+ payment_action: response.payment_action,
2018
2203
  payment: response.payment,
2019
2204
  product_items: input.product_items || product_items.get(),
2020
2205
  service_items: input.service_items || service_items.get(),
@@ -2022,17 +2207,13 @@ function createArkyStore(config) {
2022
2207
  billing_address: input.billing_address || null,
2023
2208
  total: quoteValue?.payment?.total || quoteValue?.total || response.payment?.total,
2024
2209
  currency: quoteValue?.payment?.currency || currentCurrency(),
2025
- payment_method_id: input.payment_method_id || null,
2210
+ payment_method_key: paymentMethodKey || null,
2026
2211
  created_at: Date.now()
2027
2212
  };
2028
2213
  last_order.set(stored);
2029
- product_items.set([]);
2030
- service_items.set([]);
2031
- cart.set(null);
2032
- quote.set(null);
2033
- promo_code.set(null);
2034
- cart_status.setKey("selected_shipping_method_id", null);
2035
- await client.activity.track({ type: "purchase", payload: { order_id: response.order_id, number: response.number } });
2214
+ if (input.clear_after_checkout !== false) {
2215
+ clearLocalCart();
2216
+ }
2036
2217
  return response;
2037
2218
  } catch (error) {
2038
2219
  cart_status.setKey("error", readErrorMessage(error, "Checkout failed."));
@@ -2452,7 +2633,7 @@ function createArkyStore(config) {
2452
2633
  ...toServiceCartItem(slot),
2453
2634
  forms: []
2454
2635
  })),
2455
- payment_method_id: paymentMethodId,
2636
+ payment_method_key: paymentMethodId,
2456
2637
  promo_code: state.promoCode || void 0,
2457
2638
  forms
2458
2639
  });
@@ -2473,7 +2654,7 @@ function createArkyStore(config) {
2473
2654
  service_state.setKey("promoCode", promoCode || null);
2474
2655
  const response = await fetchQuote({
2475
2656
  service_items: state.cart.map(toServiceCartItem),
2476
- payment_method_id: paymentMethodId,
2657
+ payment_method_key: paymentMethodId,
2477
2658
  promo_code: promoCode || void 0
2478
2659
  });
2479
2660
  service_state.setKey("cartId", cart.get()?.id || null);
@@ -2520,18 +2701,38 @@ function createArkyStore(config) {
2520
2701
  }
2521
2702
  };
2522
2703
  service_items.subscribe((items) => setServiceCartFromServiceItems(items));
2523
- async function loadNode(params, options) {
2704
+ async function loadEntry(params, options) {
2524
2705
  cms_state.setKey("loading", true);
2525
2706
  cms_state.setKey("error", null);
2526
2707
  try {
2527
- const { locale: nextLocale, market: nextMarket, ...nodeParams } = params;
2708
+ const { locale: nextLocale, market: nextMarket, ...entryParams } = params;
2528
2709
  setContext({ locale: nextLocale, market: nextMarket });
2529
- const node = await client.cms.node.get(nodeParams, options);
2530
- const key = nodeParams.key || nodeParams.id || nodeParams.slug || node.id;
2531
- cms_state.setKey("nodes", { ...cms_state.get().nodes, [key]: node });
2532
- return node;
2710
+ if (entryParams.id) {
2711
+ const entry2 = await client.cms.entry.get(entryParams, options);
2712
+ const cacheKey = entryParams.key || entryParams.id || entry2.id;
2713
+ cms_state.setKey("entries", { ...cms_state.get().entries, [cacheKey]: entry2 });
2714
+ return entry2;
2715
+ }
2716
+ if (!entryParams.collection_id || !entryParams.key) {
2717
+ throw new Error("ArkyCmsEntryParams requires id, or collection_id and key");
2718
+ }
2719
+ const result = await client.cms.entry.find(
2720
+ {
2721
+ ...entryParams,
2722
+ collection_id: entryParams.collection_id,
2723
+ key: entryParams.key,
2724
+ limit: 1
2725
+ },
2726
+ options
2727
+ );
2728
+ const entry = result.items?.[0];
2729
+ if (!entry) {
2730
+ throw new Error("CMS entry not found");
2731
+ }
2732
+ cms_state.setKey("entries", { ...cms_state.get().entries, [entryParams.key]: entry });
2733
+ return entry;
2533
2734
  } catch (error) {
2534
- cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS node."));
2735
+ cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS entry."));
2535
2736
  throw error;
2536
2737
  } finally {
2537
2738
  cms_state.setKey("loading", false);
@@ -2618,19 +2819,14 @@ function createArkyStore(config) {
2618
2819
  eshop_state.setKey("loading_availability", false);
2619
2820
  }
2620
2821
  }
2621
- async function setup(options = {}) {
2622
- setContext(options);
2623
- const shouldIdentify = options.identify === true || !!options.hydrateCart || !!options.track;
2624
- const results = {
2625
- session: session.get()
2626
- };
2627
- if (shouldIdentify) results.session = await ensureSession();
2628
- if (options.hydrateCart) results.cart = await ensureCart();
2629
- if (options.track) await client.activity.track(options.track);
2630
- return results;
2822
+ async function useExperiment(params) {
2823
+ await ensureSession();
2824
+ const input = typeof params === "string" ? { key: params } : params;
2825
+ return client.experiments.use(input);
2631
2826
  }
2632
- async function initialize(options = {}) {
2633
- return setup(options);
2827
+ async function trackAction(params) {
2828
+ await ensureSession();
2829
+ return client.action.track(params);
2634
2830
  }
2635
2831
  const cart_store = {
2636
2832
  cart,
@@ -2644,17 +2840,26 @@ function createArkyStore(config) {
2644
2840
  service_item_count,
2645
2841
  item_count,
2646
2842
  snapshot,
2647
- ensure: ensureCart,
2648
- hydrate: hydrateCart,
2649
- sync: syncCart,
2843
+ load: ensureCart,
2844
+ refresh: syncCart,
2650
2845
  addProduct,
2651
2846
  setProductQuantity,
2652
2847
  removeProduct,
2653
2848
  addServiceItem,
2654
2849
  removeServiceItem,
2655
2850
  clear: clearCart,
2851
+ clearLocal: clearLocalCart,
2656
2852
  quote: fetchQuote,
2657
2853
  checkout,
2854
+ payment: {
2855
+ controller: payment_controller,
2856
+ ready: payment_ready,
2857
+ setController: setPaymentController,
2858
+ getController: () => payment_controller.get(),
2859
+ mountStripe: mountStripePayment,
2860
+ update: updatePaymentController,
2861
+ destroy: destroyPaymentController
2862
+ },
2658
2863
  applyPromoCode(code, input = {}) {
2659
2864
  promo_code.set(code);
2660
2865
  return fetchQuote({ ...input, promo_code: code });
@@ -2728,30 +2933,29 @@ function createArkyStore(config) {
2728
2933
  currency,
2729
2934
  allowed_payment_methods,
2730
2935
  payment_config,
2731
- setup,
2732
- initialize,
2936
+ cart: cart_store,
2733
2937
  identify,
2734
2938
  verify: client.verify,
2735
2939
  me: client.me,
2736
2940
  logout: client.logout,
2737
2941
  onAuthStateChanged: client.onAuthStateChanged,
2738
- get currentSession() {
2739
- return session.get();
2740
- },
2741
2942
  get isAuthenticated() {
2742
2943
  return client.isAuthenticated;
2743
2944
  },
2744
2945
  setMarket,
2745
2946
  setLocale,
2746
2947
  setContext,
2948
+ getStoreId: client.getStoreId,
2747
2949
  getMarket: currentMarketKey,
2748
2950
  getLocale: currentLocale,
2749
2951
  cms: {
2750
2952
  state: cms_state,
2751
- node: {
2752
- get: loadNode,
2753
- find: (params, options) => client.cms.node.find(params, options),
2754
- getChildren: (params, options) => client.cms.node.getChildren(params, options)
2953
+ collection: {
2954
+ get: (params, options) => client.cms.collection.get(params, options)
2955
+ },
2956
+ entry: {
2957
+ get: loadEntry,
2958
+ find: (params, options) => client.cms.entry.find(params, options)
2755
2959
  },
2756
2960
  form: {
2757
2961
  get: loadForm,
@@ -2772,24 +2976,28 @@ function createArkyStore(config) {
2772
2976
  cart: cart_store
2773
2977
  },
2774
2978
  crm: client.crm,
2775
- activity: {
2979
+ action: {
2776
2980
  track(params) {
2777
- return client.activity.track(params);
2981
+ return trackAction(params);
2778
2982
  },
2779
2983
  pageView(payload = {}) {
2780
- return client.activity.track({ type: "page_view", payload });
2984
+ return trackAction({ key: "page.view", payload });
2781
2985
  },
2782
2986
  state: nanostores.atom(null)
2783
2987
  },
2988
+ experiments: {
2989
+ use: useExperiment
2990
+ },
2991
+ support: client.support,
2784
2992
  store: client.store,
2785
- automation: client.automation,
2786
2993
  utils: client.utils
2787
2994
  };
2788
2995
  }
2789
2996
 
2790
- exports.COMMON_ACTIVITY_TYPES = COMMON_ACTIVITY_TYPES;
2791
- exports.createArkyStore = createArkyStore;
2997
+ exports.COMMON_ACTION_KEYS = COMMON_ACTION_KEYS;
2792
2998
  exports.createCartController = createCartController;
2793
2999
  exports.createStorefront = createStorefront;
3000
+ exports.createStripeConfirmationTokenController = createStripeConfirmationTokenController;
3001
+ exports.initialize = initialize;
2794
3002
  //# sourceMappingURL=storefront.cjs.map
2795
3003
  //# sourceMappingURL=storefront.cjs.map