arky-sdk 0.9.6 → 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.
- package/README.md +113 -194
- package/dist/{admin-DjYydKeB.d.ts → admin-BKXmDIVk.d.ts} +412 -405
- package/dist/{admin-DlL8mCxL.d.cts → admin-CAwQrMOX.d.cts} +412 -405
- package/dist/admin.cjs +767 -373
- 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 +767 -373
- package/dist/admin.js.map +1 -1
- package/dist/{api-BbBHcd4p.d.cts → api-DJI3S6XA.d.cts} +1440 -525
- package/dist/{api-BbBHcd4p.d.ts → api-DJI3S6XA.d.ts} +1440 -525
- package/dist/{index-CZxubTDA.d.ts → index-BaSBPLdF.d.ts} +1 -1
- package/dist/{index-nCF3Z6Af.d.cts → index-u-gjHnKs.d.cts} +1 -1
- package/dist/index.cjs +874 -471
- 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 +874 -471
- package/dist/index.js.map +1 -1
- package/dist/storefront.cjs +493 -300
- package/dist/storefront.cjs.map +1 -1
- package/dist/storefront.d.cts +172 -89
- package/dist/storefront.d.ts +172 -89
- package/dist/storefront.js +491 -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/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.js
CHANGED
|
@@ -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
|
|
150
|
-
"
|
|
151
|
-
"
|
|
152
|
-
"
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
157
|
-
"
|
|
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
|
-
"
|
|
34
|
+
"verified.email",
|
|
162
35
|
"search",
|
|
163
36
|
"share",
|
|
164
|
-
"
|
|
37
|
+
"wishlist.added"
|
|
165
38
|
];
|
|
166
|
-
var
|
|
167
|
-
|
|
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}/
|
|
172
|
-
{
|
|
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,
|
|
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, updateProfileSession) => {
|
|
|
209
83
|
}
|
|
210
84
|
},
|
|
211
85
|
cms: {
|
|
212
|
-
|
|
213
|
-
|
|
86
|
+
collection: {
|
|
87
|
+
get(params, options) {
|
|
214
88
|
const store_id = params.store_id || apiConfig.storeId;
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
226
|
-
`${base(store_id)}/
|
|
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)}/
|
|
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, updateProfileSession) => {
|
|
|
409
268
|
{
|
|
410
269
|
id: params.id,
|
|
411
270
|
store_id,
|
|
412
|
-
|
|
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, updateProfileSession) => {
|
|
|
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, updateProfileSession) => {
|
|
|
496
365
|
}
|
|
497
366
|
},
|
|
498
367
|
crm: {
|
|
499
|
-
|
|
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)}/
|
|
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, updateProfileSession) => {
|
|
|
510
379
|
options
|
|
511
380
|
);
|
|
512
381
|
if (result?.token?.token) {
|
|
513
|
-
|
|
382
|
+
updateContactSession(() => ({
|
|
514
383
|
access_token: result.token.token,
|
|
515
|
-
|
|
384
|
+
contact: result.contact,
|
|
516
385
|
store: result.store,
|
|
517
386
|
market: result.market
|
|
518
387
|
}));
|
|
@@ -522,12 +391,12 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
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)}/
|
|
394
|
+
`${base(store_id)}/account/verify`,
|
|
526
395
|
{ store_id, code: params.code },
|
|
527
396
|
options
|
|
528
397
|
);
|
|
529
398
|
if (result?.token) {
|
|
530
|
-
|
|
399
|
+
updateContactSession(
|
|
531
400
|
(prev) => prev ? { ...prev, access_token: result.token } : null
|
|
532
401
|
);
|
|
533
402
|
}
|
|
@@ -537,29 +406,29 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
537
406
|
const store_id = apiConfig.storeId;
|
|
538
407
|
try {
|
|
539
408
|
await apiConfig.httpClient.post(
|
|
540
|
-
`${base(store_id)}/
|
|
409
|
+
`${base(store_id)}/account/logout`,
|
|
541
410
|
{},
|
|
542
411
|
options
|
|
543
412
|
);
|
|
544
413
|
} finally {
|
|
545
|
-
|
|
414
|
+
updateContactSession(() => null);
|
|
546
415
|
}
|
|
547
416
|
},
|
|
548
417
|
getMe(options) {
|
|
549
|
-
return apiConfig.httpClient.get(`${base()}/
|
|
418
|
+
return apiConfig.httpClient.get(`${base()}/account/me`, options);
|
|
550
419
|
}
|
|
551
420
|
},
|
|
552
|
-
|
|
421
|
+
contactList: {
|
|
553
422
|
get(params, options) {
|
|
554
423
|
const store_id = params.store_id || apiConfig.storeId;
|
|
555
424
|
return apiConfig.httpClient.get(
|
|
556
|
-
`${base(store_id)}/
|
|
425
|
+
`${base(store_id)}/contact-lists/${params.id}`,
|
|
557
426
|
options
|
|
558
427
|
);
|
|
559
428
|
},
|
|
560
429
|
find(params, options) {
|
|
561
430
|
const { store_id, ...queryParams } = params || {};
|
|
562
|
-
return apiConfig.httpClient.get(`${base(store_id)}/
|
|
431
|
+
return apiConfig.httpClient.get(`${base(store_id)}/contact-lists`, {
|
|
563
432
|
...options,
|
|
564
433
|
params: queryParams
|
|
565
434
|
});
|
|
@@ -567,7 +436,7 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
567
436
|
subscribe(params, options) {
|
|
568
437
|
const { store_id, id, ...payload } = params;
|
|
569
438
|
return apiConfig.httpClient.post(
|
|
570
|
-
`${base(store_id)}/
|
|
439
|
+
`${base(store_id)}/contact-lists/${id}/subscribe`,
|
|
571
440
|
payload,
|
|
572
441
|
options
|
|
573
442
|
);
|
|
@@ -575,25 +444,37 @@ var createStorefrontApi = (apiConfig, updateProfileSession) => {
|
|
|
575
444
|
checkAccess(params, options) {
|
|
576
445
|
const store_id = params.store_id || apiConfig.storeId;
|
|
577
446
|
return apiConfig.httpClient.get(
|
|
578
|
-
`${base(store_id)}/
|
|
447
|
+
`${base(store_id)}/contact-lists/${params.id}/access`,
|
|
579
448
|
options
|
|
580
449
|
);
|
|
581
450
|
},
|
|
582
451
|
unsubscribe(token, options) {
|
|
583
|
-
return apiConfig.httpClient.
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
452
|
+
return apiConfig.httpClient.post(
|
|
453
|
+
`${base()}/contact-lists/unsubscribe`,
|
|
454
|
+
{ token },
|
|
455
|
+
options
|
|
456
|
+
);
|
|
587
457
|
},
|
|
588
458
|
confirm(token, options) {
|
|
589
|
-
return apiConfig.httpClient.
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
459
|
+
return apiConfig.httpClient.post(
|
|
460
|
+
`${base()}/contact-lists/confirm`,
|
|
461
|
+
{ token },
|
|
462
|
+
options
|
|
463
|
+
);
|
|
593
464
|
}
|
|
594
465
|
}
|
|
595
466
|
},
|
|
596
|
-
|
|
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
|
+
}
|
|
477
|
+
}
|
|
597
478
|
};
|
|
598
479
|
};
|
|
599
480
|
|
|
@@ -818,7 +699,7 @@ function createHttpClient(cfg) {
|
|
|
818
699
|
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
819
700
|
}
|
|
820
701
|
const finalPath = options?.params ? path + buildQueryString(options.params) : path;
|
|
821
|
-
const fetchOpts = { method, headers };
|
|
702
|
+
const fetchOpts = { method, headers, signal: options?.signal };
|
|
822
703
|
if (!["GET", "DELETE"].includes(method) && body !== void 0) {
|
|
823
704
|
fetchOpts.body = JSON.stringify(body);
|
|
824
705
|
}
|
|
@@ -829,13 +710,15 @@ function createHttpClient(cfg) {
|
|
|
829
710
|
try {
|
|
830
711
|
res = await fetch(fullUrl, fetchOpts);
|
|
831
712
|
} catch (error) {
|
|
713
|
+
const aborted = options?.signal?.aborted || error instanceof Error && error.name === "AbortError";
|
|
832
714
|
const err = new Error(error instanceof Error ? error.message : "Network request failed");
|
|
833
|
-
err.name = "NetworkError";
|
|
715
|
+
err.name = aborted ? "AbortError" : "NetworkError";
|
|
834
716
|
err.method = method;
|
|
835
717
|
err.url = fullUrl;
|
|
718
|
+
err.aborted = aborted;
|
|
836
719
|
if (options?.onError && method !== "GET") {
|
|
837
720
|
Promise.resolve(
|
|
838
|
-
options.onError({ error: err, method, url: fullUrl, aborted
|
|
721
|
+
options.onError({ error: err, method, url: fullUrl, aborted })
|
|
839
722
|
).catch(() => {
|
|
840
723
|
});
|
|
841
724
|
}
|
|
@@ -963,6 +846,133 @@ function createStorefrontSupportApi(config) {
|
|
|
963
846
|
};
|
|
964
847
|
}
|
|
965
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
|
+
|
|
966
976
|
// src/utils/price.ts
|
|
967
977
|
function formatCurrency(amount, currencyCode, locale = "en") {
|
|
968
978
|
if (!currencyCode) return "";
|
|
@@ -1252,22 +1262,22 @@ function createUtilitySurface(apiConfig) {
|
|
|
1252
1262
|
getFirstAvailableFCId
|
|
1253
1263
|
};
|
|
1254
1264
|
}
|
|
1255
|
-
var
|
|
1256
|
-
function
|
|
1265
|
+
var CONTACT_STORAGE_KEY = "arky_contact_session";
|
|
1266
|
+
function readContactSession() {
|
|
1257
1267
|
if (typeof window === "undefined") return null;
|
|
1258
1268
|
try {
|
|
1259
|
-
const raw = localStorage.getItem(
|
|
1269
|
+
const raw = localStorage.getItem(CONTACT_STORAGE_KEY);
|
|
1260
1270
|
return raw ? JSON.parse(raw) : null;
|
|
1261
1271
|
} catch {
|
|
1262
1272
|
return null;
|
|
1263
1273
|
}
|
|
1264
1274
|
}
|
|
1265
|
-
function
|
|
1275
|
+
function writeContactSession(s) {
|
|
1266
1276
|
if (typeof window === "undefined") return;
|
|
1267
1277
|
if (s) {
|
|
1268
|
-
localStorage.setItem(
|
|
1278
|
+
localStorage.setItem(CONTACT_STORAGE_KEY, JSON.stringify(s));
|
|
1269
1279
|
} else {
|
|
1270
|
-
localStorage.removeItem(
|
|
1280
|
+
localStorage.removeItem(CONTACT_STORAGE_KEY);
|
|
1271
1281
|
}
|
|
1272
1282
|
}
|
|
1273
1283
|
function createStorefront(config) {
|
|
@@ -1276,10 +1286,10 @@ function createStorefront(config) {
|
|
|
1276
1286
|
const listeners = /* @__PURE__ */ new Set();
|
|
1277
1287
|
let bareIdentifyPromise = null;
|
|
1278
1288
|
function toPublic(s) {
|
|
1279
|
-
return s ? {
|
|
1289
|
+
return s ? { contact: s.contact, store: s.store, market: s.market } : null;
|
|
1280
1290
|
}
|
|
1281
1291
|
function emit() {
|
|
1282
|
-
const pub = toPublic(
|
|
1292
|
+
const pub = toPublic(readContactSession());
|
|
1283
1293
|
for (const l of listeners) {
|
|
1284
1294
|
Promise.resolve().then(() => l(pub)).catch(() => {
|
|
1285
1295
|
});
|
|
@@ -1287,9 +1297,9 @@ function createStorefront(config) {
|
|
|
1287
1297
|
}
|
|
1288
1298
|
const updateSession = (updater) => {
|
|
1289
1299
|
if (config.apiToken) return;
|
|
1290
|
-
const prev =
|
|
1300
|
+
const prev = readContactSession();
|
|
1291
1301
|
const next = updater(prev);
|
|
1292
|
-
|
|
1302
|
+
writeContactSession(next);
|
|
1293
1303
|
emit();
|
|
1294
1304
|
};
|
|
1295
1305
|
const authStorage = config.apiToken ? {
|
|
@@ -1300,7 +1310,7 @@ function createStorefront(config) {
|
|
|
1300
1310
|
}
|
|
1301
1311
|
} : {
|
|
1302
1312
|
getTokens() {
|
|
1303
|
-
const s =
|
|
1313
|
+
const s = readContactSession();
|
|
1304
1314
|
return s ? { access_token: s.access_token } : null;
|
|
1305
1315
|
},
|
|
1306
1316
|
onTokensRefreshed() {
|
|
@@ -1327,20 +1337,20 @@ function createStorefront(config) {
|
|
|
1327
1337
|
authStorage
|
|
1328
1338
|
};
|
|
1329
1339
|
const storefrontApi = createStorefrontApi(apiConfig, updateSession);
|
|
1330
|
-
const
|
|
1340
|
+
const contactApi = storefrontApi.crm.contact;
|
|
1331
1341
|
function identify(params) {
|
|
1332
1342
|
if (params?.market !== void 0) apiConfig.market = params.market;
|
|
1333
1343
|
const isBareCall = !params?.email && !params?.verify;
|
|
1334
1344
|
if (isBareCall && bareIdentifyPromise) return bareIdentifyPromise;
|
|
1335
1345
|
const promise = (async () => {
|
|
1336
1346
|
try {
|
|
1337
|
-
const result = await
|
|
1347
|
+
const result = await contactApi.identify({
|
|
1338
1348
|
market: apiConfig.market,
|
|
1339
1349
|
email: params?.email,
|
|
1340
1350
|
verify: params?.verify
|
|
1341
1351
|
});
|
|
1342
1352
|
return {
|
|
1343
|
-
|
|
1353
|
+
contact: result.contact,
|
|
1344
1354
|
store: result.store,
|
|
1345
1355
|
market: result.market
|
|
1346
1356
|
};
|
|
@@ -1349,9 +1359,11 @@ function createStorefront(config) {
|
|
|
1349
1359
|
const status = e?.statusCode || e?.status || e?.response?.status;
|
|
1350
1360
|
if (isBareCall && status === 401) {
|
|
1351
1361
|
updateSession(() => null);
|
|
1352
|
-
const result = await
|
|
1362
|
+
const result = await contactApi.identify({
|
|
1363
|
+
market: apiConfig.market
|
|
1364
|
+
});
|
|
1353
1365
|
return {
|
|
1354
|
-
|
|
1366
|
+
contact: result.contact,
|
|
1355
1367
|
store: result.store,
|
|
1356
1368
|
market: result.market
|
|
1357
1369
|
};
|
|
@@ -1366,7 +1378,7 @@ function createStorefront(config) {
|
|
|
1366
1378
|
return promise;
|
|
1367
1379
|
}
|
|
1368
1380
|
async function verify(params) {
|
|
1369
|
-
const result = await
|
|
1381
|
+
const result = await contactApi.verify(params);
|
|
1370
1382
|
bareIdentifyPromise = null;
|
|
1371
1383
|
return result;
|
|
1372
1384
|
}
|
|
@@ -1374,7 +1386,7 @@ function createStorefront(config) {
|
|
|
1374
1386
|
if (config.apiToken) return;
|
|
1375
1387
|
bareIdentifyPromise = null;
|
|
1376
1388
|
try {
|
|
1377
|
-
await
|
|
1389
|
+
await contactApi.logout();
|
|
1378
1390
|
} catch {
|
|
1379
1391
|
updateSession(() => null);
|
|
1380
1392
|
}
|
|
@@ -1383,19 +1395,19 @@ function createStorefront(config) {
|
|
|
1383
1395
|
identify,
|
|
1384
1396
|
verify,
|
|
1385
1397
|
logout,
|
|
1386
|
-
me: () =>
|
|
1398
|
+
me: () => contactApi.getMe(),
|
|
1387
1399
|
get session() {
|
|
1388
1400
|
if (config.apiToken) return null;
|
|
1389
|
-
return toPublic(
|
|
1401
|
+
return toPublic(readContactSession());
|
|
1390
1402
|
},
|
|
1391
1403
|
get isAuthenticated() {
|
|
1392
1404
|
if (config.apiToken) return true;
|
|
1393
|
-
const s =
|
|
1405
|
+
const s = readContactSession();
|
|
1394
1406
|
return s !== null && !!s.access_token;
|
|
1395
1407
|
},
|
|
1396
1408
|
onAuthStateChanged(listener) {
|
|
1397
1409
|
listeners.add(listener);
|
|
1398
|
-
const current = toPublic(
|
|
1410
|
+
const current = toPublic(readContactSession());
|
|
1399
1411
|
if (current) {
|
|
1400
1412
|
Promise.resolve().then(() => listener(current)).catch(() => {
|
|
1401
1413
|
});
|
|
@@ -1409,7 +1421,8 @@ function createStorefront(config) {
|
|
|
1409
1421
|
cms: storefrontApi.cms,
|
|
1410
1422
|
eshop: storefrontApi.eshop,
|
|
1411
1423
|
crm: storefrontApi.crm,
|
|
1412
|
-
|
|
1424
|
+
action: storefrontApi.action,
|
|
1425
|
+
experiments: storefrontApi.experiments,
|
|
1413
1426
|
support: createStorefrontSupportApi(apiConfig),
|
|
1414
1427
|
setStoreId: (storeId) => {
|
|
1415
1428
|
apiConfig.storeId = storeId;
|
|
@@ -1425,11 +1438,81 @@ function createStorefront(config) {
|
|
|
1425
1438
|
apiConfig.locale = l;
|
|
1426
1439
|
},
|
|
1427
1440
|
getLocale: () => apiConfig.locale,
|
|
1428
|
-
extractBlockValues,
|
|
1429
1441
|
utils: createUtilitySurface(apiConfig)
|
|
1430
1442
|
};
|
|
1431
1443
|
}
|
|
1432
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
|
+
|
|
1433
1516
|
// src/storefrontStore/utils.ts
|
|
1434
1517
|
function readErrorMessage(error, fallback) {
|
|
1435
1518
|
if (error instanceof Error && error.message) return error.message;
|
|
@@ -1481,7 +1564,7 @@ function priceForMarket(prices, market, fallbackCurrency) {
|
|
|
1481
1564
|
market: price?.market || market,
|
|
1482
1565
|
currency: price?.currency || fallbackCurrency || "",
|
|
1483
1566
|
compare_at: price?.compare_at,
|
|
1484
|
-
|
|
1567
|
+
contact_list_id: price?.contact_list_id
|
|
1485
1568
|
};
|
|
1486
1569
|
}
|
|
1487
1570
|
function availableStock(client, variant) {
|
|
@@ -1645,8 +1728,11 @@ function normalizeTimezoneGroups(groups) {
|
|
|
1645
1728
|
return normalized;
|
|
1646
1729
|
}
|
|
1647
1730
|
|
|
1648
|
-
// src/storefrontStore/
|
|
1649
|
-
function
|
|
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) {
|
|
1650
1736
|
const client = createStorefront(config);
|
|
1651
1737
|
const session = atom(client.session);
|
|
1652
1738
|
const locale = atom(config.locale || client.getLocale());
|
|
@@ -1657,7 +1743,7 @@ function createArkyStore(config) {
|
|
|
1657
1743
|
const payment_config = computed(session, (value) => {
|
|
1658
1744
|
const store = value?.store;
|
|
1659
1745
|
const methods = value?.market?.payment_methods || [];
|
|
1660
|
-
const hasCreditCard = methods.some((method) => method.
|
|
1746
|
+
const hasCreditCard = methods.some((method) => method.type === "credit_card");
|
|
1661
1747
|
return { provider: store?.payment || null, enabled: hasCreditCard && !!store?.payment };
|
|
1662
1748
|
});
|
|
1663
1749
|
const cart = atom(null);
|
|
@@ -1666,6 +1752,8 @@ function createArkyStore(config) {
|
|
|
1666
1752
|
const quote = atom(null);
|
|
1667
1753
|
const promo_code = atom(null);
|
|
1668
1754
|
const last_order = atom(null);
|
|
1755
|
+
const payment_controller = atom(null);
|
|
1756
|
+
const payment_ready = computed(payment_controller, (value) => value !== null);
|
|
1669
1757
|
const cart_status = map({
|
|
1670
1758
|
loading: false,
|
|
1671
1759
|
syncing: false,
|
|
@@ -1717,7 +1805,7 @@ function createArkyStore(config) {
|
|
|
1717
1805
|
return cartWriteRevision;
|
|
1718
1806
|
}
|
|
1719
1807
|
const cms_state = map({
|
|
1720
|
-
|
|
1808
|
+
entries: {},
|
|
1721
1809
|
forms: {},
|
|
1722
1810
|
loading: false,
|
|
1723
1811
|
error: null
|
|
@@ -1756,6 +1844,51 @@ function createArkyStore(config) {
|
|
|
1756
1844
|
function currentCurrency() {
|
|
1757
1845
|
return currency.get() || market.get()?.currency || null;
|
|
1758
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
|
+
}
|
|
1759
1892
|
function marketForLocale(value) {
|
|
1760
1893
|
return config.marketForLocale?.(value) || null;
|
|
1761
1894
|
}
|
|
@@ -1801,7 +1934,7 @@ function createArkyStore(config) {
|
|
|
1801
1934
|
cartRequest = (async () => {
|
|
1802
1935
|
await ensureSession();
|
|
1803
1936
|
const response = await client.cart.refresh({ market: currentMarketKey() });
|
|
1804
|
-
await
|
|
1937
|
+
await applyCartResponse(response, { ifRevision: refreshRevision });
|
|
1805
1938
|
return response;
|
|
1806
1939
|
})();
|
|
1807
1940
|
try {
|
|
@@ -1814,7 +1947,7 @@ function createArkyStore(config) {
|
|
|
1814
1947
|
cart_status.setKey("loading", false);
|
|
1815
1948
|
}
|
|
1816
1949
|
}
|
|
1817
|
-
async function
|
|
1950
|
+
async function buildProductCartItem(item, source) {
|
|
1818
1951
|
try {
|
|
1819
1952
|
const product = await client.eshop.product.get({ id: item.product_id });
|
|
1820
1953
|
const variant = product.variants.find((candidate) => candidate.id === item.variant_id);
|
|
@@ -1826,6 +1959,7 @@ function createArkyStore(config) {
|
|
|
1826
1959
|
product_name: productName(product, currentLocale()),
|
|
1827
1960
|
product_slug: entitySlug(product, currentLocale()),
|
|
1828
1961
|
variant_attributes: variant.attributes,
|
|
1962
|
+
requires_shipping: variant.requires_shipping !== false,
|
|
1829
1963
|
price: priceForMarket(variant.prices, currentMarketKey(), currentCurrency()),
|
|
1830
1964
|
quantity: item.quantity,
|
|
1831
1965
|
added_at: source.created_at ? source.created_at * 1e3 : Date.now(),
|
|
@@ -1835,7 +1969,7 @@ function createArkyStore(config) {
|
|
|
1835
1969
|
return null;
|
|
1836
1970
|
}
|
|
1837
1971
|
}
|
|
1838
|
-
async function
|
|
1972
|
+
async function buildServiceCartItems(items) {
|
|
1839
1973
|
const rows = [];
|
|
1840
1974
|
for (const item of items) {
|
|
1841
1975
|
let service = null;
|
|
@@ -1863,7 +1997,7 @@ function createArkyStore(config) {
|
|
|
1863
1997
|
}
|
|
1864
1998
|
return rows;
|
|
1865
1999
|
}
|
|
1866
|
-
async function
|
|
2000
|
+
async function applyCartResponse(response, options = {}) {
|
|
1867
2001
|
if (options.ifRevision !== void 0 && options.ifRevision !== cartWriteRevision) {
|
|
1868
2002
|
return cart.get() || response;
|
|
1869
2003
|
}
|
|
@@ -1874,9 +2008,9 @@ function createArkyStore(config) {
|
|
|
1874
2008
|
quote.set(response.quote_snapshot || null);
|
|
1875
2009
|
const items = response.items || [];
|
|
1876
2010
|
const products = await Promise.all(
|
|
1877
|
-
items.filter((item) => item.type === "product").map((item) =>
|
|
2011
|
+
items.filter((item) => item.type === "product").map((item) => buildProductCartItem(item, response))
|
|
1878
2012
|
);
|
|
1879
|
-
const services = await
|
|
2013
|
+
const services = await buildServiceCartItems(
|
|
1880
2014
|
items.filter((item) => item.type === "service")
|
|
1881
2015
|
);
|
|
1882
2016
|
product_items.set(products.filter((item) => item !== null));
|
|
@@ -1902,14 +2036,14 @@ function createArkyStore(config) {
|
|
|
1902
2036
|
billing_address: input.billing_address || void 0,
|
|
1903
2037
|
forms: normalizeForms(input.forms),
|
|
1904
2038
|
promo_code: input.promo_code === void 0 ? promo_code.get() || void 0 : input.promo_code || void 0,
|
|
1905
|
-
|
|
2039
|
+
payment_method_key: input.payment_method_key || void 0,
|
|
1906
2040
|
shipping_method_id: input.shipping_method_id || cart_status.get().selected_shipping_method_id || void 0
|
|
1907
2041
|
});
|
|
1908
2042
|
if (input.promo_code !== void 0) promo_code.set(input.promo_code);
|
|
1909
2043
|
if (input.shipping_method_id !== void 0) {
|
|
1910
2044
|
cart_status.setKey("selected_shipping_method_id", input.shipping_method_id);
|
|
1911
2045
|
}
|
|
1912
|
-
await
|
|
2046
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1913
2047
|
return response;
|
|
1914
2048
|
} catch (error) {
|
|
1915
2049
|
cart_status.setKey("error", readErrorMessage(error, "Failed to sync cart."));
|
|
@@ -1932,8 +2066,7 @@ function createArkyStore(config) {
|
|
|
1932
2066
|
quantity
|
|
1933
2067
|
}
|
|
1934
2068
|
});
|
|
1935
|
-
await
|
|
1936
|
-
await client.activity.track({ type: "cart_added", payload: { product_id: product.id, variant_id: variant.id, quantity } });
|
|
2069
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1937
2070
|
return response;
|
|
1938
2071
|
} catch (error) {
|
|
1939
2072
|
cart_status.setKey("error", readErrorMessage(error, "Failed to add product to cart."));
|
|
@@ -1962,8 +2095,7 @@ function createArkyStore(config) {
|
|
|
1962
2095
|
product_id: item.product_id,
|
|
1963
2096
|
variant_id: item.variant_id
|
|
1964
2097
|
});
|
|
1965
|
-
await
|
|
1966
|
-
await client.activity.track({ type: "cart_removed", payload: { product_id: item.product_id, variant_id: item.variant_id } });
|
|
2098
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1967
2099
|
return response;
|
|
1968
2100
|
}
|
|
1969
2101
|
async function addServiceItem(item) {
|
|
@@ -1980,16 +2112,20 @@ function createArkyStore(config) {
|
|
|
1980
2112
|
}
|
|
1981
2113
|
async function clearCart() {
|
|
1982
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() {
|
|
1983
2123
|
product_items.set([]);
|
|
1984
2124
|
service_items.set([]);
|
|
2125
|
+
cart.set(null);
|
|
1985
2126
|
quote.set(null);
|
|
1986
2127
|
promo_code.set(null);
|
|
1987
2128
|
cart_status.setKey("selected_shipping_method_id", null);
|
|
1988
|
-
const current = cart.get();
|
|
1989
|
-
if (!current) return null;
|
|
1990
|
-
const response = await client.cart.clear({ id: current.id });
|
|
1991
|
-
await hydrateCart(response, { ifRevision: writeRevision });
|
|
1992
|
-
return response;
|
|
1993
2129
|
}
|
|
1994
2130
|
async function fetchQuote(input = {}) {
|
|
1995
2131
|
if (checkoutItems(input).length === 0) {
|
|
@@ -2017,16 +2153,51 @@ function createArkyStore(config) {
|
|
|
2017
2153
|
cart_status.setKey("error", null);
|
|
2018
2154
|
try {
|
|
2019
2155
|
const current = await syncCart(input);
|
|
2020
|
-
|
|
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
|
+
}
|
|
2021
2187
|
const response = await client.cart.checkout({
|
|
2022
2188
|
id: current.id,
|
|
2023
|
-
|
|
2189
|
+
payment_method_key: paymentMethodKey,
|
|
2190
|
+
confirmation_token_id: confirmationTokenId,
|
|
2191
|
+
return_url: returnUrl
|
|
2024
2192
|
});
|
|
2025
|
-
|
|
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
|
+
}
|
|
2026
2197
|
const stored = {
|
|
2027
2198
|
order_id: response.order_id,
|
|
2028
2199
|
number: response.number,
|
|
2029
|
-
|
|
2200
|
+
payment_action: response.payment_action,
|
|
2030
2201
|
payment: response.payment,
|
|
2031
2202
|
product_items: input.product_items || product_items.get(),
|
|
2032
2203
|
service_items: input.service_items || service_items.get(),
|
|
@@ -2034,17 +2205,13 @@ function createArkyStore(config) {
|
|
|
2034
2205
|
billing_address: input.billing_address || null,
|
|
2035
2206
|
total: quoteValue?.payment?.total || quoteValue?.total || response.payment?.total,
|
|
2036
2207
|
currency: quoteValue?.payment?.currency || currentCurrency(),
|
|
2037
|
-
|
|
2208
|
+
payment_method_key: paymentMethodKey || null,
|
|
2038
2209
|
created_at: Date.now()
|
|
2039
2210
|
};
|
|
2040
2211
|
last_order.set(stored);
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
quote.set(null);
|
|
2045
|
-
promo_code.set(null);
|
|
2046
|
-
cart_status.setKey("selected_shipping_method_id", null);
|
|
2047
|
-
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
|
+
}
|
|
2048
2215
|
return response;
|
|
2049
2216
|
} catch (error) {
|
|
2050
2217
|
cart_status.setKey("error", readErrorMessage(error, "Checkout failed."));
|
|
@@ -2464,7 +2631,7 @@ function createArkyStore(config) {
|
|
|
2464
2631
|
...toServiceCartItem(slot),
|
|
2465
2632
|
forms: []
|
|
2466
2633
|
})),
|
|
2467
|
-
|
|
2634
|
+
payment_method_key: paymentMethodId,
|
|
2468
2635
|
promo_code: state.promoCode || void 0,
|
|
2469
2636
|
forms
|
|
2470
2637
|
});
|
|
@@ -2485,7 +2652,7 @@ function createArkyStore(config) {
|
|
|
2485
2652
|
service_state.setKey("promoCode", promoCode || null);
|
|
2486
2653
|
const response = await fetchQuote({
|
|
2487
2654
|
service_items: state.cart.map(toServiceCartItem),
|
|
2488
|
-
|
|
2655
|
+
payment_method_key: paymentMethodId,
|
|
2489
2656
|
promo_code: promoCode || void 0
|
|
2490
2657
|
});
|
|
2491
2658
|
service_state.setKey("cartId", cart.get()?.id || null);
|
|
@@ -2532,18 +2699,38 @@ function createArkyStore(config) {
|
|
|
2532
2699
|
}
|
|
2533
2700
|
};
|
|
2534
2701
|
service_items.subscribe((items) => setServiceCartFromServiceItems(items));
|
|
2535
|
-
async function
|
|
2702
|
+
async function loadEntry(params, options) {
|
|
2536
2703
|
cms_state.setKey("loading", true);
|
|
2537
2704
|
cms_state.setKey("error", null);
|
|
2538
2705
|
try {
|
|
2539
|
-
const { locale: nextLocale, market: nextMarket, ...
|
|
2706
|
+
const { locale: nextLocale, market: nextMarket, ...entryParams } = params;
|
|
2540
2707
|
setContext({ locale: nextLocale, market: nextMarket });
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
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;
|
|
2545
2732
|
} catch (error) {
|
|
2546
|
-
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS
|
|
2733
|
+
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS entry."));
|
|
2547
2734
|
throw error;
|
|
2548
2735
|
} finally {
|
|
2549
2736
|
cms_state.setKey("loading", false);
|
|
@@ -2630,19 +2817,14 @@ function createArkyStore(config) {
|
|
|
2630
2817
|
eshop_state.setKey("loading_availability", false);
|
|
2631
2818
|
}
|
|
2632
2819
|
}
|
|
2633
|
-
async function
|
|
2634
|
-
|
|
2635
|
-
const
|
|
2636
|
-
|
|
2637
|
-
session: session.get()
|
|
2638
|
-
};
|
|
2639
|
-
if (shouldIdentify) results.session = await ensureSession();
|
|
2640
|
-
if (options.hydrateCart) results.cart = await ensureCart();
|
|
2641
|
-
if (options.track) await client.activity.track(options.track);
|
|
2642
|
-
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);
|
|
2643
2824
|
}
|
|
2644
|
-
async function
|
|
2645
|
-
|
|
2825
|
+
async function trackAction(params) {
|
|
2826
|
+
await ensureSession();
|
|
2827
|
+
return client.action.track(params);
|
|
2646
2828
|
}
|
|
2647
2829
|
const cart_store = {
|
|
2648
2830
|
cart,
|
|
@@ -2656,17 +2838,26 @@ function createArkyStore(config) {
|
|
|
2656
2838
|
service_item_count,
|
|
2657
2839
|
item_count,
|
|
2658
2840
|
snapshot,
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
sync: syncCart,
|
|
2841
|
+
load: ensureCart,
|
|
2842
|
+
refresh: syncCart,
|
|
2662
2843
|
addProduct,
|
|
2663
2844
|
setProductQuantity,
|
|
2664
2845
|
removeProduct,
|
|
2665
2846
|
addServiceItem,
|
|
2666
2847
|
removeServiceItem,
|
|
2667
2848
|
clear: clearCart,
|
|
2849
|
+
clearLocal: clearLocalCart,
|
|
2668
2850
|
quote: fetchQuote,
|
|
2669
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
|
+
},
|
|
2670
2861
|
applyPromoCode(code, input = {}) {
|
|
2671
2862
|
promo_code.set(code);
|
|
2672
2863
|
return fetchQuote({ ...input, promo_code: code });
|
|
@@ -2740,16 +2931,12 @@ function createArkyStore(config) {
|
|
|
2740
2931
|
currency,
|
|
2741
2932
|
allowed_payment_methods,
|
|
2742
2933
|
payment_config,
|
|
2743
|
-
|
|
2744
|
-
initialize,
|
|
2934
|
+
cart: cart_store,
|
|
2745
2935
|
identify,
|
|
2746
2936
|
verify: client.verify,
|
|
2747
2937
|
me: client.me,
|
|
2748
2938
|
logout: client.logout,
|
|
2749
2939
|
onAuthStateChanged: client.onAuthStateChanged,
|
|
2750
|
-
get currentSession() {
|
|
2751
|
-
return session.get();
|
|
2752
|
-
},
|
|
2753
2940
|
get isAuthenticated() {
|
|
2754
2941
|
return client.isAuthenticated;
|
|
2755
2942
|
},
|
|
@@ -2761,10 +2948,12 @@ function createArkyStore(config) {
|
|
|
2761
2948
|
getLocale: currentLocale,
|
|
2762
2949
|
cms: {
|
|
2763
2950
|
state: cms_state,
|
|
2764
|
-
|
|
2765
|
-
get:
|
|
2766
|
-
|
|
2767
|
-
|
|
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)
|
|
2768
2957
|
},
|
|
2769
2958
|
form: {
|
|
2770
2959
|
get: loadForm,
|
|
@@ -2785,21 +2974,24 @@ function createArkyStore(config) {
|
|
|
2785
2974
|
cart: cart_store
|
|
2786
2975
|
},
|
|
2787
2976
|
crm: client.crm,
|
|
2788
|
-
|
|
2977
|
+
action: {
|
|
2789
2978
|
track(params) {
|
|
2790
|
-
return
|
|
2979
|
+
return trackAction(params);
|
|
2791
2980
|
},
|
|
2792
2981
|
pageView(payload = {}) {
|
|
2793
|
-
return
|
|
2982
|
+
return trackAction({ key: "page.view", payload });
|
|
2794
2983
|
},
|
|
2795
2984
|
state: atom(null)
|
|
2796
2985
|
},
|
|
2986
|
+
experiments: {
|
|
2987
|
+
use: useExperiment
|
|
2988
|
+
},
|
|
2797
2989
|
support: client.support,
|
|
2798
2990
|
store: client.store,
|
|
2799
2991
|
utils: client.utils
|
|
2800
2992
|
};
|
|
2801
2993
|
}
|
|
2802
2994
|
|
|
2803
|
-
export {
|
|
2995
|
+
export { COMMON_ACTION_KEYS, createCartController, createStorefront, createStripeConfirmationTokenController, initialize };
|
|
2804
2996
|
//# sourceMappingURL=storefront.js.map
|
|
2805
2997
|
//# sourceMappingURL=storefront.js.map
|