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