@cimplify/sdk 0.92.0 → 0.94.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-OAHSF542.js → chunk-6Y7KC5YZ.js} +11 -0
- package/dist/{chunk-3MBMIEWT.js → chunk-AWNWP5J3.js} +4 -4
- package/dist/{chunk-3XD2FVP4.mjs → chunk-FKARGZK3.mjs} +195 -60
- package/dist/{chunk-DCRN67NO.js → chunk-QLGZIBRO.js} +237 -102
- package/dist/{chunk-54H2YYIW.mjs → chunk-QXWX7CD2.mjs} +2 -2
- package/dist/{chunk-IVJEUGWF.js → chunk-VEOAMBEX.js} +1 -3
- package/dist/{chunk-T7LDBZZZ.mjs → chunk-VUSHG3HA.mjs} +1 -3
- package/dist/{chunk-PYBFTMHI.mjs → chunk-X36FZZT6.mjs} +11 -0
- package/dist/{client-CeW3acve.d.ts → client-BTL9d_nN.d.mts} +29 -2
- package/dist/{client-BQbSKlHS.d.mts → client-BX30FAWZ.d.ts} +29 -2
- package/dist/{client-Bw4HtLP1.d.mts → client-Bhe2TnFW.d.mts} +2 -2
- package/dist/{client-Otzv_rgP.d.ts → client-DrkuEK_I.d.ts} +2 -2
- package/dist/{index-CmIboQjl.d.mts → index-BuNjyfaV.d.mts} +3 -3
- package/dist/{index-DgoRwz8l.d.ts → index-D-w5h82t.d.ts} +3 -3
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +69 -69
- package/dist/index.mjs +3 -3
- package/dist/mock/cli.mjs +11 -0
- package/dist/mock/library.js +11 -0
- package/dist/mock/library.mjs +11 -0
- package/dist/mock/msw.js +11 -0
- package/dist/mock/msw.mjs +11 -0
- package/dist/{payment-Cq8FT1B6.d.ts → payment-By0JidTe.d.ts} +1 -1
- package/dist/{payment-BFtLqiG2.d.mts → payment-pKPpaORI.d.mts} +1 -1
- package/dist/{price-DaFXT-Lr.d.ts → price-23RNXftz.d.ts} +1 -1
- package/dist/{price-DleDWk_s.d.mts → price-BvRtp6ak.d.mts} +1 -1
- package/dist/{product-bZ8G5Z8D.d.mts → product-O8-wcHSe.d.mts} +11 -0
- package/dist/{product-bZ8G5Z8D.d.ts → product-O8-wcHSe.d.ts} +11 -0
- package/dist/react.d.mts +20 -6
- package/dist/react.d.ts +20 -6
- package/dist/react.js +208 -76
- package/dist/react.mjs +190 -59
- package/dist/{server-D-iK-bNt.d.mts → server-BN9ZCAKT.d.mts} +5 -1
- package/dist/{server-DwsY9hlX.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/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/chat-widget.json +1 -1
package/dist/advanced.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { k as AuthService, C as BusinessService, O as CartOperations, P as CatalogueQueries, ab as CheckoutOperations, ab as CheckoutService, ah as CimplifyElement, ai as CimplifyElements, aK as ELEMENT_TYPES, aL as EVENT_TYPES, aO as ElementEventType, aP as ElementOptions, aQ as ElementType, aY as ElementsOptions, b4 as FetchQuoteInput, bd as FxService, bh as GetProductsOptions, bk as InventoryService, bs as LinkService, by as LiteService, bF as MESSAGE_TYPES, c5 as OrderQueries, cr as PriceQuote, cx as QuoteBundleSelectionInput, cy as QuoteCompositeSelectionInput, cz as QuoteDynamicBuckets, cA as QuoteStatus, cB as QuoteUiMessage, cD as RefreshQuoteInput, cE as RefreshQuoteResult, d4 as SchedulingService, dK as createElements } from './client-
|
|
2
|
-
import './product-
|
|
3
|
-
import './payment-
|
|
1
|
+
export { k as AuthService, C as BusinessService, O as CartOperations, P as CatalogueQueries, ab as CheckoutOperations, ab as CheckoutService, ah as CimplifyElement, ai as CimplifyElements, aK as ELEMENT_TYPES, aL as EVENT_TYPES, aO as ElementEventType, aP as ElementOptions, aQ as ElementType, aY as ElementsOptions, b4 as FetchQuoteInput, bd as FxService, bh as GetProductsOptions, bk as InventoryService, bs as LinkService, by as LiteService, bF as MESSAGE_TYPES, c5 as OrderQueries, cr as PriceQuote, cx as QuoteBundleSelectionInput, cy as QuoteCompositeSelectionInput, cz as QuoteDynamicBuckets, cA as QuoteStatus, cB as QuoteUiMessage, cD as RefreshQuoteInput, cE as RefreshQuoteResult, d4 as SchedulingService, dK as createElements } from './client-BTL9d_nN.mjs';
|
|
2
|
+
import './product-O8-wcHSe.mjs';
|
|
3
|
+
import './payment-pKPpaORI.mjs';
|
|
4
4
|
|
|
5
5
|
declare function generateIdempotencyKey(prefix?: string): string;
|
|
6
6
|
|
package/dist/advanced.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { k as AuthService, C as BusinessService, O as CartOperations, P as CatalogueQueries, ab as CheckoutOperations, ab as CheckoutService, ah as CimplifyElement, ai as CimplifyElements, aK as ELEMENT_TYPES, aL as EVENT_TYPES, aO as ElementEventType, aP as ElementOptions, aQ as ElementType, aY as ElementsOptions, b4 as FetchQuoteInput, bd as FxService, bh as GetProductsOptions, bk as InventoryService, bs as LinkService, by as LiteService, bF as MESSAGE_TYPES, c5 as OrderQueries, cr as PriceQuote, cx as QuoteBundleSelectionInput, cy as QuoteCompositeSelectionInput, cz as QuoteDynamicBuckets, cA as QuoteStatus, cB as QuoteUiMessage, cD as RefreshQuoteInput, cE as RefreshQuoteResult, d4 as SchedulingService, dK as createElements } from './client-
|
|
2
|
-
import './product-
|
|
3
|
-
import './payment-
|
|
1
|
+
export { k as AuthService, C as BusinessService, O as CartOperations, P as CatalogueQueries, ab as CheckoutOperations, ab as CheckoutService, ah as CimplifyElement, ai as CimplifyElements, aK as ELEMENT_TYPES, aL as EVENT_TYPES, aO as ElementEventType, aP as ElementOptions, aQ as ElementType, aY as ElementsOptions, b4 as FetchQuoteInput, bd as FxService, bh as GetProductsOptions, bk as InventoryService, bs as LinkService, by as LiteService, bF as MESSAGE_TYPES, c5 as OrderQueries, cr as PriceQuote, cx as QuoteBundleSelectionInput, cy as QuoteCompositeSelectionInput, cz as QuoteDynamicBuckets, cA as QuoteStatus, cB as QuoteUiMessage, cD as RefreshQuoteInput, cE as RefreshQuoteResult, d4 as SchedulingService, dK as createElements } from './client-BX30FAWZ.js';
|
|
2
|
+
import './product-O8-wcHSe.js';
|
|
3
|
+
import './payment-By0JidTe.js';
|
|
4
4
|
|
|
5
5
|
declare function generateIdempotencyKey(prefix?: string): string;
|
|
6
6
|
|
package/dist/advanced.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkVEOAMBEX_js = require('./chunk-VEOAMBEX.js');
|
|
4
4
|
require('./chunk-PTPOQVXS.js');
|
|
5
5
|
require('./chunk-AETVRBKI.js');
|
|
6
6
|
require('./chunk-OWW5GUSB.js');
|
|
@@ -9,77 +9,77 @@ require('./chunk-OWW5GUSB.js');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "AuthService", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunkVEOAMBEX_js.AuthService; }
|
|
13
13
|
});
|
|
14
14
|
Object.defineProperty(exports, "BusinessService", {
|
|
15
15
|
enumerable: true,
|
|
16
|
-
get: function () { return
|
|
16
|
+
get: function () { return chunkVEOAMBEX_js.BusinessService; }
|
|
17
17
|
});
|
|
18
18
|
Object.defineProperty(exports, "CartOperations", {
|
|
19
19
|
enumerable: true,
|
|
20
|
-
get: function () { return
|
|
20
|
+
get: function () { return chunkVEOAMBEX_js.CartOperations; }
|
|
21
21
|
});
|
|
22
22
|
Object.defineProperty(exports, "CatalogueQueries", {
|
|
23
23
|
enumerable: true,
|
|
24
|
-
get: function () { return
|
|
24
|
+
get: function () { return chunkVEOAMBEX_js.CatalogueQueries; }
|
|
25
25
|
});
|
|
26
26
|
Object.defineProperty(exports, "CheckoutOperations", {
|
|
27
27
|
enumerable: true,
|
|
28
|
-
get: function () { return
|
|
28
|
+
get: function () { return chunkVEOAMBEX_js.CheckoutService; }
|
|
29
29
|
});
|
|
30
30
|
Object.defineProperty(exports, "CheckoutService", {
|
|
31
31
|
enumerable: true,
|
|
32
|
-
get: function () { return
|
|
32
|
+
get: function () { return chunkVEOAMBEX_js.CheckoutService; }
|
|
33
33
|
});
|
|
34
34
|
Object.defineProperty(exports, "CimplifyElement", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkVEOAMBEX_js.CimplifyElement; }
|
|
37
37
|
});
|
|
38
38
|
Object.defineProperty(exports, "CimplifyElements", {
|
|
39
39
|
enumerable: true,
|
|
40
|
-
get: function () { return
|
|
40
|
+
get: function () { return chunkVEOAMBEX_js.CimplifyElements; }
|
|
41
41
|
});
|
|
42
42
|
Object.defineProperty(exports, "ELEMENT_TYPES", {
|
|
43
43
|
enumerable: true,
|
|
44
|
-
get: function () { return
|
|
44
|
+
get: function () { return chunkVEOAMBEX_js.ELEMENT_TYPES; }
|
|
45
45
|
});
|
|
46
46
|
Object.defineProperty(exports, "EVENT_TYPES", {
|
|
47
47
|
enumerable: true,
|
|
48
|
-
get: function () { return
|
|
48
|
+
get: function () { return chunkVEOAMBEX_js.EVENT_TYPES; }
|
|
49
49
|
});
|
|
50
50
|
Object.defineProperty(exports, "FxService", {
|
|
51
51
|
enumerable: true,
|
|
52
|
-
get: function () { return
|
|
52
|
+
get: function () { return chunkVEOAMBEX_js.FxService; }
|
|
53
53
|
});
|
|
54
54
|
Object.defineProperty(exports, "InventoryService", {
|
|
55
55
|
enumerable: true,
|
|
56
|
-
get: function () { return
|
|
56
|
+
get: function () { return chunkVEOAMBEX_js.InventoryService; }
|
|
57
57
|
});
|
|
58
58
|
Object.defineProperty(exports, "LinkService", {
|
|
59
59
|
enumerable: true,
|
|
60
|
-
get: function () { return
|
|
60
|
+
get: function () { return chunkVEOAMBEX_js.LinkService; }
|
|
61
61
|
});
|
|
62
62
|
Object.defineProperty(exports, "LiteService", {
|
|
63
63
|
enumerable: true,
|
|
64
|
-
get: function () { return
|
|
64
|
+
get: function () { return chunkVEOAMBEX_js.LiteService; }
|
|
65
65
|
});
|
|
66
66
|
Object.defineProperty(exports, "MESSAGE_TYPES", {
|
|
67
67
|
enumerable: true,
|
|
68
|
-
get: function () { return
|
|
68
|
+
get: function () { return chunkVEOAMBEX_js.MESSAGE_TYPES; }
|
|
69
69
|
});
|
|
70
70
|
Object.defineProperty(exports, "OrderQueries", {
|
|
71
71
|
enumerable: true,
|
|
72
|
-
get: function () { return
|
|
72
|
+
get: function () { return chunkVEOAMBEX_js.OrderQueries; }
|
|
73
73
|
});
|
|
74
74
|
Object.defineProperty(exports, "SchedulingService", {
|
|
75
75
|
enumerable: true,
|
|
76
|
-
get: function () { return
|
|
76
|
+
get: function () { return chunkVEOAMBEX_js.SchedulingService; }
|
|
77
77
|
});
|
|
78
78
|
Object.defineProperty(exports, "createElements", {
|
|
79
79
|
enumerable: true,
|
|
80
|
-
get: function () { return
|
|
80
|
+
get: function () { return chunkVEOAMBEX_js.createElements; }
|
|
81
81
|
});
|
|
82
82
|
Object.defineProperty(exports, "generateIdempotencyKey", {
|
|
83
83
|
enumerable: true,
|
|
84
|
-
get: function () { return
|
|
84
|
+
get: function () { return chunkVEOAMBEX_js.generateIdempotencyKey; }
|
|
85
85
|
});
|
package/dist/advanced.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AuthService, BusinessService, CartOperations, CatalogueQueries, CheckoutService as CheckoutOperations, CheckoutService, CimplifyElement, CimplifyElements, ELEMENT_TYPES, EVENT_TYPES, FxService, InventoryService, LinkService, LiteService, MESSAGE_TYPES, OrderQueries, SchedulingService, createElements, generateIdempotencyKey } from './chunk-
|
|
1
|
+
export { AuthService, BusinessService, CartOperations, CatalogueQueries, CheckoutService as CheckoutOperations, CheckoutService, CimplifyElement, CimplifyElements, ELEMENT_TYPES, EVENT_TYPES, FxService, InventoryService, LinkService, LiteService, MESSAGE_TYPES, OrderQueries, SchedulingService, createElements, generateIdempotencyKey } from './chunk-VUSHG3HA.mjs';
|
|
2
2
|
import './chunk-KFLGQGMC.mjs';
|
|
3
3
|
import './chunk-K5EN2W2Q.mjs';
|
|
4
4
|
import './chunk-3G6RQLXK.mjs';
|
|
@@ -2482,6 +2482,10 @@ function buildV1(deps) {
|
|
|
2482
2482
|
"/support/conversation",
|
|
2483
2483
|
(c) => tryRoute(c, () => deps.support.openConversation(deps.defaultBusinessId, c.var.session.customer_id))
|
|
2484
2484
|
);
|
|
2485
|
+
app.get(
|
|
2486
|
+
"/support/conversation",
|
|
2487
|
+
(c) => tryRoute(c, () => deps.support.peekConversation(deps.defaultBusinessId, c.var.session.customer_id))
|
|
2488
|
+
);
|
|
2485
2489
|
app.post("/support/conversation/messages", async (c) => {
|
|
2486
2490
|
const body = await c.req.json().catch(() => ({}));
|
|
2487
2491
|
return tryRoute(
|
|
@@ -5480,6 +5484,13 @@ function createSupportService(opts) {
|
|
|
5480
5484
|
registry.conversations.put(id, conv);
|
|
5481
5485
|
return conv;
|
|
5482
5486
|
},
|
|
5487
|
+
peekConversation(businessId, customerId) {
|
|
5488
|
+
const matches = registry.conversations.list(
|
|
5489
|
+
(c) => c.business_id === businessId && c.customer_id === customerId
|
|
5490
|
+
);
|
|
5491
|
+
const conv = matches[matches.length - 1];
|
|
5492
|
+
return conv ? { conversation: conv, messages: conv.messages } : { conversation: null, messages: [] };
|
|
5493
|
+
},
|
|
5483
5494
|
sendMessage(conversationId, body) {
|
|
5484
5495
|
const conv = registry.conversations.get(conversationId);
|
|
5485
5496
|
if (!conv) throw notFound(`Conversation ${conversationId} not found`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunk6Y7KC5YZ_js = require('./chunk-6Y7KC5YZ.js');
|
|
4
|
+
var chunkQLGZIBRO_js = require('./chunk-QLGZIBRO.js');
|
|
5
5
|
var zod = require('zod');
|
|
6
6
|
|
|
7
7
|
var cimplifyRegistry = zod.z.registry();
|
|
@@ -600,7 +600,7 @@ async function toForwardedRequest(input, init) {
|
|
|
600
600
|
};
|
|
601
601
|
}
|
|
602
602
|
function createTestClient(options = {}) {
|
|
603
|
-
const mock =
|
|
603
|
+
const mock = chunk6Y7KC5YZ_js.createMockApp(options);
|
|
604
604
|
let sessionToken;
|
|
605
605
|
const fetchImpl = async (input, init) => {
|
|
606
606
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
@@ -619,7 +619,7 @@ function createTestClient(options = {}) {
|
|
|
619
619
|
if (echoed) sessionToken = echoed;
|
|
620
620
|
return res;
|
|
621
621
|
};
|
|
622
|
-
const client =
|
|
622
|
+
const client = chunkQLGZIBRO_js.createCimplifyClient({
|
|
623
623
|
baseUrl: TEST_BASE_URL,
|
|
624
624
|
// Link mock lives at /v1/link on the same Hono app, so point the SDK's
|
|
625
625
|
// separate Link transport at the same TEST_BASE_URL.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { safe, generateIdempotencyKey, err, CatalogueQueries, CartOperations, CheckoutService, OrderQueries, LinkService, AuthService, BusinessService, InventoryService, SchedulingService, LiteService, FxService, createElements } from './chunk-
|
|
1
|
+
import { safe, generateIdempotencyKey, err, ok, CatalogueQueries, CartOperations, CheckoutService, OrderQueries, LinkService, AuthService, BusinessService, InventoryService, SchedulingService, LiteService, FxService, createElements } from './chunk-VUSHG3HA.mjs';
|
|
2
2
|
import { CimplifyError, ErrorCode, IdempotencyMismatchError, enrichError } from './chunk-K5EN2W2Q.mjs';
|
|
3
3
|
|
|
4
4
|
// src/store-credit.ts
|
|
@@ -72,6 +72,21 @@ var ActivityService = class {
|
|
|
72
72
|
is_new_visitor: isNewVisitor
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Record a page the visitor landed on. Product and category views already
|
|
77
|
+
* imply one, so call this for everything else — home, listings, booking,
|
|
78
|
+
* checkout — or entry pages, exits and bounce rate are computed from
|
|
79
|
+
* product pages alone.
|
|
80
|
+
*/
|
|
81
|
+
trackPageView(options = {}) {
|
|
82
|
+
this.sendEvents([
|
|
83
|
+
{
|
|
84
|
+
type: "page_view",
|
|
85
|
+
page_path: options.pagePath ?? currentPath(),
|
|
86
|
+
page_title: options.pageTitle ?? currentTitle()
|
|
87
|
+
}
|
|
88
|
+
]);
|
|
89
|
+
}
|
|
75
90
|
trackProductView(productId, options = {}) {
|
|
76
91
|
const event = {
|
|
77
92
|
type: "product_view",
|
|
@@ -120,6 +135,12 @@ function currentPath() {
|
|
|
120
135
|
}
|
|
121
136
|
return void 0;
|
|
122
137
|
}
|
|
138
|
+
function currentTitle() {
|
|
139
|
+
if (typeof document !== "undefined" && document.title) {
|
|
140
|
+
return document.title;
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
123
144
|
function resolveVisitor() {
|
|
124
145
|
try {
|
|
125
146
|
const existing = localStorage.getItem(VISITOR_ID_STORAGE_KEY);
|
|
@@ -331,16 +352,21 @@ function createClientEvents() {
|
|
|
331
352
|
}
|
|
332
353
|
|
|
333
354
|
// src/support.ts
|
|
355
|
+
var CLAIM_TIMEOUT_MS = 15e3;
|
|
334
356
|
var SupportService = class {
|
|
335
357
|
constructor(client) {
|
|
336
358
|
this.client = client;
|
|
337
359
|
this.claimInFlight = null;
|
|
360
|
+
this.claimInFlightToken = null;
|
|
338
361
|
this.lastClaimedAccessToken = null;
|
|
339
362
|
this.claimedName = null;
|
|
340
363
|
this.client.events.on(SESSION_CLEARED, () => {
|
|
341
364
|
this.lastClaimedAccessToken = null;
|
|
342
365
|
this.claimedName = null;
|
|
343
366
|
});
|
|
367
|
+
this.client.events.on(SESSION_CLAIMED, (event) => {
|
|
368
|
+
if (event.customerName) this.claimedName = event.customerName;
|
|
369
|
+
});
|
|
344
370
|
}
|
|
345
371
|
/** The verified customer this session's conversation was claimed for, null while anonymous. */
|
|
346
372
|
get claimedCustomerName() {
|
|
@@ -361,20 +387,34 @@ var SupportService = class {
|
|
|
361
387
|
if (!accessToken) {
|
|
362
388
|
return err(new CimplifyError("not_authenticated", "No access token to claim with"));
|
|
363
389
|
}
|
|
364
|
-
if (this.claimInFlight)
|
|
390
|
+
if (this.claimInFlight) {
|
|
391
|
+
if (this.claimInFlightToken === accessToken) return this.claimInFlight;
|
|
392
|
+
await this.claimInFlight;
|
|
393
|
+
return this.claimConversation();
|
|
394
|
+
}
|
|
365
395
|
if (this.lastClaimedAccessToken === accessToken) {
|
|
366
396
|
return err(new CimplifyError("already_claimed", "Session already claimed for this token"));
|
|
367
397
|
}
|
|
398
|
+
const epoch = this.client.getSessionEpoch();
|
|
399
|
+
this.claimInFlightToken = accessToken;
|
|
368
400
|
this.claimInFlight = (async () => {
|
|
369
401
|
const result = await safe(
|
|
370
|
-
this.client.post(
|
|
371
|
-
|
|
372
|
-
|
|
402
|
+
this.client.post(
|
|
403
|
+
"/api/v1/support/conversation/claim",
|
|
404
|
+
{ access_token: accessToken },
|
|
405
|
+
{ timeoutMs: CLAIM_TIMEOUT_MS }
|
|
406
|
+
)
|
|
373
407
|
);
|
|
374
408
|
if (result.ok) {
|
|
409
|
+
if (this.client.getSessionEpoch() !== epoch) {
|
|
410
|
+
return err(
|
|
411
|
+
new CimplifyError("session_cleared", "Session was cleared during the claim")
|
|
412
|
+
);
|
|
413
|
+
}
|
|
375
414
|
this.lastClaimedAccessToken = accessToken;
|
|
376
415
|
this.claimedName = result.value.customer_name || null;
|
|
377
416
|
this.client.adoptSessionToken(result.value.session_token);
|
|
417
|
+
this.client.publishSessionClaimed(this.claimedName);
|
|
378
418
|
this.client.events.emit(SESSION_CLAIMED, {
|
|
379
419
|
sessionToken: result.value.session_token,
|
|
380
420
|
threadId: result.value.thread_id ?? null,
|
|
@@ -387,8 +427,25 @@ var SupportService = class {
|
|
|
387
427
|
return await this.claimInFlight;
|
|
388
428
|
} finally {
|
|
389
429
|
this.claimInFlight = null;
|
|
430
|
+
this.claimInFlightToken = null;
|
|
390
431
|
}
|
|
391
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* Peek at the conversation without creating one: resolves the existing
|
|
435
|
+
* thread (or null) so a page load can hydrate history without littering
|
|
436
|
+
* the inbox with empty threads.
|
|
437
|
+
*/
|
|
438
|
+
async peekConversation() {
|
|
439
|
+
const result = await safe(
|
|
440
|
+
this.client.get("/api/v1/support/conversation")
|
|
441
|
+
);
|
|
442
|
+
if (!result.ok) return result;
|
|
443
|
+
if (!result.value.conversation) return ok(null);
|
|
444
|
+
return ok({
|
|
445
|
+
conversation: result.value.conversation,
|
|
446
|
+
messages: result.value.messages
|
|
447
|
+
});
|
|
448
|
+
}
|
|
392
449
|
/** Open (or resume) the customer's widget conversation. */
|
|
393
450
|
async openConversation(opts) {
|
|
394
451
|
const idempotencyKey = opts?.idempotencyKey ?? generateIdempotencyKey();
|
|
@@ -458,6 +515,7 @@ var SupportService = class {
|
|
|
458
515
|
|
|
459
516
|
// src/client.ts
|
|
460
517
|
var SESSION_TOKEN_STORAGE_KEY = "cimplify_session_token";
|
|
518
|
+
var SESSION_SYNC_STORAGE_KEY = "cimplify_session_sync";
|
|
461
519
|
var ORDER_TOKEN_PREFIX = "cimplify_ot_";
|
|
462
520
|
var SESSION_TOKEN_HEADER = "x-session-token";
|
|
463
521
|
var ORDER_TOKEN_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -574,6 +632,7 @@ var CimplifyClient = class {
|
|
|
574
632
|
constructor(config = {}) {
|
|
575
633
|
this.accessToken = null;
|
|
576
634
|
this.sessionToken = null;
|
|
635
|
+
this.sessionEpoch = 0;
|
|
577
636
|
this.context = {};
|
|
578
637
|
this.businessId = null;
|
|
579
638
|
this.businessIdResolvePromise = null;
|
|
@@ -596,6 +655,7 @@ var CimplifyClient = class {
|
|
|
596
655
|
this.hooks = config.hooks ?? {};
|
|
597
656
|
this.fetchImpl = (config.fetch ?? globalThis.fetch).bind(globalThis);
|
|
598
657
|
this.sessionToken = this.loadSessionToken() ?? this.mintSessionToken();
|
|
658
|
+
this.watchCrossTabSession();
|
|
599
659
|
if (!this.publicKey && !config.suppressPublicKeyWarning) {
|
|
600
660
|
console.warn(
|
|
601
661
|
'[Cimplify] No public key found. Set NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY in your environment, or pass { publicKey: "cpk_..." } to createCimplifyClient().'
|
|
@@ -662,10 +722,15 @@ var CimplifyClient = class {
|
|
|
662
722
|
const previous = this.accessToken;
|
|
663
723
|
this.accessToken = null;
|
|
664
724
|
this.sessionToken = null;
|
|
665
|
-
|
|
666
|
-
|
|
725
|
+
this.sessionEpoch++;
|
|
726
|
+
try {
|
|
727
|
+
this.safeStorage()?.removeItem(SESSION_TOKEN_STORAGE_KEY);
|
|
728
|
+
} catch {
|
|
667
729
|
}
|
|
668
730
|
this.sessionToken = this.mintSessionToken();
|
|
731
|
+
if (this.sessionToken) {
|
|
732
|
+
this.broadcastSessionSync({ type: "cleared", token: this.sessionToken });
|
|
733
|
+
}
|
|
669
734
|
this.hooks.onSessionChange?.({
|
|
670
735
|
previousToken: previous,
|
|
671
736
|
newToken: null,
|
|
@@ -674,42 +739,89 @@ var CimplifyClient = class {
|
|
|
674
739
|
this.events.emit(AUTH_TOKEN_CHANGED, { token: null });
|
|
675
740
|
this.events.emit(SESSION_CLEARED, {});
|
|
676
741
|
}
|
|
677
|
-
|
|
678
|
-
|
|
742
|
+
getSessionEpoch() {
|
|
743
|
+
return this.sessionEpoch;
|
|
744
|
+
}
|
|
745
|
+
publishSessionClaimed(customerName) {
|
|
746
|
+
if (!this.sessionToken) return;
|
|
747
|
+
this.broadcastSessionSync({
|
|
748
|
+
type: "claimed",
|
|
749
|
+
token: this.sessionToken,
|
|
750
|
+
name: customerName
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
broadcastSessionSync(payload) {
|
|
754
|
+
try {
|
|
755
|
+
this.safeStorage()?.setItem(
|
|
756
|
+
SESSION_SYNC_STORAGE_KEY,
|
|
757
|
+
JSON.stringify({ ...payload, at: Date.now() })
|
|
758
|
+
);
|
|
759
|
+
} catch {
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
watchCrossTabSession() {
|
|
763
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return;
|
|
764
|
+
window.addEventListener("storage", (event) => {
|
|
765
|
+
if (event.key !== SESSION_SYNC_STORAGE_KEY || !event.newValue) return;
|
|
766
|
+
let payload;
|
|
679
767
|
try {
|
|
680
|
-
|
|
681
|
-
localStorage.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
|
|
768
|
+
payload = JSON.parse(event.newValue);
|
|
682
769
|
} catch {
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
if (!payload?.token || payload.token === this.sessionToken) return;
|
|
773
|
+
if (payload.type === "claimed") {
|
|
774
|
+
this.sessionToken = payload.token;
|
|
775
|
+
this.events.emit(SESSION_CLAIMED, {
|
|
776
|
+
sessionToken: payload.token,
|
|
777
|
+
threadId: null,
|
|
778
|
+
customerName: payload.name ?? ""
|
|
779
|
+
});
|
|
780
|
+
} else if (payload.type === "cleared") {
|
|
781
|
+
this.accessToken = null;
|
|
782
|
+
this.sessionToken = payload.token;
|
|
783
|
+
this.sessionEpoch++;
|
|
784
|
+
this.events.emit(AUTH_TOKEN_CHANGED, { token: null });
|
|
785
|
+
this.events.emit(SESSION_CLEARED, {});
|
|
683
786
|
}
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
setOrderToken(orderId, token) {
|
|
790
|
+
try {
|
|
791
|
+
const entry = JSON.stringify({ token, storedAt: Date.now() });
|
|
792
|
+
this.safeStorage()?.setItem(`${ORDER_TOKEN_PREFIX}${orderId}`, entry);
|
|
793
|
+
} catch {
|
|
684
794
|
}
|
|
685
795
|
}
|
|
686
796
|
getOrderToken(orderId) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
}
|
|
696
|
-
return entry.token;
|
|
697
|
-
} catch {
|
|
797
|
+
try {
|
|
798
|
+
const storage = this.safeStorage();
|
|
799
|
+
if (!storage) return null;
|
|
800
|
+
const raw = storage.getItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
801
|
+
if (!raw) return null;
|
|
802
|
+
const entry = JSON.parse(raw);
|
|
803
|
+
if (Date.now() - entry.storedAt > ORDER_TOKEN_TTL_MS) {
|
|
804
|
+
storage.removeItem(`${ORDER_TOKEN_PREFIX}${orderId}`);
|
|
698
805
|
return null;
|
|
699
806
|
}
|
|
807
|
+
return entry.token;
|
|
808
|
+
} catch {
|
|
809
|
+
return null;
|
|
700
810
|
}
|
|
701
|
-
return null;
|
|
702
811
|
}
|
|
703
812
|
clearOrderTokens() {
|
|
704
|
-
|
|
813
|
+
try {
|
|
814
|
+
const storage = this.safeStorage();
|
|
815
|
+
if (!storage) return;
|
|
705
816
|
const keysToRemove = [];
|
|
706
|
-
for (let i = 0; i <
|
|
707
|
-
const key =
|
|
817
|
+
for (let i = 0; i < storage.length; i++) {
|
|
818
|
+
const key = storage.key(i);
|
|
708
819
|
if (key?.startsWith(ORDER_TOKEN_PREFIX)) {
|
|
709
820
|
keysToRemove.push(key);
|
|
710
821
|
}
|
|
711
822
|
}
|
|
712
|
-
keysToRemove.forEach((k) =>
|
|
823
|
+
keysToRemove.forEach((k) => storage.removeItem(k));
|
|
824
|
+
} catch {
|
|
713
825
|
}
|
|
714
826
|
}
|
|
715
827
|
setLocationId(locationId) {
|
|
@@ -768,22 +880,29 @@ var CimplifyClient = class {
|
|
|
768
880
|
this.businessIdResolvePromise = null;
|
|
769
881
|
}
|
|
770
882
|
}
|
|
771
|
-
async authedFetch(url, options) {
|
|
772
|
-
return this.resilientFetch(url, options);
|
|
883
|
+
async authedFetch(url, options, timeoutMs) {
|
|
884
|
+
return this.resilientFetch(url, options, timeoutMs);
|
|
773
885
|
}
|
|
774
886
|
// Storage guards: even the `window.localStorage` property access throws in
|
|
775
887
|
// some sandboxed iframes and strict private-browsing modes. These run in the
|
|
776
888
|
// constructor at module load, so a throw would white-screen the whole app —
|
|
777
889
|
// fall back to an in-memory session token instead.
|
|
778
|
-
|
|
890
|
+
safeStorage() {
|
|
779
891
|
try {
|
|
780
892
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
781
|
-
return localStorage
|
|
893
|
+
return window.localStorage;
|
|
782
894
|
}
|
|
783
895
|
} catch {
|
|
784
896
|
}
|
|
785
897
|
return null;
|
|
786
898
|
}
|
|
899
|
+
loadSessionToken() {
|
|
900
|
+
try {
|
|
901
|
+
return this.safeStorage()?.getItem(SESSION_TOKEN_STORAGE_KEY) ?? null;
|
|
902
|
+
} catch {
|
|
903
|
+
return null;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
787
906
|
/**
|
|
788
907
|
* Mint the session token client-side so the very first request already
|
|
789
908
|
* carries it. Without this, parallel first-load requests each get a
|
|
@@ -803,15 +922,15 @@ var CimplifyClient = class {
|
|
|
803
922
|
}
|
|
804
923
|
saveSessionToken(token) {
|
|
805
924
|
try {
|
|
806
|
-
|
|
807
|
-
localStorage.setItem(SESSION_TOKEN_STORAGE_KEY, token);
|
|
808
|
-
}
|
|
925
|
+
this.safeStorage()?.setItem(SESSION_TOKEN_STORAGE_KEY, token);
|
|
809
926
|
} catch {
|
|
810
927
|
}
|
|
811
928
|
}
|
|
812
929
|
captureSessionToken(response) {
|
|
930
|
+
if (typeof window === "undefined") return;
|
|
931
|
+
if (this.sessionToken) return;
|
|
813
932
|
const token = response.headers.get(SESSION_TOKEN_HEADER);
|
|
814
|
-
if (token
|
|
933
|
+
if (token) {
|
|
815
934
|
this.sessionToken = token;
|
|
816
935
|
this.saveSessionToken(token);
|
|
817
936
|
}
|
|
@@ -839,7 +958,7 @@ var CimplifyClient = class {
|
|
|
839
958
|
}
|
|
840
959
|
return headers;
|
|
841
960
|
}
|
|
842
|
-
async resilientFetch(url, options) {
|
|
961
|
+
async resilientFetch(url, options, timeoutMs) {
|
|
843
962
|
const method = options.method || "GET";
|
|
844
963
|
const path = url.replace(this.baseUrl, "").replace(this.linkApiUrl, "");
|
|
845
964
|
const startTime = Date.now();
|
|
@@ -856,7 +975,7 @@ var CimplifyClient = class {
|
|
|
856
975
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
857
976
|
try {
|
|
858
977
|
const controller = new AbortController();
|
|
859
|
-
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
978
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs ?? this.timeout);
|
|
860
979
|
const response = await this.fetchImpl(url, {
|
|
861
980
|
...options,
|
|
862
981
|
signal: controller.signal
|
|
@@ -987,29 +1106,41 @@ var CimplifyClient = class {
|
|
|
987
1106
|
});
|
|
988
1107
|
}
|
|
989
1108
|
async post(path, body, opts) {
|
|
990
|
-
const response = await this.authedFetch(
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1109
|
+
const response = await this.authedFetch(
|
|
1110
|
+
this.buildUrl(this.baseUrl, path),
|
|
1111
|
+
{
|
|
1112
|
+
method: "POST",
|
|
1113
|
+
credentials: this.credentials,
|
|
1114
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1115
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1116
|
+
},
|
|
1117
|
+
opts?.timeoutMs
|
|
1118
|
+
);
|
|
996
1119
|
return this.handleRestResponse(response);
|
|
997
1120
|
}
|
|
998
1121
|
async patch(path, body, opts) {
|
|
999
|
-
const response = await this.authedFetch(
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1122
|
+
const response = await this.authedFetch(
|
|
1123
|
+
this.buildUrl(this.baseUrl, path),
|
|
1124
|
+
{
|
|
1125
|
+
method: "PATCH",
|
|
1126
|
+
credentials: this.credentials,
|
|
1127
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1128
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1129
|
+
},
|
|
1130
|
+
opts?.timeoutMs
|
|
1131
|
+
);
|
|
1005
1132
|
return this.handleRestResponse(response);
|
|
1006
1133
|
}
|
|
1007
1134
|
async delete(path, opts) {
|
|
1008
|
-
const response = await this.authedFetch(
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1135
|
+
const response = await this.authedFetch(
|
|
1136
|
+
this.buildUrl(this.baseUrl, path),
|
|
1137
|
+
{
|
|
1138
|
+
method: "DELETE",
|
|
1139
|
+
credentials: this.credentials,
|
|
1140
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts)
|
|
1141
|
+
},
|
|
1142
|
+
opts?.timeoutMs
|
|
1143
|
+
);
|
|
1013
1144
|
return this.handleRestResponse(response);
|
|
1014
1145
|
}
|
|
1015
1146
|
async linkGet(path, opts) {
|
|
@@ -1025,12 +1156,16 @@ var CimplifyClient = class {
|
|
|
1025
1156
|
});
|
|
1026
1157
|
}
|
|
1027
1158
|
async linkPost(path, body, opts) {
|
|
1028
|
-
const response = await this.authedFetch(
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1159
|
+
const response = await this.authedFetch(
|
|
1160
|
+
`${this.linkApiUrl}${path}`,
|
|
1161
|
+
{
|
|
1162
|
+
method: "POST",
|
|
1163
|
+
credentials: this.credentials,
|
|
1164
|
+
headers: mergeOptionHeaders(this.getHeaders(), opts),
|
|
1165
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1166
|
+
},
|
|
1167
|
+
opts?.timeoutMs
|
|
1168
|
+
);
|
|
1034
1169
|
return this.handleRestResponse(response);
|
|
1035
1170
|
}
|
|
1036
1171
|
async linkDelete(path, opts) {
|