swell-js 5.9.2 → 5.9.4

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.
@@ -4871,8 +4871,36 @@
4871
4871
  };
4872
4872
  }
4873
4873
 
4874
+ function isCreateIntentRequest(method, url) {
4875
+ if (String(method).toLowerCase() !== 'post') {
4876
+ return false;
4877
+ }
4878
+
4879
+ return trimEnd(trimStart(url)) === 'intent';
4880
+ }
4881
+
4882
+ // Attach a captcha token to create-intent requests. The host supplies it via
4883
+ // the getCaptchaToken option and owns the widget and token lifecycle; here we
4884
+ // only forward it, so every intent-based payment method is covered. A rejection
4885
+ // from the host (timeout / failed challenge) propagates and aborts the request.
4886
+ async function addCaptchaToken(method, url, data, options) {
4887
+ if (
4888
+ typeof options.getCaptchaToken !== 'function' ||
4889
+ !isCreateIntentRequest(method, url)
4890
+ ) {
4891
+ return data;
4892
+ }
4893
+
4894
+ const token = await options.getCaptchaToken();
4895
+
4896
+ return token ? { ...data, captcha_token: token } : data;
4897
+ }
4898
+
4874
4899
  async function vaultRequest(method, url, data, options) {
4875
4900
  const { vaultUrl, timeout, key } = options;
4901
+
4902
+ data = await addCaptchaToken(method, url, data, options);
4903
+
4876
4904
  const requestData = {
4877
4905
  $jsonp: {
4878
4906
  method,
@@ -5083,7 +5111,7 @@
5083
5111
  vaultRequest: vaultRequest
5084
5112
  });
5085
5113
 
5086
- function methods$e(options) {
5114
+ function methods$f(options) {
5087
5115
  return {
5088
5116
  async createToken(data) {
5089
5117
  let error = null;
@@ -5300,7 +5328,7 @@
5300
5328
 
5301
5329
  const RECORD_TIMEOUT = 5000;
5302
5330
 
5303
- function methods$d(opt) {
5331
+ function methods$e(opt) {
5304
5332
  let VALUES = {
5305
5333
  /*
5306
5334
  [model]: {
@@ -5462,7 +5490,7 @@
5462
5490
  };
5463
5491
  }
5464
5492
 
5465
- function methods$c(api) {
5493
+ function methods$d(api) {
5466
5494
  const { get, list } = defaultMethods(api, '/attributes', ['list', 'get']);
5467
5495
 
5468
5496
  return {
@@ -5474,7 +5502,7 @@
5474
5502
  };
5475
5503
  }
5476
5504
 
5477
- function methods$b(api, opt) {
5505
+ function methods$c(api, opt) {
5478
5506
  const { get, list } = defaultMethods(api, '/products', ['list', 'get']);
5479
5507
  return {
5480
5508
  get: (id, ...args) => {
@@ -5683,7 +5711,7 @@
5683
5711
  }
5684
5712
 
5685
5713
  async function getFilterableAttributeFilters(api, products, options) {
5686
- const { results: filterableAttributes } = await methods$c(api).list({
5714
+ const { results: filterableAttributes } = await methods$d(api).list({
5687
5715
  filterable: true,
5688
5716
  });
5689
5717
 
@@ -5867,7 +5895,7 @@
5867
5895
  };
5868
5896
  }
5869
5897
 
5870
- function methods$a(api, options) {
5898
+ function methods$b(api, options) {
5871
5899
  return {
5872
5900
  state: null,
5873
5901
  order: null,
@@ -6052,7 +6080,7 @@
6052
6080
  };
6053
6081
  }
6054
6082
 
6055
- function methods$9(api) {
6083
+ function methods$a(api) {
6056
6084
  return {
6057
6085
  state: null,
6058
6086
 
@@ -6226,7 +6254,7 @@
6226
6254
  }
6227
6255
 
6228
6256
  async updateCart(data) {
6229
- const cart = await methods$a(this.api, this.options).update(data);
6257
+ const cart = await methods$b(this.api, this.options).update(data);
6230
6258
 
6231
6259
  this.setProps({ cart });
6232
6260
  }
@@ -6462,7 +6490,7 @@
6462
6490
  }
6463
6491
  }
6464
6492
 
6465
- function methods$8(api) {
6493
+ function methods$9(api) {
6466
6494
  const { get, list } = defaultMethods(api, '/categories', ['list', 'get']);
6467
6495
 
6468
6496
  return {
@@ -6474,7 +6502,7 @@
6474
6502
  };
6475
6503
  }
6476
6504
 
6477
- function methods$7(api) {
6505
+ function methods$8(api) {
6478
6506
  const { get, list } = defaultMethods(api, '/subscriptions', ['list', 'get']);
6479
6507
  return {
6480
6508
  get: (id, ...args) => {
@@ -6539,7 +6567,7 @@
6539
6567
  };
6540
6568
  }
6541
6569
 
6542
- function methods$6(api) {
6570
+ function methods$7(api) {
6543
6571
  const { get, list } = defaultMethods(api, '/invoices', ['list', 'get']);
6544
6572
  return {
6545
6573
  get: (id, ...args) => {
@@ -6550,7 +6578,7 @@
6550
6578
  };
6551
6579
  }
6552
6580
 
6553
- function methods$5(api, opt) {
6581
+ function methods$6(api, opt) {
6554
6582
  return {
6555
6583
  get: (type, id, query) => {
6556
6584
  return api.cache.getFetch(`content_${type}`, id, () =>
@@ -6566,7 +6594,7 @@
6566
6594
  };
6567
6595
  }
6568
6596
 
6569
- function methods$4(api, opt) {
6597
+ function methods$5(api, opt) {
6570
6598
  return {
6571
6599
  state: null,
6572
6600
  menuState: null,
@@ -6861,7 +6889,7 @@
6861
6889
  }
6862
6890
  }
6863
6891
 
6864
- function methods$3(api, opt) {
6892
+ function methods$4(api, opt) {
6865
6893
  return {
6866
6894
  /**
6867
6895
  * Get the decoded session as an object of session values
@@ -7249,7 +7277,7 @@
7249
7277
  * @returns {Promise<Cart>}
7250
7278
  */
7251
7279
  async getCart() {
7252
- const cart = await methods$a(this.api, this.options).get();
7280
+ const cart = await methods$b(this.api, this.options).get();
7253
7281
 
7254
7282
  if (!cart) {
7255
7283
  throw new Error('Cart not found');
@@ -7277,7 +7305,7 @@
7277
7305
  }
7278
7306
  }
7279
7307
 
7280
- const updatedCart = await methods$a(this.api, this.options).update(
7308
+ const updatedCart = await methods$b(this.api, this.options).update(
7281
7309
  updateData,
7282
7310
  );
7283
7311
 
@@ -7290,7 +7318,7 @@
7290
7318
  * @returns {Promise<object>}
7291
7319
  */
7292
7320
  async getSettings() {
7293
- return methods$4(this.api, this.options).get();
7321
+ return methods$5(this.api, this.options).get();
7294
7322
  }
7295
7323
 
7296
7324
  /**
@@ -12906,7 +12934,7 @@
12906
12934
  }
12907
12935
 
12908
12936
  async _getPaymentMethods() {
12909
- const paymentMethods = await methods$4(this.api, this.options).payments();
12937
+ const paymentMethods = await methods$5(this.api, this.options).payments();
12910
12938
 
12911
12939
  if (paymentMethods.error) {
12912
12940
  throw new Error(paymentMethods.error);
@@ -13136,7 +13164,7 @@
13136
13164
  }
13137
13165
  }
13138
13166
 
13139
- function methods$2(api, opt) {
13167
+ function methods$3(api, opt) {
13140
13168
  return {
13141
13169
  code: null,
13142
13170
  state: null,
@@ -13192,7 +13220,7 @@
13192
13220
  return typeof navigator === 'object' ? navigator.language : 'en-US';
13193
13221
  }
13194
13222
 
13195
- function methods$1(api, opt) {
13223
+ function methods$2(api, opt) {
13196
13224
  // Reads a store setting without ever returning a Promise. Until settings
13197
13225
  // load, this starts the request and reports `loaded: false`.
13198
13226
  function readSetting(path, def) {
@@ -13413,7 +13441,7 @@
13413
13441
  };
13414
13442
  }
13415
13443
 
13416
- function methods(api, _opt) {
13444
+ function methods$1(api, _opt) {
13417
13445
  return {
13418
13446
  /**
13419
13447
  * Make a request to an app function and greceiveet a response
@@ -13482,6 +13510,85 @@
13482
13510
  };
13483
13511
  }
13484
13512
 
13513
+ const PURPOSES = ['analytics', 'marketing', 'sale_of_data'];
13514
+
13515
+ /**
13516
+ * The page the shopper landed on, which the consent call sends along: the
13517
+ * first URL of this document and its referrer. Read when needed, so nothing
13518
+ * is kept before the shopper answers.
13519
+ *
13520
+ * @returns {{url: string, referrer: string} | undefined}
13521
+ */
13522
+ function getLanding() {
13523
+ if (isServer()) {
13524
+ return undefined;
13525
+ }
13526
+
13527
+ let url = window.location.href;
13528
+
13529
+ try {
13530
+ const [navigation] = window.performance.getEntriesByType('navigation');
13531
+ if (navigation?.name) {
13532
+ url = navigation.name;
13533
+ }
13534
+ } catch {
13535
+ // Navigation timing is not available
13536
+ }
13537
+
13538
+ return { url, referrer: window.document.referrer || '' };
13539
+ }
13540
+
13541
+ function methods(api) {
13542
+ // Calls run one after another. Consent tools fire several events for one
13543
+ // answer, and the first call may set the visitor cookie that the next one
13544
+ // has to send: in parallel, each would start a visitor of its own.
13545
+ let queue = Promise.resolve();
13546
+
13547
+ return {
13548
+ /**
13549
+ * Records the shopper's consent for attribution, from the storefront's
13550
+ * consent banner. Purposes left out stay as they are.
13551
+ *
13552
+ * Calls the storefront's own origin, so that Swell sees the page's
13553
+ * cookies and sets the visitor cookie on the storefront's domain.
13554
+ *
13555
+ * @param {{analytics?: boolean, marketing?: boolean, sale_of_data?: boolean}} consent
13556
+ */
13557
+ set(consent = {}) {
13558
+ if (isServer()) {
13559
+ return Promise.reject(new Error('consent.set() runs in the browser'));
13560
+ }
13561
+
13562
+ const data = {};
13563
+
13564
+ for (const purpose of PURPOSES) {
13565
+ // camelCase clients pass saleOfData
13566
+ const camel = purpose.replace(/_(\w)/g, (_m, c) => c.toUpperCase());
13567
+ const value = consent[purpose] ?? consent[camel];
13568
+
13569
+ if (typeof value === 'boolean') {
13570
+ data[purpose] = value;
13571
+ }
13572
+ }
13573
+
13574
+ const result = queue.then(() =>
13575
+ api.request(
13576
+ 'put',
13577
+ '/session/consent',
13578
+ { ...data, landing: getLanding() },
13579
+ undefined,
13580
+ { fullUrl: `${window.location.origin}/api/session/consent` },
13581
+ ),
13582
+ );
13583
+
13584
+ // A failed call doesn't hold back the next one
13585
+ queue = result.catch(() => undefined);
13586
+
13587
+ return result;
13588
+ },
13589
+ };
13590
+ }
13591
+
13485
13592
  /**
13486
13593
  * @template {'snake' | 'camel'} C
13487
13594
  * @typedef {import('../types').InitOptions<C>} InitOptions<C>
@@ -13513,7 +13620,7 @@
13513
13620
  const api = {};
13514
13621
 
13515
13622
  Object.assign(api, {
13516
- version: '5.9.2',
13623
+ version: '5.9.4',
13517
13624
  options,
13518
13625
  request,
13519
13626
 
@@ -13543,6 +13650,7 @@
13543
13650
  options.getCart = opt.getCart;
13544
13651
  options.updateCart = opt.updateCart;
13545
13652
  options.headers = opt.headers || {};
13653
+ options.getCaptchaToken = opt.getCaptchaToken;
13546
13654
  },
13547
13655
 
13548
13656
  // Backward compatibility
@@ -13566,39 +13674,41 @@
13566
13674
  return api.request('delete', url, data);
13567
13675
  },
13568
13676
 
13569
- cache: methods$d(options),
13677
+ cache: methods$e(options),
13570
13678
 
13571
- card: methods$e(options),
13679
+ card: methods$f(options),
13572
13680
 
13573
- cart: methods$a(api, options),
13681
+ cart: methods$b(api, options),
13574
13682
 
13575
- account: methods$9(api),
13683
+ account: methods$a(api),
13576
13684
 
13577
13685
  app: new AppController(api, options),
13578
13686
 
13579
- products: methods$b(api, options),
13687
+ products: methods$c(api, options),
13580
13688
 
13581
- categories: methods$8(api),
13689
+ categories: methods$9(api),
13582
13690
 
13583
- attributes: methods$c(api),
13691
+ attributes: methods$d(api),
13584
13692
 
13585
- subscriptions: methods$7(api),
13693
+ subscriptions: methods$8(api),
13586
13694
 
13587
- invoices: methods$6(api),
13695
+ invoices: methods$7(api),
13588
13696
 
13589
- content: methods$5(api, options),
13697
+ content: methods$6(api, options),
13590
13698
 
13591
- settings: methods$4(api, options),
13699
+ settings: methods$5(api, options),
13592
13700
 
13593
13701
  payment: new PaymentController(api, options),
13594
13702
 
13595
- locale: methods$2(api, options),
13703
+ locale: methods$3(api, options),
13704
+
13705
+ currency: methods$2(api, options),
13596
13706
 
13597
- currency: methods$1(api, options),
13707
+ session: methods$4(api, options),
13598
13708
 
13599
- session: methods$3(api, options),
13709
+ functions: methods$1(api),
13600
13710
 
13601
- functions: methods(api),
13711
+ consent: methods(api),
13602
13712
 
13603
13713
  utils,
13604
13714
 
@@ -13672,6 +13782,13 @@
13672
13782
  reqHeaders['X-Session'] = session;
13673
13783
  }
13674
13784
 
13785
+ // The storefront's visitor, for attribution: the cookie is on the
13786
+ // storefront's domain and doesn't reach the store's API host
13787
+ const visitor = allOptions.getCookie('swell-visitor');
13788
+ if (visitor) {
13789
+ reqHeaders['X-Visitor'] = visitor;
13790
+ }
13791
+
13675
13792
  if (locale) {
13676
13793
  reqHeaders['X-Locale'] = locale;
13677
13794
  }