@blotoutio/providers-blotout-wallet-sdk 0.62.1 → 0.63.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 CHANGED
@@ -36,6 +36,54 @@ new Set([
36
36
 
37
37
  const delay = (n, resolvedValue) => new Promise((resolve) => setTimeout(() => resolve(resolvedValue), n));
38
38
 
39
+ const createEnabled = () => ({
40
+ name: 'enabled',
41
+ groupNames: new Set(),
42
+ segment: 0,
43
+ groupName: '',
44
+ isEnabled: true,
45
+ });
46
+ const createDisabled = () => ({
47
+ name: 'disabled',
48
+ groupNames: new Set(),
49
+ segment: 0,
50
+ groupName: '',
51
+ isEnabled: false,
52
+ });
53
+ const createABTest = ({ userId }) => {
54
+ const [sample] = userId.split('-');
55
+ const segment = parseInt(sample, 16) % 2;
56
+ return {
57
+ name: 'ab-test',
58
+ groupNames: new Set(['enabled', 'control']),
59
+ segment,
60
+ groupName: segment == 1 ? 'enabled' : 'control',
61
+ isEnabled: segment == 1,
62
+ };
63
+ };
64
+ const createPreview = ({ previewKey, userPreviewKey }) => {
65
+ const isEnabled = !!(previewKey && previewKey === userPreviewKey);
66
+ return {
67
+ name: 'preview',
68
+ groupNames: new Set(['preview']),
69
+ groupName: isEnabled ? 'preview' : '',
70
+ segment: isEnabled ? 1 : 0,
71
+ isEnabled,
72
+ };
73
+ };
74
+ const createExperiment = (props) => {
75
+ switch (props.name) {
76
+ case 'enabled':
77
+ return createEnabled();
78
+ case 'disabled':
79
+ return createDisabled();
80
+ case 'ab-test':
81
+ return createABTest(props);
82
+ case 'preview':
83
+ return createPreview(props);
84
+ }
85
+ };
86
+
39
87
  const customAttributes = {
40
88
  '--bw-primary': { type: 'color', defaultValue: '#000000' },
41
89
  '--bw-title-color': { type: 'color', defaultValue: '#000000' },
@@ -61,144 +109,37 @@ const customAttributes = {
61
109
  };
62
110
 
63
111
  const packageName = 'blotoutWallet';
64
- const cartTokenCookie = 'cart';
65
- const cartTokenTwoCookie = 'cart2';
66
- const cartTokenLinkCookie = 'bwCartLinkToken';
112
+ const PREVIEW_KEY_NAME = '_blotoutWalletPreview';
67
113
 
68
- const getCookieValue = (key) => {
69
- var _a;
70
- try {
71
- if (!document || !document.cookie) {
72
- return '';
73
- }
74
- const cookies = parseCookies(document.cookie);
75
- return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
76
- }
77
- catch {
78
- return '';
79
- }
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, ...cookieValues]) => {
86
- const cookieValue = cookieValues.join('=');
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
- };
103
- const setCookie = (key, value, options) => {
104
- var _a;
105
- try {
106
- if (!document) {
107
- return;
108
- }
109
- const extras = [`path=${(_a = options === null || options === void 0 ? void 0 : options.path) !== null && _a !== void 0 ? _a : '/'}`];
110
- if (options === null || options === void 0 ? void 0 : options['maxAge']) {
111
- extras.push(`max-age=${options['maxAge']}`);
112
- }
113
- if (options === null || options === void 0 ? void 0 : options.expires) {
114
- extras.push(`expires=${options.expires}`);
115
- }
116
- if (options === null || options === void 0 ? void 0 : options.partitioned) {
117
- extras.push('partitioned');
118
- }
119
- if (options === null || options === void 0 ? void 0 : options.samesite) {
120
- extras.push(`samesite=${options.samesite}`);
121
- }
122
- if (options === null || options === void 0 ? void 0 : options.secure) {
123
- extras.push('secure');
124
- }
125
- document.cookie = `${key}=${encodeURIComponent(value)};${extras.join(';')}`;
126
- }
127
- catch {
128
- return;
129
- }
130
- };
114
+ var _a;
115
+ const registryKey = Symbol.for('blotout-wallet');
116
+ (_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
131
117
 
132
- const canLog = () => {
118
+ // eslint-disable-next-line @nx/enforce-module-boundaries
119
+ const getPreviewKey = () => {
120
+ let key = null;
133
121
  try {
134
- return localStorage.getItem('edgeTagDebug') === '1';
122
+ key = localStorage.getItem(PREVIEW_KEY_NAME) || null;
135
123
  }
136
124
  catch {
137
- return false;
125
+ /* do nothing */
138
126
  }
127
+ return key;
139
128
  };
140
- const logger = {
141
- log: (...args) => {
142
- if (canLog()) {
143
- console.log(...args);
144
- }
145
- },
146
- error: (...args) => {
147
- if (canLog()) {
148
- console.error(...args);
149
- }
150
- },
151
- info: (...args) => {
152
- if (canLog()) {
153
- console.info(...args);
154
- }
155
- },
156
- trace: (...args) => {
157
- if (canLog()) {
158
- console.trace(...args);
159
- }
160
- },
161
- table: (...args) => {
162
- if (canLog()) {
163
- console.table(...args);
164
- }
165
- },
166
- dir: (...args) => {
167
- if (canLog()) {
168
- console.dir(...args);
169
- }
170
- },
171
- };
172
-
173
- var _a;
174
- const registryKey = Symbol.for('blotout-wallet');
175
- (_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
176
129
 
177
- // eslint-disable-next-line @nx/enforce-module-boundaries
178
- const tag = ({ eventName }) => {
130
+ const tag = () => {
131
+ const result = {
132
+ cartToken: null,
133
+ previewKey: getPreviewKey(),
134
+ };
179
135
  if (!window) {
180
- return;
136
+ return result;
181
137
  }
182
- const platform = window[registryKey].platform;
183
- switch (platform) {
184
- case 'SHOPIFY': {
185
- let cartToken = getCookieValue(cartTokenCookie);
186
- const cartTokenLink = getCookieValue(cartTokenLinkCookie);
187
- if (!cartToken) {
188
- cartToken = getCookieValue(cartTokenTwoCookie);
189
- }
190
- if (eventName === 'Purchase') {
191
- setCookie(cartTokenTwoCookie, cartToken, { path: '/', maxAge: 10 });
192
- }
193
- if (cartTokenLink) {
194
- setCookie(cartTokenLinkCookie, '', { maxAge: 0 });
195
- }
196
- return { cartToken, cartTokenLink };
197
- }
198
- default: {
199
- return {};
200
- }
138
+ const store = window[registryKey].storeAPI;
139
+ if (store) {
140
+ result.cartToken = store.getCartToken();
201
141
  }
142
+ return result;
202
143
  };
203
144
 
204
145
  /******************************************************************************
@@ -418,6 +359,111 @@ const flipIn = (element) => {
418
359
  return animation.finished;
419
360
  };
420
361
 
362
+ const getCookieValue = (key) => {
363
+ var _a;
364
+ try {
365
+ if (!document || !document.cookie) {
366
+ return '';
367
+ }
368
+ const cookies = parseCookies(document.cookie);
369
+ return (_a = cookies[key]) !== null && _a !== void 0 ? _a : '';
370
+ }
371
+ catch {
372
+ return '';
373
+ }
374
+ };
375
+ const parseCookies = (cookie) => {
376
+ return Object.fromEntries(cookie
377
+ .split(/;\s+/)
378
+ .map((r) => r.split('=').map((str) => str.trim()))
379
+ .map(([cookieKey, ...cookieValues]) => {
380
+ const cookieValue = cookieValues.join('=');
381
+ if (!cookieKey) {
382
+ return [];
383
+ }
384
+ let decodedValue = '';
385
+ if (cookieValue) {
386
+ try {
387
+ decodedValue = decodeURIComponent(cookieValue);
388
+ }
389
+ catch (e) {
390
+ console.log(`Unable to decode cookie ${cookieKey}: ${e}`);
391
+ decodedValue = cookieValue;
392
+ }
393
+ }
394
+ return [cookieKey, decodedValue];
395
+ }));
396
+ };
397
+ const setCookie = (key, value, options) => {
398
+ var _a;
399
+ try {
400
+ if (!document) {
401
+ return;
402
+ }
403
+ const extras = [`path=${(_a = options === null || options === void 0 ? void 0 : options.path) !== null && _a !== void 0 ? _a : '/'}`];
404
+ if (options === null || options === void 0 ? void 0 : options['maxAge']) {
405
+ extras.push(`max-age=${options['maxAge']}`);
406
+ }
407
+ if (options === null || options === void 0 ? void 0 : options.expires) {
408
+ extras.push(`expires=${options.expires}`);
409
+ }
410
+ if (options === null || options === void 0 ? void 0 : options.partitioned) {
411
+ extras.push('partitioned');
412
+ }
413
+ if (options === null || options === void 0 ? void 0 : options.samesite) {
414
+ extras.push(`samesite=${options.samesite}`);
415
+ }
416
+ if (options === null || options === void 0 ? void 0 : options.secure) {
417
+ extras.push('secure');
418
+ }
419
+ document.cookie = `${key}=${encodeURIComponent(value)};${extras.join(';')}`;
420
+ }
421
+ catch {
422
+ return;
423
+ }
424
+ };
425
+
426
+ const canLog = () => {
427
+ try {
428
+ return localStorage.getItem('edgeTagDebug') === '1';
429
+ }
430
+ catch {
431
+ return false;
432
+ }
433
+ };
434
+ const logger = {
435
+ log: (...args) => {
436
+ if (canLog()) {
437
+ console.log(...args);
438
+ }
439
+ },
440
+ error: (...args) => {
441
+ if (canLog()) {
442
+ console.error(...args);
443
+ }
444
+ },
445
+ info: (...args) => {
446
+ if (canLog()) {
447
+ console.info(...args);
448
+ }
449
+ },
450
+ trace: (...args) => {
451
+ if (canLog()) {
452
+ console.trace(...args);
453
+ }
454
+ },
455
+ table: (...args) => {
456
+ if (canLog()) {
457
+ console.table(...args);
458
+ }
459
+ },
460
+ dir: (...args) => {
461
+ if (canLog()) {
462
+ console.dir(...args);
463
+ }
464
+ },
465
+ };
466
+
421
467
  const cart = (attrs) => b `<svg class=${attrs === null || attrs === void 0 ? void 0 : attrs.class} style=${attrs === null || attrs === void 0 ? void 0 : attrs.style} width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
422
468
  <g clip-path="url(#clip0_10367_379)">
423
469
  <path d="M20 60C22.2091 60 24 58.2091 24 56C24 53.7909 22.2091 52 20 52C17.7909 52 16 53.7909 16 56C16 58.2091 17.7909 60 20 60Z" fill="currentColor"/>
@@ -450,6 +496,7 @@ const circleCross = (attrs) => b `<svg class=${attrs === null || attrs === void
450
496
  <path d="M47.5332 12.334L51.2443 16.0451L15.5379 51.7515L11.8268 48.0404L47.5332 12.334Z" fill="currentColor"/>
451
497
  </svg>
452
498
  `;
499
+ const logoImage = `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAgCAYAAABU1PscAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEt0lEQVRYhdWYX4hUdRTHP+d358+6azNGqUVqilrQXaNIClKSQHsQpJceSu4IBSFIvQRWLwWW9dBD0IMYvUTNSAUGGVRYGLFQQU8aO2VhhVpBlOHcdXd2Z+b+vj3MrG6z7c7OpO32hTt/DjO/+/2ec37nnPszgJEoXCvYB2w3WCIwFi5+B44AB3Kl8nEbKYTrJT4ZSLlV1cSb13zzmx2BGWlneGmo5rUvJfH8QMqtGm34hez1i0gkvBeIzUDkgO3V5P9BfhISYDgzdqQMFrenjQGZwDAgEdQXYF5J4IxrXTs1ZyCojHs9UU30QN3rlZSzsXlh2QFe4NqNzgzgvEnFfKn8ruCoQW2h5tg0AS0YWF8lCg3I/JeEukVqvgmYzezFuWBeBQRmeClJoAokvawxbwICMzz6WbAf7BhQp4cJYE4CDEg7I3CGJERzs0ui7kXSQ5UNHJjsq4b0ea40fKr7FZqYi4Ag5Yxqw39X8zoKHBfEhpYCdwPbsoEtq3k5dSNEgPCtT8RRuBK4AUhP2i6PAOOPsYbfCxwWVsmXhqcu/mqlEK6ZSLQ37WxnIuV9FxraUMg4e9wZ1xmGEA0vGppdTEcB+WJ5CBia/D5S2JAWygJjueKwzxfLPwF74ig8lQnsqbrXsq4icQlBzavevJd+aHG73ZndhJSZack5b+KRaPB6occkfx+wBPgljsJDwDu5UjnOlcovx1G4OhvYrrpXvofpw4DXgTdypfKPAHEUbnLGCx62zOSUOZXgkcLgeqEjAyn3ZNbZxrSzdX2B25IN7DVnvBRH4XIAwcGJRKfpIofb0P6/oFOb6BiB8d0brTZafbE/5W4da/jU5B3qCGcQmO0GfR1HYSlXKn8bR+GXKbPVDZTrMgoCHgG2xlF4BgiADYlYyyxPWB0F1MaqG4B7qonPtvPxgowzEmkH8AEQA8PO7AJSriv6kGScpZ2xCdgkoOFFIolZItp5D8hWpB2ZxgzuTCQkVgDZlumcGY0uyQMUa16fctnLKDqfNOv1P8IZmBFLF0kvphn+2WGt1xbVXKl8Fjjbmc/fMYc+YCe89H0msI31RKl21zgMB8c8qrRM673U32nZxINHdwKb4yic4EqNErni8Ggchc/VEhWzgV1T92o9DRl9gTGe+C8ScUimP+PC4FKku+qeqzr1gkQiMFvp0QH9i2FuTmU0Vyp/hLFzItGQF+MtAiOjDf9WIh4WnMoXvxFSIRvYzTA9UjOJwAgCY3Fg5Hu55tzIcsXyx5Vdt3xm3tYLloD9CpzNlYYbACOFwa2S9tS9lndTPqUeXd/CTAIEjOdLZVUK4ToTi4CTuTfLNaA89Yf+0dvsQrX+kKT9zuxG9ThH9AqLo9AzZfM4Ay8qwNPAGWAbUADea10nMRszKS+4A3gw7exeSf2Jem/BPQsYiULf3ugMSLmmSYAk0s5R955EjNGsGH2ZwDImrOY7jIxXCM6MlCB2xt+GL9E8CzIueTRJPAY4o3/SXuvlSeYywQyEzjngw0XBtOMhYHo6iOb4kKj5Pl+wpge9xGEn7NnRhj89kHJyC/XwZwoCM7LOkXY2BLxtAJUoXGPwDHC/wdUL8Xi9lbYe+A14HziYK5VP/AXU+TX099lFgwAAAABJRU5ErkJggg==`;
453
500
 
454
501
  /**
455
502
  * Sets the max-age for the dismissed popup cookie
@@ -474,7 +521,8 @@ let BlotoutWallet = class BlotoutWallet extends s {
474
521
  this.transitionTo = (newState) => {
475
522
  return flipOut(this.dialog)
476
523
  .then(() => (this.state = newState))
477
- .then(() => flipIn(this.dialog));
524
+ .then(() => flipIn(this.dialog))
525
+ .catch(logger.error);
478
526
  };
479
527
  this.restoreCart = async () => {
480
528
  if (!this.lastExpiredCart) {
@@ -500,8 +548,6 @@ let BlotoutWallet = class BlotoutWallet extends s {
500
548
  }
501
549
  await this.storeApi.addItems(this.lastExpiredCart.items);
502
550
  const expiredCartId = this.lastExpiredCart.cartId;
503
- // this cookie will be cleared once the next event is processed
504
- setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
505
551
  // We attempt to mark the cart as restored, but if the request fails,
506
552
  // we log the error in the console and let the user continue. Since the
507
553
  // problem is probably in the `/cart/restore` endpoint, further attempts
@@ -634,7 +680,13 @@ let BlotoutWallet = class BlotoutWallet extends s {
634
680
  method: 'POST',
635
681
  headers: this.getHeaders(),
636
682
  body: JSON.stringify({ action: 'popupDismissed' }),
637
- }).catch(logger.error);
683
+ })
684
+ .then(async (response) => {
685
+ if (!response.ok) {
686
+ throw new Error(`Error while recording user event - ${response.status}: ${response.statusText}\n\n${await response.text()}`);
687
+ }
688
+ })
689
+ .catch(logger.error);
638
690
  }
639
691
  connectedCallback() {
640
692
  var _a;
@@ -702,7 +754,13 @@ let BlotoutWallet = class BlotoutWallet extends s {
702
754
  method: 'POST',
703
755
  headers: this.getHeaders(),
704
756
  body: JSON.stringify({ action: 'popupShown' }),
705
- }).catch(logger.error);
757
+ })
758
+ .then(async (response) => {
759
+ if (!response.ok) {
760
+ throw new Error(`Error while recording user event - ${response.status}: ${response.statusText}\n\n${await response.text()}`);
761
+ }
762
+ })
763
+ .catch(logger.error);
706
764
  }
707
765
  hideModal(action) {
708
766
  fadeOutToBottom(this.dialog)
@@ -722,8 +780,14 @@ let BlotoutWallet = class BlotoutWallet extends s {
722
780
  getUrl(path) {
723
781
  const url = new URL(`/providers/blotoutWallet${path}`, this.edgeURL);
724
782
  if (this.storeApi) {
725
- const { cartToken } = this.storeApi.getCartInfo();
726
- url.searchParams.set('t', cartToken);
783
+ const cartToken = this.storeApi.getCartToken();
784
+ if (cartToken) {
785
+ url.searchParams.set('t', cartToken);
786
+ }
787
+ const previewKey = getPreviewKey();
788
+ if (previewKey) {
789
+ url.searchParams.set('pk', previewKey);
790
+ }
727
791
  }
728
792
  return url;
729
793
  }
@@ -920,8 +984,25 @@ BlotoutWallet = __decorate([
920
984
  t$1('blotout-wallet')
921
985
  ], BlotoutWallet);
922
986
 
987
+ const logStyles = `
988
+ padding: 4px 8px 4px 36px;
989
+ border: 1px dashed red;
990
+ border-radius: 3px;
991
+ font-weight: bold;
992
+ background: url(${logoImage}) 8px 50% no-repeat;
993
+ background-size: 24px 16px;
994
+ `;
995
+ const log = (message) => console.log(`%c${message}`, logStyles);
923
996
  const init = (params) => {
924
997
  var _a, _b, _c, _d, _e, _f;
998
+ let store = window[registryKey].storeAPI;
999
+ if (!store) {
1000
+ store = window[registryKey].storeAPI =
1001
+ (_b = (_a = window[registryKey]).storeAPIFactory) === null || _b === void 0 ? void 0 : _b.call(_a);
1002
+ }
1003
+ if (!store) {
1004
+ throw new Error('Implementation for store API missing!');
1005
+ }
925
1006
  if (
926
1007
  // if loaded in non-browser SDKs
927
1008
  !window ||
@@ -929,15 +1010,22 @@ const init = (params) => {
929
1010
  window.top !== window) {
930
1011
  return;
931
1012
  }
932
- let store = window[registryKey].storeAPI;
933
- if (!store) {
934
- store = window[registryKey].storeAPI =
935
- (_b = (_a = window[registryKey]).storeAPIFactory) === null || _b === void 0 ? void 0 : _b.call(_a);
936
- if (!store) {
937
- throw new Error('Implementation for store API missing!');
1013
+ const { enabled, previewKey, mode = 'disabled', } = (_c = params.manifest.variables) !== null && _c !== void 0 ? _c : {};
1014
+ const experiment = createExperiment({
1015
+ name: mode,
1016
+ userId: params.userId,
1017
+ previewKey,
1018
+ userPreviewKey: getPreviewKey(),
1019
+ });
1020
+ if (experiment.name == 'preview') {
1021
+ if (experiment.isEnabled) {
1022
+ log('Previewing functionality using preview key');
1023
+ }
1024
+ else {
1025
+ log('Preview key set but does not match the configured key');
938
1026
  }
939
1027
  }
940
- if ((_c = params.manifest.variables) === null || _c === void 0 ? void 0 : _c['enabled']) {
1028
+ if (enabled || experiment.isEnabled) {
941
1029
  // if the component is already defined, skip creating the element to avoid
942
1030
  // layering multiple widgets
943
1031
  if (window[registryKey].wallet) {