swell-js 5.9.1 → 5.9.3

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/dist/api.mjs CHANGED
@@ -3,7 +3,7 @@ import { getCookie, setCookie } from './cookie.mjs';
3
3
  import methods$4 from './cache.mjs';
4
4
  import methods$3 from './cart.mjs';
5
5
  import methods$6 from './account.mjs';
6
- import { j as isFunction, l as loadScript, e as isObject, v as vaultRequest, k as isEmpty, d as defaultMethods, x as trimEnd, y as utils, z as trimStart, A as trimBoth, b as toSnake, o as base64Encode, i as isServer, t as toCamel } from './index.3949a230.mjs';
6
+ import { j as isFunction, l as loadScript, e as isObject, v as vaultRequest, k as isEmpty, d as defaultMethods, x as trimEnd, y as utils, z as trimStart, A as trimBoth, b as toSnake, o as base64Encode, i as isServer, t as toCamel } from './index.76eb52e5.mjs';
7
7
  import { Q as stringifyQuery } from './find.ba551a2e.mjs';
8
8
  import 'deepmerge';
9
9
  import 'fast-case';
@@ -15,7 +15,7 @@ import methods$b from './content.mjs';
15
15
  import methods$c from './settings.mjs';
16
16
  import PaymentController from './payment.mjs';
17
17
  import methods$d from './locale.mjs';
18
- import methods$e from './currency.mjs';
18
+ import methods$e, { isCurrencyCode } from './currency.mjs';
19
19
  import './round.c68b8be5.mjs';
20
20
 
21
21
  class AppComponent {
@@ -455,7 +455,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
455
455
  const api = {};
456
456
 
457
457
  Object.assign(api, {
458
- version: '5.9.1',
458
+ version: '5.9.3',
459
459
  options,
460
460
  request,
461
461
 
@@ -485,6 +485,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
485
485
  options.getCart = opt.getCart;
486
486
  options.updateCart = opt.updateCart;
487
487
  options.headers = opt.headers || {};
488
+ options.getCaptchaToken = opt.getCaptchaToken;
488
489
  },
489
490
 
490
491
  // Backward compatibility
@@ -571,8 +572,10 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
571
572
 
572
573
  const session = allOptions.session || allOptions.getCookie('swell-session');
573
574
  const locale = allOptions.locale || allOptions.getCookie('swell-locale');
575
+ const cookieCurrency = allOptions.getCookie('swell-currency');
574
576
  const currency =
575
- allOptions.currency || allOptions.getCookie('swell-currency');
577
+ allOptions.currency ||
578
+ (isCurrencyCode(cookieCurrency) ? cookieCurrency : undefined);
576
579
  const path = allOptions.path || '/api';
577
580
 
578
581
  const baseUrl = `${allOptions.url}${allOptions.base || ''}${path}`;
@@ -1,4 +1,4 @@
1
- import { d as defaultMethods } from './index.3949a230.mjs';
1
+ import { d as defaultMethods } from './index.76eb52e5.mjs';
2
2
  import './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
package/dist/cache.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { s as set, m as merge, t as toCamel, a as toCamelPath } from './index.3949a230.mjs';
1
+ import { s as set, m as merge, t as toCamel, a as toCamelPath } from './index.76eb52e5.mjs';
2
2
  import { g as get } from './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
package/dist/card.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { b as toSnake, v as vaultRequest } from './index.3949a230.mjs';
1
+ import { b as toSnake, v as vaultRequest } from './index.76eb52e5.mjs';
2
2
  import './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
package/dist/cart.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import './find.ba551a2e.mjs';
2
- import { c as cloneDeep } from './index.3949a230.mjs';
2
+ import { c as cloneDeep } from './index.76eb52e5.mjs';
3
3
  import 'deepmerge';
4
4
  import 'fast-case';
5
5
  import { cleanProductOptions } from './products.mjs';
@@ -1,4 +1,4 @@
1
- import { d as defaultMethods } from './index.3949a230.mjs';
1
+ import { d as defaultMethods } from './index.76eb52e5.mjs';
2
2
  import './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
package/dist/cookie.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as isServer } from './index.3949a230.mjs';
1
+ import { i as isServer } from './index.76eb52e5.mjs';
2
2
  import './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
package/dist/currency.mjs CHANGED
@@ -5,7 +5,30 @@ import 'fast-case';
5
5
 
6
6
  const FORMATTERS = {};
7
7
 
8
+ // A currency code is three letters. Anything else, such as a pending settings
9
+ // Promise that was stringified to "[object Promise]", is not a currency.
10
+ function isCurrencyCode(value) {
11
+ return typeof value === 'string' && /^[a-z]{3}$/i.test(value);
12
+ }
13
+
14
+ function defaultLocale() {
15
+ return typeof navigator === 'object' ? navigator.language : 'en-US';
16
+ }
17
+
8
18
  function methods(api, opt) {
19
+ // Reads a store setting without ever returning a Promise. Until settings
20
+ // load, this starts the request and reports `loaded: false`.
21
+ function readSetting(path, def) {
22
+ const value = opt.api.settings.get(path, def);
23
+
24
+ if (value && typeof value.then === 'function') {
25
+ value.catch(() => {}); // callers that await settings report the error
26
+ return { loaded: false, value: def };
27
+ }
28
+
29
+ return { loaded: true, value };
30
+ }
31
+
9
32
  return {
10
33
  code: null,
11
34
  state: null,
@@ -23,52 +46,72 @@ function methods(api, opt) {
23
46
 
24
47
  selected() {
25
48
  if (!this.code) {
26
- this.set(
27
- opt.getCookie('swell-currency') ||
28
- opt.api.settings.get('store.currency'),
29
- );
49
+ const cookieCode = opt.getCookie('swell-currency');
50
+
51
+ if (isCurrencyCode(cookieCode)) {
52
+ this.set(cookieCode);
53
+ } else {
54
+ const storeCode = readSetting('store.currency');
55
+
56
+ if (!storeCode.loaded) {
57
+ // Settings are still loading: use a stand-in without saving it,
58
+ // so the store currency is picked up once they arrive.
59
+ return 'USD';
60
+ }
61
+
62
+ this.set(isCurrencyCode(storeCode.value) ? storeCode.value : 'USD');
63
+ }
30
64
  }
31
65
 
32
66
  return this.code;
33
67
  },
34
68
 
35
69
  get() {
36
- if (!this.code) {
37
- this.code = this.selected();
70
+ const code = this.selected();
71
+
72
+ if (this.state) {
73
+ return this.state;
38
74
  }
39
- if (!this.state) {
40
- this.state = this.set(this.code);
75
+
76
+ if (!readSetting('store.currencies').loaded) {
77
+ // Not cached, so the currency's rate and decimals apply once
78
+ // settings load.
79
+ return { code };
41
80
  }
42
- return this.state;
81
+
82
+ return this.set(code);
43
83
  },
44
84
 
45
85
  set(code = 'USD') {
46
- this.code = code;
47
- this.state = find(this.list(), { code }) || { code };
86
+ if (!isCurrencyCode(code)) {
87
+ // Never store or persist something that isn't a currency code.
88
+ return this.state || { code: this.code || 'USD' };
89
+ }
48
90
 
49
- this.locale = String(
50
- opt.api.settings.get(
51
- 'store.locale',
52
- typeof navigator === 'object' ? navigator.language : 'en-US',
53
- ),
54
- );
91
+ const list = readSetting('store.currencies', []);
92
+ const state = (list.loaded && find(list.value, { code })) || { code };
93
+
94
+ this.code = code;
95
+ // Only cache a state built from the loaded currency list.
96
+ this.state = list.loaded ? state : null;
97
+ this.locale = String(readSetting('store.locale', defaultLocale()).value);
55
98
 
56
99
  opt.setCookie('swell-currency', code);
57
100
 
58
- return this.state;
101
+ return state;
59
102
  },
60
103
 
61
104
  format(amount, params = {}) {
62
105
  let state = this.get();
63
106
  if (params.code && params.code !== state.code) {
64
- const list = this.list();
107
+ const list = readSetting('store.currencies', []).value;
65
108
  state = find(list, { code: params.code }) || { code: params.code };
66
109
  }
67
110
 
68
111
  const { code = 'USD', type, decimals, rate } = state;
69
112
  const formatCode = params.code || code;
70
113
  const formatRate = params.rate || rate;
71
- const formatLocale = params.locale || this.locale;
114
+ const formatLocale = params.locale || this.locale || defaultLocale();
72
115
  const formatDecimals = 'decimals' in params ? params.decimals : decimals;
73
116
  const { convert = true } = params;
74
117
 
@@ -193,4 +236,4 @@ function methods(api, opt) {
193
236
  };
194
237
  }
195
238
 
196
- export { methods as default };
239
+ export { methods as default, isCurrencyCode };
@@ -1586,8 +1586,36 @@ function defaultMethods(api, uri, methods) {
1586
1586
  };
1587
1587
  }
1588
1588
 
1589
+ function isCreateIntentRequest(method, url) {
1590
+ if (String(method).toLowerCase() !== 'post') {
1591
+ return false;
1592
+ }
1593
+
1594
+ return trimEnd(trimStart(url)) === 'intent';
1595
+ }
1596
+
1597
+ // Attach a captcha token to create-intent requests. The host supplies it via
1598
+ // the getCaptchaToken option and owns the widget and token lifecycle; here we
1599
+ // only forward it, so every intent-based payment method is covered. A rejection
1600
+ // from the host (timeout / failed challenge) propagates and aborts the request.
1601
+ async function addCaptchaToken(method, url, data, options) {
1602
+ if (
1603
+ typeof options.getCaptchaToken !== 'function' ||
1604
+ !isCreateIntentRequest(method, url)
1605
+ ) {
1606
+ return data;
1607
+ }
1608
+
1609
+ const token = await options.getCaptchaToken();
1610
+
1611
+ return token ? { ...data, captcha_token: token } : data;
1612
+ }
1613
+
1589
1614
  async function vaultRequest(method, url, data, options) {
1590
1615
  const { vaultUrl, timeout, key } = options;
1616
+
1617
+ data = await addCaptchaToken(method, url, data, options);
1618
+
1591
1619
  const requestData = {
1592
1620
  $jsonp: {
1593
1621
  method,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  export { default } from './api.mjs';
2
2
  import './card.mjs';
3
- import './index.3949a230.mjs';
3
+ import './index.76eb52e5.mjs';
4
4
  import './find.ba551a2e.mjs';
5
5
  import './round.c68b8be5.mjs';
6
6
  import 'deepmerge';
package/dist/payment.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import methods from './cart.mjs';
2
2
  import methods$1 from './settings.mjs';
3
- import { e as isObject, j as isFunction, l as loadScript, c as cloneDeep, v as vaultRequest, b as toSnake, p as pick, k as isEmpty, n as isLiveMode, o as base64Encode, q as getLocationParams, w as removeUrlParams, t as toCamel } from './index.3949a230.mjs';
3
+ import { e as isObject, j as isFunction, l as loadScript, c as cloneDeep, v as vaultRequest, b as toSnake, p as pick, k as isEmpty, n as isLiveMode, o as base64Encode, q as getLocationParams, w as removeUrlParams, t as toCamel } from './index.76eb52e5.mjs';
4
4
  import { g as get } from './find.ba551a2e.mjs';
5
5
  import 'deepmerge';
6
6
  import 'fast-case';
package/dist/products.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { d as defaultMethods, r as reduce, b as toSnake, t as toCamel, g as snakeCase, u as uniq, h as isEqual } from './index.3949a230.mjs';
1
+ import { d as defaultMethods, r as reduce, b as toSnake, t as toCamel, g as snakeCase, u as uniq, h as isEqual } from './index.76eb52e5.mjs';
2
2
  import methods$1 from './attributes.mjs';
3
3
  import { g as get, f as find } from './find.ba551a2e.mjs';
4
4
  import './round.c68b8be5.mjs';
package/dist/settings.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { s as set, t as toCamel, m as merge, c as cloneDeep, e as isObject, f as camelCase } from './index.3949a230.mjs';
1
+ import { s as set, t as toCamel, m as merge, c as cloneDeep, e as isObject, f as camelCase } from './index.76eb52e5.mjs';
2
2
  import { g as get, f as find } from './find.ba551a2e.mjs';
3
3
  import './round.c68b8be5.mjs';
4
4
  import 'deepmerge';
@@ -1,5 +1,5 @@
1
1
  import { cleanProductOptions } from './products.mjs';
2
- import { d as defaultMethods } from './index.3949a230.mjs';
2
+ import { d as defaultMethods } from './index.76eb52e5.mjs';
3
3
  import './attributes.mjs';
4
4
  import './find.ba551a2e.mjs';
5
5
  import './round.c68b8be5.mjs';
package/dist/swell.cjs CHANGED
@@ -4726,8 +4726,36 @@ function defaultMethods(api, uri, methods) {
4726
4726
  };
4727
4727
  }
4728
4728
 
4729
+ function isCreateIntentRequest(method, url) {
4730
+ if (String(method).toLowerCase() !== 'post') {
4731
+ return false;
4732
+ }
4733
+
4734
+ return trimEnd(trimStart(url)) === 'intent';
4735
+ }
4736
+
4737
+ // Attach a captcha token to create-intent requests. The host supplies it via
4738
+ // the getCaptchaToken option and owns the widget and token lifecycle; here we
4739
+ // only forward it, so every intent-based payment method is covered. A rejection
4740
+ // from the host (timeout / failed challenge) propagates and aborts the request.
4741
+ async function addCaptchaToken(method, url, data, options) {
4742
+ if (
4743
+ typeof options.getCaptchaToken !== 'function' ||
4744
+ !isCreateIntentRequest(method, url)
4745
+ ) {
4746
+ return data;
4747
+ }
4748
+
4749
+ const token = await options.getCaptchaToken();
4750
+
4751
+ return token ? { ...data, captcha_token: token } : data;
4752
+ }
4753
+
4729
4754
  async function vaultRequest(method, url, data, options) {
4730
4755
  const { vaultUrl, timeout, key } = options;
4756
+
4757
+ data = await addCaptchaToken(method, url, data, options);
4758
+
4731
4759
  const requestData = {
4732
4760
  $jsonp: {
4733
4761
  method,
@@ -13037,7 +13065,30 @@ function methods$2(api, opt) {
13037
13065
 
13038
13066
  const FORMATTERS = {};
13039
13067
 
13068
+ // A currency code is three letters. Anything else, such as a pending settings
13069
+ // Promise that was stringified to "[object Promise]", is not a currency.
13070
+ function isCurrencyCode(value) {
13071
+ return typeof value === 'string' && /^[a-z]{3}$/i.test(value);
13072
+ }
13073
+
13074
+ function defaultLocale() {
13075
+ return typeof navigator === 'object' ? navigator.language : 'en-US';
13076
+ }
13077
+
13040
13078
  function methods$1(api, opt) {
13079
+ // Reads a store setting without ever returning a Promise. Until settings
13080
+ // load, this starts the request and reports `loaded: false`.
13081
+ function readSetting(path, def) {
13082
+ const value = opt.api.settings.get(path, def);
13083
+
13084
+ if (value && typeof value.then === 'function') {
13085
+ value.catch(() => {}); // callers that await settings report the error
13086
+ return { loaded: false, value: def };
13087
+ }
13088
+
13089
+ return { loaded: true, value };
13090
+ }
13091
+
13041
13092
  return {
13042
13093
  code: null,
13043
13094
  state: null,
@@ -13055,52 +13106,72 @@ function methods$1(api, opt) {
13055
13106
 
13056
13107
  selected() {
13057
13108
  if (!this.code) {
13058
- this.set(
13059
- opt.getCookie('swell-currency') ||
13060
- opt.api.settings.get('store.currency'),
13061
- );
13109
+ const cookieCode = opt.getCookie('swell-currency');
13110
+
13111
+ if (isCurrencyCode(cookieCode)) {
13112
+ this.set(cookieCode);
13113
+ } else {
13114
+ const storeCode = readSetting('store.currency');
13115
+
13116
+ if (!storeCode.loaded) {
13117
+ // Settings are still loading: use a stand-in without saving it,
13118
+ // so the store currency is picked up once they arrive.
13119
+ return 'USD';
13120
+ }
13121
+
13122
+ this.set(isCurrencyCode(storeCode.value) ? storeCode.value : 'USD');
13123
+ }
13062
13124
  }
13063
13125
 
13064
13126
  return this.code;
13065
13127
  },
13066
13128
 
13067
13129
  get() {
13068
- if (!this.code) {
13069
- this.code = this.selected();
13130
+ const code = this.selected();
13131
+
13132
+ if (this.state) {
13133
+ return this.state;
13070
13134
  }
13071
- if (!this.state) {
13072
- this.state = this.set(this.code);
13135
+
13136
+ if (!readSetting('store.currencies').loaded) {
13137
+ // Not cached, so the currency's rate and decimals apply once
13138
+ // settings load.
13139
+ return { code };
13073
13140
  }
13074
- return this.state;
13141
+
13142
+ return this.set(code);
13075
13143
  },
13076
13144
 
13077
13145
  set(code = 'USD') {
13078
- this.code = code;
13079
- this.state = find$1(this.list(), { code }) || { code };
13146
+ if (!isCurrencyCode(code)) {
13147
+ // Never store or persist something that isn't a currency code.
13148
+ return this.state || { code: this.code || 'USD' };
13149
+ }
13080
13150
 
13081
- this.locale = String(
13082
- opt.api.settings.get(
13083
- 'store.locale',
13084
- typeof navigator === 'object' ? navigator.language : 'en-US',
13085
- ),
13086
- );
13151
+ const list = readSetting('store.currencies', []);
13152
+ const state = (list.loaded && find$1(list.value, { code })) || { code };
13153
+
13154
+ this.code = code;
13155
+ // Only cache a state built from the loaded currency list.
13156
+ this.state = list.loaded ? state : null;
13157
+ this.locale = String(readSetting('store.locale', defaultLocale()).value);
13087
13158
 
13088
13159
  opt.setCookie('swell-currency', code);
13089
13160
 
13090
- return this.state;
13161
+ return state;
13091
13162
  },
13092
13163
 
13093
13164
  format(amount, params = {}) {
13094
13165
  let state = this.get();
13095
13166
  if (params.code && params.code !== state.code) {
13096
- const list = this.list();
13167
+ const list = readSetting('store.currencies', []).value;
13097
13168
  state = find$1(list, { code: params.code }) || { code: params.code };
13098
13169
  }
13099
13170
 
13100
13171
  const { code = 'USD', type, decimals, rate } = state;
13101
13172
  const formatCode = params.code || code;
13102
13173
  const formatRate = params.rate || rate;
13103
- const formatLocale = params.locale || this.locale;
13174
+ const formatLocale = params.locale || this.locale || defaultLocale();
13104
13175
  const formatDecimals = 'decimals' in params ? params.decimals : decimals;
13105
13176
  const { convert = true } = params;
13106
13177
 
@@ -13325,7 +13396,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
13325
13396
  const api = {};
13326
13397
 
13327
13398
  Object.assign(api, {
13328
- version: '5.9.1',
13399
+ version: '5.9.3',
13329
13400
  options,
13330
13401
  request,
13331
13402
 
@@ -13355,6 +13426,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
13355
13426
  options.getCart = opt.getCart;
13356
13427
  options.updateCart = opt.updateCart;
13357
13428
  options.headers = opt.headers || {};
13429
+ options.getCaptchaToken = opt.getCaptchaToken;
13358
13430
  },
13359
13431
 
13360
13432
  // Backward compatibility
@@ -13441,8 +13513,10 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
13441
13513
 
13442
13514
  const session = allOptions.session || allOptions.getCookie('swell-session');
13443
13515
  const locale = allOptions.locale || allOptions.getCookie('swell-locale');
13516
+ const cookieCurrency = allOptions.getCookie('swell-currency');
13444
13517
  const currency =
13445
- allOptions.currency || allOptions.getCookie('swell-currency');
13518
+ allOptions.currency ||
13519
+ (isCurrencyCode(cookieCurrency) ? cookieCurrency : undefined);
13446
13520
  const path = allOptions.path || '/api';
13447
13521
 
13448
13522
  const baseUrl = `${allOptions.url}${allOptions.base || ''}${path}`;