arky-sdk 0.9.6 → 0.9.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +113 -194
- package/dist/admin-D8HiRDCl.d.cts +1536 -0
- package/dist/admin-Dnnv18wN.d.ts +1536 -0
- package/dist/admin.cjs +832 -375
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +3 -3
- package/dist/admin.d.ts +3 -3
- package/dist/admin.js +832 -375
- package/dist/admin.js.map +1 -1
- package/dist/api-D4lMmvF0.d.cts +4337 -0
- package/dist/api-D4lMmvF0.d.ts +4337 -0
- package/dist/{index-nCF3Z6Af.d.cts → index-BS2x278C.d.cts} +1 -1
- package/dist/{index-CZxubTDA.d.ts → index-Be8suRwP.d.ts} +1 -1
- package/dist/index.cjs +934 -460
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +934 -460
- package/dist/index.js.map +1 -1
- package/dist/storefront.cjs +501 -300
- package/dist/storefront.cjs.map +1 -1
- package/dist/storefront.d.cts +174 -89
- package/dist/storefront.d.ts +174 -89
- package/dist/storefront.js +499 -299
- package/dist/storefront.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.cts +2 -2
- package/dist/utils.d.ts +2 -2
- package/package.json +7 -10
- package/scripts/contract-admin.mjs +137 -0
- package/scripts/contract-storefront.mjs +296 -0
- package/dist/admin-DjYydKeB.d.ts +0 -1389
- package/dist/admin-DlL8mCxL.d.cts +0 -1389
- package/dist/api-BbBHcd4p.d.cts +0 -3289
- package/dist/api-BbBHcd4p.d.ts +0 -3289
- package/dist/storefront-store.cjs +0 -2809
- package/dist/storefront-store.cjs.map +0 -1
- package/dist/storefront-store.d.cts +0 -5
- package/dist/storefront-store.d.ts +0 -5
- package/dist/storefront-store.js +0 -2807
- package/dist/storefront-store.js.map +0 -1
- package/scripts/smoke-store.mjs +0 -41
package/dist/storefront.cjs
CHANGED
|
@@ -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
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
158
|
-
"
|
|
159
|
-
"
|
|
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
|
-
"
|
|
36
|
+
"verified.email",
|
|
164
37
|
"search",
|
|
165
38
|
"share",
|
|
166
|
-
"
|
|
39
|
+
"wishlist.added"
|
|
167
40
|
];
|
|
168
|
-
var
|
|
169
|
-
|
|
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}/
|
|
174
|
-
{
|
|
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,
|
|
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, updateProfileSession) => {
|
|
|
211
85
|
}
|
|
212
86
|
},
|
|
213
87
|
cms: {
|
|
214
|
-
|
|
215
|
-
|
|
88
|
+
collection: {
|
|
89
|
+
get(params, options) {
|
|
216
90
|
const store_id = params.store_id || apiConfig.storeId;
|
|
217
|
-
|
|
218
|
-
|
|
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
|
-
|
|
228
|
-
`${base(store_id)}/
|
|
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)}/
|
|
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, updateProfileSession) => {
|
|
|
411
270
|
{
|
|
412
271
|
id: params.id,
|
|
413
272
|
store_id,
|
|
414
|
-
|
|
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, updateProfileSession) => {
|
|
|
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, updateProfileSession) => {
|
|
|
498
367
|
}
|
|
499
368
|
},
|
|
500
369
|
crm: {
|
|
501
|
-
|
|
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)}/
|
|
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, updateProfileSession) => {
|
|
|
512
381
|
options
|
|
513
382
|
);
|
|
514
383
|
if (result?.token?.token) {
|
|
515
|
-
|
|
384
|
+
updateContactSession(() => ({
|
|
516
385
|
access_token: result.token.token,
|
|
517
|
-
|
|
386
|
+
contact: result.contact,
|
|
518
387
|
store: result.store,
|
|
519
388
|
market: result.market
|
|
520
389
|
}));
|
|
@@ -524,12 +393,12 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
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)}/
|
|
396
|
+
`${base(store_id)}/account/verify`,
|
|
528
397
|
{ store_id, code: params.code },
|
|
529
398
|
options
|
|
530
399
|
);
|
|
531
400
|
if (result?.token) {
|
|
532
|
-
|
|
401
|
+
updateContactSession(
|
|
533
402
|
(prev) => prev ? { ...prev, access_token: result.token } : null
|
|
534
403
|
);
|
|
535
404
|
}
|
|
@@ -539,29 +408,29 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
539
408
|
const store_id = apiConfig.storeId;
|
|
540
409
|
try {
|
|
541
410
|
await apiConfig.httpClient.post(
|
|
542
|
-
`${base(store_id)}/
|
|
411
|
+
`${base(store_id)}/account/logout`,
|
|
543
412
|
{},
|
|
544
413
|
options
|
|
545
414
|
);
|
|
546
415
|
} finally {
|
|
547
|
-
|
|
416
|
+
updateContactSession(() => null);
|
|
548
417
|
}
|
|
549
418
|
},
|
|
550
419
|
getMe(options) {
|
|
551
|
-
return apiConfig.httpClient.get(`${base()}/
|
|
420
|
+
return apiConfig.httpClient.get(`${base()}/account/me`, options);
|
|
552
421
|
}
|
|
553
422
|
},
|
|
554
|
-
|
|
423
|
+
contactList: {
|
|
555
424
|
get(params, options) {
|
|
556
425
|
const store_id = params.store_id || apiConfig.storeId;
|
|
557
426
|
return apiConfig.httpClient.get(
|
|
558
|
-
`${base(store_id)}/
|
|
427
|
+
`${base(store_id)}/contact-lists/${params.id}`,
|
|
559
428
|
options
|
|
560
429
|
);
|
|
561
430
|
},
|
|
562
431
|
find(params, options) {
|
|
563
432
|
const { store_id, ...queryParams } = params || {};
|
|
564
|
-
return apiConfig.httpClient.get(`${base(store_id)}/
|
|
433
|
+
return apiConfig.httpClient.get(`${base(store_id)}/contact-lists`, {
|
|
565
434
|
...options,
|
|
566
435
|
params: queryParams
|
|
567
436
|
});
|
|
@@ -569,7 +438,7 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
569
438
|
subscribe(params, options) {
|
|
570
439
|
const { store_id, id, ...payload } = params;
|
|
571
440
|
return apiConfig.httpClient.post(
|
|
572
|
-
`${base(store_id)}/
|
|
441
|
+
`${base(store_id)}/contact-lists/${id}/subscribe`,
|
|
573
442
|
payload,
|
|
574
443
|
options
|
|
575
444
|
);
|
|
@@ -577,25 +446,45 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
577
446
|
checkAccess(params, options) {
|
|
578
447
|
const store_id = params.store_id || apiConfig.storeId;
|
|
579
448
|
return apiConfig.httpClient.get(
|
|
580
|
-
`${base(store_id)}/
|
|
449
|
+
`${base(store_id)}/contact-lists/${params.id}/access`,
|
|
450
|
+
options
|
|
451
|
+
);
|
|
452
|
+
},
|
|
453
|
+
checkContentAccess(params, options) {
|
|
454
|
+
const { store_id, ...payload } = params;
|
|
455
|
+
return apiConfig.httpClient.post(
|
|
456
|
+
`${base(store_id)}/contact-lists/access`,
|
|
457
|
+
payload,
|
|
581
458
|
options
|
|
582
459
|
);
|
|
583
460
|
},
|
|
584
461
|
unsubscribe(token, options) {
|
|
585
|
-
return apiConfig.httpClient.
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
462
|
+
return apiConfig.httpClient.post(
|
|
463
|
+
`${base()}/contact-lists/unsubscribe`,
|
|
464
|
+
{ token },
|
|
465
|
+
options
|
|
466
|
+
);
|
|
589
467
|
},
|
|
590
468
|
confirm(token, options) {
|
|
591
|
-
return apiConfig.httpClient.
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
469
|
+
return apiConfig.httpClient.post(
|
|
470
|
+
`${base()}/contact-lists/confirm`,
|
|
471
|
+
{ token },
|
|
472
|
+
options
|
|
473
|
+
);
|
|
595
474
|
}
|
|
596
475
|
}
|
|
597
476
|
},
|
|
598
|
-
|
|
477
|
+
action: createActionApi(apiConfig),
|
|
478
|
+
experiments: {
|
|
479
|
+
use(params, options) {
|
|
480
|
+
const store_id = params.store_id || apiConfig.storeId;
|
|
481
|
+
return apiConfig.httpClient.post(
|
|
482
|
+
`${base(store_id)}/experiments/use`,
|
|
483
|
+
{ key: params.key },
|
|
484
|
+
options
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
599
488
|
};
|
|
600
489
|
};
|
|
601
490
|
|
|
@@ -820,7 +709,7 @@ function createHttpClient(cfg) {
|
|
|
820
709
|
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
821
710
|
}
|
|
822
711
|
const finalPath = options?.params ? path + buildQueryString(options.params) : path;
|
|
823
|
-
const fetchOpts = { method, headers };
|
|
712
|
+
const fetchOpts = { method, headers, signal: options?.signal };
|
|
824
713
|
if (!["GET", "DELETE"].includes(method) && body !== void 0) {
|
|
825
714
|
fetchOpts.body = JSON.stringify(body);
|
|
826
715
|
}
|
|
@@ -831,13 +720,15 @@ function createHttpClient(cfg) {
|
|
|
831
720
|
try {
|
|
832
721
|
res = await fetch(fullUrl, fetchOpts);
|
|
833
722
|
} catch (error) {
|
|
723
|
+
const aborted = options?.signal?.aborted || error instanceof Error && error.name === "AbortError";
|
|
834
724
|
const err = new Error(error instanceof Error ? error.message : "Network request failed");
|
|
835
|
-
err.name = "NetworkError";
|
|
725
|
+
err.name = aborted ? "AbortError" : "NetworkError";
|
|
836
726
|
err.method = method;
|
|
837
727
|
err.url = fullUrl;
|
|
728
|
+
err.aborted = aborted;
|
|
838
729
|
if (options?.onError && method !== "GET") {
|
|
839
730
|
Promise.resolve(
|
|
840
|
-
options.onError({ error: err, method, url: fullUrl, aborted
|
|
731
|
+
options.onError({ error: err, method, url: fullUrl, aborted })
|
|
841
732
|
).catch(() => {
|
|
842
733
|
});
|
|
843
734
|
}
|
|
@@ -965,6 +856,133 @@ function createStorefrontSupportApi(config) {
|
|
|
965
856
|
};
|
|
966
857
|
}
|
|
967
858
|
|
|
859
|
+
// src/utils/blocks.ts
|
|
860
|
+
function getBlockLabel(block) {
|
|
861
|
+
if (!block) return "";
|
|
862
|
+
return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) ?? "";
|
|
863
|
+
}
|
|
864
|
+
function formatBlockValue(block) {
|
|
865
|
+
if (!block || block.value === null || block.value === void 0) return "";
|
|
866
|
+
const value = block.value;
|
|
867
|
+
switch (block.type) {
|
|
868
|
+
case "boolean":
|
|
869
|
+
return value ? "Yes" : "No";
|
|
870
|
+
case "number":
|
|
871
|
+
if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
|
|
872
|
+
return new Date(value).toLocaleDateString();
|
|
873
|
+
}
|
|
874
|
+
return String(value);
|
|
875
|
+
case "media":
|
|
876
|
+
if (value && typeof value === "object") {
|
|
877
|
+
return value.mime_type ? value.name || value.id : value.title || value.name || value.id;
|
|
878
|
+
}
|
|
879
|
+
return String(value);
|
|
880
|
+
default:
|
|
881
|
+
return String(value);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
function prepareBlocksForSubmission(formData, blockTypes) {
|
|
885
|
+
return Object.keys(formData).filter((key) => formData[key] !== null && formData[key] !== void 0).map((key) => ({
|
|
886
|
+
key,
|
|
887
|
+
value: (blockTypes?.[key] || "text") === "array" && !Array.isArray(formData[key]) ? [formData[key]] : formData[key]
|
|
888
|
+
}));
|
|
889
|
+
}
|
|
890
|
+
function extractBlockValues(blocks) {
|
|
891
|
+
const values = {};
|
|
892
|
+
blocks.forEach((block) => {
|
|
893
|
+
values[block.key] = block.value ?? null;
|
|
894
|
+
});
|
|
895
|
+
return values;
|
|
896
|
+
}
|
|
897
|
+
var getBlockValue = (entry, blockKey) => {
|
|
898
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
899
|
+
return block?.value ?? null;
|
|
900
|
+
};
|
|
901
|
+
var getBlockTextValue = (block, locale = "en") => {
|
|
902
|
+
if (!block || block.value === null || block.value === void 0) return "";
|
|
903
|
+
const blockType = block.type;
|
|
904
|
+
if (blockType === "localized_text" || blockType === "markdown") {
|
|
905
|
+
if (typeof block.value === "object" && block.value !== null) {
|
|
906
|
+
return block.value[locale] ?? block.value["en"] ?? "";
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (typeof block.value === "string") return block.value;
|
|
910
|
+
return String(block.value ?? "");
|
|
911
|
+
};
|
|
912
|
+
var getBlockValues = (entry, blockKey) => {
|
|
913
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
914
|
+
if (!block) return [];
|
|
915
|
+
if (block.type === "array" && Array.isArray(block.value)) {
|
|
916
|
+
return block.value;
|
|
917
|
+
}
|
|
918
|
+
return [];
|
|
919
|
+
};
|
|
920
|
+
function unwrapBlock(block, locale) {
|
|
921
|
+
if (!block?.type || block.value === void 0) return block;
|
|
922
|
+
const blockType = block.type;
|
|
923
|
+
if (blockType === "array") {
|
|
924
|
+
return block.value.map((obj) => {
|
|
925
|
+
const parsed = {};
|
|
926
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
927
|
+
parsed[k] = unwrapBlock(v, locale);
|
|
928
|
+
}
|
|
929
|
+
return parsed;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
if (blockType === "object") {
|
|
933
|
+
const parsed = {};
|
|
934
|
+
for (const [k, v] of Object.entries(block.value || {})) {
|
|
935
|
+
parsed[k] = unwrapBlock(v, locale);
|
|
936
|
+
}
|
|
937
|
+
return parsed;
|
|
938
|
+
}
|
|
939
|
+
if (blockType === "localized_text" || blockType === "markdown") {
|
|
940
|
+
return block.value?.[locale];
|
|
941
|
+
}
|
|
942
|
+
return block.value;
|
|
943
|
+
}
|
|
944
|
+
var getBlockObjectValues = (entry, blockKey, locale = "en") => {
|
|
945
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
946
|
+
if (!block || block.type !== "array" || !Array.isArray(block.value)) return [];
|
|
947
|
+
return block.value.map((obj) => {
|
|
948
|
+
if (!obj?.value || !Array.isArray(obj.value)) return {};
|
|
949
|
+
return obj.value.reduce((acc, current) => {
|
|
950
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
951
|
+
return acc;
|
|
952
|
+
}, {});
|
|
953
|
+
});
|
|
954
|
+
};
|
|
955
|
+
var getBlockFromArray = (entry, blockKey, locale = "en") => {
|
|
956
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
957
|
+
if (!block) return {};
|
|
958
|
+
if (block.type === "array" && Array.isArray(block.value)) {
|
|
959
|
+
return block.value.reduce((acc, current) => {
|
|
960
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
961
|
+
return acc;
|
|
962
|
+
}, {});
|
|
963
|
+
}
|
|
964
|
+
if (block.type === "object" && block.value && typeof block.value === "object") {
|
|
965
|
+
const result = {};
|
|
966
|
+
for (const [k, v] of Object.entries(block.value)) {
|
|
967
|
+
result[k] = unwrapBlock(v, locale);
|
|
968
|
+
}
|
|
969
|
+
return result;
|
|
970
|
+
}
|
|
971
|
+
return { [block.key]: unwrapBlock(block, locale) };
|
|
972
|
+
};
|
|
973
|
+
var getImageUrl = (imageBlock, isBlock = true) => {
|
|
974
|
+
if (!imageBlock) return null;
|
|
975
|
+
if (imageBlock.type === "media") {
|
|
976
|
+
const mediaValue = imageBlock.value;
|
|
977
|
+
return mediaValue?.resolutions?.original?.url || mediaValue?.url || null;
|
|
978
|
+
}
|
|
979
|
+
if (isBlock) {
|
|
980
|
+
if (typeof imageBlock === "string") return imageBlock;
|
|
981
|
+
if (imageBlock.url) return imageBlock.url;
|
|
982
|
+
}
|
|
983
|
+
return imageBlock.resolutions?.original?.url || null;
|
|
984
|
+
};
|
|
985
|
+
|
|
968
986
|
// src/utils/price.ts
|
|
969
987
|
function formatCurrency(amount, currencyCode, locale = "en") {
|
|
970
988
|
if (!currencyCode) return "";
|
|
@@ -1254,22 +1272,22 @@ function createUtilitySurface(apiConfig) {
|
|
|
1254
1272
|
getFirstAvailableFCId
|
|
1255
1273
|
};
|
|
1256
1274
|
}
|
|
1257
|
-
var
|
|
1258
|
-
function
|
|
1275
|
+
var CONTACT_STORAGE_KEY = "arky_contact_session";
|
|
1276
|
+
function readContactSession() {
|
|
1259
1277
|
if (typeof window === "undefined") return null;
|
|
1260
1278
|
try {
|
|
1261
|
-
const raw = localStorage.getItem(
|
|
1279
|
+
const raw = localStorage.getItem(CONTACT_STORAGE_KEY);
|
|
1262
1280
|
return raw ? JSON.parse(raw) : null;
|
|
1263
1281
|
} catch {
|
|
1264
1282
|
return null;
|
|
1265
1283
|
}
|
|
1266
1284
|
}
|
|
1267
|
-
function
|
|
1285
|
+
function writeContactSession(s) {
|
|
1268
1286
|
if (typeof window === "undefined") return;
|
|
1269
1287
|
if (s) {
|
|
1270
|
-
localStorage.setItem(
|
|
1288
|
+
localStorage.setItem(CONTACT_STORAGE_KEY, JSON.stringify(s));
|
|
1271
1289
|
} else {
|
|
1272
|
-
localStorage.removeItem(
|
|
1290
|
+
localStorage.removeItem(CONTACT_STORAGE_KEY);
|
|
1273
1291
|
}
|
|
1274
1292
|
}
|
|
1275
1293
|
function createStorefront(config) {
|
|
@@ -1278,10 +1296,10 @@ function createStorefront(config) {
|
|
|
1278
1296
|
const listeners = /* @__PURE__ */ new Set();
|
|
1279
1297
|
let bareIdentifyPromise = null;
|
|
1280
1298
|
function toPublic(s) {
|
|
1281
|
-
return s ? {
|
|
1299
|
+
return s ? { contact: s.contact, store: s.store, market: s.market } : null;
|
|
1282
1300
|
}
|
|
1283
1301
|
function emit() {
|
|
1284
|
-
const pub = toPublic(
|
|
1302
|
+
const pub = toPublic(readContactSession());
|
|
1285
1303
|
for (const l of listeners) {
|
|
1286
1304
|
Promise.resolve().then(() => l(pub)).catch(() => {
|
|
1287
1305
|
});
|
|
@@ -1289,9 +1307,9 @@ function createStorefront(config) {
|
|
|
1289
1307
|
}
|
|
1290
1308
|
const updateSession = (updater) => {
|
|
1291
1309
|
if (config.apiToken) return;
|
|
1292
|
-
const prev =
|
|
1310
|
+
const prev = readContactSession();
|
|
1293
1311
|
const next = updater(prev);
|
|
1294
|
-
|
|
1312
|
+
writeContactSession(next);
|
|
1295
1313
|
emit();
|
|
1296
1314
|
};
|
|
1297
1315
|
const authStorage = config.apiToken ? {
|
|
@@ -1302,7 +1320,7 @@ function createStorefront(config) {
|
|
|
1302
1320
|
}
|
|
1303
1321
|
} : {
|
|
1304
1322
|
getTokens() {
|
|
1305
|
-
const s =
|
|
1323
|
+
const s = readContactSession();
|
|
1306
1324
|
return s ? { access_token: s.access_token } : null;
|
|
1307
1325
|
},
|
|
1308
1326
|
onTokensRefreshed() {
|
|
@@ -1329,20 +1347,20 @@ function createStorefront(config) {
|
|
|
1329
1347
|
authStorage
|
|
1330
1348
|
};
|
|
1331
1349
|
const storefrontApi = createStorefrontApi(apiConfig, updateSession);
|
|
1332
|
-
const
|
|
1350
|
+
const contactApi = storefrontApi.crm.contact;
|
|
1333
1351
|
function identify(params) {
|
|
1334
1352
|
if (params?.market !== void 0) apiConfig.market = params.market;
|
|
1335
1353
|
const isBareCall = !params?.email && !params?.verify;
|
|
1336
1354
|
if (isBareCall && bareIdentifyPromise) return bareIdentifyPromise;
|
|
1337
1355
|
const promise = (async () => {
|
|
1338
1356
|
try {
|
|
1339
|
-
const result = await
|
|
1357
|
+
const result = await contactApi.identify({
|
|
1340
1358
|
market: apiConfig.market,
|
|
1341
1359
|
email: params?.email,
|
|
1342
1360
|
verify: params?.verify
|
|
1343
1361
|
});
|
|
1344
1362
|
return {
|
|
1345
|
-
|
|
1363
|
+
contact: result.contact,
|
|
1346
1364
|
store: result.store,
|
|
1347
1365
|
market: result.market
|
|
1348
1366
|
};
|
|
@@ -1351,9 +1369,11 @@ function createStorefront(config) {
|
|
|
1351
1369
|
const status = e?.statusCode || e?.status || e?.response?.status;
|
|
1352
1370
|
if (isBareCall && status === 401) {
|
|
1353
1371
|
updateSession(() => null);
|
|
1354
|
-
const result = await
|
|
1372
|
+
const result = await contactApi.identify({
|
|
1373
|
+
market: apiConfig.market
|
|
1374
|
+
});
|
|
1355
1375
|
return {
|
|
1356
|
-
|
|
1376
|
+
contact: result.contact,
|
|
1357
1377
|
store: result.store,
|
|
1358
1378
|
market: result.market
|
|
1359
1379
|
};
|
|
@@ -1368,7 +1388,7 @@ function createStorefront(config) {
|
|
|
1368
1388
|
return promise;
|
|
1369
1389
|
}
|
|
1370
1390
|
async function verify(params) {
|
|
1371
|
-
const result = await
|
|
1391
|
+
const result = await contactApi.verify(params);
|
|
1372
1392
|
bareIdentifyPromise = null;
|
|
1373
1393
|
return result;
|
|
1374
1394
|
}
|
|
@@ -1376,7 +1396,7 @@ function createStorefront(config) {
|
|
|
1376
1396
|
if (config.apiToken) return;
|
|
1377
1397
|
bareIdentifyPromise = null;
|
|
1378
1398
|
try {
|
|
1379
|
-
await
|
|
1399
|
+
await contactApi.logout();
|
|
1380
1400
|
} catch {
|
|
1381
1401
|
updateSession(() => null);
|
|
1382
1402
|
}
|
|
@@ -1385,19 +1405,19 @@ function createStorefront(config) {
|
|
|
1385
1405
|
identify,
|
|
1386
1406
|
verify,
|
|
1387
1407
|
logout,
|
|
1388
|
-
me: () =>
|
|
1408
|
+
me: () => contactApi.getMe(),
|
|
1389
1409
|
get session() {
|
|
1390
1410
|
if (config.apiToken) return null;
|
|
1391
|
-
return toPublic(
|
|
1411
|
+
return toPublic(readContactSession());
|
|
1392
1412
|
},
|
|
1393
1413
|
get isAuthenticated() {
|
|
1394
1414
|
if (config.apiToken) return true;
|
|
1395
|
-
const s =
|
|
1415
|
+
const s = readContactSession();
|
|
1396
1416
|
return s !== null && !!s.access_token;
|
|
1397
1417
|
},
|
|
1398
1418
|
onAuthStateChanged(listener) {
|
|
1399
1419
|
listeners.add(listener);
|
|
1400
|
-
const current = toPublic(
|
|
1420
|
+
const current = toPublic(readContactSession());
|
|
1401
1421
|
if (current) {
|
|
1402
1422
|
Promise.resolve().then(() => listener(current)).catch(() => {
|
|
1403
1423
|
});
|
|
@@ -1411,7 +1431,8 @@ function createStorefront(config) {
|
|
|
1411
1431
|
cms: storefrontApi.cms,
|
|
1412
1432
|
eshop: storefrontApi.eshop,
|
|
1413
1433
|
crm: storefrontApi.crm,
|
|
1414
|
-
|
|
1434
|
+
action: storefrontApi.action,
|
|
1435
|
+
experiments: storefrontApi.experiments,
|
|
1415
1436
|
support: createStorefrontSupportApi(apiConfig),
|
|
1416
1437
|
setStoreId: (storeId) => {
|
|
1417
1438
|
apiConfig.storeId = storeId;
|
|
@@ -1427,11 +1448,81 @@ function createStorefront(config) {
|
|
|
1427
1448
|
apiConfig.locale = l;
|
|
1428
1449
|
},
|
|
1429
1450
|
getLocale: () => apiConfig.locale,
|
|
1430
|
-
extractBlockValues,
|
|
1431
1451
|
utils: createUtilitySurface(apiConfig)
|
|
1432
1452
|
};
|
|
1433
1453
|
}
|
|
1434
1454
|
|
|
1455
|
+
// src/payments/stripe.ts
|
|
1456
|
+
function normalizeCurrency(currency) {
|
|
1457
|
+
return currency.trim().toLowerCase();
|
|
1458
|
+
}
|
|
1459
|
+
async function createStripeConfirmationTokenController(config) {
|
|
1460
|
+
const { loadStripe } = await import('@stripe/stripe-js');
|
|
1461
|
+
const stripe = await loadStripe(config.publishableKey);
|
|
1462
|
+
if (!stripe) throw new Error("Stripe failed to initialize");
|
|
1463
|
+
let elements = createElements(stripe, config);
|
|
1464
|
+
let paymentElement = elements.create("payment", {
|
|
1465
|
+
layout: "tabs"
|
|
1466
|
+
});
|
|
1467
|
+
return {
|
|
1468
|
+
mount(target) {
|
|
1469
|
+
if (!paymentElement) {
|
|
1470
|
+
paymentElement = elements.create("payment", { layout: "tabs" });
|
|
1471
|
+
}
|
|
1472
|
+
paymentElement.mount(target);
|
|
1473
|
+
},
|
|
1474
|
+
update(input) {
|
|
1475
|
+
elements.update({
|
|
1476
|
+
...input.amount !== void 0 ? { amount: input.amount } : {},
|
|
1477
|
+
...input.currency ? { currency: normalizeCurrency(input.currency) } : {}
|
|
1478
|
+
});
|
|
1479
|
+
},
|
|
1480
|
+
async createConfirmationToken(options = {}) {
|
|
1481
|
+
const submitResult = await elements.submit();
|
|
1482
|
+
if (submitResult.error) {
|
|
1483
|
+
throw new Error(submitResult.error.message || "Payment details are incomplete");
|
|
1484
|
+
}
|
|
1485
|
+
const tokenInput = {
|
|
1486
|
+
elements,
|
|
1487
|
+
params: {
|
|
1488
|
+
...options.return_url ? { return_url: options.return_url } : {},
|
|
1489
|
+
...options.billing_details ? { payment_method_data: { billing_details: options.billing_details } } : {}
|
|
1490
|
+
}
|
|
1491
|
+
};
|
|
1492
|
+
const result = await stripe.createConfirmationToken(tokenInput);
|
|
1493
|
+
if (result.error) {
|
|
1494
|
+
throw new Error(result.error.message || "Payment confirmation token failed");
|
|
1495
|
+
}
|
|
1496
|
+
if (!result.confirmationToken?.id) {
|
|
1497
|
+
throw new Error("Stripe did not return a confirmation token");
|
|
1498
|
+
}
|
|
1499
|
+
return {
|
|
1500
|
+
confirmation_token_id: result.confirmationToken.id,
|
|
1501
|
+
return_url: options.return_url
|
|
1502
|
+
};
|
|
1503
|
+
},
|
|
1504
|
+
async handleNextAction(clientSecret) {
|
|
1505
|
+
const result = await stripe.handleNextAction({ clientSecret });
|
|
1506
|
+
if (result.error) {
|
|
1507
|
+
throw new Error(result.error.message || "Payment authentication failed");
|
|
1508
|
+
}
|
|
1509
|
+
},
|
|
1510
|
+
destroy() {
|
|
1511
|
+
paymentElement?.destroy();
|
|
1512
|
+
paymentElement = null;
|
|
1513
|
+
}
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
function createElements(stripe, config) {
|
|
1517
|
+
return stripe.elements({
|
|
1518
|
+
mode: "payment",
|
|
1519
|
+
amount: config.amount,
|
|
1520
|
+
currency: normalizeCurrency(config.currency),
|
|
1521
|
+
paymentMethodCreation: "manual",
|
|
1522
|
+
...config.appearance ? { appearance: config.appearance } : {}
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1435
1526
|
// src/storefrontStore/utils.ts
|
|
1436
1527
|
function readErrorMessage(error, fallback) {
|
|
1437
1528
|
if (error instanceof Error && error.message) return error.message;
|
|
@@ -1483,7 +1574,7 @@ function priceForMarket(prices, market, fallbackCurrency) {
|
|
|
1483
1574
|
market: price?.market || market,
|
|
1484
1575
|
currency: price?.currency || fallbackCurrency || "",
|
|
1485
1576
|
compare_at: price?.compare_at,
|
|
1486
|
-
|
|
1577
|
+
contact_list_id: price?.contact_list_id
|
|
1487
1578
|
};
|
|
1488
1579
|
}
|
|
1489
1580
|
function availableStock(client, variant) {
|
|
@@ -1647,8 +1738,11 @@ function normalizeTimezoneGroups(groups) {
|
|
|
1647
1738
|
return normalized;
|
|
1648
1739
|
}
|
|
1649
1740
|
|
|
1650
|
-
// src/storefrontStore/
|
|
1651
|
-
function
|
|
1741
|
+
// src/storefrontStore/initialize.ts
|
|
1742
|
+
function firstFiniteNumber(...values) {
|
|
1743
|
+
return values.find((value) => typeof value === "number" && Number.isFinite(value));
|
|
1744
|
+
}
|
|
1745
|
+
function initialize(config) {
|
|
1652
1746
|
const client = createStorefront(config);
|
|
1653
1747
|
const session = nanostores.atom(client.session);
|
|
1654
1748
|
const locale = nanostores.atom(config.locale || client.getLocale());
|
|
@@ -1659,7 +1753,7 @@ function createArkyStore(config) {
|
|
|
1659
1753
|
const payment_config = nanostores.computed(session, (value) => {
|
|
1660
1754
|
const store = value?.store;
|
|
1661
1755
|
const methods = value?.market?.payment_methods || [];
|
|
1662
|
-
const hasCreditCard = methods.some((method) => method.
|
|
1756
|
+
const hasCreditCard = methods.some((method) => method.type === "credit_card");
|
|
1663
1757
|
return { provider: store?.payment || null, enabled: hasCreditCard && !!store?.payment };
|
|
1664
1758
|
});
|
|
1665
1759
|
const cart = nanostores.atom(null);
|
|
@@ -1668,6 +1762,8 @@ function createArkyStore(config) {
|
|
|
1668
1762
|
const quote = nanostores.atom(null);
|
|
1669
1763
|
const promo_code = nanostores.atom(null);
|
|
1670
1764
|
const last_order = nanostores.atom(null);
|
|
1765
|
+
const payment_controller = nanostores.atom(null);
|
|
1766
|
+
const payment_ready = nanostores.computed(payment_controller, (value) => value !== null);
|
|
1671
1767
|
const cart_status = nanostores.map({
|
|
1672
1768
|
loading: false,
|
|
1673
1769
|
syncing: false,
|
|
@@ -1719,7 +1815,7 @@ function createArkyStore(config) {
|
|
|
1719
1815
|
return cartWriteRevision;
|
|
1720
1816
|
}
|
|
1721
1817
|
const cms_state = nanostores.map({
|
|
1722
|
-
|
|
1818
|
+
entries: {},
|
|
1723
1819
|
forms: {},
|
|
1724
1820
|
loading: false,
|
|
1725
1821
|
error: null
|
|
@@ -1758,6 +1854,51 @@ function createArkyStore(config) {
|
|
|
1758
1854
|
function currentCurrency() {
|
|
1759
1855
|
return currency.get() || market.get()?.currency || null;
|
|
1760
1856
|
}
|
|
1857
|
+
function currentStripePublishableKey() {
|
|
1858
|
+
const provider = payment_config.get()?.provider;
|
|
1859
|
+
return provider?.publishable_key || provider?.publishableKey || provider?.publicKey || null;
|
|
1860
|
+
}
|
|
1861
|
+
function currentPaymentAmount() {
|
|
1862
|
+
return Math.max(
|
|
1863
|
+
0,
|
|
1864
|
+
firstFiniteNumber(
|
|
1865
|
+
quote.get()?.charge_amount,
|
|
1866
|
+
quote.get()?.payment?.total,
|
|
1867
|
+
cart.get()?.quote_snapshot?.charge_amount,
|
|
1868
|
+
cart.get()?.quote_snapshot?.payment?.total,
|
|
1869
|
+
cart.get()?.quote_snapshot?.total
|
|
1870
|
+
) ?? 0
|
|
1871
|
+
);
|
|
1872
|
+
}
|
|
1873
|
+
function setPaymentController(controller) {
|
|
1874
|
+
const current = payment_controller.get();
|
|
1875
|
+
if (current && current !== controller) {
|
|
1876
|
+
current.destroy();
|
|
1877
|
+
}
|
|
1878
|
+
payment_controller.set(controller);
|
|
1879
|
+
return controller;
|
|
1880
|
+
}
|
|
1881
|
+
function destroyPaymentController() {
|
|
1882
|
+
setPaymentController(null);
|
|
1883
|
+
}
|
|
1884
|
+
async function mountStripePayment(target, options = {}) {
|
|
1885
|
+
const publishableKey = options.publishableKey || currentStripePublishableKey();
|
|
1886
|
+
if (!publishableKey) {
|
|
1887
|
+
throw new Error("Stripe publishable key is required to mount card payment");
|
|
1888
|
+
}
|
|
1889
|
+
const controller = await createStripeConfirmationTokenController({
|
|
1890
|
+
publishableKey,
|
|
1891
|
+
amount: Math.max(0, options.amount ?? currentPaymentAmount()),
|
|
1892
|
+
currency: options.currency || currentCurrency() || "usd",
|
|
1893
|
+
...options.appearance ? { appearance: options.appearance } : {}
|
|
1894
|
+
});
|
|
1895
|
+
controller.mount(target);
|
|
1896
|
+
setPaymentController(controller);
|
|
1897
|
+
return controller;
|
|
1898
|
+
}
|
|
1899
|
+
function updatePaymentController(input) {
|
|
1900
|
+
payment_controller.get()?.update(input);
|
|
1901
|
+
}
|
|
1761
1902
|
function marketForLocale(value) {
|
|
1762
1903
|
return config.marketForLocale?.(value) || null;
|
|
1763
1904
|
}
|
|
@@ -1803,7 +1944,7 @@ function createArkyStore(config) {
|
|
|
1803
1944
|
cartRequest = (async () => {
|
|
1804
1945
|
await ensureSession();
|
|
1805
1946
|
const response = await client.cart.refresh({ market: currentMarketKey() });
|
|
1806
|
-
await
|
|
1947
|
+
await applyCartResponse(response, { ifRevision: refreshRevision });
|
|
1807
1948
|
return response;
|
|
1808
1949
|
})();
|
|
1809
1950
|
try {
|
|
@@ -1816,7 +1957,7 @@ function createArkyStore(config) {
|
|
|
1816
1957
|
cart_status.setKey("loading", false);
|
|
1817
1958
|
}
|
|
1818
1959
|
}
|
|
1819
|
-
async function
|
|
1960
|
+
async function buildProductCartItem(item, source) {
|
|
1820
1961
|
try {
|
|
1821
1962
|
const product = await client.eshop.product.get({ id: item.product_id });
|
|
1822
1963
|
const variant = product.variants.find((candidate) => candidate.id === item.variant_id);
|
|
@@ -1828,6 +1969,7 @@ function createArkyStore(config) {
|
|
|
1828
1969
|
product_name: productName(product, currentLocale()),
|
|
1829
1970
|
product_slug: entitySlug(product, currentLocale()),
|
|
1830
1971
|
variant_attributes: variant.attributes,
|
|
1972
|
+
requires_shipping: variant.requires_shipping !== false,
|
|
1831
1973
|
price: priceForMarket(variant.prices, currentMarketKey(), currentCurrency()),
|
|
1832
1974
|
quantity: item.quantity,
|
|
1833
1975
|
added_at: source.created_at ? source.created_at * 1e3 : Date.now(),
|
|
@@ -1837,7 +1979,7 @@ function createArkyStore(config) {
|
|
|
1837
1979
|
return null;
|
|
1838
1980
|
}
|
|
1839
1981
|
}
|
|
1840
|
-
async function
|
|
1982
|
+
async function buildServiceCartItems(items) {
|
|
1841
1983
|
const rows = [];
|
|
1842
1984
|
for (const item of items) {
|
|
1843
1985
|
let service = null;
|
|
@@ -1865,7 +2007,7 @@ function createArkyStore(config) {
|
|
|
1865
2007
|
}
|
|
1866
2008
|
return rows;
|
|
1867
2009
|
}
|
|
1868
|
-
async function
|
|
2010
|
+
async function applyCartResponse(response, options = {}) {
|
|
1869
2011
|
if (options.ifRevision !== void 0 && options.ifRevision !== cartWriteRevision) {
|
|
1870
2012
|
return cart.get() || response;
|
|
1871
2013
|
}
|
|
@@ -1876,9 +2018,9 @@ function createArkyStore(config) {
|
|
|
1876
2018
|
quote.set(response.quote_snapshot || null);
|
|
1877
2019
|
const items = response.items || [];
|
|
1878
2020
|
const products = await Promise.all(
|
|
1879
|
-
items.filter((item) => item.type === "product").map((item) =>
|
|
2021
|
+
items.filter((item) => item.type === "product").map((item) => buildProductCartItem(item, response))
|
|
1880
2022
|
);
|
|
1881
|
-
const services = await
|
|
2023
|
+
const services = await buildServiceCartItems(
|
|
1882
2024
|
items.filter((item) => item.type === "service")
|
|
1883
2025
|
);
|
|
1884
2026
|
product_items.set(products.filter((item) => item !== null));
|
|
@@ -1904,14 +2046,14 @@ function createArkyStore(config) {
|
|
|
1904
2046
|
billing_address: input.billing_address || void 0,
|
|
1905
2047
|
forms: normalizeForms(input.forms),
|
|
1906
2048
|
promo_code: input.promo_code === void 0 ? promo_code.get() || void 0 : input.promo_code || void 0,
|
|
1907
|
-
|
|
2049
|
+
payment_method_key: input.payment_method_key || void 0,
|
|
1908
2050
|
shipping_method_id: input.shipping_method_id || cart_status.get().selected_shipping_method_id || void 0
|
|
1909
2051
|
});
|
|
1910
2052
|
if (input.promo_code !== void 0) promo_code.set(input.promo_code);
|
|
1911
2053
|
if (input.shipping_method_id !== void 0) {
|
|
1912
2054
|
cart_status.setKey("selected_shipping_method_id", input.shipping_method_id);
|
|
1913
2055
|
}
|
|
1914
|
-
await
|
|
2056
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1915
2057
|
return response;
|
|
1916
2058
|
} catch (error) {
|
|
1917
2059
|
cart_status.setKey("error", readErrorMessage(error, "Failed to sync cart."));
|
|
@@ -1934,8 +2076,7 @@ function createArkyStore(config) {
|
|
|
1934
2076
|
quantity
|
|
1935
2077
|
}
|
|
1936
2078
|
});
|
|
1937
|
-
await
|
|
1938
|
-
await client.activity.track({ type: "cart_added", payload: { product_id: product.id, variant_id: variant.id, quantity } });
|
|
2079
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1939
2080
|
return response;
|
|
1940
2081
|
} catch (error) {
|
|
1941
2082
|
cart_status.setKey("error", readErrorMessage(error, "Failed to add product to cart."));
|
|
@@ -1964,8 +2105,7 @@ function createArkyStore(config) {
|
|
|
1964
2105
|
product_id: item.product_id,
|
|
1965
2106
|
variant_id: item.variant_id
|
|
1966
2107
|
});
|
|
1967
|
-
await
|
|
1968
|
-
await client.activity.track({ type: "cart_removed", payload: { product_id: item.product_id, variant_id: item.variant_id } });
|
|
2108
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1969
2109
|
return response;
|
|
1970
2110
|
}
|
|
1971
2111
|
async function addServiceItem(item) {
|
|
@@ -1982,16 +2122,20 @@ function createArkyStore(config) {
|
|
|
1982
2122
|
}
|
|
1983
2123
|
async function clearCart() {
|
|
1984
2124
|
const writeRevision = nextCartWriteRevision();
|
|
2125
|
+
const current = cart.get();
|
|
2126
|
+
clearLocalCart();
|
|
2127
|
+
if (!current) return null;
|
|
2128
|
+
const response = await client.cart.clear({ id: current.id });
|
|
2129
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
2130
|
+
return response;
|
|
2131
|
+
}
|
|
2132
|
+
function clearLocalCart() {
|
|
1985
2133
|
product_items.set([]);
|
|
1986
2134
|
service_items.set([]);
|
|
2135
|
+
cart.set(null);
|
|
1987
2136
|
quote.set(null);
|
|
1988
2137
|
promo_code.set(null);
|
|
1989
2138
|
cart_status.setKey("selected_shipping_method_id", null);
|
|
1990
|
-
const current = cart.get();
|
|
1991
|
-
if (!current) return null;
|
|
1992
|
-
const response = await client.cart.clear({ id: current.id });
|
|
1993
|
-
await hydrateCart(response, { ifRevision: writeRevision });
|
|
1994
|
-
return response;
|
|
1995
2139
|
}
|
|
1996
2140
|
async function fetchQuote(input = {}) {
|
|
1997
2141
|
if (checkoutItems(input).length === 0) {
|
|
@@ -2019,16 +2163,51 @@ function createArkyStore(config) {
|
|
|
2019
2163
|
cart_status.setKey("error", null);
|
|
2020
2164
|
try {
|
|
2021
2165
|
const current = await syncCart(input);
|
|
2022
|
-
|
|
2166
|
+
const quoteValue = quote.get();
|
|
2167
|
+
const paymentMethodKey = input.payment_method_key || current.payment_method_key || quoteValue?.payment?.payment_method_key || void 0;
|
|
2168
|
+
let chargeAmount = firstFiniteNumber(
|
|
2169
|
+
quoteValue?.charge_amount,
|
|
2170
|
+
quoteValue?.payment?.total,
|
|
2171
|
+
current.quote_snapshot?.charge_amount,
|
|
2172
|
+
current.quote_snapshot?.payment?.total
|
|
2173
|
+
);
|
|
2174
|
+
if (paymentMethodKey === "credit_card" && chargeAmount === void 0) {
|
|
2175
|
+
const latestQuote = await client.cart.quote({ id: current.id });
|
|
2176
|
+
quote.set(latestQuote);
|
|
2177
|
+
chargeAmount = firstFiniteNumber(
|
|
2178
|
+
latestQuote.charge_amount,
|
|
2179
|
+
latestQuote.payment?.total,
|
|
2180
|
+
latestQuote.total
|
|
2181
|
+
);
|
|
2182
|
+
}
|
|
2183
|
+
const needsConfirmationToken = paymentMethodKey === "credit_card" && (chargeAmount === void 0 || chargeAmount > 0);
|
|
2184
|
+
let confirmationTokenId;
|
|
2185
|
+
let returnUrl = input.return_url;
|
|
2186
|
+
const paymentController = input.payment ?? payment_controller.get();
|
|
2187
|
+
if (needsConfirmationToken) {
|
|
2188
|
+
if (!paymentController) throw new Error("Payment controller is required for card checkout");
|
|
2189
|
+
returnUrl = returnUrl || (typeof window !== "undefined" ? window.location.href : void 0);
|
|
2190
|
+
const token = await paymentController.createConfirmationToken({
|
|
2191
|
+
return_url: returnUrl,
|
|
2192
|
+
billing_details: input.billing_details
|
|
2193
|
+
});
|
|
2194
|
+
confirmationTokenId = token.confirmation_token_id;
|
|
2195
|
+
returnUrl = token.return_url || returnUrl;
|
|
2196
|
+
}
|
|
2023
2197
|
const response = await client.cart.checkout({
|
|
2024
2198
|
id: current.id,
|
|
2025
|
-
|
|
2199
|
+
payment_method_key: paymentMethodKey,
|
|
2200
|
+
confirmation_token_id: confirmationTokenId,
|
|
2201
|
+
return_url: returnUrl
|
|
2026
2202
|
});
|
|
2027
|
-
|
|
2203
|
+
if (response.payment_action.type === "handle_next_action") {
|
|
2204
|
+
if (!paymentController) throw new Error("Payment controller is required for card authentication");
|
|
2205
|
+
await paymentController.handleNextAction(response.payment_action.client_secret);
|
|
2206
|
+
}
|
|
2028
2207
|
const stored = {
|
|
2029
2208
|
order_id: response.order_id,
|
|
2030
2209
|
number: response.number,
|
|
2031
|
-
|
|
2210
|
+
payment_action: response.payment_action,
|
|
2032
2211
|
payment: response.payment,
|
|
2033
2212
|
product_items: input.product_items || product_items.get(),
|
|
2034
2213
|
service_items: input.service_items || service_items.get(),
|
|
@@ -2036,17 +2215,13 @@ function createArkyStore(config) {
|
|
|
2036
2215
|
billing_address: input.billing_address || null,
|
|
2037
2216
|
total: quoteValue?.payment?.total || quoteValue?.total || response.payment?.total,
|
|
2038
2217
|
currency: quoteValue?.payment?.currency || currentCurrency(),
|
|
2039
|
-
|
|
2218
|
+
payment_method_key: paymentMethodKey || null,
|
|
2040
2219
|
created_at: Date.now()
|
|
2041
2220
|
};
|
|
2042
2221
|
last_order.set(stored);
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
quote.set(null);
|
|
2047
|
-
promo_code.set(null);
|
|
2048
|
-
cart_status.setKey("selected_shipping_method_id", null);
|
|
2049
|
-
await client.activity.track({ type: "purchase", payload: { order_id: response.order_id, number: response.number } });
|
|
2222
|
+
if (input.clear_after_checkout !== false) {
|
|
2223
|
+
clearLocalCart();
|
|
2224
|
+
}
|
|
2050
2225
|
return response;
|
|
2051
2226
|
} catch (error) {
|
|
2052
2227
|
cart_status.setKey("error", readErrorMessage(error, "Checkout failed."));
|
|
@@ -2466,7 +2641,7 @@ function createArkyStore(config) {
|
|
|
2466
2641
|
...toServiceCartItem(slot),
|
|
2467
2642
|
forms: []
|
|
2468
2643
|
})),
|
|
2469
|
-
|
|
2644
|
+
payment_method_key: paymentMethodId,
|
|
2470
2645
|
promo_code: state.promoCode || void 0,
|
|
2471
2646
|
forms
|
|
2472
2647
|
});
|
|
@@ -2487,7 +2662,7 @@ function createArkyStore(config) {
|
|
|
2487
2662
|
service_state.setKey("promoCode", promoCode || null);
|
|
2488
2663
|
const response = await fetchQuote({
|
|
2489
2664
|
service_items: state.cart.map(toServiceCartItem),
|
|
2490
|
-
|
|
2665
|
+
payment_method_key: paymentMethodId,
|
|
2491
2666
|
promo_code: promoCode || void 0
|
|
2492
2667
|
});
|
|
2493
2668
|
service_state.setKey("cartId", cart.get()?.id || null);
|
|
@@ -2534,18 +2709,38 @@ function createArkyStore(config) {
|
|
|
2534
2709
|
}
|
|
2535
2710
|
};
|
|
2536
2711
|
service_items.subscribe((items) => setServiceCartFromServiceItems(items));
|
|
2537
|
-
async function
|
|
2712
|
+
async function loadEntry(params, options) {
|
|
2538
2713
|
cms_state.setKey("loading", true);
|
|
2539
2714
|
cms_state.setKey("error", null);
|
|
2540
2715
|
try {
|
|
2541
|
-
const { locale: nextLocale, market: nextMarket, ...
|
|
2716
|
+
const { locale: nextLocale, market: nextMarket, ...entryParams } = params;
|
|
2542
2717
|
setContext({ locale: nextLocale, market: nextMarket });
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2718
|
+
if (entryParams.id) {
|
|
2719
|
+
const entry2 = await client.cms.entry.get(entryParams, options);
|
|
2720
|
+
const cacheKey = entryParams.key || entryParams.id || entry2.id;
|
|
2721
|
+
cms_state.setKey("entries", { ...cms_state.get().entries, [cacheKey]: entry2 });
|
|
2722
|
+
return entry2;
|
|
2723
|
+
}
|
|
2724
|
+
if (!entryParams.collection_id || !entryParams.key) {
|
|
2725
|
+
throw new Error("ArkyCmsEntryParams requires id, or collection_id and key");
|
|
2726
|
+
}
|
|
2727
|
+
const result = await client.cms.entry.find(
|
|
2728
|
+
{
|
|
2729
|
+
...entryParams,
|
|
2730
|
+
collection_id: entryParams.collection_id,
|
|
2731
|
+
key: entryParams.key,
|
|
2732
|
+
limit: 1
|
|
2733
|
+
},
|
|
2734
|
+
options
|
|
2735
|
+
);
|
|
2736
|
+
const entry = result.items?.[0];
|
|
2737
|
+
if (!entry) {
|
|
2738
|
+
throw new Error("CMS entry not found");
|
|
2739
|
+
}
|
|
2740
|
+
cms_state.setKey("entries", { ...cms_state.get().entries, [entryParams.key]: entry });
|
|
2741
|
+
return entry;
|
|
2547
2742
|
} catch (error) {
|
|
2548
|
-
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS
|
|
2743
|
+
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS entry."));
|
|
2549
2744
|
throw error;
|
|
2550
2745
|
} finally {
|
|
2551
2746
|
cms_state.setKey("loading", false);
|
|
@@ -2632,19 +2827,14 @@ function createArkyStore(config) {
|
|
|
2632
2827
|
eshop_state.setKey("loading_availability", false);
|
|
2633
2828
|
}
|
|
2634
2829
|
}
|
|
2635
|
-
async function
|
|
2636
|
-
|
|
2637
|
-
const
|
|
2638
|
-
|
|
2639
|
-
session: session.get()
|
|
2640
|
-
};
|
|
2641
|
-
if (shouldIdentify) results.session = await ensureSession();
|
|
2642
|
-
if (options.hydrateCart) results.cart = await ensureCart();
|
|
2643
|
-
if (options.track) await client.activity.track(options.track);
|
|
2644
|
-
return results;
|
|
2830
|
+
async function useExperiment(params) {
|
|
2831
|
+
await ensureSession();
|
|
2832
|
+
const input = typeof params === "string" ? { key: params } : params;
|
|
2833
|
+
return client.experiments.use(input);
|
|
2645
2834
|
}
|
|
2646
|
-
async function
|
|
2647
|
-
|
|
2835
|
+
async function trackAction(params) {
|
|
2836
|
+
await ensureSession();
|
|
2837
|
+
return client.action.track(params);
|
|
2648
2838
|
}
|
|
2649
2839
|
const cart_store = {
|
|
2650
2840
|
cart,
|
|
@@ -2658,17 +2848,26 @@ function createArkyStore(config) {
|
|
|
2658
2848
|
service_item_count,
|
|
2659
2849
|
item_count,
|
|
2660
2850
|
snapshot,
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
sync: syncCart,
|
|
2851
|
+
load: ensureCart,
|
|
2852
|
+
refresh: syncCart,
|
|
2664
2853
|
addProduct,
|
|
2665
2854
|
setProductQuantity,
|
|
2666
2855
|
removeProduct,
|
|
2667
2856
|
addServiceItem,
|
|
2668
2857
|
removeServiceItem,
|
|
2669
2858
|
clear: clearCart,
|
|
2859
|
+
clearLocal: clearLocalCart,
|
|
2670
2860
|
quote: fetchQuote,
|
|
2671
2861
|
checkout,
|
|
2862
|
+
payment: {
|
|
2863
|
+
controller: payment_controller,
|
|
2864
|
+
ready: payment_ready,
|
|
2865
|
+
setController: setPaymentController,
|
|
2866
|
+
getController: () => payment_controller.get(),
|
|
2867
|
+
mountStripe: mountStripePayment,
|
|
2868
|
+
update: updatePaymentController,
|
|
2869
|
+
destroy: destroyPaymentController
|
|
2870
|
+
},
|
|
2672
2871
|
applyPromoCode(code, input = {}) {
|
|
2673
2872
|
promo_code.set(code);
|
|
2674
2873
|
return fetchQuote({ ...input, promo_code: code });
|
|
@@ -2742,16 +2941,12 @@ function createArkyStore(config) {
|
|
|
2742
2941
|
currency,
|
|
2743
2942
|
allowed_payment_methods,
|
|
2744
2943
|
payment_config,
|
|
2745
|
-
|
|
2746
|
-
initialize,
|
|
2944
|
+
cart: cart_store,
|
|
2747
2945
|
identify,
|
|
2748
2946
|
verify: client.verify,
|
|
2749
2947
|
me: client.me,
|
|
2750
2948
|
logout: client.logout,
|
|
2751
2949
|
onAuthStateChanged: client.onAuthStateChanged,
|
|
2752
|
-
get currentSession() {
|
|
2753
|
-
return session.get();
|
|
2754
|
-
},
|
|
2755
2950
|
get isAuthenticated() {
|
|
2756
2951
|
return client.isAuthenticated;
|
|
2757
2952
|
},
|
|
@@ -2763,10 +2958,12 @@ function createArkyStore(config) {
|
|
|
2763
2958
|
getLocale: currentLocale,
|
|
2764
2959
|
cms: {
|
|
2765
2960
|
state: cms_state,
|
|
2766
|
-
|
|
2767
|
-
get:
|
|
2768
|
-
|
|
2769
|
-
|
|
2961
|
+
collection: {
|
|
2962
|
+
get: (params, options) => client.cms.collection.get(params, options)
|
|
2963
|
+
},
|
|
2964
|
+
entry: {
|
|
2965
|
+
get: loadEntry,
|
|
2966
|
+
find: (params, options) => client.cms.entry.find(params, options)
|
|
2770
2967
|
},
|
|
2771
2968
|
form: {
|
|
2772
2969
|
get: loadForm,
|
|
@@ -2787,24 +2984,28 @@ function createArkyStore(config) {
|
|
|
2787
2984
|
cart: cart_store
|
|
2788
2985
|
},
|
|
2789
2986
|
crm: client.crm,
|
|
2790
|
-
|
|
2987
|
+
action: {
|
|
2791
2988
|
track(params) {
|
|
2792
|
-
return
|
|
2989
|
+
return trackAction(params);
|
|
2793
2990
|
},
|
|
2794
2991
|
pageView(payload = {}) {
|
|
2795
|
-
return
|
|
2992
|
+
return trackAction({ key: "page.view", payload });
|
|
2796
2993
|
},
|
|
2797
2994
|
state: nanostores.atom(null)
|
|
2798
2995
|
},
|
|
2996
|
+
experiments: {
|
|
2997
|
+
use: useExperiment
|
|
2998
|
+
},
|
|
2799
2999
|
support: client.support,
|
|
2800
3000
|
store: client.store,
|
|
2801
3001
|
utils: client.utils
|
|
2802
3002
|
};
|
|
2803
3003
|
}
|
|
2804
3004
|
|
|
2805
|
-
exports.
|
|
2806
|
-
exports.createArkyStore = createArkyStore;
|
|
3005
|
+
exports.COMMON_ACTION_KEYS = COMMON_ACTION_KEYS;
|
|
2807
3006
|
exports.createCartController = createCartController;
|
|
2808
3007
|
exports.createStorefront = createStorefront;
|
|
3008
|
+
exports.createStripeConfirmationTokenController = createStripeConfirmationTokenController;
|
|
3009
|
+
exports.initialize = initialize;
|
|
2809
3010
|
//# sourceMappingURL=storefront.cjs.map
|
|
2810
3011
|
//# sourceMappingURL=storefront.cjs.map
|