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.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,45 @@ 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`,
|
|
448
|
+
options
|
|
449
|
+
);
|
|
450
|
+
},
|
|
451
|
+
checkContentAccess(params, options) {
|
|
452
|
+
const { store_id, ...payload } = params;
|
|
453
|
+
return apiConfig.httpClient.post(
|
|
454
|
+
`${base(store_id)}/contact-lists/access`,
|
|
455
|
+
payload,
|
|
579
456
|
options
|
|
580
457
|
);
|
|
581
458
|
},
|
|
582
459
|
unsubscribe(token, options) {
|
|
583
|
-
return apiConfig.httpClient.
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
460
|
+
return apiConfig.httpClient.post(
|
|
461
|
+
`${base()}/contact-lists/unsubscribe`,
|
|
462
|
+
{ token },
|
|
463
|
+
options
|
|
464
|
+
);
|
|
587
465
|
},
|
|
588
466
|
confirm(token, options) {
|
|
589
|
-
return apiConfig.httpClient.
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
467
|
+
return apiConfig.httpClient.post(
|
|
468
|
+
`${base()}/contact-lists/confirm`,
|
|
469
|
+
{ token },
|
|
470
|
+
options
|
|
471
|
+
);
|
|
593
472
|
}
|
|
594
473
|
}
|
|
595
474
|
},
|
|
596
|
-
|
|
475
|
+
action: createActionApi(apiConfig),
|
|
476
|
+
experiments: {
|
|
477
|
+
use(params, options) {
|
|
478
|
+
const store_id = params.store_id || apiConfig.storeId;
|
|
479
|
+
return apiConfig.httpClient.post(
|
|
480
|
+
`${base(store_id)}/experiments/use`,
|
|
481
|
+
{ key: params.key },
|
|
482
|
+
options
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
597
486
|
};
|
|
598
487
|
};
|
|
599
488
|
|
|
@@ -818,7 +707,7 @@ function createHttpClient(cfg) {
|
|
|
818
707
|
headers["Authorization"] = `Bearer ${tokens.access_token}`;
|
|
819
708
|
}
|
|
820
709
|
const finalPath = options?.params ? path + buildQueryString(options.params) : path;
|
|
821
|
-
const fetchOpts = { method, headers };
|
|
710
|
+
const fetchOpts = { method, headers, signal: options?.signal };
|
|
822
711
|
if (!["GET", "DELETE"].includes(method) && body !== void 0) {
|
|
823
712
|
fetchOpts.body = JSON.stringify(body);
|
|
824
713
|
}
|
|
@@ -829,13 +718,15 @@ function createHttpClient(cfg) {
|
|
|
829
718
|
try {
|
|
830
719
|
res = await fetch(fullUrl, fetchOpts);
|
|
831
720
|
} catch (error) {
|
|
721
|
+
const aborted = options?.signal?.aborted || error instanceof Error && error.name === "AbortError";
|
|
832
722
|
const err = new Error(error instanceof Error ? error.message : "Network request failed");
|
|
833
|
-
err.name = "NetworkError";
|
|
723
|
+
err.name = aborted ? "AbortError" : "NetworkError";
|
|
834
724
|
err.method = method;
|
|
835
725
|
err.url = fullUrl;
|
|
726
|
+
err.aborted = aborted;
|
|
836
727
|
if (options?.onError && method !== "GET") {
|
|
837
728
|
Promise.resolve(
|
|
838
|
-
options.onError({ error: err, method, url: fullUrl, aborted
|
|
729
|
+
options.onError({ error: err, method, url: fullUrl, aborted })
|
|
839
730
|
).catch(() => {
|
|
840
731
|
});
|
|
841
732
|
}
|
|
@@ -963,6 +854,133 @@ function createStorefrontSupportApi(config) {
|
|
|
963
854
|
};
|
|
964
855
|
}
|
|
965
856
|
|
|
857
|
+
// src/utils/blocks.ts
|
|
858
|
+
function getBlockLabel(block) {
|
|
859
|
+
if (!block) return "";
|
|
860
|
+
return block.key?.replace(/_/g, " ").replace(/\b\w/g, (l) => l.toUpperCase()) ?? "";
|
|
861
|
+
}
|
|
862
|
+
function formatBlockValue(block) {
|
|
863
|
+
if (!block || block.value === null || block.value === void 0) return "";
|
|
864
|
+
const value = block.value;
|
|
865
|
+
switch (block.type) {
|
|
866
|
+
case "boolean":
|
|
867
|
+
return value ? "Yes" : "No";
|
|
868
|
+
case "number":
|
|
869
|
+
if (block.properties?.variant === "DATE" || block.properties?.variant === "DATE_TIME") {
|
|
870
|
+
return new Date(value).toLocaleDateString();
|
|
871
|
+
}
|
|
872
|
+
return String(value);
|
|
873
|
+
case "media":
|
|
874
|
+
if (value && typeof value === "object") {
|
|
875
|
+
return value.mime_type ? value.name || value.id : value.title || value.name || value.id;
|
|
876
|
+
}
|
|
877
|
+
return String(value);
|
|
878
|
+
default:
|
|
879
|
+
return String(value);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
function prepareBlocksForSubmission(formData, blockTypes) {
|
|
883
|
+
return Object.keys(formData).filter((key) => formData[key] !== null && formData[key] !== void 0).map((key) => ({
|
|
884
|
+
key,
|
|
885
|
+
value: (blockTypes?.[key] || "text") === "array" && !Array.isArray(formData[key]) ? [formData[key]] : formData[key]
|
|
886
|
+
}));
|
|
887
|
+
}
|
|
888
|
+
function extractBlockValues(blocks) {
|
|
889
|
+
const values = {};
|
|
890
|
+
blocks.forEach((block) => {
|
|
891
|
+
values[block.key] = block.value ?? null;
|
|
892
|
+
});
|
|
893
|
+
return values;
|
|
894
|
+
}
|
|
895
|
+
var getBlockValue = (entry, blockKey) => {
|
|
896
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
897
|
+
return block?.value ?? null;
|
|
898
|
+
};
|
|
899
|
+
var getBlockTextValue = (block, locale = "en") => {
|
|
900
|
+
if (!block || block.value === null || block.value === void 0) return "";
|
|
901
|
+
const blockType = block.type;
|
|
902
|
+
if (blockType === "localized_text" || blockType === "markdown") {
|
|
903
|
+
if (typeof block.value === "object" && block.value !== null) {
|
|
904
|
+
return block.value[locale] ?? block.value["en"] ?? "";
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (typeof block.value === "string") return block.value;
|
|
908
|
+
return String(block.value ?? "");
|
|
909
|
+
};
|
|
910
|
+
var getBlockValues = (entry, blockKey) => {
|
|
911
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
912
|
+
if (!block) return [];
|
|
913
|
+
if (block.type === "array" && Array.isArray(block.value)) {
|
|
914
|
+
return block.value;
|
|
915
|
+
}
|
|
916
|
+
return [];
|
|
917
|
+
};
|
|
918
|
+
function unwrapBlock(block, locale) {
|
|
919
|
+
if (!block?.type || block.value === void 0) return block;
|
|
920
|
+
const blockType = block.type;
|
|
921
|
+
if (blockType === "array") {
|
|
922
|
+
return block.value.map((obj) => {
|
|
923
|
+
const parsed = {};
|
|
924
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
925
|
+
parsed[k] = unwrapBlock(v, locale);
|
|
926
|
+
}
|
|
927
|
+
return parsed;
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (blockType === "object") {
|
|
931
|
+
const parsed = {};
|
|
932
|
+
for (const [k, v] of Object.entries(block.value || {})) {
|
|
933
|
+
parsed[k] = unwrapBlock(v, locale);
|
|
934
|
+
}
|
|
935
|
+
return parsed;
|
|
936
|
+
}
|
|
937
|
+
if (blockType === "localized_text" || blockType === "markdown") {
|
|
938
|
+
return block.value?.[locale];
|
|
939
|
+
}
|
|
940
|
+
return block.value;
|
|
941
|
+
}
|
|
942
|
+
var getBlockObjectValues = (entry, blockKey, locale = "en") => {
|
|
943
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
944
|
+
if (!block || block.type !== "array" || !Array.isArray(block.value)) return [];
|
|
945
|
+
return block.value.map((obj) => {
|
|
946
|
+
if (!obj?.value || !Array.isArray(obj.value)) return {};
|
|
947
|
+
return obj.value.reduce((acc, current) => {
|
|
948
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
949
|
+
return acc;
|
|
950
|
+
}, {});
|
|
951
|
+
});
|
|
952
|
+
};
|
|
953
|
+
var getBlockFromArray = (entry, blockKey, locale = "en") => {
|
|
954
|
+
const block = entry?.blocks?.find((f) => f.key === blockKey);
|
|
955
|
+
if (!block) return {};
|
|
956
|
+
if (block.type === "array" && Array.isArray(block.value)) {
|
|
957
|
+
return block.value.reduce((acc, current) => {
|
|
958
|
+
acc[current.key] = unwrapBlock(current, locale);
|
|
959
|
+
return acc;
|
|
960
|
+
}, {});
|
|
961
|
+
}
|
|
962
|
+
if (block.type === "object" && block.value && typeof block.value === "object") {
|
|
963
|
+
const result = {};
|
|
964
|
+
for (const [k, v] of Object.entries(block.value)) {
|
|
965
|
+
result[k] = unwrapBlock(v, locale);
|
|
966
|
+
}
|
|
967
|
+
return result;
|
|
968
|
+
}
|
|
969
|
+
return { [block.key]: unwrapBlock(block, locale) };
|
|
970
|
+
};
|
|
971
|
+
var getImageUrl = (imageBlock, isBlock = true) => {
|
|
972
|
+
if (!imageBlock) return null;
|
|
973
|
+
if (imageBlock.type === "media") {
|
|
974
|
+
const mediaValue = imageBlock.value;
|
|
975
|
+
return mediaValue?.resolutions?.original?.url || mediaValue?.url || null;
|
|
976
|
+
}
|
|
977
|
+
if (isBlock) {
|
|
978
|
+
if (typeof imageBlock === "string") return imageBlock;
|
|
979
|
+
if (imageBlock.url) return imageBlock.url;
|
|
980
|
+
}
|
|
981
|
+
return imageBlock.resolutions?.original?.url || null;
|
|
982
|
+
};
|
|
983
|
+
|
|
966
984
|
// src/utils/price.ts
|
|
967
985
|
function formatCurrency(amount, currencyCode, locale = "en") {
|
|
968
986
|
if (!currencyCode) return "";
|
|
@@ -1252,22 +1270,22 @@ function createUtilitySurface(apiConfig) {
|
|
|
1252
1270
|
getFirstAvailableFCId
|
|
1253
1271
|
};
|
|
1254
1272
|
}
|
|
1255
|
-
var
|
|
1256
|
-
function
|
|
1273
|
+
var CONTACT_STORAGE_KEY = "arky_contact_session";
|
|
1274
|
+
function readContactSession() {
|
|
1257
1275
|
if (typeof window === "undefined") return null;
|
|
1258
1276
|
try {
|
|
1259
|
-
const raw = localStorage.getItem(
|
|
1277
|
+
const raw = localStorage.getItem(CONTACT_STORAGE_KEY);
|
|
1260
1278
|
return raw ? JSON.parse(raw) : null;
|
|
1261
1279
|
} catch {
|
|
1262
1280
|
return null;
|
|
1263
1281
|
}
|
|
1264
1282
|
}
|
|
1265
|
-
function
|
|
1283
|
+
function writeContactSession(s) {
|
|
1266
1284
|
if (typeof window === "undefined") return;
|
|
1267
1285
|
if (s) {
|
|
1268
|
-
localStorage.setItem(
|
|
1286
|
+
localStorage.setItem(CONTACT_STORAGE_KEY, JSON.stringify(s));
|
|
1269
1287
|
} else {
|
|
1270
|
-
localStorage.removeItem(
|
|
1288
|
+
localStorage.removeItem(CONTACT_STORAGE_KEY);
|
|
1271
1289
|
}
|
|
1272
1290
|
}
|
|
1273
1291
|
function createStorefront(config) {
|
|
@@ -1276,10 +1294,10 @@ function createStorefront(config) {
|
|
|
1276
1294
|
const listeners = /* @__PURE__ */ new Set();
|
|
1277
1295
|
let bareIdentifyPromise = null;
|
|
1278
1296
|
function toPublic(s) {
|
|
1279
|
-
return s ? {
|
|
1297
|
+
return s ? { contact: s.contact, store: s.store, market: s.market } : null;
|
|
1280
1298
|
}
|
|
1281
1299
|
function emit() {
|
|
1282
|
-
const pub = toPublic(
|
|
1300
|
+
const pub = toPublic(readContactSession());
|
|
1283
1301
|
for (const l of listeners) {
|
|
1284
1302
|
Promise.resolve().then(() => l(pub)).catch(() => {
|
|
1285
1303
|
});
|
|
@@ -1287,9 +1305,9 @@ function createStorefront(config) {
|
|
|
1287
1305
|
}
|
|
1288
1306
|
const updateSession = (updater) => {
|
|
1289
1307
|
if (config.apiToken) return;
|
|
1290
|
-
const prev =
|
|
1308
|
+
const prev = readContactSession();
|
|
1291
1309
|
const next = updater(prev);
|
|
1292
|
-
|
|
1310
|
+
writeContactSession(next);
|
|
1293
1311
|
emit();
|
|
1294
1312
|
};
|
|
1295
1313
|
const authStorage = config.apiToken ? {
|
|
@@ -1300,7 +1318,7 @@ function createStorefront(config) {
|
|
|
1300
1318
|
}
|
|
1301
1319
|
} : {
|
|
1302
1320
|
getTokens() {
|
|
1303
|
-
const s =
|
|
1321
|
+
const s = readContactSession();
|
|
1304
1322
|
return s ? { access_token: s.access_token } : null;
|
|
1305
1323
|
},
|
|
1306
1324
|
onTokensRefreshed() {
|
|
@@ -1327,20 +1345,20 @@ function createStorefront(config) {
|
|
|
1327
1345
|
authStorage
|
|
1328
1346
|
};
|
|
1329
1347
|
const storefrontApi = createStorefrontApi(apiConfig, updateSession);
|
|
1330
|
-
const
|
|
1348
|
+
const contactApi = storefrontApi.crm.contact;
|
|
1331
1349
|
function identify(params) {
|
|
1332
1350
|
if (params?.market !== void 0) apiConfig.market = params.market;
|
|
1333
1351
|
const isBareCall = !params?.email && !params?.verify;
|
|
1334
1352
|
if (isBareCall && bareIdentifyPromise) return bareIdentifyPromise;
|
|
1335
1353
|
const promise = (async () => {
|
|
1336
1354
|
try {
|
|
1337
|
-
const result = await
|
|
1355
|
+
const result = await contactApi.identify({
|
|
1338
1356
|
market: apiConfig.market,
|
|
1339
1357
|
email: params?.email,
|
|
1340
1358
|
verify: params?.verify
|
|
1341
1359
|
});
|
|
1342
1360
|
return {
|
|
1343
|
-
|
|
1361
|
+
contact: result.contact,
|
|
1344
1362
|
store: result.store,
|
|
1345
1363
|
market: result.market
|
|
1346
1364
|
};
|
|
@@ -1349,9 +1367,11 @@ function createStorefront(config) {
|
|
|
1349
1367
|
const status = e?.statusCode || e?.status || e?.response?.status;
|
|
1350
1368
|
if (isBareCall && status === 401) {
|
|
1351
1369
|
updateSession(() => null);
|
|
1352
|
-
const result = await
|
|
1370
|
+
const result = await contactApi.identify({
|
|
1371
|
+
market: apiConfig.market
|
|
1372
|
+
});
|
|
1353
1373
|
return {
|
|
1354
|
-
|
|
1374
|
+
contact: result.contact,
|
|
1355
1375
|
store: result.store,
|
|
1356
1376
|
market: result.market
|
|
1357
1377
|
};
|
|
@@ -1366,7 +1386,7 @@ function createStorefront(config) {
|
|
|
1366
1386
|
return promise;
|
|
1367
1387
|
}
|
|
1368
1388
|
async function verify(params) {
|
|
1369
|
-
const result = await
|
|
1389
|
+
const result = await contactApi.verify(params);
|
|
1370
1390
|
bareIdentifyPromise = null;
|
|
1371
1391
|
return result;
|
|
1372
1392
|
}
|
|
@@ -1374,7 +1394,7 @@ function createStorefront(config) {
|
|
|
1374
1394
|
if (config.apiToken) return;
|
|
1375
1395
|
bareIdentifyPromise = null;
|
|
1376
1396
|
try {
|
|
1377
|
-
await
|
|
1397
|
+
await contactApi.logout();
|
|
1378
1398
|
} catch {
|
|
1379
1399
|
updateSession(() => null);
|
|
1380
1400
|
}
|
|
@@ -1383,19 +1403,19 @@ function createStorefront(config) {
|
|
|
1383
1403
|
identify,
|
|
1384
1404
|
verify,
|
|
1385
1405
|
logout,
|
|
1386
|
-
me: () =>
|
|
1406
|
+
me: () => contactApi.getMe(),
|
|
1387
1407
|
get session() {
|
|
1388
1408
|
if (config.apiToken) return null;
|
|
1389
|
-
return toPublic(
|
|
1409
|
+
return toPublic(readContactSession());
|
|
1390
1410
|
},
|
|
1391
1411
|
get isAuthenticated() {
|
|
1392
1412
|
if (config.apiToken) return true;
|
|
1393
|
-
const s =
|
|
1413
|
+
const s = readContactSession();
|
|
1394
1414
|
return s !== null && !!s.access_token;
|
|
1395
1415
|
},
|
|
1396
1416
|
onAuthStateChanged(listener) {
|
|
1397
1417
|
listeners.add(listener);
|
|
1398
|
-
const current = toPublic(
|
|
1418
|
+
const current = toPublic(readContactSession());
|
|
1399
1419
|
if (current) {
|
|
1400
1420
|
Promise.resolve().then(() => listener(current)).catch(() => {
|
|
1401
1421
|
});
|
|
@@ -1409,7 +1429,8 @@ function createStorefront(config) {
|
|
|
1409
1429
|
cms: storefrontApi.cms,
|
|
1410
1430
|
eshop: storefrontApi.eshop,
|
|
1411
1431
|
crm: storefrontApi.crm,
|
|
1412
|
-
|
|
1432
|
+
action: storefrontApi.action,
|
|
1433
|
+
experiments: storefrontApi.experiments,
|
|
1413
1434
|
support: createStorefrontSupportApi(apiConfig),
|
|
1414
1435
|
setStoreId: (storeId) => {
|
|
1415
1436
|
apiConfig.storeId = storeId;
|
|
@@ -1425,11 +1446,81 @@ function createStorefront(config) {
|
|
|
1425
1446
|
apiConfig.locale = l;
|
|
1426
1447
|
},
|
|
1427
1448
|
getLocale: () => apiConfig.locale,
|
|
1428
|
-
extractBlockValues,
|
|
1429
1449
|
utils: createUtilitySurface(apiConfig)
|
|
1430
1450
|
};
|
|
1431
1451
|
}
|
|
1432
1452
|
|
|
1453
|
+
// src/payments/stripe.ts
|
|
1454
|
+
function normalizeCurrency(currency) {
|
|
1455
|
+
return currency.trim().toLowerCase();
|
|
1456
|
+
}
|
|
1457
|
+
async function createStripeConfirmationTokenController(config) {
|
|
1458
|
+
const { loadStripe } = await import('@stripe/stripe-js');
|
|
1459
|
+
const stripe = await loadStripe(config.publishableKey);
|
|
1460
|
+
if (!stripe) throw new Error("Stripe failed to initialize");
|
|
1461
|
+
let elements = createElements(stripe, config);
|
|
1462
|
+
let paymentElement = elements.create("payment", {
|
|
1463
|
+
layout: "tabs"
|
|
1464
|
+
});
|
|
1465
|
+
return {
|
|
1466
|
+
mount(target) {
|
|
1467
|
+
if (!paymentElement) {
|
|
1468
|
+
paymentElement = elements.create("payment", { layout: "tabs" });
|
|
1469
|
+
}
|
|
1470
|
+
paymentElement.mount(target);
|
|
1471
|
+
},
|
|
1472
|
+
update(input) {
|
|
1473
|
+
elements.update({
|
|
1474
|
+
...input.amount !== void 0 ? { amount: input.amount } : {},
|
|
1475
|
+
...input.currency ? { currency: normalizeCurrency(input.currency) } : {}
|
|
1476
|
+
});
|
|
1477
|
+
},
|
|
1478
|
+
async createConfirmationToken(options = {}) {
|
|
1479
|
+
const submitResult = await elements.submit();
|
|
1480
|
+
if (submitResult.error) {
|
|
1481
|
+
throw new Error(submitResult.error.message || "Payment details are incomplete");
|
|
1482
|
+
}
|
|
1483
|
+
const tokenInput = {
|
|
1484
|
+
elements,
|
|
1485
|
+
params: {
|
|
1486
|
+
...options.return_url ? { return_url: options.return_url } : {},
|
|
1487
|
+
...options.billing_details ? { payment_method_data: { billing_details: options.billing_details } } : {}
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
const result = await stripe.createConfirmationToken(tokenInput);
|
|
1491
|
+
if (result.error) {
|
|
1492
|
+
throw new Error(result.error.message || "Payment confirmation token failed");
|
|
1493
|
+
}
|
|
1494
|
+
if (!result.confirmationToken?.id) {
|
|
1495
|
+
throw new Error("Stripe did not return a confirmation token");
|
|
1496
|
+
}
|
|
1497
|
+
return {
|
|
1498
|
+
confirmation_token_id: result.confirmationToken.id,
|
|
1499
|
+
return_url: options.return_url
|
|
1500
|
+
};
|
|
1501
|
+
},
|
|
1502
|
+
async handleNextAction(clientSecret) {
|
|
1503
|
+
const result = await stripe.handleNextAction({ clientSecret });
|
|
1504
|
+
if (result.error) {
|
|
1505
|
+
throw new Error(result.error.message || "Payment authentication failed");
|
|
1506
|
+
}
|
|
1507
|
+
},
|
|
1508
|
+
destroy() {
|
|
1509
|
+
paymentElement?.destroy();
|
|
1510
|
+
paymentElement = null;
|
|
1511
|
+
}
|
|
1512
|
+
};
|
|
1513
|
+
}
|
|
1514
|
+
function createElements(stripe, config) {
|
|
1515
|
+
return stripe.elements({
|
|
1516
|
+
mode: "payment",
|
|
1517
|
+
amount: config.amount,
|
|
1518
|
+
currency: normalizeCurrency(config.currency),
|
|
1519
|
+
paymentMethodCreation: "manual",
|
|
1520
|
+
...config.appearance ? { appearance: config.appearance } : {}
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1433
1524
|
// src/storefrontStore/utils.ts
|
|
1434
1525
|
function readErrorMessage(error, fallback) {
|
|
1435
1526
|
if (error instanceof Error && error.message) return error.message;
|
|
@@ -1481,7 +1572,7 @@ function priceForMarket(prices, market, fallbackCurrency) {
|
|
|
1481
1572
|
market: price?.market || market,
|
|
1482
1573
|
currency: price?.currency || fallbackCurrency || "",
|
|
1483
1574
|
compare_at: price?.compare_at,
|
|
1484
|
-
|
|
1575
|
+
contact_list_id: price?.contact_list_id
|
|
1485
1576
|
};
|
|
1486
1577
|
}
|
|
1487
1578
|
function availableStock(client, variant) {
|
|
@@ -1645,8 +1736,11 @@ function normalizeTimezoneGroups(groups) {
|
|
|
1645
1736
|
return normalized;
|
|
1646
1737
|
}
|
|
1647
1738
|
|
|
1648
|
-
// src/storefrontStore/
|
|
1649
|
-
function
|
|
1739
|
+
// src/storefrontStore/initialize.ts
|
|
1740
|
+
function firstFiniteNumber(...values) {
|
|
1741
|
+
return values.find((value) => typeof value === "number" && Number.isFinite(value));
|
|
1742
|
+
}
|
|
1743
|
+
function initialize(config) {
|
|
1650
1744
|
const client = createStorefront(config);
|
|
1651
1745
|
const session = atom(client.session);
|
|
1652
1746
|
const locale = atom(config.locale || client.getLocale());
|
|
@@ -1657,7 +1751,7 @@ function createArkyStore(config) {
|
|
|
1657
1751
|
const payment_config = computed(session, (value) => {
|
|
1658
1752
|
const store = value?.store;
|
|
1659
1753
|
const methods = value?.market?.payment_methods || [];
|
|
1660
|
-
const hasCreditCard = methods.some((method) => method.
|
|
1754
|
+
const hasCreditCard = methods.some((method) => method.type === "credit_card");
|
|
1661
1755
|
return { provider: store?.payment || null, enabled: hasCreditCard && !!store?.payment };
|
|
1662
1756
|
});
|
|
1663
1757
|
const cart = atom(null);
|
|
@@ -1666,6 +1760,8 @@ function createArkyStore(config) {
|
|
|
1666
1760
|
const quote = atom(null);
|
|
1667
1761
|
const promo_code = atom(null);
|
|
1668
1762
|
const last_order = atom(null);
|
|
1763
|
+
const payment_controller = atom(null);
|
|
1764
|
+
const payment_ready = computed(payment_controller, (value) => value !== null);
|
|
1669
1765
|
const cart_status = map({
|
|
1670
1766
|
loading: false,
|
|
1671
1767
|
syncing: false,
|
|
@@ -1717,7 +1813,7 @@ function createArkyStore(config) {
|
|
|
1717
1813
|
return cartWriteRevision;
|
|
1718
1814
|
}
|
|
1719
1815
|
const cms_state = map({
|
|
1720
|
-
|
|
1816
|
+
entries: {},
|
|
1721
1817
|
forms: {},
|
|
1722
1818
|
loading: false,
|
|
1723
1819
|
error: null
|
|
@@ -1756,6 +1852,51 @@ function createArkyStore(config) {
|
|
|
1756
1852
|
function currentCurrency() {
|
|
1757
1853
|
return currency.get() || market.get()?.currency || null;
|
|
1758
1854
|
}
|
|
1855
|
+
function currentStripePublishableKey() {
|
|
1856
|
+
const provider = payment_config.get()?.provider;
|
|
1857
|
+
return provider?.publishable_key || provider?.publishableKey || provider?.publicKey || null;
|
|
1858
|
+
}
|
|
1859
|
+
function currentPaymentAmount() {
|
|
1860
|
+
return Math.max(
|
|
1861
|
+
0,
|
|
1862
|
+
firstFiniteNumber(
|
|
1863
|
+
quote.get()?.charge_amount,
|
|
1864
|
+
quote.get()?.payment?.total,
|
|
1865
|
+
cart.get()?.quote_snapshot?.charge_amount,
|
|
1866
|
+
cart.get()?.quote_snapshot?.payment?.total,
|
|
1867
|
+
cart.get()?.quote_snapshot?.total
|
|
1868
|
+
) ?? 0
|
|
1869
|
+
);
|
|
1870
|
+
}
|
|
1871
|
+
function setPaymentController(controller) {
|
|
1872
|
+
const current = payment_controller.get();
|
|
1873
|
+
if (current && current !== controller) {
|
|
1874
|
+
current.destroy();
|
|
1875
|
+
}
|
|
1876
|
+
payment_controller.set(controller);
|
|
1877
|
+
return controller;
|
|
1878
|
+
}
|
|
1879
|
+
function destroyPaymentController() {
|
|
1880
|
+
setPaymentController(null);
|
|
1881
|
+
}
|
|
1882
|
+
async function mountStripePayment(target, options = {}) {
|
|
1883
|
+
const publishableKey = options.publishableKey || currentStripePublishableKey();
|
|
1884
|
+
if (!publishableKey) {
|
|
1885
|
+
throw new Error("Stripe publishable key is required to mount card payment");
|
|
1886
|
+
}
|
|
1887
|
+
const controller = await createStripeConfirmationTokenController({
|
|
1888
|
+
publishableKey,
|
|
1889
|
+
amount: Math.max(0, options.amount ?? currentPaymentAmount()),
|
|
1890
|
+
currency: options.currency || currentCurrency() || "usd",
|
|
1891
|
+
...options.appearance ? { appearance: options.appearance } : {}
|
|
1892
|
+
});
|
|
1893
|
+
controller.mount(target);
|
|
1894
|
+
setPaymentController(controller);
|
|
1895
|
+
return controller;
|
|
1896
|
+
}
|
|
1897
|
+
function updatePaymentController(input) {
|
|
1898
|
+
payment_controller.get()?.update(input);
|
|
1899
|
+
}
|
|
1759
1900
|
function marketForLocale(value) {
|
|
1760
1901
|
return config.marketForLocale?.(value) || null;
|
|
1761
1902
|
}
|
|
@@ -1801,7 +1942,7 @@ function createArkyStore(config) {
|
|
|
1801
1942
|
cartRequest = (async () => {
|
|
1802
1943
|
await ensureSession();
|
|
1803
1944
|
const response = await client.cart.refresh({ market: currentMarketKey() });
|
|
1804
|
-
await
|
|
1945
|
+
await applyCartResponse(response, { ifRevision: refreshRevision });
|
|
1805
1946
|
return response;
|
|
1806
1947
|
})();
|
|
1807
1948
|
try {
|
|
@@ -1814,7 +1955,7 @@ function createArkyStore(config) {
|
|
|
1814
1955
|
cart_status.setKey("loading", false);
|
|
1815
1956
|
}
|
|
1816
1957
|
}
|
|
1817
|
-
async function
|
|
1958
|
+
async function buildProductCartItem(item, source) {
|
|
1818
1959
|
try {
|
|
1819
1960
|
const product = await client.eshop.product.get({ id: item.product_id });
|
|
1820
1961
|
const variant = product.variants.find((candidate) => candidate.id === item.variant_id);
|
|
@@ -1826,6 +1967,7 @@ function createArkyStore(config) {
|
|
|
1826
1967
|
product_name: productName(product, currentLocale()),
|
|
1827
1968
|
product_slug: entitySlug(product, currentLocale()),
|
|
1828
1969
|
variant_attributes: variant.attributes,
|
|
1970
|
+
requires_shipping: variant.requires_shipping !== false,
|
|
1829
1971
|
price: priceForMarket(variant.prices, currentMarketKey(), currentCurrency()),
|
|
1830
1972
|
quantity: item.quantity,
|
|
1831
1973
|
added_at: source.created_at ? source.created_at * 1e3 : Date.now(),
|
|
@@ -1835,7 +1977,7 @@ function createArkyStore(config) {
|
|
|
1835
1977
|
return null;
|
|
1836
1978
|
}
|
|
1837
1979
|
}
|
|
1838
|
-
async function
|
|
1980
|
+
async function buildServiceCartItems(items) {
|
|
1839
1981
|
const rows = [];
|
|
1840
1982
|
for (const item of items) {
|
|
1841
1983
|
let service = null;
|
|
@@ -1863,7 +2005,7 @@ function createArkyStore(config) {
|
|
|
1863
2005
|
}
|
|
1864
2006
|
return rows;
|
|
1865
2007
|
}
|
|
1866
|
-
async function
|
|
2008
|
+
async function applyCartResponse(response, options = {}) {
|
|
1867
2009
|
if (options.ifRevision !== void 0 && options.ifRevision !== cartWriteRevision) {
|
|
1868
2010
|
return cart.get() || response;
|
|
1869
2011
|
}
|
|
@@ -1874,9 +2016,9 @@ function createArkyStore(config) {
|
|
|
1874
2016
|
quote.set(response.quote_snapshot || null);
|
|
1875
2017
|
const items = response.items || [];
|
|
1876
2018
|
const products = await Promise.all(
|
|
1877
|
-
items.filter((item) => item.type === "product").map((item) =>
|
|
2019
|
+
items.filter((item) => item.type === "product").map((item) => buildProductCartItem(item, response))
|
|
1878
2020
|
);
|
|
1879
|
-
const services = await
|
|
2021
|
+
const services = await buildServiceCartItems(
|
|
1880
2022
|
items.filter((item) => item.type === "service")
|
|
1881
2023
|
);
|
|
1882
2024
|
product_items.set(products.filter((item) => item !== null));
|
|
@@ -1902,14 +2044,14 @@ function createArkyStore(config) {
|
|
|
1902
2044
|
billing_address: input.billing_address || void 0,
|
|
1903
2045
|
forms: normalizeForms(input.forms),
|
|
1904
2046
|
promo_code: input.promo_code === void 0 ? promo_code.get() || void 0 : input.promo_code || void 0,
|
|
1905
|
-
|
|
2047
|
+
payment_method_key: input.payment_method_key || void 0,
|
|
1906
2048
|
shipping_method_id: input.shipping_method_id || cart_status.get().selected_shipping_method_id || void 0
|
|
1907
2049
|
});
|
|
1908
2050
|
if (input.promo_code !== void 0) promo_code.set(input.promo_code);
|
|
1909
2051
|
if (input.shipping_method_id !== void 0) {
|
|
1910
2052
|
cart_status.setKey("selected_shipping_method_id", input.shipping_method_id);
|
|
1911
2053
|
}
|
|
1912
|
-
await
|
|
2054
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1913
2055
|
return response;
|
|
1914
2056
|
} catch (error) {
|
|
1915
2057
|
cart_status.setKey("error", readErrorMessage(error, "Failed to sync cart."));
|
|
@@ -1932,8 +2074,7 @@ function createArkyStore(config) {
|
|
|
1932
2074
|
quantity
|
|
1933
2075
|
}
|
|
1934
2076
|
});
|
|
1935
|
-
await
|
|
1936
|
-
await client.activity.track({ type: "cart_added", payload: { product_id: product.id, variant_id: variant.id, quantity } });
|
|
2077
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1937
2078
|
return response;
|
|
1938
2079
|
} catch (error) {
|
|
1939
2080
|
cart_status.setKey("error", readErrorMessage(error, "Failed to add product to cart."));
|
|
@@ -1962,8 +2103,7 @@ function createArkyStore(config) {
|
|
|
1962
2103
|
product_id: item.product_id,
|
|
1963
2104
|
variant_id: item.variant_id
|
|
1964
2105
|
});
|
|
1965
|
-
await
|
|
1966
|
-
await client.activity.track({ type: "cart_removed", payload: { product_id: item.product_id, variant_id: item.variant_id } });
|
|
2106
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
1967
2107
|
return response;
|
|
1968
2108
|
}
|
|
1969
2109
|
async function addServiceItem(item) {
|
|
@@ -1980,16 +2120,20 @@ function createArkyStore(config) {
|
|
|
1980
2120
|
}
|
|
1981
2121
|
async function clearCart() {
|
|
1982
2122
|
const writeRevision = nextCartWriteRevision();
|
|
2123
|
+
const current = cart.get();
|
|
2124
|
+
clearLocalCart();
|
|
2125
|
+
if (!current) return null;
|
|
2126
|
+
const response = await client.cart.clear({ id: current.id });
|
|
2127
|
+
await applyCartResponse(response, { ifRevision: writeRevision });
|
|
2128
|
+
return response;
|
|
2129
|
+
}
|
|
2130
|
+
function clearLocalCart() {
|
|
1983
2131
|
product_items.set([]);
|
|
1984
2132
|
service_items.set([]);
|
|
2133
|
+
cart.set(null);
|
|
1985
2134
|
quote.set(null);
|
|
1986
2135
|
promo_code.set(null);
|
|
1987
2136
|
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
2137
|
}
|
|
1994
2138
|
async function fetchQuote(input = {}) {
|
|
1995
2139
|
if (checkoutItems(input).length === 0) {
|
|
@@ -2017,16 +2161,51 @@ function createArkyStore(config) {
|
|
|
2017
2161
|
cart_status.setKey("error", null);
|
|
2018
2162
|
try {
|
|
2019
2163
|
const current = await syncCart(input);
|
|
2020
|
-
|
|
2164
|
+
const quoteValue = quote.get();
|
|
2165
|
+
const paymentMethodKey = input.payment_method_key || current.payment_method_key || quoteValue?.payment?.payment_method_key || void 0;
|
|
2166
|
+
let chargeAmount = firstFiniteNumber(
|
|
2167
|
+
quoteValue?.charge_amount,
|
|
2168
|
+
quoteValue?.payment?.total,
|
|
2169
|
+
current.quote_snapshot?.charge_amount,
|
|
2170
|
+
current.quote_snapshot?.payment?.total
|
|
2171
|
+
);
|
|
2172
|
+
if (paymentMethodKey === "credit_card" && chargeAmount === void 0) {
|
|
2173
|
+
const latestQuote = await client.cart.quote({ id: current.id });
|
|
2174
|
+
quote.set(latestQuote);
|
|
2175
|
+
chargeAmount = firstFiniteNumber(
|
|
2176
|
+
latestQuote.charge_amount,
|
|
2177
|
+
latestQuote.payment?.total,
|
|
2178
|
+
latestQuote.total
|
|
2179
|
+
);
|
|
2180
|
+
}
|
|
2181
|
+
const needsConfirmationToken = paymentMethodKey === "credit_card" && (chargeAmount === void 0 || chargeAmount > 0);
|
|
2182
|
+
let confirmationTokenId;
|
|
2183
|
+
let returnUrl = input.return_url;
|
|
2184
|
+
const paymentController = input.payment ?? payment_controller.get();
|
|
2185
|
+
if (needsConfirmationToken) {
|
|
2186
|
+
if (!paymentController) throw new Error("Payment controller is required for card checkout");
|
|
2187
|
+
returnUrl = returnUrl || (typeof window !== "undefined" ? window.location.href : void 0);
|
|
2188
|
+
const token = await paymentController.createConfirmationToken({
|
|
2189
|
+
return_url: returnUrl,
|
|
2190
|
+
billing_details: input.billing_details
|
|
2191
|
+
});
|
|
2192
|
+
confirmationTokenId = token.confirmation_token_id;
|
|
2193
|
+
returnUrl = token.return_url || returnUrl;
|
|
2194
|
+
}
|
|
2021
2195
|
const response = await client.cart.checkout({
|
|
2022
2196
|
id: current.id,
|
|
2023
|
-
|
|
2197
|
+
payment_method_key: paymentMethodKey,
|
|
2198
|
+
confirmation_token_id: confirmationTokenId,
|
|
2199
|
+
return_url: returnUrl
|
|
2024
2200
|
});
|
|
2025
|
-
|
|
2201
|
+
if (response.payment_action.type === "handle_next_action") {
|
|
2202
|
+
if (!paymentController) throw new Error("Payment controller is required for card authentication");
|
|
2203
|
+
await paymentController.handleNextAction(response.payment_action.client_secret);
|
|
2204
|
+
}
|
|
2026
2205
|
const stored = {
|
|
2027
2206
|
order_id: response.order_id,
|
|
2028
2207
|
number: response.number,
|
|
2029
|
-
|
|
2208
|
+
payment_action: response.payment_action,
|
|
2030
2209
|
payment: response.payment,
|
|
2031
2210
|
product_items: input.product_items || product_items.get(),
|
|
2032
2211
|
service_items: input.service_items || service_items.get(),
|
|
@@ -2034,17 +2213,13 @@ function createArkyStore(config) {
|
|
|
2034
2213
|
billing_address: input.billing_address || null,
|
|
2035
2214
|
total: quoteValue?.payment?.total || quoteValue?.total || response.payment?.total,
|
|
2036
2215
|
currency: quoteValue?.payment?.currency || currentCurrency(),
|
|
2037
|
-
|
|
2216
|
+
payment_method_key: paymentMethodKey || null,
|
|
2038
2217
|
created_at: Date.now()
|
|
2039
2218
|
};
|
|
2040
2219
|
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 } });
|
|
2220
|
+
if (input.clear_after_checkout !== false) {
|
|
2221
|
+
clearLocalCart();
|
|
2222
|
+
}
|
|
2048
2223
|
return response;
|
|
2049
2224
|
} catch (error) {
|
|
2050
2225
|
cart_status.setKey("error", readErrorMessage(error, "Checkout failed."));
|
|
@@ -2464,7 +2639,7 @@ function createArkyStore(config) {
|
|
|
2464
2639
|
...toServiceCartItem(slot),
|
|
2465
2640
|
forms: []
|
|
2466
2641
|
})),
|
|
2467
|
-
|
|
2642
|
+
payment_method_key: paymentMethodId,
|
|
2468
2643
|
promo_code: state.promoCode || void 0,
|
|
2469
2644
|
forms
|
|
2470
2645
|
});
|
|
@@ -2485,7 +2660,7 @@ function createArkyStore(config) {
|
|
|
2485
2660
|
service_state.setKey("promoCode", promoCode || null);
|
|
2486
2661
|
const response = await fetchQuote({
|
|
2487
2662
|
service_items: state.cart.map(toServiceCartItem),
|
|
2488
|
-
|
|
2663
|
+
payment_method_key: paymentMethodId,
|
|
2489
2664
|
promo_code: promoCode || void 0
|
|
2490
2665
|
});
|
|
2491
2666
|
service_state.setKey("cartId", cart.get()?.id || null);
|
|
@@ -2532,18 +2707,38 @@ function createArkyStore(config) {
|
|
|
2532
2707
|
}
|
|
2533
2708
|
};
|
|
2534
2709
|
service_items.subscribe((items) => setServiceCartFromServiceItems(items));
|
|
2535
|
-
async function
|
|
2710
|
+
async function loadEntry(params, options) {
|
|
2536
2711
|
cms_state.setKey("loading", true);
|
|
2537
2712
|
cms_state.setKey("error", null);
|
|
2538
2713
|
try {
|
|
2539
|
-
const { locale: nextLocale, market: nextMarket, ...
|
|
2714
|
+
const { locale: nextLocale, market: nextMarket, ...entryParams } = params;
|
|
2540
2715
|
setContext({ locale: nextLocale, market: nextMarket });
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2716
|
+
if (entryParams.id) {
|
|
2717
|
+
const entry2 = await client.cms.entry.get(entryParams, options);
|
|
2718
|
+
const cacheKey = entryParams.key || entryParams.id || entry2.id;
|
|
2719
|
+
cms_state.setKey("entries", { ...cms_state.get().entries, [cacheKey]: entry2 });
|
|
2720
|
+
return entry2;
|
|
2721
|
+
}
|
|
2722
|
+
if (!entryParams.collection_id || !entryParams.key) {
|
|
2723
|
+
throw new Error("ArkyCmsEntryParams requires id, or collection_id and key");
|
|
2724
|
+
}
|
|
2725
|
+
const result = await client.cms.entry.find(
|
|
2726
|
+
{
|
|
2727
|
+
...entryParams,
|
|
2728
|
+
collection_id: entryParams.collection_id,
|
|
2729
|
+
key: entryParams.key,
|
|
2730
|
+
limit: 1
|
|
2731
|
+
},
|
|
2732
|
+
options
|
|
2733
|
+
);
|
|
2734
|
+
const entry = result.items?.[0];
|
|
2735
|
+
if (!entry) {
|
|
2736
|
+
throw new Error("CMS entry not found");
|
|
2737
|
+
}
|
|
2738
|
+
cms_state.setKey("entries", { ...cms_state.get().entries, [entryParams.key]: entry });
|
|
2739
|
+
return entry;
|
|
2545
2740
|
} catch (error) {
|
|
2546
|
-
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS
|
|
2741
|
+
cms_state.setKey("error", readErrorMessage(error, "Failed to load CMS entry."));
|
|
2547
2742
|
throw error;
|
|
2548
2743
|
} finally {
|
|
2549
2744
|
cms_state.setKey("loading", false);
|
|
@@ -2630,19 +2825,14 @@ function createArkyStore(config) {
|
|
|
2630
2825
|
eshop_state.setKey("loading_availability", false);
|
|
2631
2826
|
}
|
|
2632
2827
|
}
|
|
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;
|
|
2828
|
+
async function useExperiment(params) {
|
|
2829
|
+
await ensureSession();
|
|
2830
|
+
const input = typeof params === "string" ? { key: params } : params;
|
|
2831
|
+
return client.experiments.use(input);
|
|
2643
2832
|
}
|
|
2644
|
-
async function
|
|
2645
|
-
|
|
2833
|
+
async function trackAction(params) {
|
|
2834
|
+
await ensureSession();
|
|
2835
|
+
return client.action.track(params);
|
|
2646
2836
|
}
|
|
2647
2837
|
const cart_store = {
|
|
2648
2838
|
cart,
|
|
@@ -2656,17 +2846,26 @@ function createArkyStore(config) {
|
|
|
2656
2846
|
service_item_count,
|
|
2657
2847
|
item_count,
|
|
2658
2848
|
snapshot,
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
sync: syncCart,
|
|
2849
|
+
load: ensureCart,
|
|
2850
|
+
refresh: syncCart,
|
|
2662
2851
|
addProduct,
|
|
2663
2852
|
setProductQuantity,
|
|
2664
2853
|
removeProduct,
|
|
2665
2854
|
addServiceItem,
|
|
2666
2855
|
removeServiceItem,
|
|
2667
2856
|
clear: clearCart,
|
|
2857
|
+
clearLocal: clearLocalCart,
|
|
2668
2858
|
quote: fetchQuote,
|
|
2669
2859
|
checkout,
|
|
2860
|
+
payment: {
|
|
2861
|
+
controller: payment_controller,
|
|
2862
|
+
ready: payment_ready,
|
|
2863
|
+
setController: setPaymentController,
|
|
2864
|
+
getController: () => payment_controller.get(),
|
|
2865
|
+
mountStripe: mountStripePayment,
|
|
2866
|
+
update: updatePaymentController,
|
|
2867
|
+
destroy: destroyPaymentController
|
|
2868
|
+
},
|
|
2670
2869
|
applyPromoCode(code, input = {}) {
|
|
2671
2870
|
promo_code.set(code);
|
|
2672
2871
|
return fetchQuote({ ...input, promo_code: code });
|
|
@@ -2740,16 +2939,12 @@ function createArkyStore(config) {
|
|
|
2740
2939
|
currency,
|
|
2741
2940
|
allowed_payment_methods,
|
|
2742
2941
|
payment_config,
|
|
2743
|
-
|
|
2744
|
-
initialize,
|
|
2942
|
+
cart: cart_store,
|
|
2745
2943
|
identify,
|
|
2746
2944
|
verify: client.verify,
|
|
2747
2945
|
me: client.me,
|
|
2748
2946
|
logout: client.logout,
|
|
2749
2947
|
onAuthStateChanged: client.onAuthStateChanged,
|
|
2750
|
-
get currentSession() {
|
|
2751
|
-
return session.get();
|
|
2752
|
-
},
|
|
2753
2948
|
get isAuthenticated() {
|
|
2754
2949
|
return client.isAuthenticated;
|
|
2755
2950
|
},
|
|
@@ -2761,10 +2956,12 @@ function createArkyStore(config) {
|
|
|
2761
2956
|
getLocale: currentLocale,
|
|
2762
2957
|
cms: {
|
|
2763
2958
|
state: cms_state,
|
|
2764
|
-
|
|
2765
|
-
get:
|
|
2766
|
-
|
|
2767
|
-
|
|
2959
|
+
collection: {
|
|
2960
|
+
get: (params, options) => client.cms.collection.get(params, options)
|
|
2961
|
+
},
|
|
2962
|
+
entry: {
|
|
2963
|
+
get: loadEntry,
|
|
2964
|
+
find: (params, options) => client.cms.entry.find(params, options)
|
|
2768
2965
|
},
|
|
2769
2966
|
form: {
|
|
2770
2967
|
get: loadForm,
|
|
@@ -2785,21 +2982,24 @@ function createArkyStore(config) {
|
|
|
2785
2982
|
cart: cart_store
|
|
2786
2983
|
},
|
|
2787
2984
|
crm: client.crm,
|
|
2788
|
-
|
|
2985
|
+
action: {
|
|
2789
2986
|
track(params) {
|
|
2790
|
-
return
|
|
2987
|
+
return trackAction(params);
|
|
2791
2988
|
},
|
|
2792
2989
|
pageView(payload = {}) {
|
|
2793
|
-
return
|
|
2990
|
+
return trackAction({ key: "page.view", payload });
|
|
2794
2991
|
},
|
|
2795
2992
|
state: atom(null)
|
|
2796
2993
|
},
|
|
2994
|
+
experiments: {
|
|
2995
|
+
use: useExperiment
|
|
2996
|
+
},
|
|
2797
2997
|
support: client.support,
|
|
2798
2998
|
store: client.store,
|
|
2799
2999
|
utils: client.utils
|
|
2800
3000
|
};
|
|
2801
3001
|
}
|
|
2802
3002
|
|
|
2803
|
-
export {
|
|
3003
|
+
export { COMMON_ACTION_KEYS, createCartController, createStorefront, createStripeConfirmationTokenController, initialize };
|
|
2804
3004
|
//# sourceMappingURL=storefront.js.map
|
|
2805
3005
|
//# sourceMappingURL=storefront.js.map
|