@blotoutio/providers-blotout-wallet-sdk 0.62.0 → 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,143 +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, 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
- };
102
- const setCookie = (key, value, options) => {
103
- var _a;
104
- try {
105
- if (!document) {
106
- return;
107
- }
108
- const extras = [`path=${(_a = options === null || options === void 0 ? void 0 : options.path) !== null && _a !== void 0 ? _a : '/'}`];
109
- if (options === null || options === void 0 ? void 0 : options['maxAge']) {
110
- extras.push(`max-age=${options['maxAge']}`);
111
- }
112
- if (options === null || options === void 0 ? void 0 : options.expires) {
113
- extras.push(`expires=${options.expires}`);
114
- }
115
- if (options === null || options === void 0 ? void 0 : options.partitioned) {
116
- extras.push('partitioned');
117
- }
118
- if (options === null || options === void 0 ? void 0 : options.samesite) {
119
- extras.push(`samesite=${options.samesite}`);
120
- }
121
- if (options === null || options === void 0 ? void 0 : options.secure) {
122
- extras.push('secure');
123
- }
124
- document.cookie = `${key}=${value};${extras.join(';')}`;
125
- }
126
- catch {
127
- return;
128
- }
129
- };
114
+ var _a;
115
+ const registryKey = Symbol.for('blotout-wallet');
116
+ (_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
130
117
 
131
- const canLog = () => {
118
+ // eslint-disable-next-line @nx/enforce-module-boundaries
119
+ const getPreviewKey = () => {
120
+ let key = null;
132
121
  try {
133
- return localStorage.getItem('edgeTagDebug') === '1';
122
+ key = localStorage.getItem(PREVIEW_KEY_NAME) || null;
134
123
  }
135
124
  catch {
136
- return false;
125
+ /* do nothing */
137
126
  }
127
+ return key;
138
128
  };
139
- const logger = {
140
- log: (...args) => {
141
- if (canLog()) {
142
- console.log(...args);
143
- }
144
- },
145
- error: (...args) => {
146
- if (canLog()) {
147
- console.error(...args);
148
- }
149
- },
150
- info: (...args) => {
151
- if (canLog()) {
152
- console.info(...args);
153
- }
154
- },
155
- trace: (...args) => {
156
- if (canLog()) {
157
- console.trace(...args);
158
- }
159
- },
160
- table: (...args) => {
161
- if (canLog()) {
162
- console.table(...args);
163
- }
164
- },
165
- dir: (...args) => {
166
- if (canLog()) {
167
- console.dir(...args);
168
- }
169
- },
170
- };
171
-
172
- var _a;
173
- const registryKey = Symbol.for('blotout-wallet');
174
- (_a = window[registryKey]) !== null && _a !== void 0 ? _a : (window[registryKey] = {});
175
129
 
176
- // eslint-disable-next-line @nx/enforce-module-boundaries
177
- const tag = ({ eventName }) => {
130
+ const tag = () => {
131
+ const result = {
132
+ cartToken: null,
133
+ previewKey: getPreviewKey(),
134
+ };
178
135
  if (!window) {
179
- return;
136
+ return result;
180
137
  }
181
- const platform = window[registryKey].platform;
182
- switch (platform) {
183
- case 'SHOPIFY': {
184
- let cartToken = getCookieValue(cartTokenCookie);
185
- const cartTokenLink = getCookieValue(cartTokenLinkCookie);
186
- if (!cartToken) {
187
- cartToken = getCookieValue(cartTokenTwoCookie);
188
- }
189
- if (eventName === 'Purchase') {
190
- setCookie(cartTokenTwoCookie, cartToken, { path: '/', maxAge: 10 });
191
- }
192
- if (cartTokenLink) {
193
- setCookie(cartTokenLinkCookie, '', { maxAge: 0 });
194
- }
195
- return { cartToken, cartTokenLink };
196
- }
197
- default: {
198
- return {};
199
- }
138
+ const store = window[registryKey].storeAPI;
139
+ if (store) {
140
+ result.cartToken = store.getCartToken();
200
141
  }
142
+ return result;
201
143
  };
202
144
 
203
145
  /******************************************************************************
@@ -417,6 +359,111 @@ const flipIn = (element) => {
417
359
  return animation.finished;
418
360
  };
419
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
+
420
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">
421
468
  <g clip-path="url(#clip0_10367_379)">
422
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"/>
@@ -449,6 +496,7 @@ const circleCross = (attrs) => b `<svg class=${attrs === null || attrs === void
449
496
  <path d="M47.5332 12.334L51.2443 16.0451L15.5379 51.7515L11.8268 48.0404L47.5332 12.334Z" fill="currentColor"/>
450
497
  </svg>
451
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==`;
452
500
 
453
501
  /**
454
502
  * Sets the max-age for the dismissed popup cookie
@@ -473,7 +521,8 @@ let BlotoutWallet = class BlotoutWallet extends s {
473
521
  this.transitionTo = (newState) => {
474
522
  return flipOut(this.dialog)
475
523
  .then(() => (this.state = newState))
476
- .then(() => flipIn(this.dialog));
524
+ .then(() => flipIn(this.dialog))
525
+ .catch(logger.error);
477
526
  };
478
527
  this.restoreCart = async () => {
479
528
  if (!this.lastExpiredCart) {
@@ -499,8 +548,6 @@ let BlotoutWallet = class BlotoutWallet extends s {
499
548
  }
500
549
  await this.storeApi.addItems(this.lastExpiredCart.items);
501
550
  const expiredCartId = this.lastExpiredCart.cartId;
502
- // this cookie will be cleared once the next event is processed
503
- setCookie(cartTokenLinkCookie, expiredCartId, { path: '/' });
504
551
  // We attempt to mark the cart as restored, but if the request fails,
505
552
  // we log the error in the console and let the user continue. Since the
506
553
  // problem is probably in the `/cart/restore` endpoint, further attempts
@@ -633,7 +680,13 @@ let BlotoutWallet = class BlotoutWallet extends s {
633
680
  method: 'POST',
634
681
  headers: this.getHeaders(),
635
682
  body: JSON.stringify({ action: 'popupDismissed' }),
636
- }).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);
637
690
  }
638
691
  connectedCallback() {
639
692
  var _a;
@@ -701,7 +754,13 @@ let BlotoutWallet = class BlotoutWallet extends s {
701
754
  method: 'POST',
702
755
  headers: this.getHeaders(),
703
756
  body: JSON.stringify({ action: 'popupShown' }),
704
- }).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);
705
764
  }
706
765
  hideModal(action) {
707
766
  fadeOutToBottom(this.dialog)
@@ -721,8 +780,14 @@ let BlotoutWallet = class BlotoutWallet extends s {
721
780
  getUrl(path) {
722
781
  const url = new URL(`/providers/blotoutWallet${path}`, this.edgeURL);
723
782
  if (this.storeApi) {
724
- const { cartToken } = this.storeApi.getCartInfo();
725
- 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
+ }
726
791
  }
727
792
  return url;
728
793
  }
@@ -919,8 +984,25 @@ BlotoutWallet = __decorate([
919
984
  t$1('blotout-wallet')
920
985
  ], BlotoutWallet);
921
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);
922
996
  const init = (params) => {
923
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
+ }
924
1006
  if (
925
1007
  // if loaded in non-browser SDKs
926
1008
  !window ||
@@ -928,15 +1010,22 @@ const init = (params) => {
928
1010
  window.top !== window) {
929
1011
  return;
930
1012
  }
931
- let store = window[registryKey].storeAPI;
932
- if (!store) {
933
- store = window[registryKey].storeAPI =
934
- (_b = (_a = window[registryKey]).storeAPIFactory) === null || _b === void 0 ? void 0 : _b.call(_a);
935
- if (!store) {
936
- 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');
937
1026
  }
938
1027
  }
939
- if ((_c = params.manifest.variables) === null || _c === void 0 ? void 0 : _c['enabled']) {
1028
+ if (enabled || experiment.isEnabled) {
940
1029
  // if the component is already defined, skip creating the element to avoid
941
1030
  // layering multiple widgets
942
1031
  if (window[registryKey].wallet) {