@cstar.help/js 0.12.1 → 0.13.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/auth/index.cjs +217 -3
- package/dist/auth/index.js +215 -3
- package/dist/chat/index.cjs +46 -26
- package/dist/chat/index.d.cts +28 -24
- package/dist/chat/index.d.ts +28 -24
- package/dist/chat/index.js +46 -26
- package/dist/community/index.cjs +233 -9
- package/dist/community/index.d.cts +11 -0
- package/dist/community/index.d.ts +11 -0
- package/dist/community/index.js +231 -9
- package/dist/index.cjs +268 -73
- package/dist/index.d.cts +3259 -0
- package/dist/index.d.ts +3259 -0
- package/dist/index.js +267 -73
- package/dist/library/index.cjs +254 -9
- package/dist/library/index.d.cts +26 -3
- package/dist/library/index.d.ts +26 -3
- package/dist/library/index.js +252 -9
- package/dist/quickhelp/index.cjs +176 -2
- package/dist/quickhelp/index.d.cts +11 -0
- package/dist/quickhelp/index.d.ts +11 -0
- package/dist/quickhelp/index.js +174 -2
- package/dist/webhook/index.cjs +0 -18
- package/dist/webhook/index.d.cts +440 -0
- package/dist/webhook/index.d.ts +440 -0
- package/dist/webhook/index.js +0 -23
- package/dist/webhook/node.cjs +57 -0
- package/dist/webhook/node.d.cts +440 -0
- package/dist/webhook/node.d.ts +440 -0
- package/dist/webhook/node.js +30 -0
- package/package.json +14 -2
package/dist/chat/index.d.cts
CHANGED
|
@@ -88,13 +88,24 @@ interface RealtimeTokenResponse {
|
|
|
88
88
|
/** A ticket — a customer's support thread. */
|
|
89
89
|
interface Ticket {
|
|
90
90
|
id: string;
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Server-issued display ID (e.g. `CST-1024`). `null` immediately after
|
|
93
|
+
* `tickets.create` (the prefix is assigned asynchronously); populated on
|
|
94
|
+
* subsequent `tickets.list` / single fetches.
|
|
95
|
+
*/
|
|
96
|
+
ticketNumber: string | null;
|
|
92
97
|
subject: string;
|
|
93
98
|
status: string;
|
|
94
99
|
messageCount: number;
|
|
95
100
|
createdAt: string;
|
|
96
101
|
updatedAt: string;
|
|
97
102
|
closedAt: string | null;
|
|
103
|
+
/**
|
|
104
|
+
* Set on `tickets.create` responses — contains the first message the
|
|
105
|
+
* widget sent, so callers don't need a round-trip `messages.list(...)`
|
|
106
|
+
* to echo it back. `undefined` on list/get responses.
|
|
107
|
+
*/
|
|
108
|
+
messages?: Message[];
|
|
98
109
|
}
|
|
99
110
|
/** Paginated ticket list response. */
|
|
100
111
|
interface TicketListResponse {
|
|
@@ -244,46 +255,39 @@ interface CommunityFollowResult {
|
|
|
244
255
|
* }
|
|
245
256
|
* }
|
|
246
257
|
* ```
|
|
258
|
+
*
|
|
259
|
+
* Constructors accept either a full opts object (used by the SDK's HTTP
|
|
260
|
+
* paths) or a bare message string — handy for SDK precondition checks
|
|
261
|
+
* (`throw new ChatClientAuthError('Not identified...')`) and tests.
|
|
262
|
+
* Closes F-032's spirit for the chat-client classes.
|
|
247
263
|
*/
|
|
264
|
+
interface ChatErrorOpts {
|
|
265
|
+
message: string;
|
|
266
|
+
code?: string;
|
|
267
|
+
statusCode?: number;
|
|
268
|
+
requestId?: string | null;
|
|
269
|
+
}
|
|
248
270
|
/** Base class. Thrown by `ChatClient.fetch()` for any non-2xx response. */
|
|
249
271
|
declare class ChatClientError extends Error {
|
|
250
272
|
readonly code: string;
|
|
251
273
|
readonly statusCode: number;
|
|
252
274
|
readonly requestId: string | null;
|
|
253
|
-
constructor(
|
|
254
|
-
code?: string;
|
|
255
|
-
statusCode: number;
|
|
256
|
-
requestId?: string | null;
|
|
257
|
-
});
|
|
275
|
+
constructor(arg: ChatErrorOpts | string);
|
|
258
276
|
}
|
|
259
277
|
/** 401 / 403 — auth failed (bad/expired token, wrong team, etc.). */
|
|
260
278
|
declare class ChatClientAuthError extends ChatClientError {
|
|
261
|
-
constructor(
|
|
262
|
-
message: string;
|
|
263
|
-
code?: string;
|
|
264
|
-
statusCode: number;
|
|
265
|
-
requestId?: string | null;
|
|
266
|
-
});
|
|
279
|
+
constructor(arg: ChatErrorOpts | string);
|
|
267
280
|
}
|
|
268
281
|
/** 429 — too many requests. Inspect `retryAfter` (seconds) before retrying. */
|
|
269
282
|
declare class ChatClientRateLimitError extends ChatClientError {
|
|
270
283
|
readonly retryAfter: number | null;
|
|
271
|
-
constructor(
|
|
272
|
-
message: string;
|
|
273
|
-
code?: string;
|
|
274
|
-
statusCode: number;
|
|
275
|
-
requestId?: string | null;
|
|
284
|
+
constructor(arg: (ChatErrorOpts & {
|
|
276
285
|
retryAfter?: number | null;
|
|
277
|
-
});
|
|
286
|
+
}) | string);
|
|
278
287
|
}
|
|
279
288
|
/** 5xx — the cStar server hit an internal error. Usually transient. */
|
|
280
289
|
declare class ChatClientServerError extends ChatClientError {
|
|
281
|
-
constructor(
|
|
282
|
-
message: string;
|
|
283
|
-
code?: string;
|
|
284
|
-
statusCode: number;
|
|
285
|
-
requestId?: string | null;
|
|
286
|
-
});
|
|
290
|
+
constructor(arg: ChatErrorOpts | string);
|
|
287
291
|
}
|
|
288
292
|
/**
|
|
289
293
|
* `fetch()` itself failed before a response was received — DNS, TLS,
|
package/dist/chat/index.d.ts
CHANGED
|
@@ -88,13 +88,24 @@ interface RealtimeTokenResponse {
|
|
|
88
88
|
/** A ticket — a customer's support thread. */
|
|
89
89
|
interface Ticket {
|
|
90
90
|
id: string;
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Server-issued display ID (e.g. `CST-1024`). `null` immediately after
|
|
93
|
+
* `tickets.create` (the prefix is assigned asynchronously); populated on
|
|
94
|
+
* subsequent `tickets.list` / single fetches.
|
|
95
|
+
*/
|
|
96
|
+
ticketNumber: string | null;
|
|
92
97
|
subject: string;
|
|
93
98
|
status: string;
|
|
94
99
|
messageCount: number;
|
|
95
100
|
createdAt: string;
|
|
96
101
|
updatedAt: string;
|
|
97
102
|
closedAt: string | null;
|
|
103
|
+
/**
|
|
104
|
+
* Set on `tickets.create` responses — contains the first message the
|
|
105
|
+
* widget sent, so callers don't need a round-trip `messages.list(...)`
|
|
106
|
+
* to echo it back. `undefined` on list/get responses.
|
|
107
|
+
*/
|
|
108
|
+
messages?: Message[];
|
|
98
109
|
}
|
|
99
110
|
/** Paginated ticket list response. */
|
|
100
111
|
interface TicketListResponse {
|
|
@@ -244,46 +255,39 @@ interface CommunityFollowResult {
|
|
|
244
255
|
* }
|
|
245
256
|
* }
|
|
246
257
|
* ```
|
|
258
|
+
*
|
|
259
|
+
* Constructors accept either a full opts object (used by the SDK's HTTP
|
|
260
|
+
* paths) or a bare message string — handy for SDK precondition checks
|
|
261
|
+
* (`throw new ChatClientAuthError('Not identified...')`) and tests.
|
|
262
|
+
* Closes F-032's spirit for the chat-client classes.
|
|
247
263
|
*/
|
|
264
|
+
interface ChatErrorOpts {
|
|
265
|
+
message: string;
|
|
266
|
+
code?: string;
|
|
267
|
+
statusCode?: number;
|
|
268
|
+
requestId?: string | null;
|
|
269
|
+
}
|
|
248
270
|
/** Base class. Thrown by `ChatClient.fetch()` for any non-2xx response. */
|
|
249
271
|
declare class ChatClientError extends Error {
|
|
250
272
|
readonly code: string;
|
|
251
273
|
readonly statusCode: number;
|
|
252
274
|
readonly requestId: string | null;
|
|
253
|
-
constructor(
|
|
254
|
-
code?: string;
|
|
255
|
-
statusCode: number;
|
|
256
|
-
requestId?: string | null;
|
|
257
|
-
});
|
|
275
|
+
constructor(arg: ChatErrorOpts | string);
|
|
258
276
|
}
|
|
259
277
|
/** 401 / 403 — auth failed (bad/expired token, wrong team, etc.). */
|
|
260
278
|
declare class ChatClientAuthError extends ChatClientError {
|
|
261
|
-
constructor(
|
|
262
|
-
message: string;
|
|
263
|
-
code?: string;
|
|
264
|
-
statusCode: number;
|
|
265
|
-
requestId?: string | null;
|
|
266
|
-
});
|
|
279
|
+
constructor(arg: ChatErrorOpts | string);
|
|
267
280
|
}
|
|
268
281
|
/** 429 — too many requests. Inspect `retryAfter` (seconds) before retrying. */
|
|
269
282
|
declare class ChatClientRateLimitError extends ChatClientError {
|
|
270
283
|
readonly retryAfter: number | null;
|
|
271
|
-
constructor(
|
|
272
|
-
message: string;
|
|
273
|
-
code?: string;
|
|
274
|
-
statusCode: number;
|
|
275
|
-
requestId?: string | null;
|
|
284
|
+
constructor(arg: (ChatErrorOpts & {
|
|
276
285
|
retryAfter?: number | null;
|
|
277
|
-
});
|
|
286
|
+
}) | string);
|
|
278
287
|
}
|
|
279
288
|
/** 5xx — the cStar server hit an internal error. Usually transient. */
|
|
280
289
|
declare class ChatClientServerError extends ChatClientError {
|
|
281
|
-
constructor(
|
|
282
|
-
message: string;
|
|
283
|
-
code?: string;
|
|
284
|
-
statusCode: number;
|
|
285
|
-
requestId?: string | null;
|
|
286
|
-
});
|
|
290
|
+
constructor(arg: ChatErrorOpts | string);
|
|
287
291
|
}
|
|
288
292
|
/**
|
|
289
293
|
* `fetch()` itself failed before a response was received — DNS, TLS,
|
package/dist/chat/index.js
CHANGED
|
@@ -248,37 +248,45 @@ var PresenceManager = class {
|
|
|
248
248
|
};
|
|
249
249
|
|
|
250
250
|
// src/chat/errors.ts
|
|
251
|
+
function normalizeChatArgs(arg, fallbackCode) {
|
|
252
|
+
if (typeof arg === "string") {
|
|
253
|
+
return { message: arg, code: fallbackCode, statusCode: 0, requestId: null };
|
|
254
|
+
}
|
|
255
|
+
return { ...arg, code: arg.code ?? fallbackCode };
|
|
256
|
+
}
|
|
251
257
|
var ChatClientError = class extends Error {
|
|
252
|
-
constructor(
|
|
253
|
-
|
|
258
|
+
constructor(arg) {
|
|
259
|
+
const opts = normalizeChatArgs(arg, "UNKNOWN");
|
|
260
|
+
super(opts.message);
|
|
254
261
|
this.name = "ChatClientError";
|
|
255
262
|
this.code = opts.code ?? "UNKNOWN";
|
|
256
|
-
this.statusCode = opts.statusCode;
|
|
263
|
+
this.statusCode = opts.statusCode ?? 0;
|
|
257
264
|
this.requestId = opts.requestId ?? null;
|
|
258
265
|
}
|
|
259
266
|
};
|
|
260
267
|
var ChatClientAuthError = class extends ChatClientError {
|
|
261
|
-
constructor(
|
|
262
|
-
super(
|
|
268
|
+
constructor(arg) {
|
|
269
|
+
super(normalizeChatArgs(arg, "AUTH_ERROR"));
|
|
263
270
|
this.name = "ChatClientAuthError";
|
|
264
271
|
}
|
|
265
272
|
};
|
|
266
273
|
var ChatClientRateLimitError = class extends ChatClientError {
|
|
267
|
-
constructor(
|
|
268
|
-
|
|
274
|
+
constructor(arg) {
|
|
275
|
+
const opts = typeof arg === "string" ? { message: arg, code: "RATE_LIMIT", statusCode: 429, requestId: null, retryAfter: null } : { ...arg, code: arg.code ?? "RATE_LIMIT" };
|
|
276
|
+
super(opts);
|
|
269
277
|
this.name = "ChatClientRateLimitError";
|
|
270
278
|
this.retryAfter = opts.retryAfter ?? null;
|
|
271
279
|
}
|
|
272
280
|
};
|
|
273
281
|
var ChatClientServerError = class extends ChatClientError {
|
|
274
|
-
constructor(
|
|
275
|
-
super(
|
|
282
|
+
constructor(arg) {
|
|
283
|
+
super(normalizeChatArgs(arg, "SERVER_ERROR"));
|
|
276
284
|
this.name = "ChatClientServerError";
|
|
277
285
|
}
|
|
278
286
|
};
|
|
279
287
|
var ChatClientNetworkError = class extends ChatClientError {
|
|
280
288
|
constructor(opts) {
|
|
281
|
-
super(opts.message,
|
|
289
|
+
super({ message: opts.message, code: "NETWORK_ERROR", statusCode: 0, requestId: null });
|
|
282
290
|
this.name = "ChatClientNetworkError";
|
|
283
291
|
this.originalError = opts.originalError;
|
|
284
292
|
}
|
|
@@ -333,6 +341,7 @@ var ChatClient = class {
|
|
|
333
341
|
this.sessionToken = response.data.sessionToken;
|
|
334
342
|
this.teamId = response.data.teamId;
|
|
335
343
|
this.customerId = response.data.customer.id;
|
|
344
|
+
this.authMode = "hmac";
|
|
336
345
|
if (this.realtimeEnabled) {
|
|
337
346
|
this.realtimeInitPromise = this.initRealtime(
|
|
338
347
|
response.data.customer.id,
|
|
@@ -530,7 +539,8 @@ var ChatClient = class {
|
|
|
530
539
|
requestId
|
|
531
540
|
});
|
|
532
541
|
}
|
|
533
|
-
throw new ChatClientError(
|
|
542
|
+
throw new ChatClientError({
|
|
543
|
+
message,
|
|
534
544
|
code,
|
|
535
545
|
statusCode: response.status,
|
|
536
546
|
requestId
|
|
@@ -668,7 +678,7 @@ var TicketsApi = class {
|
|
|
668
678
|
/** List tickets for the identified customer. */
|
|
669
679
|
async list(params) {
|
|
670
680
|
const teamId = this.chat.getTeamId();
|
|
671
|
-
if (!teamId) throw new
|
|
681
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
672
682
|
const response = await this.chat.fetch("/api/widget/conversations", {
|
|
673
683
|
method: "GET",
|
|
674
684
|
query: {
|
|
@@ -686,7 +696,7 @@ var TicketsApi = class {
|
|
|
686
696
|
/** Create a new ticket. */
|
|
687
697
|
async create(params) {
|
|
688
698
|
const teamId = this.chat.getTeamId();
|
|
689
|
-
if (!teamId) throw new
|
|
699
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
690
700
|
const response = await this.chat.fetch("/api/widget/tickets", {
|
|
691
701
|
method: "POST",
|
|
692
702
|
body: {
|
|
@@ -695,15 +705,25 @@ var TicketsApi = class {
|
|
|
695
705
|
message: params.message
|
|
696
706
|
}
|
|
697
707
|
});
|
|
708
|
+
const messages = (response.data.messages ?? []).map((m) => ({
|
|
709
|
+
id: m.id,
|
|
710
|
+
content: m.content,
|
|
711
|
+
sender: m.sender,
|
|
712
|
+
sender_name: m.sender_name,
|
|
713
|
+
created_at: m.created_at,
|
|
714
|
+
read_at: m.read_at,
|
|
715
|
+
attachments: m.attachments ?? []
|
|
716
|
+
}));
|
|
698
717
|
return {
|
|
699
718
|
id: response.data.id,
|
|
700
|
-
ticketNumber:
|
|
719
|
+
ticketNumber: null,
|
|
701
720
|
subject: response.data.subject,
|
|
702
721
|
status: response.data.status,
|
|
703
|
-
messageCount:
|
|
722
|
+
messageCount: messages.length,
|
|
704
723
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
705
724
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
706
|
-
closedAt: null
|
|
725
|
+
closedAt: null,
|
|
726
|
+
messages
|
|
707
727
|
};
|
|
708
728
|
}
|
|
709
729
|
};
|
|
@@ -714,7 +734,7 @@ var ChatCommunityApi = class {
|
|
|
714
734
|
/** Create a new community post as the identified customer. */
|
|
715
735
|
async createPost(params) {
|
|
716
736
|
const teamId = this.chat.getTeamId();
|
|
717
|
-
if (!teamId) throw new
|
|
737
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
718
738
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
719
739
|
method: "POST",
|
|
720
740
|
body: {
|
|
@@ -731,7 +751,7 @@ var ChatCommunityApi = class {
|
|
|
731
751
|
/** Update a post. Only the original author can edit. */
|
|
732
752
|
async updatePost(postId, params) {
|
|
733
753
|
const teamId = this.chat.getTeamId();
|
|
734
|
-
if (!teamId) throw new
|
|
754
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
735
755
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
736
756
|
method: "POST",
|
|
737
757
|
body: {
|
|
@@ -748,7 +768,7 @@ var ChatCommunityApi = class {
|
|
|
748
768
|
/** Delete a post (soft delete). Only the original author can delete. */
|
|
749
769
|
async deletePost(postId) {
|
|
750
770
|
const teamId = this.chat.getTeamId();
|
|
751
|
-
if (!teamId) throw new
|
|
771
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
752
772
|
await this.chat.fetch("/api/widget/community", {
|
|
753
773
|
method: "POST",
|
|
754
774
|
body: { teamId, action: "deletePost", postId }
|
|
@@ -757,7 +777,7 @@ var ChatCommunityApi = class {
|
|
|
757
777
|
/** Update a comment. Only the original author can edit. */
|
|
758
778
|
async updateComment(postId, commentId, params) {
|
|
759
779
|
const teamId = this.chat.getTeamId();
|
|
760
|
-
if (!teamId) throw new
|
|
780
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
761
781
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
762
782
|
method: "POST",
|
|
763
783
|
body: {
|
|
@@ -773,7 +793,7 @@ var ChatCommunityApi = class {
|
|
|
773
793
|
/** Delete a comment (soft delete). Only the original author can delete. */
|
|
774
794
|
async deleteComment(postId, commentId) {
|
|
775
795
|
const teamId = this.chat.getTeamId();
|
|
776
|
-
if (!teamId) throw new
|
|
796
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
777
797
|
await this.chat.fetch("/api/widget/community", {
|
|
778
798
|
method: "POST",
|
|
779
799
|
body: { teamId, action: "deleteComment", postId, commentId }
|
|
@@ -782,7 +802,7 @@ var ChatCommunityApi = class {
|
|
|
782
802
|
/** Toggle vote on a post. Returns new vote state and count. */
|
|
783
803
|
async vote(postId) {
|
|
784
804
|
const teamId = this.chat.getTeamId();
|
|
785
|
-
if (!teamId) throw new
|
|
805
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
786
806
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
787
807
|
method: "POST",
|
|
788
808
|
body: { teamId, action: "vote", postId }
|
|
@@ -792,7 +812,7 @@ var ChatCommunityApi = class {
|
|
|
792
812
|
/** Add a comment to a post. Supports 1-level nesting via parentCommentId. */
|
|
793
813
|
async comment(postId, params) {
|
|
794
814
|
const teamId = this.chat.getTeamId();
|
|
795
|
-
if (!teamId) throw new
|
|
815
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
796
816
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
797
817
|
method: "POST",
|
|
798
818
|
body: {
|
|
@@ -808,7 +828,7 @@ var ChatCommunityApi = class {
|
|
|
808
828
|
/** Toggle follow on a post. */
|
|
809
829
|
async follow(postId) {
|
|
810
830
|
const teamId = this.chat.getTeamId();
|
|
811
|
-
if (!teamId) throw new
|
|
831
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
812
832
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
813
833
|
method: "POST",
|
|
814
834
|
body: { teamId, action: "follow", postId }
|
|
@@ -818,7 +838,7 @@ var ChatCommunityApi = class {
|
|
|
818
838
|
/** Check if the current user has voted on a post. */
|
|
819
839
|
async getVoteStatus(postId) {
|
|
820
840
|
const teamId = this.chat.getTeamId();
|
|
821
|
-
if (!teamId) throw new
|
|
841
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
822
842
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
823
843
|
method: "GET",
|
|
824
844
|
query: { teamId, postId }
|
|
@@ -829,7 +849,7 @@ var ChatCommunityApi = class {
|
|
|
829
849
|
async bulkVoteStatus(postIds) {
|
|
830
850
|
if (postIds.length === 0) return {};
|
|
831
851
|
const teamId = this.chat.getTeamId();
|
|
832
|
-
if (!teamId) throw new
|
|
852
|
+
if (!teamId) throw new ChatClientAuthError("Not identified. Call chat.identify() first.");
|
|
833
853
|
const response = await this.chat.fetch("/api/widget/community", {
|
|
834
854
|
method: "GET",
|
|
835
855
|
query: { teamId, postIds: postIds.join(",") }
|
package/dist/community/index.cjs
CHANGED
|
@@ -23,6 +23,221 @@ __export(community_exports, {
|
|
|
23
23
|
CommunityClient: () => CommunityClient
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(community_exports);
|
|
26
|
+
|
|
27
|
+
// src/errors.ts
|
|
28
|
+
var ErrorType = {
|
|
29
|
+
AUTHENTICATION_ERROR: "authentication_error",
|
|
30
|
+
PERMISSION_ERROR: "permission_error",
|
|
31
|
+
INVALID_REQUEST_ERROR: "invalid_request_error",
|
|
32
|
+
NOT_FOUND_ERROR: "not_found_error",
|
|
33
|
+
CONFLICT_ERROR: "conflict_error",
|
|
34
|
+
RATE_LIMIT_ERROR: "rate_limit_error",
|
|
35
|
+
FEATURE_NOT_CONFIGURED: "feature_not_configured",
|
|
36
|
+
API_ERROR: "api_error",
|
|
37
|
+
SERVER_ERROR: "server_error"
|
|
38
|
+
};
|
|
39
|
+
var DEFAULT_DOC_URL = "https://cstar.help/developers/api/errors";
|
|
40
|
+
function normalizeArgs(messageOrStatus, maybeBody, defaults) {
|
|
41
|
+
if (typeof messageOrStatus === "string") {
|
|
42
|
+
return {
|
|
43
|
+
statusCode: defaults?.code === "rate_limit_error" ? 429 : 0,
|
|
44
|
+
body: {
|
|
45
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
46
|
+
code: defaults?.code ?? "sdk_error",
|
|
47
|
+
message: messageOrStatus,
|
|
48
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL,
|
|
49
|
+
...defaults?.feature ? { feature: defaults.feature } : {},
|
|
50
|
+
...defaults?.enable_url ? { enable_url: defaults.enable_url } : {}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
statusCode: messageOrStatus,
|
|
56
|
+
body: maybeBody ?? {
|
|
57
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
58
|
+
code: defaults?.code ?? "unknown_error",
|
|
59
|
+
message: defaults?.message ?? `Request failed with status ${messageOrStatus}`,
|
|
60
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
var CStarError = class extends Error {
|
|
65
|
+
constructor(messageOrStatus, body) {
|
|
66
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body);
|
|
67
|
+
super(resolved.message);
|
|
68
|
+
this.name = "CStarError";
|
|
69
|
+
this.type = resolved.type;
|
|
70
|
+
this.code = resolved.code;
|
|
71
|
+
this.param = resolved.param;
|
|
72
|
+
this.docUrl = resolved.doc_url;
|
|
73
|
+
this.requestId = resolved.request_id;
|
|
74
|
+
this.statusCode = statusCode;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var CStarAuthenticationError = class extends CStarError {
|
|
78
|
+
constructor(messageOrStatus, body) {
|
|
79
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
80
|
+
type: ErrorType.AUTHENTICATION_ERROR,
|
|
81
|
+
code: "authentication_failed",
|
|
82
|
+
doc_url: `${DEFAULT_DOC_URL}#authentication-error`
|
|
83
|
+
});
|
|
84
|
+
super(statusCode, resolved);
|
|
85
|
+
this.name = "CStarAuthenticationError";
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var CStarRateLimitError = class extends CStarError {
|
|
89
|
+
constructor(messageOrStatus, body, retryAfter) {
|
|
90
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
91
|
+
type: ErrorType.RATE_LIMIT_ERROR,
|
|
92
|
+
code: "rate_limit_exceeded",
|
|
93
|
+
doc_url: `${DEFAULT_DOC_URL}#rate-limit-error`
|
|
94
|
+
});
|
|
95
|
+
super(statusCode === 0 ? 429 : statusCode, resolved);
|
|
96
|
+
this.name = "CStarRateLimitError";
|
|
97
|
+
this.retryAfter = retryAfter ?? 60;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var CStarNotFoundError = class extends CStarError {
|
|
101
|
+
constructor(messageOrStatus, body) {
|
|
102
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
103
|
+
type: ErrorType.NOT_FOUND_ERROR,
|
|
104
|
+
code: "resource_not_found",
|
|
105
|
+
doc_url: `${DEFAULT_DOC_URL}#not-found-error`
|
|
106
|
+
});
|
|
107
|
+
super(statusCode, resolved);
|
|
108
|
+
this.name = "CStarNotFoundError";
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var CStarValidationError = class extends CStarError {
|
|
112
|
+
constructor(messageOrStatus, body) {
|
|
113
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
114
|
+
type: ErrorType.INVALID_REQUEST_ERROR,
|
|
115
|
+
code: "validation_error",
|
|
116
|
+
doc_url: `${DEFAULT_DOC_URL}#validation-error`
|
|
117
|
+
});
|
|
118
|
+
super(statusCode, resolved);
|
|
119
|
+
this.name = "CStarValidationError";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var CStarPermissionError = class extends CStarError {
|
|
123
|
+
constructor(messageOrStatus, body) {
|
|
124
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
125
|
+
type: ErrorType.PERMISSION_ERROR,
|
|
126
|
+
code: "permission_denied",
|
|
127
|
+
doc_url: `${DEFAULT_DOC_URL}#permission-error`
|
|
128
|
+
});
|
|
129
|
+
super(statusCode, resolved);
|
|
130
|
+
this.name = "CStarPermissionError";
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var CStarConflictError = class extends CStarError {
|
|
134
|
+
constructor(messageOrStatus, body) {
|
|
135
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
136
|
+
type: ErrorType.CONFLICT_ERROR,
|
|
137
|
+
code: "conflict",
|
|
138
|
+
doc_url: `${DEFAULT_DOC_URL}#conflict-error`
|
|
139
|
+
});
|
|
140
|
+
super(statusCode, resolved);
|
|
141
|
+
this.name = "CStarConflictError";
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var CStarServerError = class extends CStarError {
|
|
145
|
+
constructor(messageOrStatus, body) {
|
|
146
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
147
|
+
type: ErrorType.SERVER_ERROR,
|
|
148
|
+
code: "server_error",
|
|
149
|
+
doc_url: `${DEFAULT_DOC_URL}#server-error`
|
|
150
|
+
});
|
|
151
|
+
super(statusCode, resolved);
|
|
152
|
+
this.name = "CStarServerError";
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
var CStarFeatureDisabledError = class extends CStarError {
|
|
156
|
+
constructor(messageOrStatus, body) {
|
|
157
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
158
|
+
type: ErrorType.FEATURE_NOT_CONFIGURED,
|
|
159
|
+
code: "feature_not_configured",
|
|
160
|
+
doc_url: `${DEFAULT_DOC_URL}#feature-not-configured`
|
|
161
|
+
});
|
|
162
|
+
super(statusCode, resolved);
|
|
163
|
+
this.name = "CStarFeatureDisabledError";
|
|
164
|
+
this.feature = resolved.feature ?? "unknown";
|
|
165
|
+
this.enableUrl = resolved.enable_url ?? "";
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
function parsePublicError(status, body, fallbackMessage) {
|
|
169
|
+
const obj = body && typeof body === "object" ? body : null;
|
|
170
|
+
const errVal = obj?.error;
|
|
171
|
+
let message = fallbackMessage;
|
|
172
|
+
let structured = null;
|
|
173
|
+
if (typeof errVal === "string") {
|
|
174
|
+
message = errVal;
|
|
175
|
+
} else if (errVal && typeof errVal === "object") {
|
|
176
|
+
const e = errVal;
|
|
177
|
+
if (typeof e.message === "string") message = e.message;
|
|
178
|
+
structured = {
|
|
179
|
+
type: typeof e.type === "string" ? e.type : ErrorType.API_ERROR,
|
|
180
|
+
code: typeof e.code === "string" ? e.code : "api_error",
|
|
181
|
+
message,
|
|
182
|
+
param: typeof e.param === "string" ? e.param : void 0,
|
|
183
|
+
doc_url: typeof e.doc_url === "string" ? e.doc_url : DEFAULT_DOC_URL,
|
|
184
|
+
request_id: typeof e.request_id === "string" ? e.request_id : void 0,
|
|
185
|
+
feature: typeof e.feature === "string" ? e.feature : void 0,
|
|
186
|
+
enable_url: typeof e.enable_url === "string" ? e.enable_url : void 0
|
|
187
|
+
};
|
|
188
|
+
} else if (typeof obj?.message === "string") {
|
|
189
|
+
message = obj.message;
|
|
190
|
+
}
|
|
191
|
+
const errorBody = structured ?? {
|
|
192
|
+
type: ErrorType.API_ERROR,
|
|
193
|
+
code: status >= 500 ? "server_error" : "request_failed",
|
|
194
|
+
message,
|
|
195
|
+
doc_url: DEFAULT_DOC_URL
|
|
196
|
+
};
|
|
197
|
+
return parseError(status, { error: errorBody });
|
|
198
|
+
}
|
|
199
|
+
var STATUS_TO_CLASS = {
|
|
200
|
+
400: CStarValidationError,
|
|
201
|
+
401: CStarAuthenticationError,
|
|
202
|
+
403: CStarPermissionError,
|
|
203
|
+
404: CStarNotFoundError,
|
|
204
|
+
409: CStarConflictError,
|
|
205
|
+
422: CStarValidationError,
|
|
206
|
+
429: CStarRateLimitError
|
|
207
|
+
};
|
|
208
|
+
var TYPE_TO_CLASS = {
|
|
209
|
+
[ErrorType.AUTHENTICATION_ERROR]: CStarAuthenticationError,
|
|
210
|
+
[ErrorType.PERMISSION_ERROR]: CStarPermissionError,
|
|
211
|
+
[ErrorType.RATE_LIMIT_ERROR]: CStarRateLimitError,
|
|
212
|
+
[ErrorType.NOT_FOUND_ERROR]: CStarNotFoundError,
|
|
213
|
+
[ErrorType.INVALID_REQUEST_ERROR]: CStarValidationError,
|
|
214
|
+
[ErrorType.CONFLICT_ERROR]: CStarConflictError,
|
|
215
|
+
[ErrorType.SERVER_ERROR]: CStarServerError,
|
|
216
|
+
[ErrorType.FEATURE_NOT_CONFIGURED]: CStarFeatureDisabledError
|
|
217
|
+
};
|
|
218
|
+
function parseError(statusCode, body, retryAfter) {
|
|
219
|
+
const errorBody = body?.error ?? {
|
|
220
|
+
type: ErrorType.API_ERROR,
|
|
221
|
+
code: "unknown_error",
|
|
222
|
+
message: `Request failed with status ${statusCode}`,
|
|
223
|
+
doc_url: DEFAULT_DOC_URL
|
|
224
|
+
};
|
|
225
|
+
if (statusCode === 429) {
|
|
226
|
+
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
227
|
+
}
|
|
228
|
+
const StatusCls = STATUS_TO_CLASS[statusCode];
|
|
229
|
+
if (StatusCls) {
|
|
230
|
+
return new StatusCls(statusCode, errorBody);
|
|
231
|
+
}
|
|
232
|
+
const TypeCls = TYPE_TO_CLASS[errorBody.type];
|
|
233
|
+
if (TypeCls) {
|
|
234
|
+
return new TypeCls(statusCode, errorBody);
|
|
235
|
+
}
|
|
236
|
+
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
237
|
+
return new CStarError(statusCode, errorBody);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/community/index.ts
|
|
26
241
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
27
242
|
var CommunityClient = class {
|
|
28
243
|
constructor(config) {
|
|
@@ -30,6 +245,13 @@ var CommunityClient = class {
|
|
|
30
245
|
this.teamId = null;
|
|
31
246
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
32
247
|
this.teamSlug = config.teamSlug;
|
|
248
|
+
this.publishableKey = config.publishableKey ?? null;
|
|
249
|
+
this.mode = this.publishableKey?.startsWith("pk_test_") ? "test" : "live";
|
|
250
|
+
if (this.publishableKey && !/^pk_(test|live)_/.test(this.publishableKey)) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
"[cStar] CommunityClient: publishableKey must start with `pk_test_` or `pk_live_`. Secret keys (`sk_*`) cannot be used in browser/anonymous contexts."
|
|
253
|
+
);
|
|
254
|
+
}
|
|
33
255
|
}
|
|
34
256
|
/**
|
|
35
257
|
* Set a session token from identity verification.
|
|
@@ -246,13 +468,13 @@ var CommunityClient = class {
|
|
|
246
468
|
*/
|
|
247
469
|
resolveTeamId() {
|
|
248
470
|
if (this.teamId) return this.teamId;
|
|
249
|
-
throw new
|
|
471
|
+
throw new CStarValidationError(
|
|
250
472
|
"Team ID is required for authenticated operations. Pass it via setSessionToken(token, teamId) or use ChatClient.identify() which provides it automatically."
|
|
251
473
|
);
|
|
252
474
|
}
|
|
253
475
|
async authenticatedFetch(path, options) {
|
|
254
476
|
if (!this.sessionToken) {
|
|
255
|
-
throw new
|
|
477
|
+
throw new CStarValidationError(
|
|
256
478
|
"Session token required. Call setSessionToken() or use ChatClient.identify() first."
|
|
257
479
|
);
|
|
258
480
|
}
|
|
@@ -275,9 +497,8 @@ var CommunityClient = class {
|
|
|
275
497
|
body: options.body ? JSON.stringify(options.body) : void 0
|
|
276
498
|
});
|
|
277
499
|
if (!response.ok) {
|
|
278
|
-
const errorBody = await response.json().catch(() =>
|
|
279
|
-
|
|
280
|
-
throw new Error(message);
|
|
500
|
+
const errorBody = await response.json().catch(() => null);
|
|
501
|
+
throw parsePublicError(response.status, errorBody, `Community API error: ${response.status}`);
|
|
281
502
|
}
|
|
282
503
|
return response.json();
|
|
283
504
|
}
|
|
@@ -291,14 +512,17 @@ var CommunityClient = class {
|
|
|
291
512
|
const qs = params.toString();
|
|
292
513
|
if (qs) url += `?${qs}`;
|
|
293
514
|
}
|
|
515
|
+
const headers = { "Content-Type": "application/json" };
|
|
516
|
+
if (this.publishableKey) {
|
|
517
|
+
headers["Authorization"] = `Bearer ${this.publishableKey}`;
|
|
518
|
+
}
|
|
294
519
|
const response = await globalThis.fetch(url, {
|
|
295
520
|
method: "GET",
|
|
296
|
-
headers
|
|
521
|
+
headers
|
|
297
522
|
});
|
|
298
523
|
if (!response.ok) {
|
|
299
|
-
const errorBody = await response.json().catch(() =>
|
|
300
|
-
|
|
301
|
-
throw new Error(message);
|
|
524
|
+
const errorBody = await response.json().catch(() => null);
|
|
525
|
+
throw parsePublicError(response.status, errorBody, `Community API error: ${response.status}`);
|
|
302
526
|
}
|
|
303
527
|
return response.json();
|
|
304
528
|
}
|