@cimplify/sdk 0.87.0 → 0.89.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 (50) hide show
  1. package/dist/advanced.d.mts +3 -3
  2. package/dist/advanced.d.ts +3 -3
  3. package/dist/advanced.js +20 -20
  4. package/dist/advanced.mjs +1 -1
  5. package/dist/{chunk-RCGSHS2Q.mjs → chunk-DENWOZEA.mjs} +51 -12
  6. package/dist/{chunk-FWEF2DHR.js → chunk-GHFDYM5K.js} +66 -10
  7. package/dist/{chunk-PWDX5N2M.js → chunk-JHJTXAPS.js} +2 -2
  8. package/dist/{chunk-J7JDCPNW.mjs → chunk-M4ALCELT.mjs} +1 -1
  9. package/dist/{chunk-P3352VXA.js → chunk-T2CJ67QV.js} +87 -48
  10. package/dist/{chunk-U57TYZLD.mjs → chunk-ZU4ZRYUR.mjs} +66 -10
  11. package/dist/{client-BMOdyC1F.d.mts → client-CAY2NbRG.d.mts} +2 -2
  12. package/dist/{client-BvWtk822.d.ts → client-CUbwb6Om.d.ts} +2 -2
  13. package/dist/{client-BIt37FjS.d.mts → client-CqZgdUtw.d.ts} +33 -7
  14. package/dist/{client-Dfl6WY2F.d.ts → client-D8ZFs-sq.d.mts} +33 -7
  15. package/dist/{index-DW6JifS1.d.ts → index-Bc5qUxAt.d.ts} +3 -3
  16. package/dist/{index-BxOJ3BLn.d.mts → index-CmWOz9bi.d.mts} +3 -3
  17. package/dist/index.d.mts +6 -6
  18. package/dist/index.d.ts +6 -6
  19. package/dist/index.js +69 -69
  20. package/dist/index.mjs +3 -3
  21. package/dist/{payment-CLp__KpE.d.mts → payment-Dcgb9n1n.d.mts} +1 -1
  22. package/dist/{payment-DJrvivO_.d.ts → payment-Xq0WDZXh.d.ts} +1 -1
  23. package/dist/{price-Ddk8Vr8z.d.mts → price--Ma_WO5_.d.mts} +1 -1
  24. package/dist/{price-B7_UzClY.d.ts → price-DAAjKgAp.d.ts} +1 -1
  25. package/dist/{product-C0Lr81ze.d.mts → product-BakHcsP2.d.mts} +33 -2
  26. package/dist/{product-C0Lr81ze.d.ts → product-BakHcsP2.d.ts} +33 -2
  27. package/dist/react.d.mts +4 -4
  28. package/dist/react.d.ts +4 -4
  29. package/dist/react.js +36 -21
  30. package/dist/react.mjs +22 -7
  31. package/dist/{server-P2G43ENi.d.ts → server-Bei5lBrc.d.ts} +1 -1
  32. package/dist/{server-0TnEJt8U.d.mts → server-Bk_hlefX.d.mts} +1 -1
  33. package/dist/server.d.mts +4 -4
  34. package/dist/server.d.ts +4 -4
  35. package/dist/server.js +7 -7
  36. package/dist/server.mjs +2 -2
  37. package/dist/styles.css +1 -1
  38. package/dist/testing/msw.d.mts +2 -2
  39. package/dist/testing/msw.d.ts +2 -2
  40. package/dist/testing/suite.d.mts +6 -6
  41. package/dist/testing/suite.d.ts +6 -6
  42. package/dist/testing/suite.js +22 -22
  43. package/dist/testing/suite.mjs +3 -3
  44. package/dist/testing.d.mts +5 -5
  45. package/dist/testing.d.ts +5 -5
  46. package/dist/testing.js +78 -78
  47. package/dist/testing.mjs +4 -4
  48. package/dist/utils.d.mts +4 -4
  49. package/dist/utils.d.ts +4 -4
  50. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFWEF2DHR_js = require('./chunk-FWEF2DHR.js');
3
+ var chunkGHFDYM5K_js = require('./chunk-GHFDYM5K.js');
4
4
  var chunkAETVRBKI_js = require('./chunk-AETVRBKI.js');
5
5
 
6
6
  // src/store-credit.ts
@@ -13,7 +13,7 @@ var StoreCreditQueries = class {
13
13
  * currency. Requires a signed-in customer; returns an error otherwise.
14
14
  */
15
15
  async balance() {
16
- return chunkFWEF2DHR_js.safe(this.client.get("/api/v1/store-credit/balance"));
16
+ return chunkGHFDYM5K_js.safe(this.client.get("/api/v1/store-credit/balance"));
17
17
  }
18
18
  };
19
19
 
@@ -95,7 +95,7 @@ var ActivityService = class {
95
95
  this.sendEvents([event]);
96
96
  }
97
97
  async getState() {
98
- return chunkFWEF2DHR_js.safe(this.client.get("/api/v1/activity/state"));
98
+ return chunkGHFDYM5K_js.safe(this.client.get("/api/v1/activity/state"));
99
99
  }
100
100
  async getRecommendations(options) {
101
101
  const params = new URLSearchParams();
@@ -103,10 +103,10 @@ var ActivityService = class {
103
103
  if (options?.limit) params.set("limit", String(options.limit));
104
104
  const query = params.toString();
105
105
  const path = query ? `/api/v1/activity/recommendations?${query}` : "/api/v1/activity/recommendations";
106
- return chunkFWEF2DHR_js.safe(this.client.get(path));
106
+ return chunkGHFDYM5K_js.safe(this.client.get(path));
107
107
  }
108
108
  async dismissMessage(code) {
109
- return chunkFWEF2DHR_js.safe(
109
+ return chunkGHFDYM5K_js.safe(
110
110
  this.client.post("/api/v1/activity/messages/dismiss", { code })
111
111
  );
112
112
  }
@@ -142,16 +142,16 @@ var SubscriptionService = class {
142
142
  this.client = client;
143
143
  }
144
144
  async list() {
145
- return chunkFWEF2DHR_js.safe(this.client.get("/api/v1/subscriptions"));
145
+ return chunkGHFDYM5K_js.safe(this.client.get("/api/v1/subscriptions"));
146
146
  }
147
147
  async get(id) {
148
148
  const encodedId = encodeURIComponent(id);
149
- return chunkFWEF2DHR_js.safe(this.client.get(`/api/v1/subscriptions/${encodedId}`));
149
+ return chunkGHFDYM5K_js.safe(this.client.get(`/api/v1/subscriptions/${encodedId}`));
150
150
  }
151
151
  async cancel(id, reason, opts) {
152
152
  const encodedId = encodeURIComponent(id);
153
- const idempotencyKey = opts?.idempotencyKey ?? chunkFWEF2DHR_js.generateIdempotencyKey();
154
- return chunkFWEF2DHR_js.safe(
153
+ const idempotencyKey = opts?.idempotencyKey ?? chunkGHFDYM5K_js.generateIdempotencyKey();
154
+ return chunkGHFDYM5K_js.safe(
155
155
  this.client.post(
156
156
  `/api/v1/subscriptions/${encodedId}/cancel`,
157
157
  { reason },
@@ -161,20 +161,20 @@ var SubscriptionService = class {
161
161
  }
162
162
  async pause(id) {
163
163
  const encodedId = encodeURIComponent(id);
164
- return chunkFWEF2DHR_js.safe(
164
+ return chunkGHFDYM5K_js.safe(
165
165
  this.client.post(`/api/v1/subscriptions/${encodedId}/pause`)
166
166
  );
167
167
  }
168
168
  async resume(id) {
169
169
  const encodedId = encodeURIComponent(id);
170
- return chunkFWEF2DHR_js.safe(
170
+ return chunkGHFDYM5K_js.safe(
171
171
  this.client.post(`/api/v1/subscriptions/${encodedId}/resume`)
172
172
  );
173
173
  }
174
174
  async skipNextRenewal(id, opts) {
175
175
  const encodedId = encodeURIComponent(id);
176
- const idempotencyKey = opts?.idempotencyKey ?? chunkFWEF2DHR_js.generateIdempotencyKey();
177
- return chunkFWEF2DHR_js.safe(
176
+ const idempotencyKey = opts?.idempotencyKey ?? chunkGHFDYM5K_js.generateIdempotencyKey();
177
+ return chunkGHFDYM5K_js.safe(
178
178
  this.client.post(
179
179
  `/api/v1/subscriptions/${encodedId}/skip`,
180
180
  void 0,
@@ -190,8 +190,8 @@ var UploadService = class {
190
190
  this.client = client;
191
191
  }
192
192
  async init(filename, contentType, sizeBytes, opts) {
193
- const idempotencyKey = opts?.idempotencyKey ?? chunkFWEF2DHR_js.generateIdempotencyKey();
194
- return chunkFWEF2DHR_js.safe(
193
+ const idempotencyKey = opts?.idempotencyKey ?? chunkGHFDYM5K_js.generateIdempotencyKey();
194
+ return chunkGHFDYM5K_js.safe(
195
195
  this.client.post(
196
196
  "/api/v1/uploads/init",
197
197
  {
@@ -204,7 +204,7 @@ var UploadService = class {
204
204
  );
205
205
  }
206
206
  async confirm(uploadId) {
207
- return chunkFWEF2DHR_js.safe(
207
+ return chunkGHFDYM5K_js.safe(
208
208
  this.client.post("/api/v1/uploads/confirm", {
209
209
  upload_id: uploadId
210
210
  })
@@ -250,7 +250,7 @@ var PlacesService = class {
250
250
  this.client = client;
251
251
  }
252
252
  async autocomplete(input, sessionToken) {
253
- return chunkFWEF2DHR_js.safe(
253
+ return chunkGHFDYM5K_js.safe(
254
254
  this.client.post("/api/v1/places/autocomplete", {
255
255
  input,
256
256
  sessionToken
@@ -258,7 +258,7 @@ var PlacesService = class {
258
258
  );
259
259
  }
260
260
  async details(placeId, sessionToken) {
261
- return chunkFWEF2DHR_js.safe(
261
+ return chunkGHFDYM5K_js.safe(
262
262
  this.client.post("/api/v1/places/details", {
263
263
  place_id: placeId,
264
264
  sessionToken
@@ -277,7 +277,7 @@ var DeliveryService = class {
277
277
  params.set("dropoff_lat", String(dropoffLat));
278
278
  params.set("dropoff_lng", String(dropoffLng));
279
279
  if (country) params.set("country", country);
280
- return chunkFWEF2DHR_js.safe(
280
+ return chunkGHFDYM5K_js.safe(
281
281
  this.client.get(`/api/v1/delivery/fee?${params.toString()}`)
282
282
  );
283
283
  }
@@ -289,7 +289,7 @@ var DeliveryService = class {
289
289
  params.set("dropoff_lng", String(dropoffLng));
290
290
  if (opts?.country) params.set("country", opts.country);
291
291
  if (opts?.orderValue != null) params.set("order_value", String(opts.orderValue));
292
- return chunkFWEF2DHR_js.safe(
292
+ return chunkGHFDYM5K_js.safe(
293
293
  this.client.get(`/api/v1/delivery/options?${params.toString()}`)
294
294
  );
295
295
  }
@@ -302,20 +302,25 @@ var SupportService = class {
302
302
  }
303
303
  /** Open (or resume) the customer's widget conversation. */
304
304
  async openConversation(opts) {
305
- const idempotencyKey = opts?.idempotencyKey ?? chunkFWEF2DHR_js.generateIdempotencyKey();
306
- return chunkFWEF2DHR_js.safe(
305
+ const idempotencyKey = opts?.idempotencyKey ?? chunkGHFDYM5K_js.generateIdempotencyKey();
306
+ return chunkGHFDYM5K_js.safe(
307
307
  this.client.post("/api/v1/support/conversation", void 0, {
308
308
  idempotencyKey
309
309
  })
310
310
  );
311
311
  }
312
- /** Send a message in the active conversation. */
312
+ /**
313
+ * Send a message in the active conversation.
314
+ *
315
+ * The idempotency key doubles as the message `client_id`: the backend
316
+ * dedupes on it, so client retries of the same send never insert twice.
317
+ */
313
318
  async sendMessage(content, opts) {
314
- const idempotencyKey = opts?.idempotencyKey ?? chunkFWEF2DHR_js.generateIdempotencyKey();
315
- return chunkFWEF2DHR_js.safe(
319
+ const idempotencyKey = opts?.idempotencyKey ?? chunkGHFDYM5K_js.generateIdempotencyKey();
320
+ return chunkGHFDYM5K_js.safe(
316
321
  this.client.post(
317
322
  "/api/v1/support/conversation/messages",
318
- { content },
323
+ { content, client_id: idempotencyKey },
319
324
  { idempotencyKey }
320
325
  )
321
326
  );
@@ -327,7 +332,7 @@ var SupportService = class {
327
332
  if (options.limit) params.set("limit", String(options.limit));
328
333
  const query = params.toString();
329
334
  const path = query ? `/api/v1/support/conversation/messages?${query}` : "/api/v1/support/conversation/messages";
330
- return chunkFWEF2DHR_js.safe(this.client.get(path));
335
+ return chunkGHFDYM5K_js.safe(this.client.get(path));
331
336
  }
332
337
  };
333
338
 
@@ -396,6 +401,16 @@ function mergeOptionHeaders(base, opts) {
396
401
  }
397
402
  return merged;
398
403
  }
404
+ function generateSessionToken() {
405
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
406
+ return crypto.randomUUID();
407
+ }
408
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
409
+ const r = Math.random() * 16 | 0;
410
+ const v = c === "x" ? r : r & 3 | 8;
411
+ return v.toString(16);
412
+ });
413
+ }
399
414
  function isRetryable(error) {
400
415
  if (error instanceof TypeError && error.message.includes("fetch")) {
401
416
  return true;
@@ -493,7 +508,7 @@ var CimplifyClient = class {
493
508
  this.retryDelay = config.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
494
509
  this.hooks = config.hooks ?? {};
495
510
  this.fetchImpl = (config.fetch ?? globalThis.fetch).bind(globalThis);
496
- this.sessionToken = this.loadSessionToken();
511
+ this.sessionToken = this.loadSessionToken() ?? this.mintSessionToken();
497
512
  if (!this.publicKey && !config.suppressPublicKeyWarning) {
498
513
  console.warn(
499
514
  '[Cimplify] No public key found. Set NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY in your environment, or pass { publicKey: "cpk_..." } to createCimplifyClient().'
@@ -541,6 +556,7 @@ var CimplifyClient = class {
541
556
  if (typeof window !== "undefined" && window.localStorage) {
542
557
  localStorage.removeItem(SESSION_TOKEN_STORAGE_KEY);
543
558
  }
559
+ this.sessionToken = this.mintSessionToken();
544
560
  this.hooks.onSessionChange?.({
545
561
  previousToken: previous,
546
562
  newToken: null,
@@ -602,6 +618,17 @@ var CimplifyClient = class {
602
618
  }
603
619
  this.businessId = normalized;
604
620
  }
621
+ // Set the storefront public key after construction. Needed by hosts that
622
+ // create the client before they know the key (e.g. the Link element, which
623
+ // receives it in its INIT message) — without it, storefront calls carry no
624
+ // X-API-Key and the business can't be resolved.
625
+ setPublicKey(publicKey) {
626
+ const normalized = publicKey.trim();
627
+ if (!normalized) {
628
+ return;
629
+ }
630
+ this.publicKey = normalized;
631
+ }
605
632
  getBusinessId() {
606
633
  return this.businessId;
607
634
  }
@@ -639,6 +666,23 @@ var CimplifyClient = class {
639
666
  }
640
667
  return null;
641
668
  }
669
+ /**
670
+ * Mint the session token client-side so the very first request already
671
+ * carries it. Without this, parallel first-load requests each get a
672
+ * different server-minted token and last-writer-wins splits the session
673
+ * (cart writes and chat conversations land on dropped tokens).
674
+ *
675
+ * Browser-only: minting on a server-shared client instance would pin
676
+ * every visitor to one session, so SSR keeps the lazy server-minted flow.
677
+ */
678
+ mintSessionToken() {
679
+ if (typeof window === "undefined" || !window.localStorage) {
680
+ return null;
681
+ }
682
+ const token = generateSessionToken();
683
+ this.saveSessionToken(token);
684
+ return token;
685
+ }
642
686
  saveSessionToken(token) {
643
687
  if (typeof window !== "undefined" && window.localStorage) {
644
688
  try {
@@ -889,14 +933,9 @@ var CimplifyClient = class {
889
933
  const originalCreatedAt = typeof json.error === "object" && json.error?.original_created_at || "";
890
934
  throw new chunkAETVRBKI_js.IdempotencyMismatchError(errorMessage, originalCreatedAt);
891
935
  }
892
- const error = chunkAETVRBKI_js.enrichError(
893
- new chunkAETVRBKI_js.CimplifyError(
894
- errorCode,
895
- errorMessage,
896
- retryable
897
- ),
898
- { isTestMode: this.isTestMode() }
899
- );
936
+ const error = chunkAETVRBKI_js.enrichError(new chunkAETVRBKI_js.CimplifyError(errorCode, errorMessage, retryable), {
937
+ isTestMode: this.isTestMode()
938
+ });
900
939
  if ((response.status === 401 || error.code === chunkAETVRBKI_js.ErrorCode.UNAUTHORIZED) && this.accessToken) {
901
940
  console.warn(
902
941
  "[Cimplify] Received 401 Unauthorized. Access token may be missing/expired. Refresh authentication and retry the request."
@@ -922,25 +961,25 @@ var CimplifyClient = class {
922
961
  }
923
962
  get catalogue() {
924
963
  if (!this._catalogue) {
925
- this._catalogue = new chunkFWEF2DHR_js.CatalogueQueries(this);
964
+ this._catalogue = new chunkGHFDYM5K_js.CatalogueQueries(this);
926
965
  }
927
966
  return this._catalogue;
928
967
  }
929
968
  get cart() {
930
969
  if (!this._cart) {
931
- this._cart = new chunkFWEF2DHR_js.CartOperations(this);
970
+ this._cart = new chunkGHFDYM5K_js.CartOperations(this);
932
971
  }
933
972
  return this._cart;
934
973
  }
935
974
  get checkout() {
936
975
  if (!this._checkout) {
937
- this._checkout = new chunkFWEF2DHR_js.CheckoutService(this);
976
+ this._checkout = new chunkGHFDYM5K_js.CheckoutService(this);
938
977
  }
939
978
  return this._checkout;
940
979
  }
941
980
  get orders() {
942
981
  if (!this._orders) {
943
- this._orders = new chunkFWEF2DHR_js.OrderQueries(this);
982
+ this._orders = new chunkGHFDYM5K_js.OrderQueries(this);
944
983
  }
945
984
  return this._orders;
946
985
  }
@@ -970,43 +1009,43 @@ var CimplifyClient = class {
970
1009
  }
971
1010
  get link() {
972
1011
  if (!this._link) {
973
- this._link = new chunkFWEF2DHR_js.LinkService(this);
1012
+ this._link = new chunkGHFDYM5K_js.LinkService(this);
974
1013
  }
975
1014
  return this._link;
976
1015
  }
977
1016
  get auth() {
978
1017
  if (!this._auth) {
979
- this._auth = new chunkFWEF2DHR_js.AuthService(this);
1018
+ this._auth = new chunkGHFDYM5K_js.AuthService(this);
980
1019
  }
981
1020
  return this._auth;
982
1021
  }
983
1022
  get business() {
984
1023
  if (!this._business) {
985
- this._business = new chunkFWEF2DHR_js.BusinessService(this);
1024
+ this._business = new chunkGHFDYM5K_js.BusinessService(this);
986
1025
  }
987
1026
  return this._business;
988
1027
  }
989
1028
  get inventory() {
990
1029
  if (!this._inventory) {
991
- this._inventory = new chunkFWEF2DHR_js.InventoryService(this);
1030
+ this._inventory = new chunkGHFDYM5K_js.InventoryService(this);
992
1031
  }
993
1032
  return this._inventory;
994
1033
  }
995
1034
  get scheduling() {
996
1035
  if (!this._scheduling) {
997
- this._scheduling = new chunkFWEF2DHR_js.SchedulingService(this);
1036
+ this._scheduling = new chunkGHFDYM5K_js.SchedulingService(this);
998
1037
  }
999
1038
  return this._scheduling;
1000
1039
  }
1001
1040
  get lite() {
1002
1041
  if (!this._lite) {
1003
- this._lite = new chunkFWEF2DHR_js.LiteService(this);
1042
+ this._lite = new chunkGHFDYM5K_js.LiteService(this);
1004
1043
  }
1005
1044
  return this._lite;
1006
1045
  }
1007
1046
  get fx() {
1008
1047
  if (!this._fx) {
1009
- this._fx = new chunkFWEF2DHR_js.FxService(this);
1048
+ this._fx = new chunkGHFDYM5K_js.FxService(this);
1010
1049
  }
1011
1050
  return this._fx;
1012
1051
  }
@@ -1041,7 +1080,7 @@ var CimplifyClient = class {
1041
1080
  if (businessId) {
1042
1081
  this.setBusinessId(businessId);
1043
1082
  }
1044
- return chunkFWEF2DHR_js.createElements(this, businessId ?? this.businessId ?? void 0, options);
1083
+ return chunkGHFDYM5K_js.createElements(this, businessId ?? this.businessId ?? void 0, options);
1045
1084
  }
1046
1085
  };
1047
1086
  function createCimplifyClient(config = {}) {
@@ -2304,6 +2304,7 @@ var MESSAGE_TYPES = {
2304
2304
  PAYMENT_METHOD_SELECTED: "payment_method_selected",
2305
2305
  LOGOUT_COMPLETE: "logout_complete",
2306
2306
  AUTH_REQUESTED: "auth_requested",
2307
+ SESSION_ESTABLISHED: "session_established",
2307
2308
  CONTACT_PROVIDED: "contact_provided",
2308
2309
  CHECKOUT_STATUS: "checkout_status",
2309
2310
  CHECKOUT_COMPLETE: "checkout_complete",
@@ -2798,6 +2799,7 @@ var CimplifyElements = class {
2798
2799
  if (typeof window !== "undefined") {
2799
2800
  window.addEventListener("message", this.boundHandleMessage);
2800
2801
  }
2802
+ void this.restoreSession();
2801
2803
  }
2802
2804
  debug(...args) {
2803
2805
  if (this.client.isTestMode()) {
@@ -3087,6 +3089,56 @@ var CimplifyElements = class {
3087
3089
  }
3088
3090
  return null;
3089
3091
  }
3092
+ // Refresh token kept first-party (keyed by public key) so a signed-in shopper
3093
+ // survives reloads. Standard SPA tradeoff; far safer than the third-party
3094
+ // iframe, whose storage/cookies are partitioned or blocked.
3095
+ sessionStorageKey() {
3096
+ const key = this.client.getPublicKey().trim();
3097
+ return key ? `cimplify.link.rt.${key}` : null;
3098
+ }
3099
+ persistRefreshToken(refreshToken) {
3100
+ if (typeof window === "undefined") return;
3101
+ const storageKey = this.sessionStorageKey();
3102
+ if (!storageKey) return;
3103
+ try {
3104
+ if (refreshToken) {
3105
+ window.localStorage.setItem(storageKey, refreshToken);
3106
+ } else {
3107
+ window.localStorage.removeItem(storageKey);
3108
+ }
3109
+ } catch {
3110
+ }
3111
+ }
3112
+ clearPersistedSession() {
3113
+ if (typeof window === "undefined") return;
3114
+ const storageKey = this.sessionStorageKey();
3115
+ if (!storageKey) return;
3116
+ try {
3117
+ window.localStorage.removeItem(storageKey);
3118
+ } catch {
3119
+ }
3120
+ }
3121
+ async restoreSession() {
3122
+ if (typeof window === "undefined" || this.accessToken) return;
3123
+ const storageKey = this.sessionStorageKey();
3124
+ if (!storageKey) return;
3125
+ let refreshToken = null;
3126
+ try {
3127
+ refreshToken = window.localStorage.getItem(storageKey);
3128
+ } catch {
3129
+ return;
3130
+ }
3131
+ if (!refreshToken) return;
3132
+ const result = await this.client.link.refreshSession(refreshToken);
3133
+ if (!result.ok || !result.value.session_token) {
3134
+ this.clearPersistedSession();
3135
+ return;
3136
+ }
3137
+ this.persistRefreshToken(result.value.refresh_token ?? void 0);
3138
+ const data = await this.applyAccessToken(result.value.session_token);
3139
+ this.broadcastAccessToken(result.value.session_token);
3140
+ this.elements.forEach((element) => element._emitAuthenticated(data));
3141
+ }
3090
3142
  async applyAccessToken(token) {
3091
3143
  this.accessToken = token;
3092
3144
  this.accountId = decodeJwtSub(token);
@@ -3169,6 +3221,13 @@ var CimplifyElements = class {
3169
3221
  case MESSAGE_TYPES.AUTH_REQUESTED:
3170
3222
  this.startEmbeddedAuth(sourceElement, message);
3171
3223
  break;
3224
+ case MESSAGE_TYPES.SESSION_ESTABLISHED:
3225
+ this.persistRefreshToken(message.refreshToken);
3226
+ void this.applyAccessToken(message.accessToken).then((data) => {
3227
+ this.broadcastAccessToken(message.accessToken);
3228
+ sourceElement._emitAuthenticated(data);
3229
+ });
3230
+ break;
3172
3231
  case MESSAGE_TYPES.ADDRESS_CHANGED:
3173
3232
  case MESSAGE_TYPES.ADDRESS_SELECTED:
3174
3233
  this.addressData = message.address;
@@ -3196,6 +3255,7 @@ var CimplifyElements = class {
3196
3255
  this.customerData = null;
3197
3256
  this.addressData = null;
3198
3257
  this.paymentData = null;
3258
+ this.clearPersistedSession();
3199
3259
  this.client.clearSession();
3200
3260
  break;
3201
3261
  }
@@ -3244,10 +3304,11 @@ var CimplifyElement = class {
3244
3304
  }
3245
3305
  }
3246
3306
  /**
3247
- * Size the iframe to the element's reported content height. The checkout can
3248
- * exceed the viewport, so cap it at the viewport height — the checkout then
3249
- * scrolls internally instead of growing (and scrolling) the host page. Other
3250
- * element types size to content as before.
3307
+ * Size the iframe to the element's reported content height (in pixels). We do
3308
+ * NOT cap checkout at the viewport: capping forced a tall checkout to scroll
3309
+ * *inside* a viewport-height iframe — a nested scroll-within-scroll. Sizing to
3310
+ * content lets the iframe grow and the host page scroll naturally as one
3311
+ * surface, which is the standard embedded-checkout behaviour.
3251
3312
  */
3252
3313
  applyHeight(reportedHeight) {
3253
3314
  if (!this.iframe) return;
@@ -3256,12 +3317,7 @@ var CimplifyElement = class {
3256
3317
  }
3257
3318
  const content = this.lastReportedHeight;
3258
3319
  if (!content) return;
3259
- if (this.type !== "checkout" || typeof window === "undefined") {
3260
- this.iframe.style.height = `${content}px`;
3261
- return;
3262
- }
3263
- const capped = Math.max(320, Math.min(content, window.innerHeight));
3264
- this.iframe.style.height = `${capped}px`;
3320
+ this.iframe.style.height = `${Math.max(320, content)}px`;
3265
3321
  }
3266
3322
  mount(container) {
3267
3323
  if (this.mounted) {
@@ -1,5 +1,5 @@
1
- import { ac as CimplifyClient } from './client-BIt37FjS.mjs';
2
- import { A as AppHandle, C as CreateAppOptions } from './server-0TnEJt8U.mjs';
1
+ import { ac as CimplifyClient } from './client-D8ZFs-sq.mjs';
2
+ import { A as AppHandle, C as CreateAppOptions } from './server-Bk_hlefX.mjs';
3
3
 
4
4
  /**
5
5
  * Test client + fixtures.
@@ -1,5 +1,5 @@
1
- import { ac as CimplifyClient } from './client-Dfl6WY2F.js';
2
- import { A as AppHandle, C as CreateAppOptions } from './server-P2G43ENi.js';
1
+ import { ac as CimplifyClient } from './client-CqZgdUtw.js';
2
+ import { A as AppHandle, C as CreateAppOptions } from './server-Bei5lBrc.js';
3
3
 
4
4
  /**
5
5
  * Test client + fixtures.
@@ -1,5 +1,5 @@
1
- import { V as CimplifyError, S as Category, aZ as Product, f as AddOnWithOptions, aQ as Pagination, bb as ProductWithDetails, b9 as ProductVariant, bF as VariantAxis, bG as VariantAxisSelection, A as AddOn, W as Collection, G as BundleSummary, u as Bundle, a3 as Composite, a1 as ComponentSelectionInput, a8 as CompositePriceResult, U as ChosenPrice, b6 as ProductTaxonomy, bx as TaxonomyWithChildren, ax as EligiblePlansQuery, b1 as ProductBillingPlan, b7 as ProductTimeProfile, b0 as ProductAvailabilityNow, aj as Deal, b2 as ProductDealInfo, ap as DiscountValidation, bu as TagsResponse, ae as CustomAttributeDefinition, af as CustomAttributeValue, bc as PropertyFacet, bw as TaxonomyAttributeTemplate, aJ as KnowledgeArticle, by as UICart, L as CartItem, Q as CartSummary, g as AddToCartInput, N as CartMutationResult, bE as UpdateCartItemInput, ao as DiscountDetails, aO as Money, ad as CurrencyCode, aK as LineConfiguration, bL as VariantDetails, bM as VariantDetailsDTO, a as AddOnDetails, d as AddOnOptionDetails, b as AddOnGroupDetails, D as BundleSelectionData, aa as CompositeSelectionData, ag as CustomerInputValue, bS as components, bk as SchedulingMode, av as DurationUnit, bo as Subscription, bs as SubscriptionWithDetails } from './product-C0Lr81ze.mjs';
2
- import { a as AuthorizationType, c as PaymentMethod, I as InitializePaymentResult, S as SubmitAuthorizationInput, i as PaymentStatusResponse } from './payment-CLp__KpE.mjs';
1
+ import { V as CimplifyError, S as Category, aZ as Product, f as AddOnWithOptions, aQ as Pagination, bb as ProductWithDetails, b9 as ProductVariant, bF as VariantAxis, bG as VariantAxisSelection, A as AddOn, W as Collection, G as BundleSummary, u as Bundle, a3 as Composite, a1 as ComponentSelectionInput, a8 as CompositePriceResult, U as ChosenPrice, b6 as ProductTaxonomy, bx as TaxonomyWithChildren, ax as EligiblePlansQuery, b1 as ProductBillingPlan, b7 as ProductTimeProfile, b0 as ProductAvailabilityNow, aj as Deal, b2 as ProductDealInfo, ap as DiscountValidation, bu as TagsResponse, ae as CustomAttributeDefinition, af as CustomAttributeValue, bc as PropertyFacet, bw as TaxonomyAttributeTemplate, aJ as KnowledgeArticle, by as UICart, L as CartItem, Q as CartSummary, g as AddToCartInput, N as CartMutationResult, bE as UpdateCartItemInput, ao as DiscountDetails, aO as Money, ad as CurrencyCode, aK as LineConfiguration, bL as VariantDetails, bM as VariantDetailsDTO, a as AddOnDetails, d as AddOnOptionDetails, b as AddOnGroupDetails, D as BundleSelectionData, aa as CompositeSelectionData, ag as CustomerInputValue, bS as components, bk as SchedulingMode, av as DurationUnit, bo as Subscription, bs as SubscriptionWithDetails } from './product-BakHcsP2.js';
2
+ import { a as AuthorizationType, c as PaymentMethod, I as InitializePaymentResult, S as SubmitAuthorizationInput, i as PaymentStatusResponse } from './payment-Xq0WDZXh.js';
3
3
 
4
4
  interface RequestContext {
5
5
  method: "GET" | "POST" | "PATCH" | "DELETE";
@@ -1052,6 +1052,7 @@ declare const MESSAGE_TYPES: {
1052
1052
  readonly PAYMENT_METHOD_SELECTED: "payment_method_selected";
1053
1053
  readonly LOGOUT_COMPLETE: "logout_complete";
1054
1054
  readonly AUTH_REQUESTED: "auth_requested";
1055
+ readonly SESSION_ESTABLISHED: "session_established";
1055
1056
  readonly CONTACT_PROVIDED: "contact_provided";
1056
1057
  readonly CHECKOUT_STATUS: "checkout_status";
1057
1058
  readonly CHECKOUT_COMPLETE: "checkout_complete";
@@ -1269,6 +1270,10 @@ type IframeToParentMessage = {
1269
1270
  saveToLink: boolean;
1270
1271
  } | {
1271
1272
  type: typeof MESSAGE_TYPES.LOGOUT_COMPLETE;
1273
+ } | {
1274
+ type: typeof MESSAGE_TYPES.SESSION_ESTABLISHED;
1275
+ accessToken: string;
1276
+ refreshToken?: string;
1272
1277
  } | {
1273
1278
  type: typeof MESSAGE_TYPES.AUTH_REQUESTED;
1274
1279
  loginHint?: string;
@@ -2515,7 +2520,12 @@ declare class SupportService {
2515
2520
  constructor(client: CimplifyClient);
2516
2521
  /** Open (or resume) the customer's widget conversation. */
2517
2522
  openConversation(opts?: IdempotencyOption): Promise<Result<ChatConversationResponse, CimplifyError>>;
2518
- /** Send a message in the active conversation. */
2523
+ /**
2524
+ * Send a message in the active conversation.
2525
+ *
2526
+ * The idempotency key doubles as the message `client_id`: the backend
2527
+ * dedupes on it, so client retries of the same send never insert twice.
2528
+ */
2519
2529
  sendMessage(content: string, opts?: IdempotencyOption): Promise<Result<ChatMessage, CimplifyError>>;
2520
2530
  /** Poll for new messages since the given cursor. */
2521
2531
  getMessages(options?: {
@@ -2557,6 +2567,10 @@ declare class CimplifyElements {
2557
2567
  getAppearance(): ElementsOptions["appearance"];
2558
2568
  private hydrateCustomerData;
2559
2569
  private sourceElementFor;
2570
+ private sessionStorageKey;
2571
+ private persistRefreshToken;
2572
+ private clearPersistedSession;
2573
+ private restoreSession;
2560
2574
  private applyAccessToken;
2561
2575
  private broadcastAccessToken;
2562
2576
  private startEmbeddedAuth;
@@ -2586,10 +2600,11 @@ declare class CimplifyElement {
2586
2600
  private listening;
2587
2601
  constructor(type: ElementType, businessId: string | null, linkUrl: string, options: ElementOptions, parent: CimplifyElements);
2588
2602
  /**
2589
- * Size the iframe to the element's reported content height. The checkout can
2590
- * exceed the viewport, so cap it at the viewport height — the checkout then
2591
- * scrolls internally instead of growing (and scrolling) the host page. Other
2592
- * element types size to content as before.
2603
+ * Size the iframe to the element's reported content height (in pixels). We do
2604
+ * NOT cap checkout at the viewport: capping forced a tall checkout to scroll
2605
+ * *inside* a viewport-height iframe — a nested scroll-within-scroll. Sizing to
2606
+ * content lets the iframe grow and the host page scroll naturally as one
2607
+ * surface, which is the standard embedded-checkout behaviour.
2593
2608
  */
2594
2609
  private applyHeight;
2595
2610
  mount(container: string | HTMLElement): void;
@@ -2711,10 +2726,21 @@ declare class CimplifyClient {
2711
2726
  setLocationId(locationId: string | null): void;
2712
2727
  getLocationId(): string | null;
2713
2728
  setBusinessId(businessId: string): void;
2729
+ setPublicKey(publicKey: string): void;
2714
2730
  getBusinessId(): string | null;
2715
2731
  resolveBusinessId(): Promise<string>;
2716
2732
  private authedFetch;
2717
2733
  private loadSessionToken;
2734
+ /**
2735
+ * Mint the session token client-side so the very first request already
2736
+ * carries it. Without this, parallel first-load requests each get a
2737
+ * different server-minted token and last-writer-wins splits the session
2738
+ * (cart writes and chat conversations land on dropped tokens).
2739
+ *
2740
+ * Browser-only: minting on a server-shared client instance would pin
2741
+ * every visitor to one session, so SSR keeps the lazy server-minted flow.
2742
+ */
2743
+ private mintSessionToken;
2718
2744
  private saveSessionToken;
2719
2745
  private captureSessionToken;
2720
2746
  private getHeaders;