@cstar.help/js 0.17.4 → 0.18.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/README.md +45 -26
- package/dist/auth/index.cjs +220 -21
- package/dist/auth/index.d.cts +84 -32
- package/dist/auth/index.d.ts +84 -32
- package/dist/auth/index.js +210 -21
- package/dist/chat/index.cjs +131 -20
- package/dist/chat/index.d.cts +32 -4
- package/dist/chat/index.d.ts +32 -4
- package/dist/chat/index.js +131 -20
- package/dist/community/index.d.cts +1 -1
- package/dist/community/index.d.ts +1 -1
- package/dist/errors-bW8CwTn4.d.cts +121 -0
- package/dist/errors-bW8CwTn4.d.ts +121 -0
- package/dist/index.cjs +94 -41
- package/dist/index.d.cts +454 -153
- package/dist/index.d.ts +454 -153
- package/dist/index.js +94 -41
- package/dist/library/index.d.cts +1 -1
- package/dist/library/index.d.ts +1 -1
- package/dist/proactive/index.cjs +46 -33
- package/dist/proactive/index.js +45 -34
- package/dist/quickhelp/index.d.cts +1 -1
- package/dist/quickhelp/index.d.ts +1 -1
- package/dist/webhook/index.d.cts +1 -1
- package/dist/webhook/index.d.ts +1 -1
- package/dist/webhook/node.d.cts +1 -1
- package/dist/webhook/node.d.ts +1 -1
- package/dist/{webhookEvents-1N2i2GcQ.d.cts → webhookEvents-Lqpsj935.d.cts} +0 -1
- package/dist/{webhookEvents-1N2i2GcQ.d.ts → webhookEvents-Lqpsj935.d.ts} +0 -1
- package/package.json +1 -1
- package/dist/errors-b5A4wfAg.d.cts +0 -398
- package/dist/errors-b5A4wfAg.d.ts +0 -398
package/dist/index.js
CHANGED
|
@@ -237,7 +237,7 @@ function parseError(statusCode, body, retryAfter) {
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
// src/client.ts
|
|
240
|
-
var SDK_VERSION = "0.
|
|
240
|
+
var SDK_VERSION = "0.18.0";
|
|
241
241
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
242
242
|
var DEFAULT_API_VERSION = "2026-03-01";
|
|
243
243
|
var DEFAULT_MAX_RETRIES = 3;
|
|
@@ -257,7 +257,7 @@ var HttpClient = class {
|
|
|
257
257
|
this.lastMeta = { requestId: null, timestamp: null, pagination: null };
|
|
258
258
|
if (!config || typeof config.apiKey !== "string" || config.apiKey.length === 0) {
|
|
259
259
|
throw new Error(
|
|
260
|
-
"[cStar] CStarClient: apiKey is required. Pass a secret key (sk_live_... / sk_test_...)
|
|
260
|
+
"[cStar] CStarClient: apiKey is required. Pass a secret key (sk_live_... / sk_test_...). Publishable keys (pk_...) cannot read team endpoints; use them with LibraryClient or CommunityClient. See https://cstar.help/developers/quickstart"
|
|
261
261
|
);
|
|
262
262
|
}
|
|
263
263
|
if (typeof config.teamId !== "string" || config.teamId.length === 0) {
|
|
@@ -489,6 +489,8 @@ var CStarRealtime = class {
|
|
|
489
489
|
this.retryTimer = null;
|
|
490
490
|
this._connected = false;
|
|
491
491
|
this.destroyed = false;
|
|
492
|
+
/** The server closed the stream because the API key was revoked or expired. */
|
|
493
|
+
this.revoked = false;
|
|
492
494
|
this.connecting = false;
|
|
493
495
|
/** Short-lived SSE token (exchanged from secret key). */
|
|
494
496
|
this.sseToken = null;
|
|
@@ -564,7 +566,7 @@ var CStarRealtime = class {
|
|
|
564
566
|
}
|
|
565
567
|
/** Start the SSE connection. Called automatically on first handler registration. */
|
|
566
568
|
connect() {
|
|
567
|
-
if (this.eventSource || this.destroyed || this.connecting) return;
|
|
569
|
+
if (this.eventSource || this.destroyed || this.revoked || this.connecting) return;
|
|
568
570
|
if (!this.resolveEventSource()) {
|
|
569
571
|
throw new CStarRealtimeUnavailableError();
|
|
570
572
|
}
|
|
@@ -624,6 +626,7 @@ var CStarRealtime = class {
|
|
|
624
626
|
this.eventSource.close();
|
|
625
627
|
this.eventSource = null;
|
|
626
628
|
}
|
|
629
|
+
if (this.revoked) return;
|
|
627
630
|
if (this.autoReconnect && !this.destroyed && this.retryCount < this.maxRetries) {
|
|
628
631
|
this.scheduleReconnect();
|
|
629
632
|
} else if (this.retryCount >= this.maxRetries) {
|
|
@@ -633,6 +636,9 @@ var CStarRealtime = class {
|
|
|
633
636
|
this.eventSource.onmessage = (event) => {
|
|
634
637
|
this.handleMessage(event);
|
|
635
638
|
};
|
|
639
|
+
this.eventSource.addEventListener("revoked", (event) => {
|
|
640
|
+
this.handleRevoked(event);
|
|
641
|
+
});
|
|
636
642
|
const knownTypes = [
|
|
637
643
|
"ticket.created",
|
|
638
644
|
"ticket.updated",
|
|
@@ -761,6 +767,40 @@ var CStarRealtime = class {
|
|
|
761
767
|
for (const handler of this.connectionHandlers) handler(value);
|
|
762
768
|
}
|
|
763
769
|
}
|
|
770
|
+
handleRevoked(event) {
|
|
771
|
+
if (this.revoked || this.destroyed) return;
|
|
772
|
+
this.revoked = true;
|
|
773
|
+
let body = {};
|
|
774
|
+
try {
|
|
775
|
+
body = JSON.parse(event.data).error ?? {};
|
|
776
|
+
} catch {
|
|
777
|
+
}
|
|
778
|
+
if (this.retryTimer) {
|
|
779
|
+
clearTimeout(this.retryTimer);
|
|
780
|
+
this.retryTimer = null;
|
|
781
|
+
}
|
|
782
|
+
if (this.tokenRefreshTimer) {
|
|
783
|
+
clearTimeout(this.tokenRefreshTimer);
|
|
784
|
+
this.tokenRefreshTimer = null;
|
|
785
|
+
}
|
|
786
|
+
if (this.eventSource) {
|
|
787
|
+
this.eventSource.close();
|
|
788
|
+
this.eventSource = null;
|
|
789
|
+
}
|
|
790
|
+
this.sseToken = null;
|
|
791
|
+
this.sseTokenExpiresAt = 0;
|
|
792
|
+
this.connecting = false;
|
|
793
|
+
this.setConnected(false);
|
|
794
|
+
this.emitError(
|
|
795
|
+
new CStarAuthenticationError(401, {
|
|
796
|
+
type: body.type ?? "authentication_error",
|
|
797
|
+
code: body.code ?? "invalid_api_key",
|
|
798
|
+
message: body.message ?? "This API key was revoked or has expired, so the stream is closed.",
|
|
799
|
+
doc_url: body.doc_url ?? "https://www.cstar.help/developers/errors#invalid_api_key",
|
|
800
|
+
...body.request_id ? { request_id: body.request_id } : {}
|
|
801
|
+
})
|
|
802
|
+
);
|
|
803
|
+
}
|
|
764
804
|
emitError(error) {
|
|
765
805
|
for (const handler of this.errorHandlers) handler(error);
|
|
766
806
|
}
|
|
@@ -1121,9 +1161,11 @@ var TicketMessagesResource = class {
|
|
|
1121
1161
|
constructor(client) {
|
|
1122
1162
|
this.client = client;
|
|
1123
1163
|
}
|
|
1124
|
-
/** List
|
|
1125
|
-
async list(ticketId) {
|
|
1126
|
-
return this.client.request("GET", `/tickets/${ticketId}/messages
|
|
1164
|
+
/** List one page of a ticket history. Use pagination.hasMore to request the next page. */
|
|
1165
|
+
async list(ticketId, params) {
|
|
1166
|
+
return this.client.request("GET", `/tickets/${ticketId}/messages`, {
|
|
1167
|
+
query: params ? { ...params } : void 0
|
|
1168
|
+
});
|
|
1127
1169
|
}
|
|
1128
1170
|
/** Add a message to a ticket. */
|
|
1129
1171
|
async create(ticketId, params, options) {
|
|
@@ -1478,11 +1520,17 @@ var SettingsResource = class {
|
|
|
1478
1520
|
async update(params) {
|
|
1479
1521
|
return this.client.request("PATCH", "/settings", { body: params });
|
|
1480
1522
|
}
|
|
1481
|
-
/**
|
|
1523
|
+
/**
|
|
1524
|
+
* Get the chat widget's online hours (outside them the widget shows its
|
|
1525
|
+
* offline message). Not the SLA working hours that SLA deadlines use.
|
|
1526
|
+
*/
|
|
1482
1527
|
async getBusinessHours() {
|
|
1483
1528
|
return this.client.request("GET", "/settings/business-hours");
|
|
1484
1529
|
}
|
|
1485
|
-
/**
|
|
1530
|
+
/**
|
|
1531
|
+
* Update the chat widget's online hours. SLA deadlines don't change:
|
|
1532
|
+
* they follow the SLA working hours in Settings > Business Hours.
|
|
1533
|
+
*/
|
|
1486
1534
|
async updateBusinessHours(params) {
|
|
1487
1535
|
return this.client.request("PATCH", "/settings/business-hours", {
|
|
1488
1536
|
body: params
|
|
@@ -1507,8 +1555,10 @@ var NotificationsResource = class {
|
|
|
1507
1555
|
}
|
|
1508
1556
|
/** List notifications for a user. */
|
|
1509
1557
|
async list(params) {
|
|
1558
|
+
const { unreadOnly, ...query } = params;
|
|
1559
|
+
if (unreadOnly && query.isRead === void 0) query.isRead = false;
|
|
1510
1560
|
return this.client.request("GET", "/notifications", {
|
|
1511
|
-
query
|
|
1561
|
+
query
|
|
1512
1562
|
});
|
|
1513
1563
|
}
|
|
1514
1564
|
/** Get unread notification count for a user. */
|
|
@@ -1582,15 +1632,22 @@ var AttachmentsResource = class {
|
|
|
1582
1632
|
constructor(client) {
|
|
1583
1633
|
this.client = client;
|
|
1584
1634
|
}
|
|
1585
|
-
/** List
|
|
1635
|
+
/** List message files, each with a short-lived signed `url`. */
|
|
1586
1636
|
async list(params) {
|
|
1587
1637
|
return this.client.request("GET", "/attachments", {
|
|
1588
1638
|
query: params
|
|
1589
1639
|
});
|
|
1590
1640
|
}
|
|
1591
|
-
/**
|
|
1592
|
-
|
|
1593
|
-
|
|
1641
|
+
/**
|
|
1642
|
+
* Get a signed download URL, valid for `expiresIn` seconds, for a stored
|
|
1643
|
+
* file. Pass `storagePath` and `bucket` from `list()`.
|
|
1644
|
+
*/
|
|
1645
|
+
async get(storagePath, params) {
|
|
1646
|
+
return this.client.request(
|
|
1647
|
+
"GET",
|
|
1648
|
+
`/attachments/${storagePath}`,
|
|
1649
|
+
params?.bucket ? { query: { bucket: params.bucket } } : void 0
|
|
1650
|
+
);
|
|
1594
1651
|
}
|
|
1595
1652
|
/** Delete an attachment. */
|
|
1596
1653
|
async del(attachmentId) {
|
|
@@ -1606,16 +1663,12 @@ var CustomFieldsResource = class {
|
|
|
1606
1663
|
constructor(client) {
|
|
1607
1664
|
this.client = client;
|
|
1608
1665
|
}
|
|
1609
|
-
/** List custom
|
|
1666
|
+
/** List custom field definitions, optionally for one record type. There is no single-field GET. */
|
|
1610
1667
|
async list(params) {
|
|
1611
1668
|
return this.client.request("GET", "/custom-fields", {
|
|
1612
1669
|
query: params
|
|
1613
1670
|
});
|
|
1614
1671
|
}
|
|
1615
|
-
/** Get a single custom field. */
|
|
1616
|
-
async get(fieldId) {
|
|
1617
|
-
return this.client.request("GET", `/custom-fields/${fieldId}`);
|
|
1618
|
-
}
|
|
1619
1672
|
/** Create a custom field. */
|
|
1620
1673
|
async create(params, options) {
|
|
1621
1674
|
return this.client.request("POST", "/custom-fields", {
|
|
@@ -1650,11 +1703,9 @@ var SlaResource = class {
|
|
|
1650
1703
|
constructor(client) {
|
|
1651
1704
|
this.client = client;
|
|
1652
1705
|
}
|
|
1653
|
-
/** List SLA rules. */
|
|
1654
|
-
async list(
|
|
1655
|
-
return this.client.request("GET", "/sla/rules"
|
|
1656
|
-
query: params
|
|
1657
|
-
});
|
|
1706
|
+
/** List SLA rules in evaluation order. */
|
|
1707
|
+
async list() {
|
|
1708
|
+
return this.client.request("GET", "/sla/rules");
|
|
1658
1709
|
}
|
|
1659
1710
|
/** Create an SLA rule. */
|
|
1660
1711
|
async create(params, options) {
|
|
@@ -1843,25 +1894,28 @@ var TagsResource = class {
|
|
|
1843
1894
|
constructor(client) {
|
|
1844
1895
|
this.client = client;
|
|
1845
1896
|
}
|
|
1846
|
-
/** List
|
|
1897
|
+
/** List tags with usage counts, one row per tag and entity type. */
|
|
1847
1898
|
async list(params) {
|
|
1848
1899
|
return this.client.request("GET", "/tags", {
|
|
1849
1900
|
query: params
|
|
1850
1901
|
});
|
|
1851
1902
|
}
|
|
1852
|
-
/**
|
|
1853
|
-
async
|
|
1903
|
+
/** Replace `fromTag` with `toTag` on every record that carries it. */
|
|
1904
|
+
async merge(params, options) {
|
|
1854
1905
|
return this.client.request("POST", "/tags", {
|
|
1855
|
-
body: {
|
|
1906
|
+
body: { action: "merge", ...params },
|
|
1856
1907
|
idempotencyKey: options?.idempotencyKey
|
|
1857
1908
|
});
|
|
1858
1909
|
}
|
|
1859
|
-
/**
|
|
1860
|
-
async
|
|
1861
|
-
return this.client.request(
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1910
|
+
/** Remove a tag from every record that carries it. */
|
|
1911
|
+
async remove(tag, params) {
|
|
1912
|
+
return this.client.request("DELETE", "/tags", {
|
|
1913
|
+
body: { tag, ...params }
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
/** @deprecated Use `remove()`. */
|
|
1917
|
+
async del(tag, params) {
|
|
1918
|
+
return this.remove(tag, params);
|
|
1865
1919
|
}
|
|
1866
1920
|
};
|
|
1867
1921
|
|
|
@@ -2307,7 +2361,7 @@ var ViewsResource = class extends BaseResource {
|
|
|
2307
2361
|
constructor(client) {
|
|
2308
2362
|
super(client, "/views");
|
|
2309
2363
|
}
|
|
2310
|
-
/** Execute a view
|
|
2364
|
+
/** Execute a view and return the filtered results. The server uses the view's entity_type to determine which table to query. */
|
|
2311
2365
|
async execute(viewId, params) {
|
|
2312
2366
|
return this.client.request("GET", `/views/${viewId}/execute`, {
|
|
2313
2367
|
query: params
|
|
@@ -2543,7 +2597,7 @@ var WEBHOOK_EVENT_SAMPLES = {
|
|
|
2543
2597
|
"comment": {
|
|
2544
2598
|
"id": "cmt_01H8X9YZ7E0J3K4M5N6X",
|
|
2545
2599
|
"post_id": "post_01H8X9YZ7E0J3K4M5N6W",
|
|
2546
|
-
"content": "I would love this
|
|
2600
|
+
"content": "I would love this. Bumping for visibility.",
|
|
2547
2601
|
"author_id": "cus_01H8X9YZ7E0J3K4M5N6Q",
|
|
2548
2602
|
"created_at": "2026-04-27T18:55:02.000Z"
|
|
2549
2603
|
}
|
|
@@ -2763,15 +2817,14 @@ var WEBHOOK_EVENT_SAMPLES = {
|
|
|
2763
2817
|
"id": "tkt_01H8X9YZ7E0J3K4M5N6P",
|
|
2764
2818
|
"prefixed_id": "CST-1024",
|
|
2765
2819
|
"title": "Cannot reset password",
|
|
2766
|
-
"status": "
|
|
2820
|
+
"status": "closed",
|
|
2767
2821
|
"priority": "normal",
|
|
2768
|
-
"channel": "widget"
|
|
2769
|
-
"resolved_at": "2026-04-27T19:08:43.000Z"
|
|
2822
|
+
"channel": "widget"
|
|
2770
2823
|
},
|
|
2771
2824
|
"changes": {
|
|
2772
2825
|
"status": {
|
|
2773
2826
|
"from": "open",
|
|
2774
|
-
"to": "
|
|
2827
|
+
"to": "closed"
|
|
2775
2828
|
}
|
|
2776
2829
|
}
|
|
2777
2830
|
},
|
|
@@ -2804,7 +2857,7 @@ var WEBHOOK_EVENT_SAMPLES = {
|
|
|
2804
2857
|
"id": "msg_01H8X9YZ7E0J3K4M5N6R",
|
|
2805
2858
|
"sender": "agent",
|
|
2806
2859
|
"sender_name": "Riley",
|
|
2807
|
-
"content": "I just sent a reset link to your inbox
|
|
2860
|
+
"content": "I just sent a reset link to your inbox. Let me know if it lands.",
|
|
2808
2861
|
"created_at": "2026-04-27T18:55:02.000Z"
|
|
2809
2862
|
},
|
|
2810
2863
|
"customer": {
|
|
@@ -2870,7 +2923,7 @@ var WEBHOOK_EVENT_CATALOG = {
|
|
|
2870
2923
|
"survey.submitted": { label: "Customer Feedback Received", description: "Fired when a customer submits a CSAT survey response", category: "csat" },
|
|
2871
2924
|
"team.preferences_updated": { label: "Team Preferences Updated", description: "Fired when team-wide UX preferences change (e.g., bossBattlesEnabled toggled)", category: "team" },
|
|
2872
2925
|
"ticket.assigned": { label: "Ticket Assigned", description: "Fired when a ticket is assigned to an agent", category: "tickets" },
|
|
2873
|
-
"ticket.closed": { label: "Ticket Closed
|
|
2926
|
+
"ticket.closed": { label: "Ticket Closed", description: "Fired when a ticket's status changes to Closed. Moving a ticket to Resolved sends ticket.updated instead.", category: "tickets" },
|
|
2874
2927
|
"ticket.created": { label: "New Ticket Created", description: "Fired when a new ticket is created via app, widget, API, or email", category: "tickets" },
|
|
2875
2928
|
"ticket.deleted": { label: "Ticket Deleted", description: "Fired when a ticket is deleted via app or API", category: "tickets" },
|
|
2876
2929
|
"ticket.message_added": { label: "New Message on Ticket", description: "Fired when a new message is added to a ticket", category: "tickets" },
|
package/dist/library/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-
|
|
1
|
+
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-bW8CwTn4.cjs';
|
|
2
2
|
|
|
3
3
|
/** Configuration for the LibraryClient. */
|
|
4
4
|
interface LibraryConfig {
|
package/dist/library/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-
|
|
1
|
+
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-bW8CwTn4.js';
|
|
2
2
|
|
|
3
3
|
/** Configuration for the LibraryClient. */
|
|
4
4
|
interface LibraryConfig {
|
package/dist/proactive/index.cjs
CHANGED
|
@@ -23,51 +23,64 @@ __export(proactive_exports, {
|
|
|
23
23
|
ProactiveClient: () => ProactiveClient
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(proactive_exports);
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
// src/proactive/rageClick.ts
|
|
28
|
+
var INTERACTIVE_SELECTOR = 'a[href], button, input, select, textarea, label, summary, [role="button"], [role="link"], [role="checkbox"], [role="radio"], [role="switch"], [role="tab"], [role="menuitem"], [role="option"], [contenteditable="true"], [contenteditable=""]';
|
|
29
|
+
var RAGE_CLICK_THRESHOLD = 3;
|
|
30
|
+
var RAGE_CLICK_WINDOW_MS = 1e3;
|
|
31
|
+
var RAGE_CLICK_RADIUS_PX = 30;
|
|
32
|
+
var RAGE_CLICK_DEBOUNCE_MS = 2e3;
|
|
33
|
+
function describe(el) {
|
|
34
|
+
let context = el.tagName ? "on " + el.tagName.toLowerCase() : "";
|
|
35
|
+
if (typeof el.className === "string") {
|
|
36
|
+
const cls = el.className.split(" ")[0];
|
|
37
|
+
if (cls) context += "." + cls;
|
|
38
|
+
}
|
|
39
|
+
return context;
|
|
40
|
+
}
|
|
41
|
+
function createRageClickDetector(onSignal, doc) {
|
|
28
42
|
let clicks = [];
|
|
29
43
|
let lastFired = 0;
|
|
30
44
|
let handler = null;
|
|
45
|
+
function onClick(e) {
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
const target = e.target;
|
|
48
|
+
if (!target || typeof target.closest !== "function" || target.closest(INTERACTIVE_SELECTOR)) {
|
|
49
|
+
clicks = [];
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
clicks = clicks.filter((c) => now - c.t < RAGE_CLICK_WINDOW_MS && c.target === target);
|
|
53
|
+
clicks.push({ x: e.clientX, y: e.clientY, t: now, target });
|
|
54
|
+
if (clicks.length < RAGE_CLICK_THRESHOLD || now - lastFired <= RAGE_CLICK_DEBOUNCE_MS) return;
|
|
55
|
+
const first = clicks[0];
|
|
56
|
+
const allClose = clicks.every(
|
|
57
|
+
(c) => Math.hypot(first.x - c.x, first.y - c.y) <= RAGE_CLICK_RADIUS_PX
|
|
58
|
+
);
|
|
59
|
+
if (!allClose) return;
|
|
60
|
+
lastFired = now;
|
|
61
|
+
onSignal({
|
|
62
|
+
type: "rage_click",
|
|
63
|
+
confidence: Math.min(1, clicks.length / 5),
|
|
64
|
+
context: `Clicked ${clicks.length} times rapidly ${describe(target)}`,
|
|
65
|
+
timestamp: now
|
|
66
|
+
});
|
|
67
|
+
clicks = [];
|
|
68
|
+
}
|
|
31
69
|
return {
|
|
32
70
|
start() {
|
|
33
|
-
handler =
|
|
34
|
-
|
|
35
|
-
clicks = clicks.filter((c) => now - c.t < 500);
|
|
36
|
-
clicks.push({ x: e.clientX, y: e.clientY, t: now });
|
|
37
|
-
if (clicks.length >= 3 && now - lastFired > 2e3) {
|
|
38
|
-
const first = clicks[0];
|
|
39
|
-
const allClose = clicks.every((c) => {
|
|
40
|
-
const dx = first.x - c.x;
|
|
41
|
-
const dy = first.y - c.y;
|
|
42
|
-
return Math.sqrt(dx * dx + dy * dy) <= 50;
|
|
43
|
-
});
|
|
44
|
-
if (allClose) {
|
|
45
|
-
lastFired = now;
|
|
46
|
-
const el = e.target;
|
|
47
|
-
let context = el?.tagName ? "on " + el.tagName.toLowerCase() : "";
|
|
48
|
-
if (el?.className && typeof el.className === "string") {
|
|
49
|
-
const cls = el.className.split(" ")[0];
|
|
50
|
-
if (cls) context += "." + cls;
|
|
51
|
-
}
|
|
52
|
-
onSignal({
|
|
53
|
-
type: "rage_click",
|
|
54
|
-
confidence: Math.min(1, clicks.length / 5),
|
|
55
|
-
context: `Clicked ${clicks.length} times rapidly ${context}`,
|
|
56
|
-
timestamp: now
|
|
57
|
-
});
|
|
58
|
-
clicks = [];
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
document.addEventListener("click", handler, true);
|
|
71
|
+
handler = onClick;
|
|
72
|
+
(doc ?? document).addEventListener("click", handler, true);
|
|
63
73
|
},
|
|
64
74
|
stop() {
|
|
65
|
-
if (handler) document.removeEventListener("click", handler, true);
|
|
75
|
+
if (handler) (doc ?? document).removeEventListener("click", handler, true);
|
|
66
76
|
handler = null;
|
|
67
77
|
clicks = [];
|
|
68
78
|
}
|
|
69
79
|
};
|
|
70
80
|
}
|
|
81
|
+
|
|
82
|
+
// src/proactive/index.ts
|
|
83
|
+
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
71
84
|
function createExitIntentDetector(onSignal) {
|
|
72
85
|
let fired = false;
|
|
73
86
|
let handler = null;
|
package/dist/proactive/index.js
CHANGED
|
@@ -1,49 +1,60 @@
|
|
|
1
|
-
// src/proactive/
|
|
2
|
-
var
|
|
3
|
-
|
|
1
|
+
// src/proactive/rageClick.ts
|
|
2
|
+
var INTERACTIVE_SELECTOR = 'a[href], button, input, select, textarea, label, summary, [role="button"], [role="link"], [role="checkbox"], [role="radio"], [role="switch"], [role="tab"], [role="menuitem"], [role="option"], [contenteditable="true"], [contenteditable=""]';
|
|
3
|
+
var RAGE_CLICK_THRESHOLD = 3;
|
|
4
|
+
var RAGE_CLICK_WINDOW_MS = 1e3;
|
|
5
|
+
var RAGE_CLICK_RADIUS_PX = 30;
|
|
6
|
+
var RAGE_CLICK_DEBOUNCE_MS = 2e3;
|
|
7
|
+
function describe(el) {
|
|
8
|
+
let context = el.tagName ? "on " + el.tagName.toLowerCase() : "";
|
|
9
|
+
if (typeof el.className === "string") {
|
|
10
|
+
const cls = el.className.split(" ")[0];
|
|
11
|
+
if (cls) context += "." + cls;
|
|
12
|
+
}
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
function createRageClickDetector(onSignal, doc) {
|
|
4
16
|
let clicks = [];
|
|
5
17
|
let lastFired = 0;
|
|
6
18
|
let handler = null;
|
|
19
|
+
function onClick(e) {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const target = e.target;
|
|
22
|
+
if (!target || typeof target.closest !== "function" || target.closest(INTERACTIVE_SELECTOR)) {
|
|
23
|
+
clicks = [];
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
clicks = clicks.filter((c) => now - c.t < RAGE_CLICK_WINDOW_MS && c.target === target);
|
|
27
|
+
clicks.push({ x: e.clientX, y: e.clientY, t: now, target });
|
|
28
|
+
if (clicks.length < RAGE_CLICK_THRESHOLD || now - lastFired <= RAGE_CLICK_DEBOUNCE_MS) return;
|
|
29
|
+
const first = clicks[0];
|
|
30
|
+
const allClose = clicks.every(
|
|
31
|
+
(c) => Math.hypot(first.x - c.x, first.y - c.y) <= RAGE_CLICK_RADIUS_PX
|
|
32
|
+
);
|
|
33
|
+
if (!allClose) return;
|
|
34
|
+
lastFired = now;
|
|
35
|
+
onSignal({
|
|
36
|
+
type: "rage_click",
|
|
37
|
+
confidence: Math.min(1, clicks.length / 5),
|
|
38
|
+
context: `Clicked ${clicks.length} times rapidly ${describe(target)}`,
|
|
39
|
+
timestamp: now
|
|
40
|
+
});
|
|
41
|
+
clicks = [];
|
|
42
|
+
}
|
|
7
43
|
return {
|
|
8
44
|
start() {
|
|
9
|
-
handler =
|
|
10
|
-
|
|
11
|
-
clicks = clicks.filter((c) => now - c.t < 500);
|
|
12
|
-
clicks.push({ x: e.clientX, y: e.clientY, t: now });
|
|
13
|
-
if (clicks.length >= 3 && now - lastFired > 2e3) {
|
|
14
|
-
const first = clicks[0];
|
|
15
|
-
const allClose = clicks.every((c) => {
|
|
16
|
-
const dx = first.x - c.x;
|
|
17
|
-
const dy = first.y - c.y;
|
|
18
|
-
return Math.sqrt(dx * dx + dy * dy) <= 50;
|
|
19
|
-
});
|
|
20
|
-
if (allClose) {
|
|
21
|
-
lastFired = now;
|
|
22
|
-
const el = e.target;
|
|
23
|
-
let context = el?.tagName ? "on " + el.tagName.toLowerCase() : "";
|
|
24
|
-
if (el?.className && typeof el.className === "string") {
|
|
25
|
-
const cls = el.className.split(" ")[0];
|
|
26
|
-
if (cls) context += "." + cls;
|
|
27
|
-
}
|
|
28
|
-
onSignal({
|
|
29
|
-
type: "rage_click",
|
|
30
|
-
confidence: Math.min(1, clicks.length / 5),
|
|
31
|
-
context: `Clicked ${clicks.length} times rapidly ${context}`,
|
|
32
|
-
timestamp: now
|
|
33
|
-
});
|
|
34
|
-
clicks = [];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
document.addEventListener("click", handler, true);
|
|
45
|
+
handler = onClick;
|
|
46
|
+
(doc ?? document).addEventListener("click", handler, true);
|
|
39
47
|
},
|
|
40
48
|
stop() {
|
|
41
|
-
if (handler) document.removeEventListener("click", handler, true);
|
|
49
|
+
if (handler) (doc ?? document).removeEventListener("click", handler, true);
|
|
42
50
|
handler = null;
|
|
43
51
|
clicks = [];
|
|
44
52
|
}
|
|
45
53
|
};
|
|
46
54
|
}
|
|
55
|
+
|
|
56
|
+
// src/proactive/index.ts
|
|
57
|
+
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
47
58
|
function createExitIntentDetector(onSignal) {
|
|
48
59
|
let fired = false;
|
|
49
60
|
let handler = null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-
|
|
1
|
+
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-bW8CwTn4.cjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Options for the QuickHelpClient. No auth — Quick Help is anonymous by
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-
|
|
1
|
+
export { A as ApiErrorBody, C as CStarAuthenticationError, a as CStarConflictError, b as CStarError, c as CStarFeatureDisabledError, d as CStarNotFoundError, e as CStarPermissionError, f as CStarRateLimitError, g as CStarRealtimeUnavailableError, h as CStarServerError, i as CStarValidationError, E as ErrorType, p as parseError, j as parsePublicError } from '../errors-bW8CwTn4.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Options for the QuickHelpClient. No auth — Quick Help is anonymous by
|
package/dist/webhook/index.d.cts
CHANGED
package/dist/webhook/index.d.ts
CHANGED
package/dist/webhook/node.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as WebhookEvent } from '../webhookEvents-
|
|
1
|
+
import { d as WebhookEvent } from '../webhookEvents-Lqpsj935.cjs';
|
|
2
2
|
import { VerifyOptions } from './index.cjs';
|
|
3
3
|
export { DEFAULT_TOLERANCE_SECONDS, WebhookSignatureVerificationError } from './index.cjs';
|
|
4
4
|
|
package/dist/webhook/node.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as WebhookEvent } from '../webhookEvents-
|
|
1
|
+
import { d as WebhookEvent } from '../webhookEvents-Lqpsj935.js';
|
|
2
2
|
import { VerifyOptions } from './index.js';
|
|
3
3
|
export { DEFAULT_TOLERANCE_SECONDS, WebhookSignatureVerificationError } from './index.js';
|
|
4
4
|
|