@cimplify/sdk 0.90.0 → 0.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.mts +3 -3
- package/dist/advanced.d.ts +3 -3
- package/dist/advanced.js +20 -20
- package/dist/advanced.mjs +1 -1
- package/dist/{chunk-KJP4U6L3.js → chunk-6Y7KC5YZ.js} +23 -0
- package/dist/{chunk-JVWFIFQ7.js → chunk-AWNWP5J3.js} +4 -4
- package/dist/{chunk-2UDEWILL.mjs → chunk-FKARGZK3.mjs} +307 -90
- package/dist/{chunk-T7Z25EY4.js → chunk-HKN3YG76.js} +84 -0
- package/dist/{chunk-BN4V4ONE.js → chunk-QLGZIBRO.js} +348 -128
- package/dist/{chunk-NGE37REW.mjs → chunk-QXWX7CD2.mjs} +2 -2
- package/dist/{chunk-OZDDHSIB.mjs → chunk-RRBY35TJ.mjs} +80 -1
- package/dist/{chunk-GHFDYM5K.js → chunk-VEOAMBEX.js} +11 -4
- package/dist/{chunk-ZU4ZRYUR.mjs → chunk-VUSHG3HA.mjs} +11 -4
- package/dist/{chunk-NNGKC3MM.mjs → chunk-X36FZZT6.mjs} +23 -0
- package/dist/{client-YiSelM7x.d.mts → client-BTL9d_nN.d.mts} +117 -11
- package/dist/{client-CR1f94wY.d.ts → client-BX30FAWZ.d.ts} +117 -11
- package/dist/{client-DMttx1xk.d.mts → client-Bhe2TnFW.d.mts} +2 -2
- package/dist/{client-CqpOcbin.d.ts → client-DrkuEK_I.d.ts} +2 -2
- package/dist/{index-DD9z396M.d.mts → index-BuNjyfaV.d.mts} +3 -3
- package/dist/{index-CxTVu0HZ.d.ts → index-D-w5h82t.d.ts} +3 -3
- package/dist/index.d.mts +49 -7
- package/dist/index.d.ts +49 -7
- package/dist/index.js +103 -83
- package/dist/index.mjs +5 -5
- package/dist/mock/cli.mjs +23 -0
- package/dist/mock/library.js +23 -0
- package/dist/mock/library.mjs +23 -0
- package/dist/mock/msw.js +23 -0
- package/dist/mock/msw.mjs +23 -0
- package/dist/{payment-BX7ccIKY.d.ts → payment-By0JidTe.d.ts} +1 -1
- package/dist/{payment-5d8FTA1q.d.mts → payment-pKPpaORI.d.mts} +1 -1
- package/dist/{price-DtfP_Xfq.d.ts → price-23RNXftz.d.ts} +1 -1
- package/dist/{price-arl_4Rzn.d.mts → price-BvRtp6ak.d.mts} +1 -1
- package/dist/{product-DZX4QuKS.d.ts → product-O8-wcHSe.d.mts} +49 -0
- package/dist/{product-DZX4QuKS.d.mts → product-O8-wcHSe.d.ts} +49 -0
- package/dist/react.d.mts +79 -6
- package/dist/react.d.ts +79 -6
- package/dist/react.js +607 -379
- package/dist/react.mjs +539 -315
- package/dist/{server-BceZMxcK.d.mts → server-BN9ZCAKT.d.mts} +5 -1
- package/dist/{server-DoJGSC7L.d.ts → server-DDGbfW_S.d.ts} +5 -1
- package/dist/server.d.mts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +7 -7
- package/dist/server.mjs +2 -2
- package/dist/styles.css +1 -1
- package/dist/testing/msw.d.mts +2 -2
- package/dist/testing/msw.d.ts +2 -2
- package/dist/testing/msw.js +2 -2
- package/dist/testing/msw.mjs +1 -1
- package/dist/testing/suite.d.mts +6 -6
- package/dist/testing/suite.d.ts +6 -6
- package/dist/testing/suite.js +23 -23
- package/dist/testing/suite.mjs +4 -4
- package/dist/testing.d.mts +5 -5
- package/dist/testing.d.ts +5 -5
- package/dist/testing.js +79 -79
- package/dist/testing.mjs +5 -5
- package/dist/utils.d.mts +4 -4
- package/dist/utils.d.ts +4 -4
- package/package.json +1 -1
- package/registry/booking-page.json +1 -1
- package/registry/chat-widget.json +1 -1
- package/registry/customer-input-fields.json +1 -1
- package/registry/date-slot-picker.json +1 -1
- package/registry/product-customizer.json +1 -1
- package/registry/rental-service-card.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkVEOAMBEX_js = require('./chunk-VEOAMBEX.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
|
|
16
|
+
return chunkVEOAMBEX_js.safe(this.client.get("/api/v1/store-credit/balance"));
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -74,6 +74,21 @@ var ActivityService = class {
|
|
|
74
74
|
is_new_visitor: isNewVisitor
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Record a page the visitor landed on. Product and category views already
|
|
79
|
+
* imply one, so call this for everything else — home, listings, booking,
|
|
80
|
+
* checkout — or entry pages, exits and bounce rate are computed from
|
|
81
|
+
* product pages alone.
|
|
82
|
+
*/
|
|
83
|
+
trackPageView(options = {}) {
|
|
84
|
+
this.sendEvents([
|
|
85
|
+
{
|
|
86
|
+
type: "page_view",
|
|
87
|
+
page_path: options.pagePath ?? currentPath(),
|
|
88
|
+
page_title: options.pageTitle ?? currentTitle()
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
77
92
|
trackProductView(productId, options = {}) {
|
|
78
93
|
const event = {
|
|
79
94
|
type: "product_view",
|
|
@@ -95,7 +110,7 @@ var ActivityService = class {
|
|
|
95
110
|
this.sendEvents([event]);
|
|
96
111
|
}
|
|
97
112
|
async getState() {
|
|
98
|
-
return
|
|
113
|
+
return chunkVEOAMBEX_js.safe(this.client.get("/api/v1/activity/state"));
|
|
99
114
|
}
|
|
100
115
|
async getRecommendations(options) {
|
|
101
116
|
const params = new URLSearchParams();
|
|
@@ -103,10 +118,10 @@ var ActivityService = class {
|
|
|
103
118
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
104
119
|
const query = params.toString();
|
|
105
120
|
const path = query ? `/api/v1/activity/recommendations?${query}` : "/api/v1/activity/recommendations";
|
|
106
|
-
return
|
|
121
|
+
return chunkVEOAMBEX_js.safe(this.client.get(path));
|
|
107
122
|
}
|
|
108
123
|
async dismissMessage(code) {
|
|
109
|
-
return
|
|
124
|
+
return chunkVEOAMBEX_js.safe(
|
|
110
125
|
this.client.post("/api/v1/activity/messages/dismiss", { code })
|
|
111
126
|
);
|
|
112
127
|
}
|
|
@@ -122,6 +137,12 @@ function currentPath() {
|
|
|
122
137
|
}
|
|
123
138
|
return void 0;
|
|
124
139
|
}
|
|
140
|
+
function currentTitle() {
|
|
141
|
+
if (typeof document !== "undefined" && document.title) {
|
|
142
|
+
return document.title;
|
|
143
|
+
}
|
|
144
|
+
return void 0;
|
|
145
|
+
}
|
|
125
146
|
function resolveVisitor() {
|
|
126
147
|
try {
|
|
127
148
|
const existing = localStorage.getItem(VISITOR_ID_STORAGE_KEY);
|
|
@@ -142,16 +163,16 @@ var SubscriptionService = class {
|
|
|
142
163
|
this.client = client;
|
|
143
164
|
}
|
|
144
165
|
async list() {
|
|
145
|
-
return
|
|
166
|
+
return chunkVEOAMBEX_js.safe(this.client.get("/api/v1/subscriptions"));
|
|
146
167
|
}
|
|
147
168
|
async get(id) {
|
|
148
169
|
const encodedId = encodeURIComponent(id);
|
|
149
|
-
return
|
|
170
|
+
return chunkVEOAMBEX_js.safe(this.client.get(`/api/v1/subscriptions/${encodedId}`));
|
|
150
171
|
}
|
|
151
172
|
async cancel(id, reason, opts) {
|
|
152
173
|
const encodedId = encodeURIComponent(id);
|
|
153
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
154
|
-
return
|
|
174
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
175
|
+
return chunkVEOAMBEX_js.safe(
|
|
155
176
|
this.client.post(
|
|
156
177
|
`/api/v1/subscriptions/${encodedId}/cancel`,
|
|
157
178
|
{ reason },
|
|
@@ -161,20 +182,20 @@ var SubscriptionService = class {
|
|
|
161
182
|
}
|
|
162
183
|
async pause(id) {
|
|
163
184
|
const encodedId = encodeURIComponent(id);
|
|
164
|
-
return
|
|
185
|
+
return chunkVEOAMBEX_js.safe(
|
|
165
186
|
this.client.post(`/api/v1/subscriptions/${encodedId}/pause`)
|
|
166
187
|
);
|
|
167
188
|
}
|
|
168
189
|
async resume(id) {
|
|
169
190
|
const encodedId = encodeURIComponent(id);
|
|
170
|
-
return
|
|
191
|
+
return chunkVEOAMBEX_js.safe(
|
|
171
192
|
this.client.post(`/api/v1/subscriptions/${encodedId}/resume`)
|
|
172
193
|
);
|
|
173
194
|
}
|
|
174
195
|
async skipNextRenewal(id, opts) {
|
|
175
196
|
const encodedId = encodeURIComponent(id);
|
|
176
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
177
|
-
return
|
|
197
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
198
|
+
return chunkVEOAMBEX_js.safe(
|
|
178
199
|
this.client.post(
|
|
179
200
|
`/api/v1/subscriptions/${encodedId}/skip`,
|
|
180
201
|
void 0,
|
|
@@ -190,8 +211,8 @@ var UploadService = class {
|
|
|
190
211
|
this.client = client;
|
|
191
212
|
}
|
|
192
213
|
async init(filename, contentType, sizeBytes, opts) {
|
|
193
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
194
|
-
return
|
|
214
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
215
|
+
return chunkVEOAMBEX_js.safe(
|
|
195
216
|
this.client.post(
|
|
196
217
|
"/api/v1/uploads/init",
|
|
197
218
|
{
|
|
@@ -204,7 +225,7 @@ var UploadService = class {
|
|
|
204
225
|
);
|
|
205
226
|
}
|
|
206
227
|
async confirm(uploadId) {
|
|
207
|
-
return
|
|
228
|
+
return chunkVEOAMBEX_js.safe(
|
|
208
229
|
this.client.post("/api/v1/uploads/confirm", {
|
|
209
230
|
upload_id: uploadId
|
|
210
231
|
})
|
|
@@ -250,7 +271,7 @@ var PlacesService = class {
|
|
|
250
271
|
this.client = client;
|
|
251
272
|
}
|
|
252
273
|
async autocomplete(input, sessionToken) {
|
|
253
|
-
return
|
|
274
|
+
return chunkVEOAMBEX_js.safe(
|
|
254
275
|
this.client.post("/api/v1/places/autocomplete", {
|
|
255
276
|
input,
|
|
256
277
|
sessionToken
|
|
@@ -258,7 +279,7 @@ var PlacesService = class {
|
|
|
258
279
|
);
|
|
259
280
|
}
|
|
260
281
|
async details(placeId, sessionToken) {
|
|
261
|
-
return
|
|
282
|
+
return chunkVEOAMBEX_js.safe(
|
|
262
283
|
this.client.post("/api/v1/places/details", {
|
|
263
284
|
place_id: placeId,
|
|
264
285
|
sessionToken
|
|
@@ -277,7 +298,7 @@ var DeliveryService = class {
|
|
|
277
298
|
params.set("dropoff_lat", String(dropoffLat));
|
|
278
299
|
params.set("dropoff_lng", String(dropoffLng));
|
|
279
300
|
if (country) params.set("country", country);
|
|
280
|
-
return
|
|
301
|
+
return chunkVEOAMBEX_js.safe(
|
|
281
302
|
this.client.get(`/api/v1/delivery/fee?${params.toString()}`)
|
|
282
303
|
);
|
|
283
304
|
}
|
|
@@ -289,21 +310,148 @@ var DeliveryService = class {
|
|
|
289
310
|
params.set("dropoff_lng", String(dropoffLng));
|
|
290
311
|
if (opts?.country) params.set("country", opts.country);
|
|
291
312
|
if (opts?.orderValue != null) params.set("order_value", String(opts.orderValue));
|
|
292
|
-
return
|
|
313
|
+
return chunkVEOAMBEX_js.safe(
|
|
293
314
|
this.client.get(`/api/v1/delivery/options?${params.toString()}`)
|
|
294
315
|
);
|
|
295
316
|
}
|
|
296
317
|
};
|
|
297
318
|
|
|
319
|
+
// src/internal/events.ts
|
|
320
|
+
var MUTATION_ERROR = "mutation:error";
|
|
321
|
+
var AUTH_TOKEN_CHANGED = "auth:token-changed";
|
|
322
|
+
var SESSION_CLAIMED = "session:claimed";
|
|
323
|
+
var SESSION_CLEARED = "session:cleared";
|
|
324
|
+
function createClientEvents() {
|
|
325
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
326
|
+
return {
|
|
327
|
+
on(name, listener) {
|
|
328
|
+
let set = listeners.get(name);
|
|
329
|
+
if (!set) {
|
|
330
|
+
set = /* @__PURE__ */ new Set();
|
|
331
|
+
listeners.set(name, set);
|
|
332
|
+
}
|
|
333
|
+
set.add(listener);
|
|
334
|
+
return () => {
|
|
335
|
+
set?.delete(listener);
|
|
336
|
+
};
|
|
337
|
+
},
|
|
338
|
+
off(name, listener) {
|
|
339
|
+
listeners.get(name)?.delete(listener);
|
|
340
|
+
},
|
|
341
|
+
emit(name, payload) {
|
|
342
|
+
const set = listeners.get(name);
|
|
343
|
+
if (!set) return;
|
|
344
|
+
const snapshot = Array.from(set);
|
|
345
|
+
for (const listener of snapshot) {
|
|
346
|
+
try {
|
|
347
|
+
listener(payload);
|
|
348
|
+
} catch (err2) {
|
|
349
|
+
console.error(`[Cimplify] event listener for "${name}" threw:`, err2);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
298
356
|
// src/support.ts
|
|
357
|
+
var CLAIM_TIMEOUT_MS = 15e3;
|
|
299
358
|
var SupportService = class {
|
|
300
359
|
constructor(client) {
|
|
301
360
|
this.client = client;
|
|
361
|
+
this.claimInFlight = null;
|
|
362
|
+
this.claimInFlightToken = null;
|
|
363
|
+
this.lastClaimedAccessToken = null;
|
|
364
|
+
this.claimedName = null;
|
|
365
|
+
this.client.events.on(SESSION_CLEARED, () => {
|
|
366
|
+
this.lastClaimedAccessToken = null;
|
|
367
|
+
this.claimedName = null;
|
|
368
|
+
});
|
|
369
|
+
this.client.events.on(SESSION_CLAIMED, (event) => {
|
|
370
|
+
if (event.customerName) this.claimedName = event.customerName;
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
/** The verified customer this session's conversation was claimed for, null while anonymous. */
|
|
374
|
+
get claimedCustomerName() {
|
|
375
|
+
return this.claimedName;
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Claim the anonymous session for the verified Link identity: the server
|
|
379
|
+
* verifies the access token, rotates the session token (adopted here, so
|
|
380
|
+
* every subsequent request rides the bound session), folds the guest cart
|
|
381
|
+
* in, and adopts or merges the widget conversation.
|
|
382
|
+
*
|
|
383
|
+
* Idempotent and single-flight: concurrent calls share one request, and a
|
|
384
|
+
* token already claimed by this instance short-circuits without a network
|
|
385
|
+
* round trip. Emits `session:claimed` on the client's event channel.
|
|
386
|
+
*/
|
|
387
|
+
async claimConversation() {
|
|
388
|
+
const accessToken = this.client.getAccessToken();
|
|
389
|
+
if (!accessToken) {
|
|
390
|
+
return chunkVEOAMBEX_js.err(new chunkAETVRBKI_js.CimplifyError("not_authenticated", "No access token to claim with"));
|
|
391
|
+
}
|
|
392
|
+
if (this.claimInFlight) {
|
|
393
|
+
if (this.claimInFlightToken === accessToken) return this.claimInFlight;
|
|
394
|
+
await this.claimInFlight;
|
|
395
|
+
return this.claimConversation();
|
|
396
|
+
}
|
|
397
|
+
if (this.lastClaimedAccessToken === accessToken) {
|
|
398
|
+
return chunkVEOAMBEX_js.err(new chunkAETVRBKI_js.CimplifyError("already_claimed", "Session already claimed for this token"));
|
|
399
|
+
}
|
|
400
|
+
const epoch = this.client.getSessionEpoch();
|
|
401
|
+
this.claimInFlightToken = accessToken;
|
|
402
|
+
this.claimInFlight = (async () => {
|
|
403
|
+
const result = await chunkVEOAMBEX_js.safe(
|
|
404
|
+
this.client.post(
|
|
405
|
+
"/api/v1/support/conversation/claim",
|
|
406
|
+
{ access_token: accessToken },
|
|
407
|
+
{ timeoutMs: CLAIM_TIMEOUT_MS }
|
|
408
|
+
)
|
|
409
|
+
);
|
|
410
|
+
if (result.ok) {
|
|
411
|
+
if (this.client.getSessionEpoch() !== epoch) {
|
|
412
|
+
return chunkVEOAMBEX_js.err(
|
|
413
|
+
new chunkAETVRBKI_js.CimplifyError("session_cleared", "Session was cleared during the claim")
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
this.lastClaimedAccessToken = accessToken;
|
|
417
|
+
this.claimedName = result.value.customer_name || null;
|
|
418
|
+
this.client.adoptSessionToken(result.value.session_token);
|
|
419
|
+
this.client.publishSessionClaimed(this.claimedName);
|
|
420
|
+
this.client.events.emit(SESSION_CLAIMED, {
|
|
421
|
+
sessionToken: result.value.session_token,
|
|
422
|
+
threadId: result.value.thread_id ?? null,
|
|
423
|
+
customerName: result.value.customer_name
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
return result;
|
|
427
|
+
})();
|
|
428
|
+
try {
|
|
429
|
+
return await this.claimInFlight;
|
|
430
|
+
} finally {
|
|
431
|
+
this.claimInFlight = null;
|
|
432
|
+
this.claimInFlightToken = null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Peek at the conversation without creating one: resolves the existing
|
|
437
|
+
* thread (or null) so a page load can hydrate history without littering
|
|
438
|
+
* the inbox with empty threads.
|
|
439
|
+
*/
|
|
440
|
+
async peekConversation() {
|
|
441
|
+
const result = await chunkVEOAMBEX_js.safe(
|
|
442
|
+
this.client.get("/api/v1/support/conversation")
|
|
443
|
+
);
|
|
444
|
+
if (!result.ok) return result;
|
|
445
|
+
if (!result.value.conversation) return chunkVEOAMBEX_js.ok(null);
|
|
446
|
+
return chunkVEOAMBEX_js.ok({
|
|
447
|
+
conversation: result.value.conversation,
|
|
448
|
+
messages: result.value.messages
|
|
449
|
+
});
|
|
302
450
|
}
|
|
303
451
|
/** Open (or resume) the customer's widget conversation. */
|
|
304
452
|
async openConversation(opts) {
|
|
305
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
306
|
-
return
|
|
453
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
454
|
+
return chunkVEOAMBEX_js.safe(
|
|
307
455
|
this.client.post("/api/v1/support/conversation", void 0, {
|
|
308
456
|
idempotencyKey
|
|
309
457
|
})
|
|
@@ -318,8 +466,8 @@ var SupportService = class {
|
|
|
318
466
|
* server resolves it thread-scoped and echoes the quote as `reply_to`.
|
|
319
467
|
*/
|
|
320
468
|
async sendMessage(content, opts) {
|
|
321
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
322
|
-
return
|
|
469
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
470
|
+
return chunkVEOAMBEX_js.safe(
|
|
323
471
|
this.client.post(
|
|
324
472
|
"/api/v1/support/conversation/messages",
|
|
325
473
|
{
|
|
@@ -343,11 +491,11 @@ var SupportService = class {
|
|
|
343
491
|
if (options.limit) params.set("limit", String(options.limit));
|
|
344
492
|
const query = params.toString();
|
|
345
493
|
const path = query ? `/api/v1/support/conversation/messages?${query}` : "/api/v1/support/conversation/messages";
|
|
346
|
-
return
|
|
494
|
+
return chunkVEOAMBEX_js.safe(this.client.get(path));
|
|
347
495
|
}
|
|
348
496
|
/** React to a message in the active conversation by its `ChatMessage.id`. */
|
|
349
497
|
async reactToMessage(messageId, emoji) {
|
|
350
|
-
return
|
|
498
|
+
return chunkVEOAMBEX_js.safe(
|
|
351
499
|
this.client.post(
|
|
352
500
|
`/api/v1/support/conversation/messages/${messageId}/reactions`,
|
|
353
501
|
{ emoji }
|
|
@@ -356,8 +504,8 @@ var SupportService = class {
|
|
|
356
504
|
}
|
|
357
505
|
/** Ask for a person: flags the thread for the merchant's inbox. */
|
|
358
506
|
async requestHuman(opts) {
|
|
359
|
-
const idempotencyKey = opts?.idempotencyKey ??
|
|
360
|
-
return
|
|
507
|
+
const idempotencyKey = opts?.idempotencyKey ?? chunkVEOAMBEX_js.generateIdempotencyKey();
|
|
508
|
+
return chunkVEOAMBEX_js.safe(
|
|
361
509
|
this.client.post(
|
|
362
510
|
"/api/v1/support/conversation/handoff",
|
|
363
511
|
void 0,
|
|
@@ -367,41 +515,9 @@ var SupportService = class {
|
|
|
367
515
|
}
|
|
368
516
|
};
|
|
369
517
|
|
|
370
|
-
// src/internal/events.ts
|
|
371
|
-
function createClientEvents() {
|
|
372
|
-
const listeners = /* @__PURE__ */ new Map();
|
|
373
|
-
return {
|
|
374
|
-
on(name, listener) {
|
|
375
|
-
let set = listeners.get(name);
|
|
376
|
-
if (!set) {
|
|
377
|
-
set = /* @__PURE__ */ new Set();
|
|
378
|
-
listeners.set(name, set);
|
|
379
|
-
}
|
|
380
|
-
set.add(listener);
|
|
381
|
-
return () => {
|
|
382
|
-
set?.delete(listener);
|
|
383
|
-
};
|
|
384
|
-
},
|
|
385
|
-
off(name, listener) {
|
|
386
|
-
listeners.get(name)?.delete(listener);
|
|
387
|
-
},
|
|
388
|
-
emit(name, payload) {
|
|
389
|
-
const set = listeners.get(name);
|
|
390
|
-
if (!set) return;
|
|
391
|
-
const snapshot = Array.from(set);
|
|
392
|
-
for (const listener of snapshot) {
|
|
393
|
-
try {
|
|
394
|
-
listener(payload);
|
|
395
|
-
} catch (err) {
|
|
396
|
-
console.error(`[Cimplify] event listener for "${name}" threw:`, err);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
|
|
403
518
|
// src/client.ts
|
|
404
519
|
var SESSION_TOKEN_STORAGE_KEY = "cimplify_session_token";
|
|
520
|
+
var SESSION_SYNC_STORAGE_KEY = "cimplify_session_sync";
|
|
405
521
|
var ORDER_TOKEN_PREFIX = "cimplify_ot_";
|
|
406
522
|
var SESSION_TOKEN_HEADER = "x-session-token";
|
|
407
523
|
var ORDER_TOKEN_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -518,6 +634,7 @@ var CimplifyClient = class {
|
|
|
518
634
|
constructor(config = {}) {
|
|
519
635
|
this.accessToken = null;
|
|
520
636
|
this.sessionToken = null;
|
|
637
|
+
this.sessionEpoch = 0;
|
|
521
638
|
this.context = {};
|
|
522
639
|
this.businessId = null;
|
|
523
640
|
this.businessIdResolvePromise = null;
|
|
@@ -540,6 +657,7 @@ var CimplifyClient = class {
|
|
|
540
657
|
this.hooks = config.hooks ?? {};
|
|
541
658
|
this.fetchImpl = (config.fetch ?? globalThis.fetch).bind(globalThis);
|
|
542
659
|
this.sessionToken = this.loadSessionToken() ?? this.mintSessionToken();
|
|
660
|
+
this.watchCrossTabSession();
|
|
543
661
|
if (!this.publicKey && !config.suppressPublicKeyWarning) {
|
|
544
662
|
console.warn(
|
|
545
663
|
'[Cimplify] No public key found. Set NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY in your environment, or pass { publicKey: "cpk_..." } to createCimplifyClient().'
|
|
@@ -579,57 +697,133 @@ var CimplifyClient = class {
|
|
|
579
697
|
newToken: token,
|
|
580
698
|
source: "manual"
|
|
581
699
|
});
|
|
700
|
+
this.events.emit(AUTH_TOKEN_CHANGED, { token });
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Zero-UI claim: a freshly verified customer identity (OTP verify, silent
|
|
704
|
+
* refresh restore) binds the anonymous session so the conversation, cart
|
|
705
|
+
* and orders survive a cleared browser. Best-effort by design — a failed
|
|
706
|
+
* claim leaves the session anonymous, exactly as it was. Called by the
|
|
707
|
+
* auth flows, never by the raw token setter.
|
|
708
|
+
*/
|
|
709
|
+
autoClaimChatIdentity() {
|
|
710
|
+
if (typeof window === "undefined" || !this.sessionToken || !this.accessToken) return;
|
|
711
|
+
void this.support.claimConversation();
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Adopt a server-rotated session token (claim flow). The old token stays
|
|
715
|
+
* in flight-safe use until the next request; the storage swap makes the
|
|
716
|
+
* rotation durable across reloads.
|
|
717
|
+
*/
|
|
718
|
+
adoptSessionToken(token) {
|
|
719
|
+
if (!token || token === this.sessionToken) return;
|
|
720
|
+
this.sessionToken = token;
|
|
721
|
+
this.saveSessionToken(token);
|
|
582
722
|
}
|
|
583
723
|
clearSession() {
|
|
584
724
|
const previous = this.accessToken;
|
|
585
725
|
this.accessToken = null;
|
|
586
726
|
this.sessionToken = null;
|
|
587
|
-
|
|
588
|
-
|
|
727
|
+
this.sessionEpoch++;
|
|
728
|
+
try {
|
|
729
|
+
this.safeStorage()?.removeItem(SESSION_TOKEN_STORAGE_KEY);
|
|
730
|
+
} catch {
|
|
589
731
|
}
|
|
590
732
|
this.sessionToken = this.mintSessionToken();
|
|
733
|
+
if (this.sessionToken) {
|
|
734
|
+
this.broadcastSessionSync({ type: "cleared", token: this.sessionToken });
|
|
735
|
+
}
|
|
591
736
|
this.hooks.onSessionChange?.({
|
|
592
737
|
previousToken: previous,
|
|
593
738
|
newToken: null,
|
|
594
739
|
source: "clear"
|
|
595
740
|
});
|
|
741
|
+
this.events.emit(AUTH_TOKEN_CHANGED, { token: null });
|
|
742
|
+
this.events.emit(SESSION_CLEARED, {});
|
|
743
|
+
}
|
|
744
|
+
getSessionEpoch() {
|
|
745
|
+
return this.sessionEpoch;
|
|
746
|
+
}
|
|
747
|
+
publishSessionClaimed(customerName) {
|
|
748
|
+
if (!this.sessionToken) return;
|
|
749
|
+
this.broadcastSessionSync({
|
|
750
|
+
type: "claimed",
|
|
751
|
+
token: this.sessionToken,
|
|
752
|
+
name: customerName
|
|
753
|
+
});
|
|
596
754
|
}
|
|
597
|
-
|
|
598
|
-
|
|
755
|
+
broadcastSessionSync(payload) {
|
|
756
|
+
try {
|
|
757
|
+
this.safeStorage()?.setItem(
|
|
758
|
+
SESSION_SYNC_STORAGE_KEY,
|
|
759
|
+
JSON.stringify({ ...payload, at: Date.now() })
|
|
760
|
+
);
|
|
761
|
+
} catch {
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
watchCrossTabSession() {
|
|
765
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return;
|
|
766
|
+
window.addEventListener("storage", (event) => {
|
|
767
|
+
if (event.key !== SESSION_SYNC_STORAGE_KEY || !event.newValue) return;
|
|
768
|
+
let payload;
|
|
599
769
|
try {
|
|
600
|
-
|
|
601
|
-
localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
|
|
770
|
+
payload = JSON.parse(event.newValue);
|
|
602
771
|
} catch {
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
774
|
+
if (!payload?.token || payload.token === this.sessionToken) return;
|
|
775
|
+
if (payload.type === "claimed") {
|
|
776
|
+
this.sessionToken = payload.token;
|
|
777
|
+
this.events.emit(SESSION_CLAIMED, {
|
|
778
|
+
sessionToken: payload.token,
|
|
779
|
+
threadId: null,
|
|
780
|
+
customerName: payload.name ?? ""
|
|
781
|
+
});
|
|
782
|
+
} else if (payload.type === "cleared") {
|
|
783
|
+
this.accessToken = null;
|
|
784
|
+
this.sessionToken = payload.token;
|
|
785
|
+
this.sessionEpoch++;
|
|
786
|
+
this.events.emit(AUTH_TOKEN_CHANGED, { token: null });
|
|
787
|
+
this.events.emit(SESSION_CLEARED, {});
|
|
603
788
|
}
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
setOrderToken(orderId, token) {
|
|
792
|
+
try {
|
|
793
|
+
const entry = JSON.stringify({ token, storedAt: Date.now() });
|
|
794
|
+
this.safeStorage()?.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
|
|
795
|
+
} catch {
|
|
604
796
|
}
|
|
605
797
|
}
|
|
606
798
|
getOrderToken(orderId) {
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
}
|
|
616
|
-
return entry.token;
|
|
617
|
-
} catch {
|
|
799
|
+
try {
|
|
800
|
+
const storage = this.safeStorage();
|
|
801
|
+
if (!storage) return null;
|
|
802
|
+
const raw = storage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
803
|
+
if (!raw) return null;
|
|
804
|
+
const entry = JSON.parse(raw);
|
|
805
|
+
if (Date.now() - entry.storedAt > ORDER_TOKEN_TTL_MS) {
|
|
806
|
+
storage.removeItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
618
807
|
return null;
|
|
619
808
|
}
|
|
809
|
+
return entry.token;
|
|
810
|
+
} catch {
|
|
811
|
+
return null;
|
|
620
812
|
}
|
|
621
|
-
return null;
|
|
622
813
|
}
|
|
623
814
|
clearOrderTokens() {
|
|
624
|
-
|
|
815
|
+
try {
|
|
816
|
+
const storage = this.safeStorage();
|
|
817
|
+
if (!storage) return;
|
|
625
818
|
const keysToRemove = [];
|
|
626
|
-
for (let i = 0; i <
|
|
627
|
-
const key =
|
|
819
|
+
for (let i = 0; i < storage.length; i++) {
|
|
820
|
+
const key = storage.key(i);
|
|
628
821
|
if (key?.startsWith(ORDER_TOKEN_PREFIX)) {
|
|
629
822
|
keysToRemove.push(key);
|
|
630
823
|
}
|
|
631
824
|
}
|
|
632
|
-
keysToRemove.forEach((k) =>
|
|
825
|
+
keysToRemove.forEach((k) => storage.removeItem(k));
|
|
826
|
+
} catch {
|
|
633
827
|
}
|
|
634
828
|
}
|
|
635
829
|
setLocationId(locationId) {
|
|
@@ -688,22 +882,29 @@ var CimplifyClient = class {
|
|
|
688
882
|
this.businessIdResolvePromise = null;
|
|
689
883
|
}
|
|
690
884
|
}
|
|
691
|
-
async authedFetch(url, options) {
|
|
692
|
-
return this.resilientFetch(url, options);
|
|
885
|
+
async authedFetch(url, options, timeoutMs) {
|
|
886
|
+
return this.resilientFetch(url, options, timeoutMs);
|
|
693
887
|
}
|
|
694
888
|
// Storage guards: even the `window.localStorage` property access throws in
|
|
695
889
|
// some sandboxed iframes and strict private-browsing modes. These run in the
|
|
696
890
|
// constructor at module load, so a throw would white-screen the whole app —
|
|
697
891
|
// fall back to an in-memory session token instead.
|
|
698
|
-
|
|
892
|
+
safeStorage() {
|
|
699
893
|
try {
|
|
700
894
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
701
|
-
return localStorage
|
|
895
|
+
return window.localStorage;
|
|
702
896
|
}
|
|
703
897
|
} catch {
|
|
704
898
|
}
|
|
705
899
|
return null;
|
|
706
900
|
}
|
|
901
|
+
loadSessionToken() {
|
|
902
|
+
try {
|
|
903
|
+
return this.safeStorage()?.getItem(SESSION_TOKEN_STORAGE_KEY) ?? null;
|
|
904
|
+
} catch {
|
|
905
|
+
return null;
|
|
906
|
+
}
|
|
907
|
+
}
|
|
707
908
|
/**
|
|
708
909
|
* Mint the session token client-side so the very first request already
|
|
709
910
|
* carries it. Without this, parallel first-load requests each get a
|
|
@@ -723,15 +924,15 @@ var CimplifyClient = class {
|
|
|
723
924
|
}
|
|
724
925
|
saveSessionToken(token) {
|
|
725
926
|
try {
|
|
726
|
-
|
|
727
|
-
localStorage.setItem(SESSION_TOKEN_STORAGE_KEY, token);
|
|
728
|
-
}
|
|
927
|
+
this.safeStorage()?.setItem(SESSION_TOKEN_STORAGE_KEY, token);
|
|
729
928
|
} catch {
|
|
730
929
|
}
|
|
731
930
|
}
|
|
732
931
|
captureSessionToken(response) {
|
|
932
|
+
if (typeof window === "undefined") return;
|
|
933
|
+
if (this.sessionToken) return;
|
|
733
934
|
const token = response.headers.get(SESSION_TOKEN_HEADER);
|
|
734
|
-
if (token
|
|
935
|
+
if (token) {
|
|
735
936
|
this.sessionToken = token;
|
|
736
937
|
this.saveSessionToken(token);
|
|
737
938
|
}
|
|
@@ -759,7 +960,7 @@ var CimplifyClient = class {
|
|
|
759
960
|
}
|
|
760
961
|
return headers;
|
|
761
962
|
}
|
|
762
|
-
async resilientFetch(url, options) {
|
|
963
|
+
async resilientFetch(url, options, timeoutMs) {
|
|
763
964
|
const method = options.method || "GET";
|
|
764
965
|
const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
|
|
765
966
|
const startTime = Date.now();
|
|
@@ -776,7 +977,7 @@ var CimplifyClient = class {
|
|
|
776
977
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
777
978
|
try {
|
|
778
979
|
const controller = new AbortController();
|
|
779
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
980
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs ?? this.timeout);
|
|
780
981
|
const response = await this.fetchImpl(url, {
|
|
781
982
|
...options,
|
|
782
983
|
signal: controller.signal
|
|
@@ -907,29 +1108,41 @@ var CimplifyClient = class {
|
|
|
907
1108
|
});
|
|
908
1109
|
}
|
|
909
1110
|
async post(path, body, opts) {
|
|
910
|
-
const response = await this.authedFetch(
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1111
|
+
const response = await this.authedFetch(
|
|
1112
|
+
this.buildUrl(this.baseUrl, path),
|
|
1113
|
+
{
|
|
1114
|
+
method: "POST",
|
|
1115
|
+
credentials: this.credentials,
|
|
1116
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1117
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1118
|
+
},
|
|
1119
|
+
opts?.timeoutMs
|
|
1120
|
+
);
|
|
916
1121
|
return this.handleRestResponse(response);
|
|
917
1122
|
}
|
|
918
1123
|
async patch(path, body, opts) {
|
|
919
|
-
const response = await this.authedFetch(
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1124
|
+
const response = await this.authedFetch(
|
|
1125
|
+
this.buildUrl(this.baseUrl, path),
|
|
1126
|
+
{
|
|
1127
|
+
method: "PATCH",
|
|
1128
|
+
credentials: this.credentials,
|
|
1129
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1130
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1131
|
+
},
|
|
1132
|
+
opts?.timeoutMs
|
|
1133
|
+
);
|
|
925
1134
|
return this.handleRestResponse(response);
|
|
926
1135
|
}
|
|
927
1136
|
async delete(path, opts) {
|
|
928
|
-
const response = await this.authedFetch(
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1137
|
+
const response = await this.authedFetch(
|
|
1138
|
+
this.buildUrl(this.baseUrl, path),
|
|
1139
|
+
{
|
|
1140
|
+
method: "DELETE",
|
|
1141
|
+
credentials: this.credentials,
|
|
1142
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts)
|
|
1143
|
+
},
|
|
1144
|
+
opts?.timeoutMs
|
|
1145
|
+
);
|
|
933
1146
|
return this.handleRestResponse(response);
|
|
934
1147
|
}
|
|
935
1148
|
async linkGet(path, opts) {
|
|
@@ -945,12 +1158,16 @@ var CimplifyClient = class {
|
|
|
945
1158
|
});
|
|
946
1159
|
}
|
|
947
1160
|
async linkPost(path, body, opts) {
|
|
948
|
-
const response = await this.authedFetch(
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
1161
|
+
const response = await this.authedFetch(
|
|
1162
|
+
`${this.linkApiUrl}${path}`,
|
|
1163
|
+
{
|
|
1164
|
+
method: "POST",
|
|
1165
|
+
credentials: this.credentials,
|
|
1166
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1167
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1168
|
+
},
|
|
1169
|
+
opts?.timeoutMs
|
|
1170
|
+
);
|
|
954
1171
|
return this.handleRestResponse(response);
|
|
955
1172
|
}
|
|
956
1173
|
async linkDelete(path, opts) {
|
|
@@ -999,25 +1216,25 @@ var CimplifyClient = class {
|
|
|
999
1216
|
}
|
|
1000
1217
|
get catalogue() {
|
|
1001
1218
|
if (!this._catalogue) {
|
|
1002
|
-
this._catalogue = new
|
|
1219
|
+
this._catalogue = new chunkVEOAMBEX_js.CatalogueQueries(this);
|
|
1003
1220
|
}
|
|
1004
1221
|
return this._catalogue;
|
|
1005
1222
|
}
|
|
1006
1223
|
get cart() {
|
|
1007
1224
|
if (!this._cart) {
|
|
1008
|
-
this._cart = new
|
|
1225
|
+
this._cart = new chunkVEOAMBEX_js.CartOperations(this);
|
|
1009
1226
|
}
|
|
1010
1227
|
return this._cart;
|
|
1011
1228
|
}
|
|
1012
1229
|
get checkout() {
|
|
1013
1230
|
if (!this._checkout) {
|
|
1014
|
-
this._checkout = new
|
|
1231
|
+
this._checkout = new chunkVEOAMBEX_js.CheckoutService(this);
|
|
1015
1232
|
}
|
|
1016
1233
|
return this._checkout;
|
|
1017
1234
|
}
|
|
1018
1235
|
get orders() {
|
|
1019
1236
|
if (!this._orders) {
|
|
1020
|
-
this._orders = new
|
|
1237
|
+
this._orders = new chunkVEOAMBEX_js.OrderQueries(this);
|
|
1021
1238
|
}
|
|
1022
1239
|
return this._orders;
|
|
1023
1240
|
}
|
|
@@ -1047,43 +1264,43 @@ var CimplifyClient = class {
|
|
|
1047
1264
|
}
|
|
1048
1265
|
get link() {
|
|
1049
1266
|
if (!this._link) {
|
|
1050
|
-
this._link = new
|
|
1267
|
+
this._link = new chunkVEOAMBEX_js.LinkService(this);
|
|
1051
1268
|
}
|
|
1052
1269
|
return this._link;
|
|
1053
1270
|
}
|
|
1054
1271
|
get auth() {
|
|
1055
1272
|
if (!this._auth) {
|
|
1056
|
-
this._auth = new
|
|
1273
|
+
this._auth = new chunkVEOAMBEX_js.AuthService(this);
|
|
1057
1274
|
}
|
|
1058
1275
|
return this._auth;
|
|
1059
1276
|
}
|
|
1060
1277
|
get business() {
|
|
1061
1278
|
if (!this._business) {
|
|
1062
|
-
this._business = new
|
|
1279
|
+
this._business = new chunkVEOAMBEX_js.BusinessService(this);
|
|
1063
1280
|
}
|
|
1064
1281
|
return this._business;
|
|
1065
1282
|
}
|
|
1066
1283
|
get inventory() {
|
|
1067
1284
|
if (!this._inventory) {
|
|
1068
|
-
this._inventory = new
|
|
1285
|
+
this._inventory = new chunkVEOAMBEX_js.InventoryService(this);
|
|
1069
1286
|
}
|
|
1070
1287
|
return this._inventory;
|
|
1071
1288
|
}
|
|
1072
1289
|
get scheduling() {
|
|
1073
1290
|
if (!this._scheduling) {
|
|
1074
|
-
this._scheduling = new
|
|
1291
|
+
this._scheduling = new chunkVEOAMBEX_js.SchedulingService(this);
|
|
1075
1292
|
}
|
|
1076
1293
|
return this._scheduling;
|
|
1077
1294
|
}
|
|
1078
1295
|
get lite() {
|
|
1079
1296
|
if (!this._lite) {
|
|
1080
|
-
this._lite = new
|
|
1297
|
+
this._lite = new chunkVEOAMBEX_js.LiteService(this);
|
|
1081
1298
|
}
|
|
1082
1299
|
return this._lite;
|
|
1083
1300
|
}
|
|
1084
1301
|
get fx() {
|
|
1085
1302
|
if (!this._fx) {
|
|
1086
|
-
this._fx = new
|
|
1303
|
+
this._fx = new chunkVEOAMBEX_js.FxService(this);
|
|
1087
1304
|
}
|
|
1088
1305
|
return this._fx;
|
|
1089
1306
|
}
|
|
@@ -1118,7 +1335,7 @@ var CimplifyClient = class {
|
|
|
1118
1335
|
if (businessId) {
|
|
1119
1336
|
this.setBusinessId(businessId);
|
|
1120
1337
|
}
|
|
1121
|
-
return
|
|
1338
|
+
return chunkVEOAMBEX_js.createElements(this, businessId ?? this.businessId ?? void 0, options);
|
|
1122
1339
|
}
|
|
1123
1340
|
};
|
|
1124
1341
|
function createCimplifyClient(config = {}) {
|
|
@@ -1128,7 +1345,10 @@ function createCimplifyClient(config = {}) {
|
|
|
1128
1345
|
exports.ActivityService = ActivityService;
|
|
1129
1346
|
exports.CimplifyClient = CimplifyClient;
|
|
1130
1347
|
exports.DeliveryService = DeliveryService;
|
|
1348
|
+
exports.MUTATION_ERROR = MUTATION_ERROR;
|
|
1131
1349
|
exports.PlacesService = PlacesService;
|
|
1350
|
+
exports.SESSION_CLAIMED = SESSION_CLAIMED;
|
|
1351
|
+
exports.SESSION_CLEARED = SESSION_CLEARED;
|
|
1132
1352
|
exports.StoreCreditQueries = StoreCreditQueries;
|
|
1133
1353
|
exports.SubscriptionService = SubscriptionService;
|
|
1134
1354
|
exports.SupportService = SupportService;
|