@blotoutio/providers-blotout-wallet-sdk 0.60.1 → 0.62.0
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/index.cjs.js +157 -118
- package/index.js +157 -118
- package/index.mjs +157 -118
- package/package.json +1 -1
- package/stores/shopify/index.cjs.js +24 -13
- package/stores/shopify/index.js +24 -13
- package/stores/shopify/index.mjs +24 -13
package/index.cjs.js
CHANGED
@@ -34,6 +34,8 @@ new Set([
|
|
34
34
|
...expand('911,921,922,923,924,926,927,932,933,935,942,944,946,950,953,955,957-958,960-969,974,975,976,977,981-982,987,988,990-999'),
|
35
35
|
]);
|
36
36
|
|
37
|
+
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
38
|
+
|
37
39
|
const customAttributes = {
|
38
40
|
'--bw-primary': { type: 'color', defaultValue: '#000000' },
|
39
41
|
'--bw-title-color': { type: 'color', defaultValue: '#000000' },
|
@@ -64,28 +66,39 @@ const cartTokenTwoCookie = 'cart2';
|
|
64
66
|
const cartTokenLinkCookie = 'bwCartLinkToken';
|
65
67
|
|
66
68
|
const getCookieValue = (key) => {
|
69
|
+
var _a;
|
67
70
|
try {
|
68
71
|
if (!document || !document.cookie) {
|
69
72
|
return '';
|
70
73
|
}
|
71
|
-
const
|
72
|
-
|
73
|
-
const ca = decodedCookie.split(';');
|
74
|
-
for (let i = 0; i < ca.length; i++) {
|
75
|
-
let c = ca[i];
|
76
|
-
while (c.charAt(0) === ' ') {
|
77
|
-
c = c.substring(1);
|
78
|
-
}
|
79
|
-
if (c.indexOf(name) === 0) {
|
80
|
-
return c.substring(name.length, c.length);
|
81
|
-
}
|
82
|
-
}
|
83
|
-
return '';
|
74
|
+
const cookies = parseCookies(document.cookie);
|
75
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
84
76
|
}
|
85
77
|
catch {
|
86
78
|
return '';
|
87
79
|
}
|
88
80
|
};
|
81
|
+
const parseCookies = (cookie) => {
|
82
|
+
return Object.fromEntries(cookie
|
83
|
+
.split(/;\s+/)
|
84
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
85
|
+
.map(([cookieKey, cookieValue]) => {
|
86
|
+
if (!cookieKey) {
|
87
|
+
return [];
|
88
|
+
}
|
89
|
+
let decodedValue = '';
|
90
|
+
if (cookieValue) {
|
91
|
+
try {
|
92
|
+
decodedValue = decodeURIComponent(cookieValue);
|
93
|
+
}
|
94
|
+
catch (e) {
|
95
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
96
|
+
decodedValue = cookieValue;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
return [cookieKey, decodedValue];
|
100
|
+
}));
|
101
|
+
};
|
89
102
|
const setCookie = (key, value, options) => {
|
90
103
|
var _a;
|
91
104
|
try {
|
@@ -351,31 +364,43 @@ const cssVars = i$4 `
|
|
351
364
|
}
|
352
365
|
`;
|
353
366
|
|
367
|
+
const isGecko = () => /\bGecko\/\d+/.test(navigator.userAgent);
|
368
|
+
|
354
369
|
const fadeInDialog = (element) => {
|
355
|
-
const
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
370
|
+
const animations = [
|
371
|
+
element.animate([
|
372
|
+
{ transform: 'translateY(-20px)', opacity: 0 },
|
373
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
374
|
+
], { duration: 600, easing: spring, composite: 'add' }),
|
375
|
+
];
|
376
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
377
|
+
if (!isGecko()) {
|
378
|
+
animations.push(element.animate([{ opacity: 0 }, { opacity: 1 }], {
|
379
|
+
duration: 300,
|
380
|
+
easing: 'ease-out',
|
381
|
+
pseudoElement: '::backdrop',
|
382
|
+
fill: 'forwards',
|
383
|
+
}));
|
384
|
+
}
|
385
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
366
386
|
};
|
367
387
|
const fadeOutToBottom = (element) => {
|
368
|
-
const
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
388
|
+
const animations = [
|
389
|
+
element.animate([
|
390
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
391
|
+
{ transform: 'translateY(20px)', opacity: 0 },
|
392
|
+
], { duration: 600, easing: spring }),
|
393
|
+
];
|
394
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
395
|
+
if (!isGecko()) {
|
396
|
+
animations.push(element.animate([{ opacity: 1 }, { opacity: 0 }], {
|
397
|
+
duration: 300,
|
398
|
+
easing: 'ease-out',
|
399
|
+
pseudoElement: '::backdrop',
|
400
|
+
fill: 'forwards',
|
401
|
+
}));
|
402
|
+
}
|
403
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
379
404
|
};
|
380
405
|
const flipOut = (element) => {
|
381
406
|
const animation = element.animate([
|
@@ -438,7 +463,6 @@ const formatString = (str) => {
|
|
438
463
|
const parts = str.split(/<\s*br\s*\/?\s*>/);
|
439
464
|
return o(parts, x `<br />`);
|
440
465
|
};
|
441
|
-
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
442
466
|
let BlotoutWallet = class BlotoutWallet extends s {
|
443
467
|
constructor() {
|
444
468
|
super(...arguments);
|
@@ -451,78 +475,76 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
451
475
|
.then(() => (this.state = newState))
|
452
476
|
.then(() => flipIn(this.dialog));
|
453
477
|
};
|
478
|
+
this.restoreCart = async () => {
|
479
|
+
if (!this.lastExpiredCart) {
|
480
|
+
return;
|
481
|
+
}
|
482
|
+
const email = this.email.value.trim().toLowerCase();
|
483
|
+
if (email) {
|
484
|
+
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
485
|
+
const response = await fetch(this.getUrl('/user/email'), {
|
486
|
+
method: 'POST',
|
487
|
+
body: JSON.stringify({
|
488
|
+
email: email,
|
489
|
+
}),
|
490
|
+
headers: this.getHeaders(true),
|
491
|
+
});
|
492
|
+
if (!response.ok) {
|
493
|
+
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
494
|
+
}
|
495
|
+
this.email.value = '';
|
496
|
+
this.hasEmail = true;
|
497
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
498
|
+
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
499
|
+
}
|
500
|
+
await this.storeApi.addItems(this.lastExpiredCart.items);
|
501
|
+
const expiredCartId = this.lastExpiredCart.cartId;
|
502
|
+
// this cookie will be cleared once the next event is processed
|
503
|
+
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
504
|
+
// We attempt to mark the cart as restored, but if the request fails,
|
505
|
+
// we log the error in the console and let the user continue. Since the
|
506
|
+
// problem is probably in the `/cart/restore` endpoint, further attempts
|
507
|
+
// would not resolve the problem, which would just increase the number
|
508
|
+
// of failed calls and not solve the problem.
|
509
|
+
const response = await fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
510
|
+
method: 'POST',
|
511
|
+
headers: this.getHeaders(),
|
512
|
+
});
|
513
|
+
if (!response.ok) {
|
514
|
+
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
515
|
+
}
|
516
|
+
this.lastExpiredCart = undefined;
|
517
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
518
|
+
bubbles: true,
|
519
|
+
}));
|
520
|
+
// Send the request as beacon as there could be a immediate redirect in the next step
|
521
|
+
window.edgetag('tag', 'CartRecovery_CartRestored', { isSilent: !!this.silentRestore }, {}, { method: 'beacon' });
|
522
|
+
};
|
454
523
|
this.onSubmit = async (ev) => {
|
455
524
|
ev.preventDefault();
|
456
525
|
ev.stopPropagation();
|
457
|
-
const email = this.email.value.trim().toLowerCase();
|
458
526
|
try {
|
459
527
|
await this.transitionTo('loading');
|
460
|
-
|
461
|
-
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
462
|
-
const response = await fetch(this.getUrl('/user/email'), {
|
463
|
-
method: 'POST',
|
464
|
-
body: JSON.stringify({
|
465
|
-
email: email,
|
466
|
-
}),
|
467
|
-
headers: this.getHeaders(true),
|
468
|
-
});
|
469
|
-
if (!response.ok) {
|
470
|
-
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
471
|
-
}
|
472
|
-
this.email.value = '';
|
473
|
-
this.hasEmail = true;
|
474
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
475
|
-
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
476
|
-
}
|
477
|
-
if (this.lastExpiredCart) {
|
478
|
-
await this.storeApi.addItems(this.lastExpiredCart.items);
|
479
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
480
|
-
bubbles: true,
|
481
|
-
}));
|
482
|
-
const expiredCartId = this.lastExpiredCart.cartId;
|
483
|
-
// this cookie will be cleared once the next event is processed
|
484
|
-
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
485
|
-
// We attempt to mark the cart as restored, but if the request fails,
|
486
|
-
// we log the error in the console and let the user continue. Since the
|
487
|
-
// problem is probably in the `/cart/restore` endpoint, further attempts
|
488
|
-
// would not resolve the problem, which would just increase the number
|
489
|
-
// of failed calls and not solve the problem.
|
490
|
-
fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
491
|
-
method: 'POST',
|
492
|
-
headers: this.getHeaders(),
|
493
|
-
})
|
494
|
-
.then(async (response) => {
|
495
|
-
if (!response.ok) {
|
496
|
-
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
497
|
-
}
|
498
|
-
// Send the request as beacon as there could be a immediate redirect in the next step
|
499
|
-
window.edgetag('tag', 'CartRecovery_CartRestored', {}, {}, { method: 'beacon' });
|
500
|
-
// Redirect to custom path
|
501
|
-
if (this.restoreRedirect) {
|
502
|
-
try {
|
503
|
-
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
504
|
-
window.location.href = redirect.href;
|
505
|
-
}
|
506
|
-
catch (e) {
|
507
|
-
console.error('Invalid redirect URL', e);
|
508
|
-
}
|
509
|
-
}
|
510
|
-
})
|
511
|
-
.catch((err) => {
|
512
|
-
console.error(err);
|
513
|
-
});
|
514
|
-
this.lastExpiredCart = undefined;
|
515
|
-
}
|
528
|
+
await this.restoreCart();
|
516
529
|
await this.transitionTo('restored');
|
517
|
-
delay(2000)
|
518
|
-
|
519
|
-
|
530
|
+
await delay(2000);
|
531
|
+
if (this.state == 'restored') {
|
532
|
+
this.hideModal('restore');
|
533
|
+
}
|
534
|
+
// Redirect to custom path
|
535
|
+
if (this.restoreRedirect) {
|
536
|
+
try {
|
537
|
+
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
538
|
+
window.location.href = redirect.href;
|
520
539
|
}
|
521
|
-
|
540
|
+
catch (e) {
|
541
|
+
console.error('Invalid redirect URL', e);
|
542
|
+
}
|
543
|
+
}
|
522
544
|
}
|
523
545
|
catch (e) {
|
524
|
-
await this.transitionTo('failed');
|
525
546
|
logger.error(e);
|
547
|
+
await this.transitionTo('failed');
|
526
548
|
}
|
527
549
|
};
|
528
550
|
this.onDialogClick = () => {
|
@@ -632,6 +654,7 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
632
654
|
}
|
633
655
|
}
|
634
656
|
async initialize() {
|
657
|
+
var _a;
|
635
658
|
if (!this.userId) {
|
636
659
|
logger.error('No UserId set');
|
637
660
|
return;
|
@@ -640,11 +663,11 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
640
663
|
return;
|
641
664
|
}
|
642
665
|
await delay(POPUP_IMPRESSION_DELAY);
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
666
|
+
try {
|
667
|
+
const response = await fetch(this.getUrl('/cart/expired'), {
|
668
|
+
method: 'GET',
|
669
|
+
headers: this.getHeaders(),
|
670
|
+
});
|
648
671
|
if (!response.ok) {
|
649
672
|
throw new Error(`Unable to get Expired Cart ${response.status}: ${await response.text()}`);
|
650
673
|
}
|
@@ -652,16 +675,27 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
652
675
|
const result = await response.json();
|
653
676
|
this.hasEmail = result.email;
|
654
677
|
this.lastExpiredCart = result.carts[0];
|
655
|
-
if (
|
656
|
-
this.
|
657
|
-
|
678
|
+
if ((_a = result.carts) === null || _a === void 0 ? void 0 : _a.length) {
|
679
|
+
if (this.silentRestore) {
|
680
|
+
this.restoreCart().catch(logger.error);
|
681
|
+
}
|
682
|
+
else if (!this.isPopUpDismissed) {
|
683
|
+
this.showModal();
|
684
|
+
}
|
685
|
+
if (result.hasJustExpired) {
|
686
|
+
window.edgetag('tag', 'CartRecovery_CartExpiredOnVisit', {}, {}, { destination: this.edgeURL });
|
687
|
+
}
|
658
688
|
}
|
659
|
-
}
|
660
|
-
|
689
|
+
}
|
690
|
+
catch (err) {
|
691
|
+
logger.error(err);
|
692
|
+
}
|
661
693
|
}
|
662
694
|
showModal() {
|
663
695
|
this.dialog.showModal();
|
664
|
-
new Promise(requestAnimationFrame)
|
696
|
+
new Promise(requestAnimationFrame)
|
697
|
+
.catch(logger.error)
|
698
|
+
.finally(() => fadeInDialog(this.dialog));
|
665
699
|
this.dispatchEvent(new CustomEvent('blotout-wallet-shown', { bubbles: true }));
|
666
700
|
fetch(this.getUrl('/user/event'), {
|
667
701
|
method: 'POST',
|
@@ -670,7 +704,9 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
670
704
|
}).catch(logger.error);
|
671
705
|
}
|
672
706
|
hideModal(action) {
|
673
|
-
fadeOutToBottom(this.dialog)
|
707
|
+
fadeOutToBottom(this.dialog)
|
708
|
+
.catch(logger.error)
|
709
|
+
.finally(() => { var _a; return (_a = this.dialog) === null || _a === void 0 ? void 0 : _a.close(action); });
|
674
710
|
this.dispatchEvent(new CustomEvent('blotout-wallet-hidden', { bubbles: true }));
|
675
711
|
}
|
676
712
|
getHeaders(json = false) {
|
@@ -692,18 +728,20 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
692
728
|
}
|
693
729
|
async skipCarts() {
|
694
730
|
this.hideModal('skip');
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
731
|
+
try {
|
732
|
+
const response = await fetch(this.getUrl('/cart/skip'), {
|
733
|
+
method: 'POST',
|
734
|
+
headers: this.getHeaders(),
|
735
|
+
});
|
700
736
|
if (!response.ok) {
|
701
737
|
throw new Error(`Could not mark cart as skipped - ${response.status}: ${await response.text()}`);
|
702
738
|
}
|
703
739
|
window.edgetag('tag', 'CartRecovery_CartDeclined', {}, {}, { destination: this.edgeURL });
|
704
740
|
this.lastExpiredCart = undefined;
|
705
|
-
}
|
706
|
-
|
741
|
+
}
|
742
|
+
catch (e) {
|
743
|
+
logger.error(e);
|
744
|
+
}
|
707
745
|
}
|
708
746
|
render() {
|
709
747
|
if (this.isPopUpDismissed) {
|
@@ -882,7 +920,7 @@ BlotoutWallet = __decorate([
|
|
882
920
|
], BlotoutWallet);
|
883
921
|
|
884
922
|
const init = (params) => {
|
885
|
-
var _a, _b, _c, _d, _e;
|
923
|
+
var _a, _b, _c, _d, _e, _f;
|
886
924
|
if (
|
887
925
|
// if loaded in non-browser SDKs
|
888
926
|
!window ||
|
@@ -917,6 +955,7 @@ const init = (params) => {
|
|
917
955
|
element.edgeURL = params.baseUrl;
|
918
956
|
element.userId = params.userId;
|
919
957
|
element.restoreRedirect = (_e = params.manifest.variables) === null || _e === void 0 ? void 0 : _e['restoreRedirect'];
|
958
|
+
element.silentRestore = ((_f = params.manifest.variables) === null || _f === void 0 ? void 0 : _f['silentRestore']) === '1';
|
920
959
|
document.body.append(element);
|
921
960
|
}
|
922
961
|
};
|
package/index.js
CHANGED
@@ -35,6 +35,8 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
35
35
|
...expand('911,921,922,923,924,926,927,932,933,935,942,944,946,950,953,955,957-958,960-969,974,975,976,977,981-982,987,988,990-999'),
|
36
36
|
]);
|
37
37
|
|
38
|
+
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
39
|
+
|
38
40
|
const customAttributes = {
|
39
41
|
'--bw-primary': { type: 'color', defaultValue: '#000000' },
|
40
42
|
'--bw-title-color': { type: 'color', defaultValue: '#000000' },
|
@@ -65,28 +67,39 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
65
67
|
const cartTokenLinkCookie = 'bwCartLinkToken';
|
66
68
|
|
67
69
|
const getCookieValue = (key) => {
|
70
|
+
var _a;
|
68
71
|
try {
|
69
72
|
if (!document || !document.cookie) {
|
70
73
|
return '';
|
71
74
|
}
|
72
|
-
const
|
73
|
-
|
74
|
-
const ca = decodedCookie.split(';');
|
75
|
-
for (let i = 0; i < ca.length; i++) {
|
76
|
-
let c = ca[i];
|
77
|
-
while (c.charAt(0) === ' ') {
|
78
|
-
c = c.substring(1);
|
79
|
-
}
|
80
|
-
if (c.indexOf(name) === 0) {
|
81
|
-
return c.substring(name.length, c.length);
|
82
|
-
}
|
83
|
-
}
|
84
|
-
return '';
|
75
|
+
const cookies = parseCookies(document.cookie);
|
76
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
85
77
|
}
|
86
78
|
catch {
|
87
79
|
return '';
|
88
80
|
}
|
89
81
|
};
|
82
|
+
const parseCookies = (cookie) => {
|
83
|
+
return Object.fromEntries(cookie
|
84
|
+
.split(/;\s+/)
|
85
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
86
|
+
.map(([cookieKey, cookieValue]) => {
|
87
|
+
if (!cookieKey) {
|
88
|
+
return [];
|
89
|
+
}
|
90
|
+
let decodedValue = '';
|
91
|
+
if (cookieValue) {
|
92
|
+
try {
|
93
|
+
decodedValue = decodeURIComponent(cookieValue);
|
94
|
+
}
|
95
|
+
catch (e) {
|
96
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
97
|
+
decodedValue = cookieValue;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return [cookieKey, decodedValue];
|
101
|
+
}));
|
102
|
+
};
|
90
103
|
const setCookie = (key, value, options) => {
|
91
104
|
var _a;
|
92
105
|
try {
|
@@ -352,31 +365,43 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
352
365
|
}
|
353
366
|
`;
|
354
367
|
|
368
|
+
const isGecko = () => /\bGecko\/\d+/.test(navigator.userAgent);
|
369
|
+
|
355
370
|
const fadeInDialog = (element) => {
|
356
|
-
const
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
371
|
+
const animations = [
|
372
|
+
element.animate([
|
373
|
+
{ transform: 'translateY(-20px)', opacity: 0 },
|
374
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
375
|
+
], { duration: 600, easing: spring, composite: 'add' }),
|
376
|
+
];
|
377
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
378
|
+
if (!isGecko()) {
|
379
|
+
animations.push(element.animate([{ opacity: 0 }, { opacity: 1 }], {
|
380
|
+
duration: 300,
|
381
|
+
easing: 'ease-out',
|
382
|
+
pseudoElement: '::backdrop',
|
383
|
+
fill: 'forwards',
|
384
|
+
}));
|
385
|
+
}
|
386
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
367
387
|
};
|
368
388
|
const fadeOutToBottom = (element) => {
|
369
|
-
const
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
389
|
+
const animations = [
|
390
|
+
element.animate([
|
391
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
392
|
+
{ transform: 'translateY(20px)', opacity: 0 },
|
393
|
+
], { duration: 600, easing: spring }),
|
394
|
+
];
|
395
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
396
|
+
if (!isGecko()) {
|
397
|
+
animations.push(element.animate([{ opacity: 1 }, { opacity: 0 }], {
|
398
|
+
duration: 300,
|
399
|
+
easing: 'ease-out',
|
400
|
+
pseudoElement: '::backdrop',
|
401
|
+
fill: 'forwards',
|
402
|
+
}));
|
403
|
+
}
|
404
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
380
405
|
};
|
381
406
|
const flipOut = (element) => {
|
382
407
|
const animation = element.animate([
|
@@ -439,7 +464,6 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
439
464
|
const parts = str.split(/<\s*br\s*\/?\s*>/);
|
440
465
|
return o(parts, x `<br />`);
|
441
466
|
};
|
442
|
-
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
443
467
|
let BlotoutWallet = class BlotoutWallet extends s {
|
444
468
|
constructor() {
|
445
469
|
super(...arguments);
|
@@ -452,78 +476,76 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
452
476
|
.then(() => (this.state = newState))
|
453
477
|
.then(() => flipIn(this.dialog));
|
454
478
|
};
|
479
|
+
this.restoreCart = async () => {
|
480
|
+
if (!this.lastExpiredCart) {
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
const email = this.email.value.trim().toLowerCase();
|
484
|
+
if (email) {
|
485
|
+
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
486
|
+
const response = await fetch(this.getUrl('/user/email'), {
|
487
|
+
method: 'POST',
|
488
|
+
body: JSON.stringify({
|
489
|
+
email: email,
|
490
|
+
}),
|
491
|
+
headers: this.getHeaders(true),
|
492
|
+
});
|
493
|
+
if (!response.ok) {
|
494
|
+
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
495
|
+
}
|
496
|
+
this.email.value = '';
|
497
|
+
this.hasEmail = true;
|
498
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
499
|
+
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
500
|
+
}
|
501
|
+
await this.storeApi.addItems(this.lastExpiredCart.items);
|
502
|
+
const expiredCartId = this.lastExpiredCart.cartId;
|
503
|
+
// this cookie will be cleared once the next event is processed
|
504
|
+
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
505
|
+
// We attempt to mark the cart as restored, but if the request fails,
|
506
|
+
// we log the error in the console and let the user continue. Since the
|
507
|
+
// problem is probably in the `/cart/restore` endpoint, further attempts
|
508
|
+
// would not resolve the problem, which would just increase the number
|
509
|
+
// of failed calls and not solve the problem.
|
510
|
+
const response = await fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
511
|
+
method: 'POST',
|
512
|
+
headers: this.getHeaders(),
|
513
|
+
});
|
514
|
+
if (!response.ok) {
|
515
|
+
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
516
|
+
}
|
517
|
+
this.lastExpiredCart = undefined;
|
518
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
519
|
+
bubbles: true,
|
520
|
+
}));
|
521
|
+
// Send the request as beacon as there could be a immediate redirect in the next step
|
522
|
+
window.edgetag('tag', 'CartRecovery_CartRestored', { isSilent: !!this.silentRestore }, {}, { method: 'beacon' });
|
523
|
+
};
|
455
524
|
this.onSubmit = async (ev) => {
|
456
525
|
ev.preventDefault();
|
457
526
|
ev.stopPropagation();
|
458
|
-
const email = this.email.value.trim().toLowerCase();
|
459
527
|
try {
|
460
528
|
await this.transitionTo('loading');
|
461
|
-
|
462
|
-
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
463
|
-
const response = await fetch(this.getUrl('/user/email'), {
|
464
|
-
method: 'POST',
|
465
|
-
body: JSON.stringify({
|
466
|
-
email: email,
|
467
|
-
}),
|
468
|
-
headers: this.getHeaders(true),
|
469
|
-
});
|
470
|
-
if (!response.ok) {
|
471
|
-
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
472
|
-
}
|
473
|
-
this.email.value = '';
|
474
|
-
this.hasEmail = true;
|
475
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
476
|
-
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
477
|
-
}
|
478
|
-
if (this.lastExpiredCart) {
|
479
|
-
await this.storeApi.addItems(this.lastExpiredCart.items);
|
480
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
481
|
-
bubbles: true,
|
482
|
-
}));
|
483
|
-
const expiredCartId = this.lastExpiredCart.cartId;
|
484
|
-
// this cookie will be cleared once the next event is processed
|
485
|
-
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
486
|
-
// We attempt to mark the cart as restored, but if the request fails,
|
487
|
-
// we log the error in the console and let the user continue. Since the
|
488
|
-
// problem is probably in the `/cart/restore` endpoint, further attempts
|
489
|
-
// would not resolve the problem, which would just increase the number
|
490
|
-
// of failed calls and not solve the problem.
|
491
|
-
fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
492
|
-
method: 'POST',
|
493
|
-
headers: this.getHeaders(),
|
494
|
-
})
|
495
|
-
.then(async (response) => {
|
496
|
-
if (!response.ok) {
|
497
|
-
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
498
|
-
}
|
499
|
-
// Send the request as beacon as there could be a immediate redirect in the next step
|
500
|
-
window.edgetag('tag', 'CartRecovery_CartRestored', {}, {}, { method: 'beacon' });
|
501
|
-
// Redirect to custom path
|
502
|
-
if (this.restoreRedirect) {
|
503
|
-
try {
|
504
|
-
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
505
|
-
window.location.href = redirect.href;
|
506
|
-
}
|
507
|
-
catch (e) {
|
508
|
-
console.error('Invalid redirect URL', e);
|
509
|
-
}
|
510
|
-
}
|
511
|
-
})
|
512
|
-
.catch((err) => {
|
513
|
-
console.error(err);
|
514
|
-
});
|
515
|
-
this.lastExpiredCart = undefined;
|
516
|
-
}
|
529
|
+
await this.restoreCart();
|
517
530
|
await this.transitionTo('restored');
|
518
|
-
delay(2000)
|
519
|
-
|
520
|
-
|
531
|
+
await delay(2000);
|
532
|
+
if (this.state == 'restored') {
|
533
|
+
this.hideModal('restore');
|
534
|
+
}
|
535
|
+
// Redirect to custom path
|
536
|
+
if (this.restoreRedirect) {
|
537
|
+
try {
|
538
|
+
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
539
|
+
window.location.href = redirect.href;
|
521
540
|
}
|
522
|
-
|
541
|
+
catch (e) {
|
542
|
+
console.error('Invalid redirect URL', e);
|
543
|
+
}
|
544
|
+
}
|
523
545
|
}
|
524
546
|
catch (e) {
|
525
|
-
await this.transitionTo('failed');
|
526
547
|
logger.error(e);
|
548
|
+
await this.transitionTo('failed');
|
527
549
|
}
|
528
550
|
};
|
529
551
|
this.onDialogClick = () => {
|
@@ -633,6 +655,7 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
633
655
|
}
|
634
656
|
}
|
635
657
|
async initialize() {
|
658
|
+
var _a;
|
636
659
|
if (!this.userId) {
|
637
660
|
logger.error('No UserId set');
|
638
661
|
return;
|
@@ -641,11 +664,11 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
641
664
|
return;
|
642
665
|
}
|
643
666
|
await delay(POPUP_IMPRESSION_DELAY);
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
667
|
+
try {
|
668
|
+
const response = await fetch(this.getUrl('/cart/expired'), {
|
669
|
+
method: 'GET',
|
670
|
+
headers: this.getHeaders(),
|
671
|
+
});
|
649
672
|
if (!response.ok) {
|
650
673
|
throw new Error(`Unable to get Expired Cart ${response.status}: ${await response.text()}`);
|
651
674
|
}
|
@@ -653,16 +676,27 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
653
676
|
const result = await response.json();
|
654
677
|
this.hasEmail = result.email;
|
655
678
|
this.lastExpiredCart = result.carts[0];
|
656
|
-
if (
|
657
|
-
this.
|
658
|
-
|
679
|
+
if ((_a = result.carts) === null || _a === void 0 ? void 0 : _a.length) {
|
680
|
+
if (this.silentRestore) {
|
681
|
+
this.restoreCart().catch(logger.error);
|
682
|
+
}
|
683
|
+
else if (!this.isPopUpDismissed) {
|
684
|
+
this.showModal();
|
685
|
+
}
|
686
|
+
if (result.hasJustExpired) {
|
687
|
+
window.edgetag('tag', 'CartRecovery_CartExpiredOnVisit', {}, {}, { destination: this.edgeURL });
|
688
|
+
}
|
659
689
|
}
|
660
|
-
}
|
661
|
-
|
690
|
+
}
|
691
|
+
catch (err) {
|
692
|
+
logger.error(err);
|
693
|
+
}
|
662
694
|
}
|
663
695
|
showModal() {
|
664
696
|
this.dialog.showModal();
|
665
|
-
new Promise(requestAnimationFrame)
|
697
|
+
new Promise(requestAnimationFrame)
|
698
|
+
.catch(logger.error)
|
699
|
+
.finally(() => fadeInDialog(this.dialog));
|
666
700
|
this.dispatchEvent(new CustomEvent('blotout-wallet-shown', { bubbles: true }));
|
667
701
|
fetch(this.getUrl('/user/event'), {
|
668
702
|
method: 'POST',
|
@@ -671,7 +705,9 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
671
705
|
}).catch(logger.error);
|
672
706
|
}
|
673
707
|
hideModal(action) {
|
674
|
-
fadeOutToBottom(this.dialog)
|
708
|
+
fadeOutToBottom(this.dialog)
|
709
|
+
.catch(logger.error)
|
710
|
+
.finally(() => { var _a; return (_a = this.dialog) === null || _a === void 0 ? void 0 : _a.close(action); });
|
675
711
|
this.dispatchEvent(new CustomEvent('blotout-wallet-hidden', { bubbles: true }));
|
676
712
|
}
|
677
713
|
getHeaders(json = false) {
|
@@ -693,18 +729,20 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
693
729
|
}
|
694
730
|
async skipCarts() {
|
695
731
|
this.hideModal('skip');
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
732
|
+
try {
|
733
|
+
const response = await fetch(this.getUrl('/cart/skip'), {
|
734
|
+
method: 'POST',
|
735
|
+
headers: this.getHeaders(),
|
736
|
+
});
|
701
737
|
if (!response.ok) {
|
702
738
|
throw new Error(`Could not mark cart as skipped - ${response.status}: ${await response.text()}`);
|
703
739
|
}
|
704
740
|
window.edgetag('tag', 'CartRecovery_CartDeclined', {}, {}, { destination: this.edgeURL });
|
705
741
|
this.lastExpiredCart = undefined;
|
706
|
-
}
|
707
|
-
|
742
|
+
}
|
743
|
+
catch (e) {
|
744
|
+
logger.error(e);
|
745
|
+
}
|
708
746
|
}
|
709
747
|
render() {
|
710
748
|
if (this.isPopUpDismissed) {
|
@@ -883,7 +921,7 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
883
921
|
], BlotoutWallet);
|
884
922
|
|
885
923
|
const init = (params) => {
|
886
|
-
var _a, _b, _c, _d, _e;
|
924
|
+
var _a, _b, _c, _d, _e, _f;
|
887
925
|
if (
|
888
926
|
// if loaded in non-browser SDKs
|
889
927
|
!window ||
|
@@ -918,6 +956,7 @@ var ProvidersBlotoutWalletSdk = (function () {
|
|
918
956
|
element.edgeURL = params.baseUrl;
|
919
957
|
element.userId = params.userId;
|
920
958
|
element.restoreRedirect = (_e = params.manifest.variables) === null || _e === void 0 ? void 0 : _e['restoreRedirect'];
|
959
|
+
element.silentRestore = ((_f = params.manifest.variables) === null || _f === void 0 ? void 0 : _f['silentRestore']) === '1';
|
921
960
|
document.body.append(element);
|
922
961
|
}
|
923
962
|
};
|
package/index.mjs
CHANGED
@@ -32,6 +32,8 @@ new Set([
|
|
32
32
|
...expand('911,921,922,923,924,926,927,932,933,935,942,944,946,950,953,955,957-958,960-969,974,975,976,977,981-982,987,988,990-999'),
|
33
33
|
]);
|
34
34
|
|
35
|
+
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
36
|
+
|
35
37
|
const customAttributes = {
|
36
38
|
'--bw-primary': { type: 'color', defaultValue: '#000000' },
|
37
39
|
'--bw-title-color': { type: 'color', defaultValue: '#000000' },
|
@@ -62,28 +64,39 @@ const cartTokenTwoCookie = 'cart2';
|
|
62
64
|
const cartTokenLinkCookie = 'bwCartLinkToken';
|
63
65
|
|
64
66
|
const getCookieValue = (key) => {
|
67
|
+
var _a;
|
65
68
|
try {
|
66
69
|
if (!document || !document.cookie) {
|
67
70
|
return '';
|
68
71
|
}
|
69
|
-
const
|
70
|
-
|
71
|
-
const ca = decodedCookie.split(';');
|
72
|
-
for (let i = 0; i < ca.length; i++) {
|
73
|
-
let c = ca[i];
|
74
|
-
while (c.charAt(0) === ' ') {
|
75
|
-
c = c.substring(1);
|
76
|
-
}
|
77
|
-
if (c.indexOf(name) === 0) {
|
78
|
-
return c.substring(name.length, c.length);
|
79
|
-
}
|
80
|
-
}
|
81
|
-
return '';
|
72
|
+
const cookies = parseCookies(document.cookie);
|
73
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
82
74
|
}
|
83
75
|
catch {
|
84
76
|
return '';
|
85
77
|
}
|
86
78
|
};
|
79
|
+
const parseCookies = (cookie) => {
|
80
|
+
return Object.fromEntries(cookie
|
81
|
+
.split(/;\s+/)
|
82
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
83
|
+
.map(([cookieKey, cookieValue]) => {
|
84
|
+
if (!cookieKey) {
|
85
|
+
return [];
|
86
|
+
}
|
87
|
+
let decodedValue = '';
|
88
|
+
if (cookieValue) {
|
89
|
+
try {
|
90
|
+
decodedValue = decodeURIComponent(cookieValue);
|
91
|
+
}
|
92
|
+
catch (e) {
|
93
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
94
|
+
decodedValue = cookieValue;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
return [cookieKey, decodedValue];
|
98
|
+
}));
|
99
|
+
};
|
87
100
|
const setCookie = (key, value, options) => {
|
88
101
|
var _a;
|
89
102
|
try {
|
@@ -349,31 +362,43 @@ const cssVars = i$4 `
|
|
349
362
|
}
|
350
363
|
`;
|
351
364
|
|
365
|
+
const isGecko = () => /\bGecko\/\d+/.test(navigator.userAgent);
|
366
|
+
|
352
367
|
const fadeInDialog = (element) => {
|
353
|
-
const
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
368
|
+
const animations = [
|
369
|
+
element.animate([
|
370
|
+
{ transform: 'translateY(-20px)', opacity: 0 },
|
371
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
372
|
+
], { duration: 600, easing: spring, composite: 'add' }),
|
373
|
+
];
|
374
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
375
|
+
if (!isGecko()) {
|
376
|
+
animations.push(element.animate([{ opacity: 0 }, { opacity: 1 }], {
|
377
|
+
duration: 300,
|
378
|
+
easing: 'ease-out',
|
379
|
+
pseudoElement: '::backdrop',
|
380
|
+
fill: 'forwards',
|
381
|
+
}));
|
382
|
+
}
|
383
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
364
384
|
};
|
365
385
|
const fadeOutToBottom = (element) => {
|
366
|
-
const
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
386
|
+
const animations = [
|
387
|
+
element.animate([
|
388
|
+
{ transform: 'translateY(0)', opacity: 1 },
|
389
|
+
{ transform: 'translateY(20px)', opacity: 0 },
|
390
|
+
], { duration: 600, easing: spring }),
|
391
|
+
];
|
392
|
+
// Gecko does not support animating ::backdrop pseudo elements
|
393
|
+
if (!isGecko()) {
|
394
|
+
animations.push(element.animate([{ opacity: 1 }, { opacity: 0 }], {
|
395
|
+
duration: 300,
|
396
|
+
easing: 'ease-out',
|
397
|
+
pseudoElement: '::backdrop',
|
398
|
+
fill: 'forwards',
|
399
|
+
}));
|
400
|
+
}
|
401
|
+
return Promise.all(animations.map((anim) => anim.finished));
|
377
402
|
};
|
378
403
|
const flipOut = (element) => {
|
379
404
|
const animation = element.animate([
|
@@ -436,7 +461,6 @@ const formatString = (str) => {
|
|
436
461
|
const parts = str.split(/<\s*br\s*\/?\s*>/);
|
437
462
|
return o(parts, x `<br />`);
|
438
463
|
};
|
439
|
-
const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
|
440
464
|
let BlotoutWallet = class BlotoutWallet extends s {
|
441
465
|
constructor() {
|
442
466
|
super(...arguments);
|
@@ -449,78 +473,76 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
449
473
|
.then(() => (this.state = newState))
|
450
474
|
.then(() => flipIn(this.dialog));
|
451
475
|
};
|
476
|
+
this.restoreCart = async () => {
|
477
|
+
if (!this.lastExpiredCart) {
|
478
|
+
return;
|
479
|
+
}
|
480
|
+
const email = this.email.value.trim().toLowerCase();
|
481
|
+
if (email) {
|
482
|
+
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
483
|
+
const response = await fetch(this.getUrl('/user/email'), {
|
484
|
+
method: 'POST',
|
485
|
+
body: JSON.stringify({
|
486
|
+
email: email,
|
487
|
+
}),
|
488
|
+
headers: this.getHeaders(true),
|
489
|
+
});
|
490
|
+
if (!response.ok) {
|
491
|
+
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
492
|
+
}
|
493
|
+
this.email.value = '';
|
494
|
+
this.hasEmail = true;
|
495
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
496
|
+
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
497
|
+
}
|
498
|
+
await this.storeApi.addItems(this.lastExpiredCart.items);
|
499
|
+
const expiredCartId = this.lastExpiredCart.cartId;
|
500
|
+
// this cookie will be cleared once the next event is processed
|
501
|
+
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
502
|
+
// We attempt to mark the cart as restored, but if the request fails,
|
503
|
+
// we log the error in the console and let the user continue. Since the
|
504
|
+
// problem is probably in the `/cart/restore` endpoint, further attempts
|
505
|
+
// would not resolve the problem, which would just increase the number
|
506
|
+
// of failed calls and not solve the problem.
|
507
|
+
const response = await fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
508
|
+
method: 'POST',
|
509
|
+
headers: this.getHeaders(),
|
510
|
+
});
|
511
|
+
if (!response.ok) {
|
512
|
+
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
513
|
+
}
|
514
|
+
this.lastExpiredCart = undefined;
|
515
|
+
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
516
|
+
bubbles: true,
|
517
|
+
}));
|
518
|
+
// Send the request as beacon as there could be a immediate redirect in the next step
|
519
|
+
window.edgetag('tag', 'CartRecovery_CartRestored', { isSilent: !!this.silentRestore }, {}, { method: 'beacon' });
|
520
|
+
};
|
452
521
|
this.onSubmit = async (ev) => {
|
453
522
|
ev.preventDefault();
|
454
523
|
ev.stopPropagation();
|
455
|
-
const email = this.email.value.trim().toLowerCase();
|
456
524
|
try {
|
457
525
|
await this.transitionTo('loading');
|
458
|
-
|
459
|
-
window.edgetag('user', 'email', email, {}, { destination: this.edgeURL });
|
460
|
-
const response = await fetch(this.getUrl('/user/email'), {
|
461
|
-
method: 'POST',
|
462
|
-
body: JSON.stringify({
|
463
|
-
email: email,
|
464
|
-
}),
|
465
|
-
headers: this.getHeaders(true),
|
466
|
-
});
|
467
|
-
if (!response.ok) {
|
468
|
-
throw new Error(`Could not save email ${response.status}: ${await response.text()}`);
|
469
|
-
}
|
470
|
-
this.email.value = '';
|
471
|
-
this.hasEmail = true;
|
472
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-email-saved', { bubbles: true }));
|
473
|
-
window.edgetag('tag', 'CartRecovery_KeepCartEmailSaved', {}, {}, { destination: this.edgeURL });
|
474
|
-
}
|
475
|
-
if (this.lastExpiredCart) {
|
476
|
-
await this.storeApi.addItems(this.lastExpiredCart.items);
|
477
|
-
this.dispatchEvent(new CustomEvent('blotout-wallet-restored', {
|
478
|
-
bubbles: true,
|
479
|
-
}));
|
480
|
-
const expiredCartId = this.lastExpiredCart.cartId;
|
481
|
-
// this cookie will be cleared once the next event is processed
|
482
|
-
setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
|
483
|
-
// We attempt to mark the cart as restored, but if the request fails,
|
484
|
-
// we log the error in the console and let the user continue. Since the
|
485
|
-
// problem is probably in the `/cart/restore` endpoint, further attempts
|
486
|
-
// would not resolve the problem, which would just increase the number
|
487
|
-
// of failed calls and not solve the problem.
|
488
|
-
fetch(this.getUrl(`/cart/restore/${expiredCartId}`), {
|
489
|
-
method: 'POST',
|
490
|
-
headers: this.getHeaders(),
|
491
|
-
})
|
492
|
-
.then(async (response) => {
|
493
|
-
if (!response.ok) {
|
494
|
-
throw new Error(`Could not update status in DB - ${response.status}: ${response.text}\n\n${await response.text()}`);
|
495
|
-
}
|
496
|
-
// Send the request as beacon as there could be a immediate redirect in the next step
|
497
|
-
window.edgetag('tag', 'CartRecovery_CartRestored', {}, {}, { method: 'beacon' });
|
498
|
-
// Redirect to custom path
|
499
|
-
if (this.restoreRedirect) {
|
500
|
-
try {
|
501
|
-
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
502
|
-
window.location.href = redirect.href;
|
503
|
-
}
|
504
|
-
catch (e) {
|
505
|
-
console.error('Invalid redirect URL', e);
|
506
|
-
}
|
507
|
-
}
|
508
|
-
})
|
509
|
-
.catch((err) => {
|
510
|
-
console.error(err);
|
511
|
-
});
|
512
|
-
this.lastExpiredCart = undefined;
|
513
|
-
}
|
526
|
+
await this.restoreCart();
|
514
527
|
await this.transitionTo('restored');
|
515
|
-
delay(2000)
|
516
|
-
|
517
|
-
|
528
|
+
await delay(2000);
|
529
|
+
if (this.state == 'restored') {
|
530
|
+
this.hideModal('restore');
|
531
|
+
}
|
532
|
+
// Redirect to custom path
|
533
|
+
if (this.restoreRedirect) {
|
534
|
+
try {
|
535
|
+
const redirect = new URL(this.restoreRedirect, window.location.origin);
|
536
|
+
window.location.href = redirect.href;
|
518
537
|
}
|
519
|
-
|
538
|
+
catch (e) {
|
539
|
+
console.error('Invalid redirect URL', e);
|
540
|
+
}
|
541
|
+
}
|
520
542
|
}
|
521
543
|
catch (e) {
|
522
|
-
await this.transitionTo('failed');
|
523
544
|
logger.error(e);
|
545
|
+
await this.transitionTo('failed');
|
524
546
|
}
|
525
547
|
};
|
526
548
|
this.onDialogClick = () => {
|
@@ -630,6 +652,7 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
630
652
|
}
|
631
653
|
}
|
632
654
|
async initialize() {
|
655
|
+
var _a;
|
633
656
|
if (!this.userId) {
|
634
657
|
logger.error('No UserId set');
|
635
658
|
return;
|
@@ -638,11 +661,11 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
638
661
|
return;
|
639
662
|
}
|
640
663
|
await delay(POPUP_IMPRESSION_DELAY);
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
664
|
+
try {
|
665
|
+
const response = await fetch(this.getUrl('/cart/expired'), {
|
666
|
+
method: 'GET',
|
667
|
+
headers: this.getHeaders(),
|
668
|
+
});
|
646
669
|
if (!response.ok) {
|
647
670
|
throw new Error(`Unable to get Expired Cart ${response.status}: ${await response.text()}`);
|
648
671
|
}
|
@@ -650,16 +673,27 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
650
673
|
const result = await response.json();
|
651
674
|
this.hasEmail = result.email;
|
652
675
|
this.lastExpiredCart = result.carts[0];
|
653
|
-
if (
|
654
|
-
this.
|
655
|
-
|
676
|
+
if ((_a = result.carts) === null || _a === void 0 ? void 0 : _a.length) {
|
677
|
+
if (this.silentRestore) {
|
678
|
+
this.restoreCart().catch(logger.error);
|
679
|
+
}
|
680
|
+
else if (!this.isPopUpDismissed) {
|
681
|
+
this.showModal();
|
682
|
+
}
|
683
|
+
if (result.hasJustExpired) {
|
684
|
+
window.edgetag('tag', 'CartRecovery_CartExpiredOnVisit', {}, {}, { destination: this.edgeURL });
|
685
|
+
}
|
656
686
|
}
|
657
|
-
}
|
658
|
-
|
687
|
+
}
|
688
|
+
catch (err) {
|
689
|
+
logger.error(err);
|
690
|
+
}
|
659
691
|
}
|
660
692
|
showModal() {
|
661
693
|
this.dialog.showModal();
|
662
|
-
new Promise(requestAnimationFrame)
|
694
|
+
new Promise(requestAnimationFrame)
|
695
|
+
.catch(logger.error)
|
696
|
+
.finally(() => fadeInDialog(this.dialog));
|
663
697
|
this.dispatchEvent(new CustomEvent('blotout-wallet-shown', { bubbles: true }));
|
664
698
|
fetch(this.getUrl('/user/event'), {
|
665
699
|
method: 'POST',
|
@@ -668,7 +702,9 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
668
702
|
}).catch(logger.error);
|
669
703
|
}
|
670
704
|
hideModal(action) {
|
671
|
-
fadeOutToBottom(this.dialog)
|
705
|
+
fadeOutToBottom(this.dialog)
|
706
|
+
.catch(logger.error)
|
707
|
+
.finally(() => { var _a; return (_a = this.dialog) === null || _a === void 0 ? void 0 : _a.close(action); });
|
672
708
|
this.dispatchEvent(new CustomEvent('blotout-wallet-hidden', { bubbles: true }));
|
673
709
|
}
|
674
710
|
getHeaders(json = false) {
|
@@ -690,18 +726,20 @@ let BlotoutWallet = class BlotoutWallet extends s {
|
|
690
726
|
}
|
691
727
|
async skipCarts() {
|
692
728
|
this.hideModal('skip');
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
729
|
+
try {
|
730
|
+
const response = await fetch(this.getUrl('/cart/skip'), {
|
731
|
+
method: 'POST',
|
732
|
+
headers: this.getHeaders(),
|
733
|
+
});
|
698
734
|
if (!response.ok) {
|
699
735
|
throw new Error(`Could not mark cart as skipped - ${response.status}: ${await response.text()}`);
|
700
736
|
}
|
701
737
|
window.edgetag('tag', 'CartRecovery_CartDeclined', {}, {}, { destination: this.edgeURL });
|
702
738
|
this.lastExpiredCart = undefined;
|
703
|
-
}
|
704
|
-
|
739
|
+
}
|
740
|
+
catch (e) {
|
741
|
+
logger.error(e);
|
742
|
+
}
|
705
743
|
}
|
706
744
|
render() {
|
707
745
|
if (this.isPopUpDismissed) {
|
@@ -880,7 +918,7 @@ BlotoutWallet = __decorate([
|
|
880
918
|
], BlotoutWallet);
|
881
919
|
|
882
920
|
const init = (params) => {
|
883
|
-
var _a, _b, _c, _d, _e;
|
921
|
+
var _a, _b, _c, _d, _e, _f;
|
884
922
|
if (
|
885
923
|
// if loaded in non-browser SDKs
|
886
924
|
!window ||
|
@@ -915,6 +953,7 @@ const init = (params) => {
|
|
915
953
|
element.edgeURL = params.baseUrl;
|
916
954
|
element.userId = params.userId;
|
917
955
|
element.restoreRedirect = (_e = params.manifest.variables) === null || _e === void 0 ? void 0 : _e['restoreRedirect'];
|
956
|
+
element.silentRestore = ((_f = params.manifest.variables) === null || _f === void 0 ? void 0 : _f['silentRestore']) === '1';
|
918
957
|
document.body.append(element);
|
919
958
|
}
|
920
959
|
};
|
package/package.json
CHANGED
@@ -42,28 +42,39 @@ const registryKey = Symbol.for('blotout-wallet');
|
|
42
42
|
(_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
|
43
43
|
|
44
44
|
const getCookieValue = (key) => {
|
45
|
+
var _a;
|
45
46
|
try {
|
46
47
|
if (!document || !document.cookie) {
|
47
48
|
return '';
|
48
49
|
}
|
49
|
-
const
|
50
|
-
|
51
|
-
const ca = decodedCookie.split(';');
|
52
|
-
for (let i = 0; i < ca.length; i++) {
|
53
|
-
let c = ca[i];
|
54
|
-
while (c.charAt(0) === ' ') {
|
55
|
-
c = c.substring(1);
|
56
|
-
}
|
57
|
-
if (c.indexOf(name) === 0) {
|
58
|
-
return c.substring(name.length, c.length);
|
59
|
-
}
|
60
|
-
}
|
61
|
-
return '';
|
50
|
+
const cookies = parseCookies(document.cookie);
|
51
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
62
52
|
}
|
63
53
|
catch {
|
64
54
|
return '';
|
65
55
|
}
|
66
56
|
};
|
57
|
+
const parseCookies = (cookie) => {
|
58
|
+
return Object.fromEntries(cookie
|
59
|
+
.split(/;\s+/)
|
60
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
61
|
+
.map(([cookieKey, cookieValue]) => {
|
62
|
+
if (!cookieKey) {
|
63
|
+
return [];
|
64
|
+
}
|
65
|
+
let decodedValue = '';
|
66
|
+
if (cookieValue) {
|
67
|
+
try {
|
68
|
+
decodedValue = decodeURIComponent(cookieValue);
|
69
|
+
}
|
70
|
+
catch (e) {
|
71
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
72
|
+
decodedValue = cookieValue;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
return [cookieKey, decodedValue];
|
76
|
+
}));
|
77
|
+
};
|
67
78
|
|
68
79
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
69
80
|
const createShopApi = (fetchOverride = window.fetch) => ({
|
package/stores/shopify/index.js
CHANGED
@@ -43,28 +43,39 @@
|
|
43
43
|
(_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
|
44
44
|
|
45
45
|
const getCookieValue = (key) => {
|
46
|
+
var _a;
|
46
47
|
try {
|
47
48
|
if (!document || !document.cookie) {
|
48
49
|
return '';
|
49
50
|
}
|
50
|
-
const
|
51
|
-
|
52
|
-
const ca = decodedCookie.split(';');
|
53
|
-
for (let i = 0; i < ca.length; i++) {
|
54
|
-
let c = ca[i];
|
55
|
-
while (c.charAt(0) === ' ') {
|
56
|
-
c = c.substring(1);
|
57
|
-
}
|
58
|
-
if (c.indexOf(name) === 0) {
|
59
|
-
return c.substring(name.length, c.length);
|
60
|
-
}
|
61
|
-
}
|
62
|
-
return '';
|
51
|
+
const cookies = parseCookies(document.cookie);
|
52
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
63
53
|
}
|
64
54
|
catch {
|
65
55
|
return '';
|
66
56
|
}
|
67
57
|
};
|
58
|
+
const parseCookies = (cookie) => {
|
59
|
+
return Object.fromEntries(cookie
|
60
|
+
.split(/;\s+/)
|
61
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
62
|
+
.map(([cookieKey, cookieValue]) => {
|
63
|
+
if (!cookieKey) {
|
64
|
+
return [];
|
65
|
+
}
|
66
|
+
let decodedValue = '';
|
67
|
+
if (cookieValue) {
|
68
|
+
try {
|
69
|
+
decodedValue = decodeURIComponent(cookieValue);
|
70
|
+
}
|
71
|
+
catch (e) {
|
72
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
73
|
+
decodedValue = cookieValue;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
return [cookieKey, decodedValue];
|
77
|
+
}));
|
78
|
+
};
|
68
79
|
|
69
80
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
70
81
|
const createShopApi = (fetchOverride = window.fetch) => ({
|
package/stores/shopify/index.mjs
CHANGED
@@ -40,28 +40,39 @@ const registryKey = Symbol.for('blotout-wallet');
|
|
40
40
|
(_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
|
41
41
|
|
42
42
|
const getCookieValue = (key) => {
|
43
|
+
var _a;
|
43
44
|
try {
|
44
45
|
if (!document || !document.cookie) {
|
45
46
|
return '';
|
46
47
|
}
|
47
|
-
const
|
48
|
-
|
49
|
-
const ca = decodedCookie.split(';');
|
50
|
-
for (let i = 0; i < ca.length; i++) {
|
51
|
-
let c = ca[i];
|
52
|
-
while (c.charAt(0) === ' ') {
|
53
|
-
c = c.substring(1);
|
54
|
-
}
|
55
|
-
if (c.indexOf(name) === 0) {
|
56
|
-
return c.substring(name.length, c.length);
|
57
|
-
}
|
58
|
-
}
|
59
|
-
return '';
|
48
|
+
const cookies = parseCookies(document.cookie);
|
49
|
+
return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
|
60
50
|
}
|
61
51
|
catch {
|
62
52
|
return '';
|
63
53
|
}
|
64
54
|
};
|
55
|
+
const parseCookies = (cookie) => {
|
56
|
+
return Object.fromEntries(cookie
|
57
|
+
.split(/;\s+/)
|
58
|
+
.map((r) => r.split('=').map((str) => str.trim()))
|
59
|
+
.map(([cookieKey, cookieValue]) => {
|
60
|
+
if (!cookieKey) {
|
61
|
+
return [];
|
62
|
+
}
|
63
|
+
let decodedValue = '';
|
64
|
+
if (cookieValue) {
|
65
|
+
try {
|
66
|
+
decodedValue = decodeURIComponent(cookieValue);
|
67
|
+
}
|
68
|
+
catch (e) {
|
69
|
+
console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
|
70
|
+
decodedValue = cookieValue;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
return [cookieKey, decodedValue];
|
74
|
+
}));
|
75
|
+
};
|
65
76
|
|
66
77
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
67
78
|
const createShopApi = (fetchOverride = window.fetch) => ({
|