@cimplify/sdk 0.103.0 → 0.104.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.
Files changed (65) hide show
  1. package/dist/advanced.d.mts +3 -3
  2. package/dist/advanced.d.ts +3 -3
  3. package/dist/advanced.js +22 -22
  4. package/dist/advanced.mjs +3 -3
  5. package/dist/{chunk-C2JSNJUC.mjs → chunk-2WPVUIHX.mjs} +52 -11
  6. package/dist/{chunk-JG5CQNCB.js → chunk-4BKOKHE3.js} +4 -0
  7. package/dist/{chunk-R6OLQ33I.js → chunk-5BDYDZ4U.js} +239 -87
  8. package/dist/{chunk-H7ACMHM3.mjs → chunk-5RT4HYMP.mjs} +32 -4
  9. package/dist/{chunk-NNG6IFFX.js → chunk-7PDEX54K.js} +3 -3
  10. package/dist/{chunk-M4URVKHE.mjs → chunk-DYIAX3WI.mjs} +1 -1
  11. package/dist/{chunk-QOWPGS7Z.js → chunk-E4K2VQDD.js} +35 -5
  12. package/dist/{chunk-VNPEYLB2.mjs → chunk-H3RATH4B.mjs} +4 -0
  13. package/dist/{chunk-JSWJ4XDE.js → chunk-IQFFSKE2.js} +315 -108
  14. package/dist/{chunk-J6PNHDHL.mjs → chunk-OCCNG6MO.mjs} +284 -77
  15. package/dist/{chunk-GERXZQSX.mjs → chunk-OKADBZAI.mjs} +171 -20
  16. package/dist/{chunk-VIL6IQCG.js → chunk-YVAEY3VC.js} +54 -13
  17. package/dist/{client-Dqg2mc-7.d.ts → client-BVNWjk6W.d.ts} +2 -2
  18. package/dist/{client-BfpNjJ_a.d.mts → client-BuLcOWLv.d.ts} +115 -23
  19. package/dist/{client-DHBwvh7U.d.ts → client-D5AoobFc.d.mts} +115 -23
  20. package/dist/{client-DpqRobY9.d.mts → client-fM716k7G.d.mts} +2 -2
  21. package/dist/{index-C8uDqLwJ.d.ts → index-BtcoqrY1.d.ts} +3 -3
  22. package/dist/{index-e2y6AK70.d.mts → index-D7Tf3v7c.d.mts} +3 -3
  23. package/dist/index.d.mts +10 -8
  24. package/dist/index.d.ts +10 -8
  25. package/dist/index.js +107 -106
  26. package/dist/index.mjs +6 -5
  27. package/dist/{link-cuNVYc2s.d.mts → link-D9iSVxt5.d.mts} +12 -1
  28. package/dist/{link-cuNVYc2s.d.ts → link-D9iSVxt5.d.ts} +12 -1
  29. package/dist/mock/cli.mjs +53 -10
  30. package/dist/mock/library.js +53 -10
  31. package/dist/mock/library.mjs +53 -10
  32. package/dist/mock/msw.js +53 -10
  33. package/dist/mock/msw.mjs +53 -10
  34. package/dist/{payment-H5LoIvXU.d.mts → payment-g0HFkEDU.d.mts} +519 -54
  35. package/dist/{payment-H5LoIvXU.d.ts → payment-g0HFkEDU.d.ts} +519 -54
  36. package/dist/{price-C2RqscMY.d.ts → price-BLIeAb8K.d.ts} +1 -1
  37. package/dist/{price-BvePgDXe.d.mts → price-Czq_cTC_.d.mts} +1 -1
  38. package/dist/react.d.mts +4 -4
  39. package/dist/react.d.ts +4 -4
  40. package/dist/react.js +193 -169
  41. package/dist/react.mjs +54 -30
  42. package/dist/{server-C7FyLdrz.d.mts → server-BkVhOIwn.d.mts} +4 -2
  43. package/dist/{server-DoXIpSd7.d.ts → server-DKK_D-PP.d.ts} +4 -2
  44. package/dist/server.d.mts +4 -4
  45. package/dist/server.d.ts +4 -4
  46. package/dist/server.js +11 -10
  47. package/dist/server.mjs +5 -4
  48. package/dist/testing/msw.d.mts +2 -2
  49. package/dist/testing/msw.d.ts +2 -2
  50. package/dist/testing/msw.js +3 -3
  51. package/dist/testing/msw.mjs +2 -2
  52. package/dist/testing/suite.d.mts +6 -6
  53. package/dist/testing/suite.d.ts +6 -6
  54. package/dist/testing/suite.js +25 -25
  55. package/dist/testing/suite.mjs +6 -6
  56. package/dist/testing.d.mts +46 -6
  57. package/dist/testing.d.ts +46 -6
  58. package/dist/testing.js +94 -82
  59. package/dist/testing.mjs +13 -9
  60. package/dist/utils.d.mts +4 -4
  61. package/dist/utils.d.ts +4 -4
  62. package/dist/utils.js +31 -31
  63. package/dist/utils.mjs +2 -2
  64. package/package.json +1 -1
  65. package/registry/chat-widget.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { MOBILE_MONEY_PROVIDER, PAYMENT_METHOD, MAX_PAYMENT_AUTHORIZATION_STEPS } from './chunk-GOHSXBKW.mjs';
2
- import { normalizeStatusResponse, paymentAuthorizationUrl, isPaymentStatusSuccess, isPaymentStatusFailure, isPaymentStatusRequiresAction } from './chunk-M4URVKHE.mjs';
3
- import { CimplifyError, isSupportedCurrency, ErrorCode, enrichError, getErrorHint } from './chunk-VNPEYLB2.mjs';
2
+ import { normalizeStatusResponse, paymentAuthorizationUrl, isPaymentStatusSuccess, isPaymentStatusFailure, isPaymentStatusRequiresAction } from './chunk-DYIAX3WI.mjs';
3
+ import { CimplifyError, isSupportedCurrency, ErrorCode, enrichError, getErrorHint } from './chunk-H3RATH4B.mjs';
4
4
 
5
5
  // src/types/result.ts
6
6
  function ok(value) {
@@ -1833,43 +1833,86 @@ function encodePathSegment(value) {
1833
1833
  var LinkService = class {
1834
1834
  constructor(client) {
1835
1835
  this.client = client;
1836
+ this.activationGeneration = 0;
1837
+ }
1838
+ beginActivation() {
1839
+ return {
1840
+ generation: ++this.activationGeneration,
1841
+ sessionEpoch: this.client.getSessionEpoch(),
1842
+ publicKeyEpoch: this.client.getPublicKeyEpoch()
1843
+ };
1844
+ }
1845
+ isActivationFenceCurrent(fence) {
1846
+ return fence.generation === this.activationGeneration && fence.sessionEpoch === this.client.getSessionEpoch() && fence.publicKeyEpoch === this.client.getPublicKeyEpoch();
1847
+ }
1848
+ supersededActivation() {
1849
+ return {
1850
+ ok: false,
1851
+ error: new CimplifyError(
1852
+ "session_superseded",
1853
+ "A newer authentication session replaced this one"
1854
+ )
1855
+ };
1856
+ }
1857
+ async activateAuthenticatedSession(result, fence) {
1858
+ if (!result.ok || !result.value.session_token) return result;
1859
+ if (!this.isActivationFenceCurrent(fence)) return this.supersededActivation();
1860
+ const accessToken = result.value.session_token;
1861
+ this.client.setAccessToken(accessToken);
1862
+ const installedSessionEpoch = this.client.getSessionEpoch();
1863
+ if (!this.client.getPublicKey().trim()) {
1864
+ this.client.activity.refreshIdentity();
1865
+ return result;
1866
+ }
1867
+ const claim = await this.client.support.claimConversation();
1868
+ if (fence.generation !== this.activationGeneration || fence.publicKeyEpoch !== this.client.getPublicKeyEpoch() || this.client.getAccessToken() !== accessToken) {
1869
+ return this.supersededActivation();
1870
+ }
1871
+ if (!claim.ok && claim.error.code !== "already_claimed") {
1872
+ if (this.client.getSessionEpoch() !== installedSessionEpoch) {
1873
+ return this.supersededActivation();
1874
+ }
1875
+ if (this.client.hasClaimedSessionAuthority()) {
1876
+ this.client.clearSession();
1877
+ } else {
1878
+ this.client.setAccessToken(null);
1879
+ }
1880
+ return claim;
1881
+ }
1882
+ this.client.activity.refreshIdentity();
1883
+ return result;
1836
1884
  }
1837
1885
  async requestOtp(input, opts) {
1838
1886
  const idempotencyKey = opts?.idempotencyKey ?? generateIdempotencyKey();
1839
1887
  return safe(
1840
- this.client.linkPost("/v1/link/auth/request-otp", input, { idempotencyKey })
1888
+ this.client.linkPost("/v1/link/auth/request-otp", input, {
1889
+ idempotencyKey
1890
+ })
1841
1891
  );
1842
1892
  }
1843
1893
  async verifyOtp(input, opts) {
1844
1894
  const idempotencyKey = opts?.idempotencyKey ?? generateIdempotencyKey();
1895
+ const activationFence = opts?.activateSession === false ? null : this.beginActivation();
1845
1896
  const { business_id: _ignoredBusinessId, ...body } = input;
1846
1897
  const result = await safe(
1847
1898
  this.client.linkPost("/v1/link/auth/verify-otp", body, { idempotencyKey })
1848
1899
  );
1849
- if (result.ok && result.value.session_token) {
1850
- this.client.setAccessToken(result.value.session_token);
1851
- this.client.activity.refreshIdentity();
1852
- this.client.autoClaimChatIdentity();
1853
- }
1854
- return result;
1900
+ return activationFence ? this.activateAuthenticatedSession(result, activationFence) : result;
1855
1901
  }
1856
1902
  async refreshSession(sessionToken, opts) {
1857
1903
  const idempotencyKey = opts?.idempotencyKey ?? generateIdempotencyKey();
1904
+ const activationFence = opts?.activateSession === false ? null : this.beginActivation();
1858
1905
  const body = sessionToken ? { session_token: sessionToken } : {};
1859
1906
  const result = await safe(
1860
1907
  this.client.linkPost("/v1/link/auth/refresh", body, { idempotencyKey })
1861
1908
  );
1862
- if (result.ok && result.value.session_token) {
1863
- this.client.setAccessToken(result.value.session_token);
1864
- this.client.activity.refreshIdentity();
1865
- this.client.autoClaimChatIdentity();
1866
- }
1867
- return result;
1909
+ return activationFence ? this.activateAuthenticatedSession(result, activationFence) : result;
1868
1910
  }
1869
1911
  async logout() {
1870
- const result = await safe(this.client.linkPost("/v1/link/auth/logout"));
1912
+ this.activationGeneration += 1;
1913
+ const request = safe(this.client.linkPost("/v1/link/auth/logout"));
1871
1914
  this.client.clearSession();
1872
- return result;
1915
+ return request;
1873
1916
  }
1874
1917
  async checkStatus(contact) {
1875
1918
  return safe(this.client.linkPost("/v1/link/check-status", { contact }));
@@ -1915,11 +1958,9 @@ var LinkService = class {
1915
1958
  async enrollAndLinkOrder(data, opts) {
1916
1959
  const idempotencyKey = opts?.idempotencyKey ?? generateIdempotencyKey();
1917
1960
  return safe(
1918
- this.client.linkPost(
1919
- "/v1/link/enroll-and-link-order",
1920
- data,
1921
- { idempotencyKey }
1922
- )
1961
+ this.client.linkPost("/v1/link/enroll-and-link-order", data, {
1962
+ idempotencyKey
1963
+ })
1923
1964
  );
1924
1965
  }
1925
1966
  async updatePreferences(preferences) {
@@ -2342,6 +2383,7 @@ var MESSAGE_TYPES = {
2342
2383
  INIT: "init",
2343
2384
  SET_TOKEN: "set_token",
2344
2385
  SET_SESSION: "set_session",
2386
+ SESSION_CLEARED: "session_cleared",
2345
2387
  SET_CART: "set_cart",
2346
2388
  GET_DATA: "get_data",
2347
2389
  NAVIGATE: "navigate",
@@ -2358,6 +2400,8 @@ var MESSAGE_TYPES = {
2358
2400
  LOGOUT_COMPLETE: "logout_complete",
2359
2401
  AUTH_REQUESTED: "auth_requested",
2360
2402
  SESSION_ESTABLISHED: "session_established",
2403
+ SESSION_ESTABLISHMENT_FAILED: "session_establishment_failed",
2404
+ CONTINUE_WITHOUT_SAVED_DETAILS: "continue_without_saved_details",
2361
2405
  CONTACT_PROVIDED: "contact_provided",
2362
2406
  CHECKOUT_STATUS: "checkout_status",
2363
2407
  CHECKOUT_COMPLETE: "checkout_complete",
@@ -2721,6 +2765,7 @@ function toCheckoutError(code, message, recoverable) {
2721
2765
  };
2722
2766
  }
2723
2767
  var DEFAULT_LINK_URL = "https://link.cimplify.io";
2768
+ var AUTH_ESTABLISHMENT_WAIT_MS = 8e3;
2724
2769
  var AUTH_CONTACT_TYPES = new Set(Object.values(ELEMENTS_AUTH_CONTACT_TYPES));
2725
2770
  var AUTH_MODES = new Set(Object.values(ELEMENTS_AUTH_MODES));
2726
2771
  var AUTH_PROMPTS = new Set(Object.values(ELEMENTS_AUTH_PROMPTS));
@@ -2771,6 +2816,7 @@ var KNOWN_IFRAME_TYPES = /* @__PURE__ */ new Set([
2771
2816
  MESSAGE_TYPES.HEIGHT_CHANGE,
2772
2817
  MESSAGE_TYPES.AUTH_REQUESTED,
2773
2818
  MESSAGE_TYPES.SESSION_ESTABLISHED,
2819
+ MESSAGE_TYPES.CONTINUE_WITHOUT_SAVED_DETAILS,
2774
2820
  MESSAGE_TYPES.ERROR,
2775
2821
  MESSAGE_TYPES.ADDRESS_CHANGED,
2776
2822
  MESSAGE_TYPES.ADDRESS_SELECTED,
@@ -2815,6 +2861,7 @@ function parseIframeMessage(data) {
2815
2861
  if (!record.method || typeof record.method !== "object") return null;
2816
2862
  break;
2817
2863
  case MESSAGE_TYPES.CONTACT_PROVIDED:
2864
+ case MESSAGE_TYPES.CONTINUE_WITHOUT_SAVED_DETAILS:
2818
2865
  if (typeof record.contact !== "string" || typeof record.contactType !== "string") return null;
2819
2866
  break;
2820
2867
  case MESSAGE_TYPES.ERROR:
@@ -2824,7 +2871,8 @@ function parseIframeMessage(data) {
2824
2871
  if (typeof record.success !== "boolean") return null;
2825
2872
  break;
2826
2873
  case MESSAGE_TYPES.CHECKOUT_STATUS:
2827
- if (typeof record.status !== "string" || !record.context || typeof record.context !== "object") return null;
2874
+ if (typeof record.status !== "string" || !record.context || typeof record.context !== "object")
2875
+ return null;
2828
2876
  break;
2829
2877
  case MESSAGE_TYPES.READY:
2830
2878
  case MESSAGE_TYPES.HEIGHT_CHANGE:
@@ -2847,6 +2895,8 @@ var CimplifyElements = class {
2847
2895
  this.paymentData = null;
2848
2896
  this.checkoutInProgress = false;
2849
2897
  this.authInProgress = false;
2898
+ this.authEstablishmentInProgress = false;
2899
+ this.authGeneration = 0;
2850
2900
  this.activeCheckoutAbort = null;
2851
2901
  this.businessIdResolvePromise = null;
2852
2902
  this.client = client;
@@ -2881,6 +2931,12 @@ var CimplifyElements = class {
2881
2931
  }
2882
2932
  }
2883
2933
  destroy() {
2934
+ this.authGeneration += 1;
2935
+ if (this.authEstablishmentInProgress) {
2936
+ this.client.setAccessToken(null);
2937
+ }
2938
+ this.authInProgress = false;
2939
+ this.authEstablishmentInProgress = false;
2884
2940
  this.elements.forEach((element) => element.destroy());
2885
2941
  this.elements.clear();
2886
2942
  if (typeof window !== "undefined") {
@@ -2918,16 +2974,27 @@ var CimplifyElements = class {
2918
2974
  processCheckout(options) {
2919
2975
  let abortFn = null;
2920
2976
  const task = (async () => {
2921
- this.debug("[cimplify:checkout] processCheckout called", { cart_id: options.cart_id, order_type: options.order_type, location_id: options.location_id });
2977
+ this.debug("[cimplify:checkout] processCheckout called", {
2978
+ cart_id: options.cart_id,
2979
+ order_type: options.order_type,
2980
+ location_id: options.location_id
2981
+ });
2922
2982
  if (this.checkoutInProgress) {
2923
2983
  this.debug("[cimplify:checkout] BLOCKED: already processing");
2924
- return toCheckoutError(
2925
- "ALREADY_PROCESSING",
2926
- "Checkout is already in progress.",
2927
- false
2928
- );
2984
+ return toCheckoutError("ALREADY_PROCESSING", "Checkout is already in progress.", false);
2929
2985
  }
2930
2986
  this.checkoutInProgress = true;
2987
+ if (this.authEstablishmentInProgress) {
2988
+ await this.waitForAuthEstablishment(AUTH_ESTABLISHMENT_WAIT_MS);
2989
+ if (this.authEstablishmentInProgress) {
2990
+ this.checkoutInProgress = false;
2991
+ return toCheckoutError(
2992
+ "AUTH_INCOMPLETE",
2993
+ "Authentication must finish establishing the checkout session.",
2994
+ true
2995
+ );
2996
+ }
2997
+ }
2931
2998
  if (!options.cart_id) {
2932
2999
  this.debug("[cimplify:checkout] BLOCKED: no cart_id");
2933
3000
  this.checkoutInProgress = false;
@@ -2985,7 +3052,11 @@ var CimplifyElements = class {
2985
3052
  }
2986
3053
  await this.hydrateCustomerData();
2987
3054
  }
2988
- this.debug("[cimplify:checkout] customer data hydrated", { customerData: this.customerData, accountId: this.accountId, isUnifiedCheckout });
3055
+ this.debug("[cimplify:checkout] customer data hydrated", {
3056
+ customerData: this.customerData,
3057
+ accountId: this.accountId,
3058
+ isUnifiedCheckout
3059
+ });
2989
3060
  const processMessage = {
2990
3061
  type: MESSAGE_TYPES.PROCESS_CHECKOUT,
2991
3062
  cart_id: options.cart_id,
@@ -3049,7 +3120,10 @@ var CimplifyElements = class {
3049
3120
  return;
3050
3121
  }
3051
3122
  if (message.type === MESSAGE_TYPES.CHECKOUT_COMPLETE) {
3052
- this.debug("[cimplify:checkout] received checkout_complete", { success: message.success, error: message.error });
3123
+ this.debug("[cimplify:checkout] received checkout_complete", {
3124
+ success: message.success,
3125
+ error: message.error
3126
+ });
3053
3127
  settle({
3054
3128
  success: message.success,
3055
3129
  order: message.order,
@@ -3060,11 +3134,7 @@ var CimplifyElements = class {
3060
3134
  if (message.type === MESSAGE_TYPES.LOGOUT_COMPLETE) {
3061
3135
  checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3062
3136
  settle(
3063
- toCheckoutError(
3064
- "AUTH_LOST",
3065
- "Authentication was cleared during checkout.",
3066
- true
3067
- )
3137
+ toCheckoutError("AUTH_LOST", "Authentication was cleared during checkout.", true)
3068
3138
  );
3069
3139
  }
3070
3140
  };
@@ -3073,16 +3143,16 @@ var CimplifyElements = class {
3073
3143
  }
3074
3144
  abortFn = () => {
3075
3145
  checkoutElement.sendMessage({ type: MESSAGE_TYPES.ABORT_CHECKOUT });
3076
- settle(
3077
- toCheckoutError(
3078
- "CANCELLED",
3079
- "Checkout was cancelled.",
3080
- true
3081
- )
3082
- );
3146
+ settle(toCheckoutError("CANCELLED", "Checkout was cancelled.", true));
3083
3147
  };
3084
3148
  this.activeCheckoutAbort = abortFn;
3085
- this.debug("[cimplify:checkout] sending process_checkout to checkout iframe", { cart_id: processMessage.cart_id, order_type: processMessage.order_type, hasCustomer: !!processMessage.customer, hasAddress: !!processMessage.address, isUnifiedCheckout });
3149
+ this.debug("[cimplify:checkout] sending process_checkout to checkout iframe", {
3150
+ cart_id: processMessage.cart_id,
3151
+ order_type: processMessage.order_type,
3152
+ hasCustomer: !!processMessage.customer,
3153
+ hasAddress: !!processMessage.address,
3154
+ isUnifiedCheckout
3155
+ });
3086
3156
  checkoutElement.sendMessage(processMessage);
3087
3157
  this.debug("[cimplify:checkout] postMessage sent, waiting for checkout_complete...");
3088
3158
  });
@@ -3128,11 +3198,16 @@ var CimplifyElements = class {
3128
3198
  getAppearance() {
3129
3199
  return this.options.appearance;
3130
3200
  }
3131
- async hydrateCustomerData() {
3132
- if (!this.accessToken || this.customerData) return;
3201
+ isAuthGenerationCurrent(generation, token) {
3202
+ return this.authGeneration === generation && this.client.getAccessToken() === token;
3203
+ }
3204
+ async hydrateCustomerData(generation = this.authGeneration, token = this.accessToken, force = false) {
3205
+ if (!token || !this.isAuthGenerationCurrent(generation, token)) return false;
3206
+ if (this.customerData && !force) return true;
3133
3207
  const linkDataResult = await this.client.link.getLinkData();
3208
+ if (!this.isAuthGenerationCurrent(generation, token)) return false;
3134
3209
  if (!linkDataResult.ok || !linkDataResult.value?.customer) {
3135
- return;
3210
+ return true;
3136
3211
  }
3137
3212
  const customer = linkDataResult.value.customer;
3138
3213
  this.customerData = {
@@ -3141,6 +3216,7 @@ var CimplifyElements = class {
3141
3216
  phone: customer.phone || null
3142
3217
  };
3143
3218
  this.customerId = customer.id;
3219
+ return true;
3144
3220
  }
3145
3221
  sourceElementFor(event, message) {
3146
3222
  for (const element of this.elements.values()) {
@@ -3179,48 +3255,123 @@ var CimplifyElements = class {
3179
3255
  } catch {
3180
3256
  }
3181
3257
  }
3258
+ clearClaimedAuthorityAfterRestoreFailure() {
3259
+ if (!this.client.getAccessToken() && !this.client.hasClaimedSessionAuthority()) return;
3260
+ this.accessToken = null;
3261
+ this.accountId = null;
3262
+ this.customerId = null;
3263
+ this.customerData = null;
3264
+ this.addressData = null;
3265
+ this.paymentData = null;
3266
+ this.authEstablishmentInProgress = false;
3267
+ this.client.clearSession();
3268
+ this.broadcastClearedSession();
3269
+ }
3182
3270
  async restoreSession() {
3183
3271
  if (typeof window === "undefined" || this.accessToken) return;
3272
+ const generation = ++this.authGeneration;
3184
3273
  const storageKey = this.sessionStorageKey();
3185
3274
  if (!storageKey) return;
3186
3275
  let refreshToken = null;
3187
3276
  try {
3188
3277
  refreshToken = window.localStorage.getItem(storageKey);
3189
3278
  } catch {
3279
+ this.clearClaimedAuthorityAfterRestoreFailure();
3280
+ return;
3281
+ }
3282
+ if (!refreshToken) {
3283
+ this.clearClaimedAuthorityAfterRestoreFailure();
3190
3284
  return;
3191
3285
  }
3192
- if (!refreshToken) return;
3193
- const result = await this.client.link.refreshSession(refreshToken);
3286
+ const result = await this.client.link.refreshSession(refreshToken, {
3287
+ activateSession: false
3288
+ });
3289
+ if (this.authGeneration !== generation) return;
3194
3290
  if (!result.ok || !result.value.session_token) {
3195
3291
  this.clearPersistedSession();
3292
+ this.clearClaimedAuthorityAfterRestoreFailure();
3196
3293
  return;
3197
3294
  }
3198
3295
  this.persistRefreshToken(result.value.refresh_token ?? void 0);
3199
- const data = await this.applyAccessToken(result.value.session_token);
3200
- this.broadcastAccessToken(result.value.session_token);
3201
- this.elements.forEach((element) => element._emitAuthenticated(data));
3296
+ const application = await this.applyAccessToken(result.value.session_token, generation);
3297
+ if (application.kind === "claim_failed") {
3298
+ this.clearPersistedSession();
3299
+ this.broadcastClearedSession();
3300
+ return;
3301
+ }
3302
+ if (application.kind !== "authenticated" || !this.broadcastAccessToken(result.value.session_token, generation)) {
3303
+ return;
3304
+ }
3305
+ this.elements.forEach((element) => element._emitAuthenticated(application.data));
3202
3306
  }
3203
- async applyAccessToken(token) {
3307
+ async applyAccessToken(token, generation) {
3308
+ if (this.authGeneration !== generation) return { kind: "incomplete" };
3309
+ this.authEstablishmentInProgress = true;
3310
+ this.accessToken = null;
3311
+ this.accountId = null;
3312
+ this.customerId = null;
3313
+ this.customerData = null;
3314
+ this.addressData = null;
3315
+ this.paymentData = null;
3316
+ this.client.setAccessToken(token);
3317
+ const claim = await this.client.support.claimConversation();
3318
+ if (!this.isAuthGenerationCurrent(generation, token)) return { kind: "incomplete" };
3319
+ if (!claim.ok && claim.error.code !== "already_claimed") {
3320
+ if (this.client.hasClaimedSessionAuthority()) {
3321
+ this.client.clearSession();
3322
+ } else {
3323
+ this.client.setAccessToken(null);
3324
+ }
3325
+ this.authEstablishmentInProgress = false;
3326
+ return {
3327
+ kind: "claim_failed",
3328
+ code: claim.error.code,
3329
+ message: claim.error.userMessage
3330
+ };
3331
+ }
3204
3332
  this.accessToken = token;
3205
3333
  this.accountId = decodeJwtSub(token);
3206
- this.client.setAccessToken(token);
3207
- this.client.autoClaimChatIdentity();
3208
- await this.hydrateCustomerData();
3334
+ if (!await this.hydrateCustomerData(generation, token, true)) {
3335
+ return { kind: "incomplete" };
3336
+ }
3337
+ if (!this.isAuthGenerationCurrent(generation, token)) return { kind: "incomplete" };
3338
+ this.authEstablishmentInProgress = false;
3209
3339
  return {
3210
- accountId: this.accountId ?? "",
3211
- customerId: this.customerId ?? "",
3212
- token,
3213
- customer: this.customerData ?? { name: "", email: null, phone: null }
3340
+ kind: "authenticated",
3341
+ data: {
3342
+ accountId: this.accountId ?? "",
3343
+ customerId: this.customerId ?? "",
3344
+ token,
3345
+ customer: this.customerData ?? { name: "", email: null, phone: null }
3346
+ }
3214
3347
  };
3215
3348
  }
3216
- broadcastAccessToken(token) {
3349
+ async waitForAuthEstablishment(timeoutMs) {
3350
+ const deadline = Date.now() + timeoutMs;
3351
+ while (this.authEstablishmentInProgress && Date.now() < deadline) {
3352
+ await new Promise((resolve) => setTimeout(resolve, 100));
3353
+ }
3354
+ }
3355
+ broadcastAccessToken(token, generation) {
3356
+ if (!this.isAuthGenerationCurrent(generation, token) || this.accessToken !== token || this.authEstablishmentInProgress) {
3357
+ return false;
3358
+ }
3217
3359
  const sessionToken = this.client.getSessionToken();
3218
3360
  this.elements.forEach((element) => {
3219
- element.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
3220
3361
  if (sessionToken) {
3221
3362
  element.sendMessage({ type: MESSAGE_TYPES.SET_SESSION, sessionToken });
3222
3363
  }
3364
+ element.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
3365
+ });
3366
+ return true;
3367
+ }
3368
+ broadcastClearedSession() {
3369
+ const sessionToken = this.client.getSessionToken();
3370
+ if (!sessionToken) return null;
3371
+ this.elements.forEach((element) => {
3372
+ element.sendMessage({ type: MESSAGE_TYPES.SESSION_CLEARED, sessionToken });
3223
3373
  });
3374
+ return sessionToken;
3224
3375
  }
3225
3376
  startEmbeddedAuth(sourceElement, request) {
3226
3377
  if (this.authInProgress) return;
@@ -3234,6 +3385,7 @@ var CimplifyElements = class {
3234
3385
  });
3235
3386
  return;
3236
3387
  }
3388
+ const generation = ++this.authGeneration;
3237
3389
  this.authInProgress = true;
3238
3390
  void startSignIn({
3239
3391
  clientId,
@@ -3248,6 +3400,7 @@ var CimplifyElements = class {
3248
3400
  mode: "modal",
3249
3401
  silentFirst: request.mode === ELEMENTS_AUTH_MODES.CHECKOUT && request.prompt !== ELEMENTS_AUTH_PROMPTS.LOGIN,
3250
3402
  onSuccess: async ({ accessToken }) => {
3403
+ if (this.authGeneration !== generation) return;
3251
3404
  this.authInProgress = false;
3252
3405
  if (!accessToken) {
3253
3406
  sourceElement._emitError({
@@ -3256,11 +3409,18 @@ var CimplifyElements = class {
3256
3409
  });
3257
3410
  return;
3258
3411
  }
3259
- const data = await this.applyAccessToken(accessToken);
3260
- this.broadcastAccessToken(accessToken);
3261
- sourceElement._emitAuthenticated(data);
3412
+ const application = await this.applyAccessToken(accessToken, generation);
3413
+ if (application.kind === "authenticated" && this.broadcastAccessToken(accessToken, generation)) {
3414
+ sourceElement._emitAuthenticated(application.data);
3415
+ } else if (application.kind === "claim_failed") {
3416
+ sourceElement._emitError({
3417
+ code: application.code,
3418
+ message: application.message
3419
+ });
3420
+ }
3262
3421
  },
3263
3422
  onError: (err2) => {
3423
+ if (this.authGeneration !== generation) return;
3264
3424
  this.authInProgress = false;
3265
3425
  sourceElement._emitError({
3266
3426
  code: err2.error,
@@ -3268,6 +3428,7 @@ var CimplifyElements = class {
3268
3428
  });
3269
3429
  }
3270
3430
  }).catch((error) => {
3431
+ if (this.authGeneration !== generation) return;
3271
3432
  this.authInProgress = false;
3272
3433
  sourceElement._emitError({
3273
3434
  code: "AUTH_START_FAILED",
@@ -3288,11 +3449,29 @@ var CimplifyElements = class {
3288
3449
  this.startEmbeddedAuth(sourceElement, message);
3289
3450
  break;
3290
3451
  case MESSAGE_TYPES.SESSION_ESTABLISHED:
3291
- this.persistRefreshToken(message.refreshToken);
3292
- void this.applyAccessToken(message.accessToken).then((data) => {
3293
- this.broadcastAccessToken(message.accessToken);
3294
- sourceElement._emitAuthenticated(data);
3295
- });
3452
+ {
3453
+ this.authInProgress = false;
3454
+ const generation = ++this.authGeneration;
3455
+ void this.applyAccessToken(message.accessToken, generation).then((application) => {
3456
+ if (this.authGeneration !== generation) return;
3457
+ if (application.kind === "claim_failed") {
3458
+ this.clearPersistedSession();
3459
+ sourceElement.sendMessage({
3460
+ type: MESSAGE_TYPES.SESSION_ESTABLISHMENT_FAILED,
3461
+ accessToken: message.accessToken,
3462
+ code: application.code,
3463
+ message: application.message
3464
+ });
3465
+ this.broadcastClearedSession();
3466
+ return;
3467
+ }
3468
+ if (application.kind !== "authenticated" || !this.broadcastAccessToken(message.accessToken, generation)) {
3469
+ return;
3470
+ }
3471
+ this.persistRefreshToken(message.refreshToken);
3472
+ sourceElement._emitAuthenticated(application.data);
3473
+ });
3474
+ }
3296
3475
  break;
3297
3476
  case MESSAGE_TYPES.ADDRESS_CHANGED:
3298
3477
  case MESSAGE_TYPES.ADDRESS_SELECTED:
@@ -3311,7 +3490,35 @@ var CimplifyElements = class {
3311
3490
  this.customerData.phone = message.contact;
3312
3491
  }
3313
3492
  break;
3493
+ case MESSAGE_TYPES.CONTINUE_WITHOUT_SAVED_DETAILS: {
3494
+ this.authGeneration += 1;
3495
+ this.authInProgress = false;
3496
+ this.authEstablishmentInProgress = false;
3497
+ const carriedIdentityAuthority = Boolean(this.client.getAccessToken()) || this.client.hasClaimedSessionAuthority();
3498
+ this.accessToken = null;
3499
+ this.accountId = null;
3500
+ this.customerId = null;
3501
+ this.customerData = { name: "", email: null, phone: null };
3502
+ this.addressData = null;
3503
+ this.paymentData = null;
3504
+ this.clearPersistedSession();
3505
+ if (carriedIdentityAuthority) {
3506
+ this.client.clearSession();
3507
+ } else {
3508
+ this.client.setAccessToken(null);
3509
+ }
3510
+ this.broadcastClearedSession();
3511
+ if (message.contactType === "email") {
3512
+ this.customerData.email = message.contact;
3513
+ } else {
3514
+ this.customerData.phone = message.contact;
3515
+ }
3516
+ break;
3517
+ }
3314
3518
  case MESSAGE_TYPES.LOGOUT_COMPLETE:
3519
+ this.authGeneration += 1;
3520
+ this.authInProgress = false;
3521
+ this.authEstablishmentInProgress = false;
3315
3522
  if (this.checkoutInProgress && this.activeCheckoutAbort) {
3316
3523
  this.activeCheckoutAbort();
3317
3524
  }
@@ -3323,6 +3530,7 @@ var CimplifyElements = class {
3323
3530
  this.paymentData = null;
3324
3531
  this.clearPersistedSession();
3325
3532
  this.client.clearSession();
3533
+ this.broadcastClearedSession();
3326
3534
  break;
3327
3535
  }
3328
3536
  }
@@ -3456,10 +3664,9 @@ var CimplifyElement = class {
3456
3664
  const iframe = this.iframe;
3457
3665
  if (!iframe || !iframe.isConnected) {
3458
3666
  if (iframe && !iframe.isConnected) {
3459
- console.warn(
3460
- "[cimplify:checkout] sendMessage DROPPED \u2014 iframe detached",
3461
- { type: message.type }
3462
- );
3667
+ console.warn("[cimplify:checkout] sendMessage DROPPED \u2014 iframe detached", {
3668
+ type: message.type
3669
+ });
3463
3670
  }
3464
3671
  return;
3465
3672
  }
@@ -3558,13 +3765,13 @@ var CimplifyElement = class {
3558
3765
  submitLabel: this.options.submitLabel
3559
3766
  });
3560
3767
  const token = this.parent.getAccessToken();
3561
- if (token) {
3562
- this.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
3563
- }
3564
3768
  const sessionToken = this.parent.getSessionToken();
3565
3769
  if (sessionToken) {
3566
3770
  this.sendMessage({ type: MESSAGE_TYPES.SET_SESSION, sessionToken });
3567
3771
  }
3772
+ if (token) {
3773
+ this.sendMessage({ type: MESSAGE_TYPES.SET_TOKEN, token });
3774
+ }
3568
3775
  this.pendingInit = null;
3569
3776
  }
3570
3777
  this.flushPending();