@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/library/index.js
CHANGED
|
@@ -1,3 +1,216 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var ErrorType = {
|
|
3
|
+
AUTHENTICATION_ERROR: "authentication_error",
|
|
4
|
+
PERMISSION_ERROR: "permission_error",
|
|
5
|
+
INVALID_REQUEST_ERROR: "invalid_request_error",
|
|
6
|
+
NOT_FOUND_ERROR: "not_found_error",
|
|
7
|
+
CONFLICT_ERROR: "conflict_error",
|
|
8
|
+
RATE_LIMIT_ERROR: "rate_limit_error",
|
|
9
|
+
FEATURE_NOT_CONFIGURED: "feature_not_configured",
|
|
10
|
+
API_ERROR: "api_error",
|
|
11
|
+
SERVER_ERROR: "server_error"
|
|
12
|
+
};
|
|
13
|
+
var DEFAULT_DOC_URL = "https://cstar.help/developers/api/errors";
|
|
14
|
+
function normalizeArgs(messageOrStatus, maybeBody, defaults) {
|
|
15
|
+
if (typeof messageOrStatus === "string") {
|
|
16
|
+
return {
|
|
17
|
+
statusCode: defaults?.code === "rate_limit_error" ? 429 : 0,
|
|
18
|
+
body: {
|
|
19
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
20
|
+
code: defaults?.code ?? "sdk_error",
|
|
21
|
+
message: messageOrStatus,
|
|
22
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL,
|
|
23
|
+
...defaults?.feature ? { feature: defaults.feature } : {},
|
|
24
|
+
...defaults?.enable_url ? { enable_url: defaults.enable_url } : {}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
statusCode: messageOrStatus,
|
|
30
|
+
body: maybeBody ?? {
|
|
31
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
32
|
+
code: defaults?.code ?? "unknown_error",
|
|
33
|
+
message: defaults?.message ?? `Request failed with status ${messageOrStatus}`,
|
|
34
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
var CStarError = class extends Error {
|
|
39
|
+
constructor(messageOrStatus, body) {
|
|
40
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body);
|
|
41
|
+
super(resolved.message);
|
|
42
|
+
this.name = "CStarError";
|
|
43
|
+
this.type = resolved.type;
|
|
44
|
+
this.code = resolved.code;
|
|
45
|
+
this.param = resolved.param;
|
|
46
|
+
this.docUrl = resolved.doc_url;
|
|
47
|
+
this.requestId = resolved.request_id;
|
|
48
|
+
this.statusCode = statusCode;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
var CStarAuthenticationError = class extends CStarError {
|
|
52
|
+
constructor(messageOrStatus, body) {
|
|
53
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
54
|
+
type: ErrorType.AUTHENTICATION_ERROR,
|
|
55
|
+
code: "authentication_failed",
|
|
56
|
+
doc_url: `${DEFAULT_DOC_URL}#authentication-error`
|
|
57
|
+
});
|
|
58
|
+
super(statusCode, resolved);
|
|
59
|
+
this.name = "CStarAuthenticationError";
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var CStarRateLimitError = class extends CStarError {
|
|
63
|
+
constructor(messageOrStatus, body, retryAfter) {
|
|
64
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
65
|
+
type: ErrorType.RATE_LIMIT_ERROR,
|
|
66
|
+
code: "rate_limit_exceeded",
|
|
67
|
+
doc_url: `${DEFAULT_DOC_URL}#rate-limit-error`
|
|
68
|
+
});
|
|
69
|
+
super(statusCode === 0 ? 429 : statusCode, resolved);
|
|
70
|
+
this.name = "CStarRateLimitError";
|
|
71
|
+
this.retryAfter = retryAfter ?? 60;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var CStarNotFoundError = class extends CStarError {
|
|
75
|
+
constructor(messageOrStatus, body) {
|
|
76
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
77
|
+
type: ErrorType.NOT_FOUND_ERROR,
|
|
78
|
+
code: "resource_not_found",
|
|
79
|
+
doc_url: `${DEFAULT_DOC_URL}#not-found-error`
|
|
80
|
+
});
|
|
81
|
+
super(statusCode, resolved);
|
|
82
|
+
this.name = "CStarNotFoundError";
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var CStarValidationError = class extends CStarError {
|
|
86
|
+
constructor(messageOrStatus, body) {
|
|
87
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
88
|
+
type: ErrorType.INVALID_REQUEST_ERROR,
|
|
89
|
+
code: "validation_error",
|
|
90
|
+
doc_url: `${DEFAULT_DOC_URL}#validation-error`
|
|
91
|
+
});
|
|
92
|
+
super(statusCode, resolved);
|
|
93
|
+
this.name = "CStarValidationError";
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
var CStarPermissionError = class extends CStarError {
|
|
97
|
+
constructor(messageOrStatus, body) {
|
|
98
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
99
|
+
type: ErrorType.PERMISSION_ERROR,
|
|
100
|
+
code: "permission_denied",
|
|
101
|
+
doc_url: `${DEFAULT_DOC_URL}#permission-error`
|
|
102
|
+
});
|
|
103
|
+
super(statusCode, resolved);
|
|
104
|
+
this.name = "CStarPermissionError";
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var CStarConflictError = class extends CStarError {
|
|
108
|
+
constructor(messageOrStatus, body) {
|
|
109
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
110
|
+
type: ErrorType.CONFLICT_ERROR,
|
|
111
|
+
code: "conflict",
|
|
112
|
+
doc_url: `${DEFAULT_DOC_URL}#conflict-error`
|
|
113
|
+
});
|
|
114
|
+
super(statusCode, resolved);
|
|
115
|
+
this.name = "CStarConflictError";
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
var CStarServerError = class extends CStarError {
|
|
119
|
+
constructor(messageOrStatus, body) {
|
|
120
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
121
|
+
type: ErrorType.SERVER_ERROR,
|
|
122
|
+
code: "server_error",
|
|
123
|
+
doc_url: `${DEFAULT_DOC_URL}#server-error`
|
|
124
|
+
});
|
|
125
|
+
super(statusCode, resolved);
|
|
126
|
+
this.name = "CStarServerError";
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var CStarFeatureDisabledError = class extends CStarError {
|
|
130
|
+
constructor(messageOrStatus, body) {
|
|
131
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
132
|
+
type: ErrorType.FEATURE_NOT_CONFIGURED,
|
|
133
|
+
code: "feature_not_configured",
|
|
134
|
+
doc_url: `${DEFAULT_DOC_URL}#feature-not-configured`
|
|
135
|
+
});
|
|
136
|
+
super(statusCode, resolved);
|
|
137
|
+
this.name = "CStarFeatureDisabledError";
|
|
138
|
+
this.feature = resolved.feature ?? "unknown";
|
|
139
|
+
this.enableUrl = resolved.enable_url ?? "";
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
function parsePublicError(status, body, fallbackMessage) {
|
|
143
|
+
const obj = body && typeof body === "object" ? body : null;
|
|
144
|
+
const errVal = obj?.error;
|
|
145
|
+
let message = fallbackMessage;
|
|
146
|
+
let structured = null;
|
|
147
|
+
if (typeof errVal === "string") {
|
|
148
|
+
message = errVal;
|
|
149
|
+
} else if (errVal && typeof errVal === "object") {
|
|
150
|
+
const e = errVal;
|
|
151
|
+
if (typeof e.message === "string") message = e.message;
|
|
152
|
+
structured = {
|
|
153
|
+
type: typeof e.type === "string" ? e.type : ErrorType.API_ERROR,
|
|
154
|
+
code: typeof e.code === "string" ? e.code : "api_error",
|
|
155
|
+
message,
|
|
156
|
+
param: typeof e.param === "string" ? e.param : void 0,
|
|
157
|
+
doc_url: typeof e.doc_url === "string" ? e.doc_url : DEFAULT_DOC_URL,
|
|
158
|
+
request_id: typeof e.request_id === "string" ? e.request_id : void 0,
|
|
159
|
+
feature: typeof e.feature === "string" ? e.feature : void 0,
|
|
160
|
+
enable_url: typeof e.enable_url === "string" ? e.enable_url : void 0
|
|
161
|
+
};
|
|
162
|
+
} else if (typeof obj?.message === "string") {
|
|
163
|
+
message = obj.message;
|
|
164
|
+
}
|
|
165
|
+
const errorBody = structured ?? {
|
|
166
|
+
type: ErrorType.API_ERROR,
|
|
167
|
+
code: status >= 500 ? "server_error" : "request_failed",
|
|
168
|
+
message,
|
|
169
|
+
doc_url: DEFAULT_DOC_URL
|
|
170
|
+
};
|
|
171
|
+
return parseError(status, { error: errorBody });
|
|
172
|
+
}
|
|
173
|
+
var STATUS_TO_CLASS = {
|
|
174
|
+
400: CStarValidationError,
|
|
175
|
+
401: CStarAuthenticationError,
|
|
176
|
+
403: CStarPermissionError,
|
|
177
|
+
404: CStarNotFoundError,
|
|
178
|
+
409: CStarConflictError,
|
|
179
|
+
422: CStarValidationError,
|
|
180
|
+
429: CStarRateLimitError
|
|
181
|
+
};
|
|
182
|
+
var TYPE_TO_CLASS = {
|
|
183
|
+
[ErrorType.AUTHENTICATION_ERROR]: CStarAuthenticationError,
|
|
184
|
+
[ErrorType.PERMISSION_ERROR]: CStarPermissionError,
|
|
185
|
+
[ErrorType.RATE_LIMIT_ERROR]: CStarRateLimitError,
|
|
186
|
+
[ErrorType.NOT_FOUND_ERROR]: CStarNotFoundError,
|
|
187
|
+
[ErrorType.INVALID_REQUEST_ERROR]: CStarValidationError,
|
|
188
|
+
[ErrorType.CONFLICT_ERROR]: CStarConflictError,
|
|
189
|
+
[ErrorType.SERVER_ERROR]: CStarServerError,
|
|
190
|
+
[ErrorType.FEATURE_NOT_CONFIGURED]: CStarFeatureDisabledError
|
|
191
|
+
};
|
|
192
|
+
function parseError(statusCode, body, retryAfter) {
|
|
193
|
+
const errorBody = body?.error ?? {
|
|
194
|
+
type: ErrorType.API_ERROR,
|
|
195
|
+
code: "unknown_error",
|
|
196
|
+
message: `Request failed with status ${statusCode}`,
|
|
197
|
+
doc_url: DEFAULT_DOC_URL
|
|
198
|
+
};
|
|
199
|
+
if (statusCode === 429) {
|
|
200
|
+
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
201
|
+
}
|
|
202
|
+
const StatusCls = STATUS_TO_CLASS[statusCode];
|
|
203
|
+
if (StatusCls) {
|
|
204
|
+
return new StatusCls(statusCode, errorBody);
|
|
205
|
+
}
|
|
206
|
+
const TypeCls = TYPE_TO_CLASS[errorBody.type];
|
|
207
|
+
if (TypeCls) {
|
|
208
|
+
return new TypeCls(statusCode, errorBody);
|
|
209
|
+
}
|
|
210
|
+
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
211
|
+
return new CStarError(statusCode, errorBody);
|
|
212
|
+
}
|
|
213
|
+
|
|
1
214
|
// src/library/index.ts
|
|
2
215
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
3
216
|
var LibraryClient = class {
|
|
@@ -5,6 +218,13 @@ var LibraryClient = class {
|
|
|
5
218
|
this.resolvedTeamId = null;
|
|
6
219
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
7
220
|
this.teamSlug = config.teamSlug;
|
|
221
|
+
this.publishableKey = config.publishableKey ?? null;
|
|
222
|
+
this.mode = this.publishableKey?.startsWith("pk_test_") ? "test" : "live";
|
|
223
|
+
if (this.publishableKey && !/^pk_(test|live)_/.test(this.publishableKey)) {
|
|
224
|
+
throw new Error(
|
|
225
|
+
"[cStar] LibraryClient: publishableKey must start with `pk_test_` or `pk_live_`. Secret keys (`sk_*`) cannot be used in browser/anonymous contexts."
|
|
226
|
+
);
|
|
227
|
+
}
|
|
8
228
|
}
|
|
9
229
|
/** List all public categories with article counts. */
|
|
10
230
|
async categories() {
|
|
@@ -54,13 +274,19 @@ var LibraryClient = class {
|
|
|
54
274
|
*/
|
|
55
275
|
async recordView(slug) {
|
|
56
276
|
const url = `${this.baseUrl}/api/library/${this.teamSlug}/articles/${slug}/view`;
|
|
277
|
+
const headers = { "Content-Type": "application/json" };
|
|
278
|
+
if (this.publishableKey) headers["Authorization"] = `Bearer ${this.publishableKey}`;
|
|
57
279
|
const response = await globalThis.fetch(url, {
|
|
58
280
|
method: "POST",
|
|
59
|
-
headers
|
|
281
|
+
headers
|
|
60
282
|
});
|
|
61
283
|
if (!response.ok) {
|
|
62
|
-
const errorBody = await response.json().catch(() =>
|
|
63
|
-
throw
|
|
284
|
+
const errorBody = await response.json().catch(() => null);
|
|
285
|
+
throw parsePublicError(
|
|
286
|
+
response.status,
|
|
287
|
+
errorBody,
|
|
288
|
+
`View tracking failed: ${response.status}`
|
|
289
|
+
);
|
|
64
290
|
}
|
|
65
291
|
const body = await response.json();
|
|
66
292
|
return { viewCount: body.viewCount };
|
|
@@ -82,14 +308,27 @@ var LibraryClient = class {
|
|
|
82
308
|
*/
|
|
83
309
|
async submitFeedback(slug, params) {
|
|
84
310
|
const url = `${this.baseUrl}/api/library/${this.teamSlug}/articles/${slug}/feedback`;
|
|
311
|
+
const headers = { "Content-Type": "application/json" };
|
|
312
|
+
if (this.publishableKey) headers["Authorization"] = `Bearer ${this.publishableKey}`;
|
|
85
313
|
const response = await globalThis.fetch(url, {
|
|
86
314
|
method: "POST",
|
|
87
|
-
headers
|
|
315
|
+
headers,
|
|
88
316
|
body: JSON.stringify(params)
|
|
89
317
|
});
|
|
90
|
-
const body = await response.json();
|
|
318
|
+
const body = await response.json().catch(() => null);
|
|
91
319
|
if (!response.ok) {
|
|
92
|
-
throw
|
|
320
|
+
throw parsePublicError(
|
|
321
|
+
response.status,
|
|
322
|
+
body,
|
|
323
|
+
body?.error ?? `Feedback submission failed: ${response.status}`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
if (body === null) {
|
|
327
|
+
throw parsePublicError(
|
|
328
|
+
response.status,
|
|
329
|
+
null,
|
|
330
|
+
`Feedback submission returned an invalid JSON response (status ${response.status})`
|
|
331
|
+
);
|
|
93
332
|
}
|
|
94
333
|
return body;
|
|
95
334
|
}
|
|
@@ -120,13 +359,17 @@ var LibraryClient = class {
|
|
|
120
359
|
const qs = params.toString();
|
|
121
360
|
if (qs) url += `?${qs}`;
|
|
122
361
|
}
|
|
362
|
+
const headers = { "Content-Type": "application/json" };
|
|
363
|
+
if (this.publishableKey) {
|
|
364
|
+
headers["Authorization"] = `Bearer ${this.publishableKey}`;
|
|
365
|
+
}
|
|
123
366
|
const response = await globalThis.fetch(url, {
|
|
124
367
|
method: "GET",
|
|
125
|
-
headers
|
|
368
|
+
headers
|
|
126
369
|
});
|
|
127
370
|
if (!response.ok) {
|
|
128
|
-
const errorBody = await response.json().catch(() =>
|
|
129
|
-
throw
|
|
371
|
+
const errorBody = await response.json().catch(() => null);
|
|
372
|
+
throw parsePublicError(response.status, errorBody, `Library API error: ${response.status}`);
|
|
130
373
|
}
|
|
131
374
|
return response.json();
|
|
132
375
|
}
|
package/dist/quickhelp/index.cjs
CHANGED
|
@@ -24,6 +24,160 @@ __export(quickhelp_exports, {
|
|
|
24
24
|
QuickHelpError: () => QuickHelpError
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(quickhelp_exports);
|
|
27
|
+
|
|
28
|
+
// src/errors.ts
|
|
29
|
+
var ErrorType = {
|
|
30
|
+
AUTHENTICATION_ERROR: "authentication_error",
|
|
31
|
+
PERMISSION_ERROR: "permission_error",
|
|
32
|
+
INVALID_REQUEST_ERROR: "invalid_request_error",
|
|
33
|
+
NOT_FOUND_ERROR: "not_found_error",
|
|
34
|
+
CONFLICT_ERROR: "conflict_error",
|
|
35
|
+
RATE_LIMIT_ERROR: "rate_limit_error",
|
|
36
|
+
FEATURE_NOT_CONFIGURED: "feature_not_configured",
|
|
37
|
+
API_ERROR: "api_error",
|
|
38
|
+
SERVER_ERROR: "server_error"
|
|
39
|
+
};
|
|
40
|
+
var DEFAULT_DOC_URL = "https://cstar.help/developers/api/errors";
|
|
41
|
+
function normalizeArgs(messageOrStatus, maybeBody, defaults) {
|
|
42
|
+
if (typeof messageOrStatus === "string") {
|
|
43
|
+
return {
|
|
44
|
+
statusCode: defaults?.code === "rate_limit_error" ? 429 : 0,
|
|
45
|
+
body: {
|
|
46
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
47
|
+
code: defaults?.code ?? "sdk_error",
|
|
48
|
+
message: messageOrStatus,
|
|
49
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL,
|
|
50
|
+
...defaults?.feature ? { feature: defaults.feature } : {},
|
|
51
|
+
...defaults?.enable_url ? { enable_url: defaults.enable_url } : {}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
statusCode: messageOrStatus,
|
|
57
|
+
body: maybeBody ?? {
|
|
58
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
59
|
+
code: defaults?.code ?? "unknown_error",
|
|
60
|
+
message: defaults?.message ?? `Request failed with status ${messageOrStatus}`,
|
|
61
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var CStarError = class extends Error {
|
|
66
|
+
constructor(messageOrStatus, body) {
|
|
67
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body);
|
|
68
|
+
super(resolved.message);
|
|
69
|
+
this.name = "CStarError";
|
|
70
|
+
this.type = resolved.type;
|
|
71
|
+
this.code = resolved.code;
|
|
72
|
+
this.param = resolved.param;
|
|
73
|
+
this.docUrl = resolved.doc_url;
|
|
74
|
+
this.requestId = resolved.request_id;
|
|
75
|
+
this.statusCode = statusCode;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
var CStarAuthenticationError = class extends CStarError {
|
|
79
|
+
constructor(messageOrStatus, body) {
|
|
80
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
81
|
+
type: ErrorType.AUTHENTICATION_ERROR,
|
|
82
|
+
code: "authentication_failed",
|
|
83
|
+
doc_url: `${DEFAULT_DOC_URL}#authentication-error`
|
|
84
|
+
});
|
|
85
|
+
super(statusCode, resolved);
|
|
86
|
+
this.name = "CStarAuthenticationError";
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var CStarRateLimitError = class extends CStarError {
|
|
90
|
+
constructor(messageOrStatus, body, retryAfter) {
|
|
91
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
92
|
+
type: ErrorType.RATE_LIMIT_ERROR,
|
|
93
|
+
code: "rate_limit_exceeded",
|
|
94
|
+
doc_url: `${DEFAULT_DOC_URL}#rate-limit-error`
|
|
95
|
+
});
|
|
96
|
+
super(statusCode === 0 ? 429 : statusCode, resolved);
|
|
97
|
+
this.name = "CStarRateLimitError";
|
|
98
|
+
this.retryAfter = retryAfter ?? 60;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var CStarNotFoundError = class extends CStarError {
|
|
102
|
+
constructor(messageOrStatus, body) {
|
|
103
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
104
|
+
type: ErrorType.NOT_FOUND_ERROR,
|
|
105
|
+
code: "resource_not_found",
|
|
106
|
+
doc_url: `${DEFAULT_DOC_URL}#not-found-error`
|
|
107
|
+
});
|
|
108
|
+
super(statusCode, resolved);
|
|
109
|
+
this.name = "CStarNotFoundError";
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var CStarValidationError = class extends CStarError {
|
|
113
|
+
constructor(messageOrStatus, body) {
|
|
114
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
115
|
+
type: ErrorType.INVALID_REQUEST_ERROR,
|
|
116
|
+
code: "validation_error",
|
|
117
|
+
doc_url: `${DEFAULT_DOC_URL}#validation-error`
|
|
118
|
+
});
|
|
119
|
+
super(statusCode, resolved);
|
|
120
|
+
this.name = "CStarValidationError";
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
var CStarPermissionError = class extends CStarError {
|
|
124
|
+
constructor(messageOrStatus, body) {
|
|
125
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
126
|
+
type: ErrorType.PERMISSION_ERROR,
|
|
127
|
+
code: "permission_denied",
|
|
128
|
+
doc_url: `${DEFAULT_DOC_URL}#permission-error`
|
|
129
|
+
});
|
|
130
|
+
super(statusCode, resolved);
|
|
131
|
+
this.name = "CStarPermissionError";
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
var CStarConflictError = class extends CStarError {
|
|
135
|
+
constructor(messageOrStatus, body) {
|
|
136
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
137
|
+
type: ErrorType.CONFLICT_ERROR,
|
|
138
|
+
code: "conflict",
|
|
139
|
+
doc_url: `${DEFAULT_DOC_URL}#conflict-error`
|
|
140
|
+
});
|
|
141
|
+
super(statusCode, resolved);
|
|
142
|
+
this.name = "CStarConflictError";
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
var CStarServerError = class extends CStarError {
|
|
146
|
+
constructor(messageOrStatus, body) {
|
|
147
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
148
|
+
type: ErrorType.SERVER_ERROR,
|
|
149
|
+
code: "server_error",
|
|
150
|
+
doc_url: `${DEFAULT_DOC_URL}#server-error`
|
|
151
|
+
});
|
|
152
|
+
super(statusCode, resolved);
|
|
153
|
+
this.name = "CStarServerError";
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
var CStarFeatureDisabledError = class extends CStarError {
|
|
157
|
+
constructor(messageOrStatus, body) {
|
|
158
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
159
|
+
type: ErrorType.FEATURE_NOT_CONFIGURED,
|
|
160
|
+
code: "feature_not_configured",
|
|
161
|
+
doc_url: `${DEFAULT_DOC_URL}#feature-not-configured`
|
|
162
|
+
});
|
|
163
|
+
super(statusCode, resolved);
|
|
164
|
+
this.name = "CStarFeatureDisabledError";
|
|
165
|
+
this.feature = resolved.feature ?? "unknown";
|
|
166
|
+
this.enableUrl = resolved.enable_url ?? "";
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
var TYPE_TO_CLASS = {
|
|
170
|
+
[ErrorType.AUTHENTICATION_ERROR]: CStarAuthenticationError,
|
|
171
|
+
[ErrorType.PERMISSION_ERROR]: CStarPermissionError,
|
|
172
|
+
[ErrorType.RATE_LIMIT_ERROR]: CStarRateLimitError,
|
|
173
|
+
[ErrorType.NOT_FOUND_ERROR]: CStarNotFoundError,
|
|
174
|
+
[ErrorType.INVALID_REQUEST_ERROR]: CStarValidationError,
|
|
175
|
+
[ErrorType.CONFLICT_ERROR]: CStarConflictError,
|
|
176
|
+
[ErrorType.SERVER_ERROR]: CStarServerError,
|
|
177
|
+
[ErrorType.FEATURE_NOT_CONFIGURED]: CStarFeatureDisabledError
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// src/quickhelp/index.ts
|
|
27
181
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
28
182
|
var QuickHelpClient = class {
|
|
29
183
|
constructor(config) {
|
|
@@ -32,6 +186,16 @@ var QuickHelpClient = class {
|
|
|
32
186
|
}
|
|
33
187
|
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
34
188
|
this.teamId = config.teamId;
|
|
189
|
+
this.publishableKey = config.publishableKey ?? null;
|
|
190
|
+
this.mode = this.publishableKey?.startsWith("pk_test_") ? "test" : "live";
|
|
191
|
+
if (this.publishableKey && !/^pk_(test|live)_/.test(this.publishableKey)) {
|
|
192
|
+
throw new Error(
|
|
193
|
+
"[cStar] QuickHelpClient: publishableKey must start with `pk_test_` or `pk_live_`. Secret keys (`sk_*`) cannot be used in browser/anonymous contexts."
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
authHeaders() {
|
|
198
|
+
return this.publishableKey ? { Authorization: `Bearer ${this.publishableKey}` } : {};
|
|
35
199
|
}
|
|
36
200
|
/**
|
|
37
201
|
* Fetch the sanitized public config (title, subtitle, placeholder,
|
|
@@ -42,7 +206,7 @@ var QuickHelpClient = class {
|
|
|
42
206
|
*/
|
|
43
207
|
async config() {
|
|
44
208
|
const url = `${this.baseUrl}/api/quickhelp/config/${encodeURIComponent(this.teamId)}`;
|
|
45
|
-
const res = await globalThis.fetch(url, { method: "GET" });
|
|
209
|
+
const res = await globalThis.fetch(url, { method: "GET", headers: this.authHeaders() });
|
|
46
210
|
if (res.status === 404) return null;
|
|
47
211
|
if (!res.ok) {
|
|
48
212
|
const body2 = await res.json().catch(() => null);
|
|
@@ -61,7 +225,7 @@ var QuickHelpClient = class {
|
|
|
61
225
|
const url = `${this.baseUrl}/api/quickhelp/ask`;
|
|
62
226
|
const res = await globalThis.fetch(url, {
|
|
63
227
|
method: "POST",
|
|
64
|
-
headers: { "Content-Type": "application/json" },
|
|
228
|
+
headers: { "Content-Type": "application/json", ...this.authHeaders() },
|
|
65
229
|
body: JSON.stringify({
|
|
66
230
|
team_id: this.teamId,
|
|
67
231
|
session_id: params.sessionId ?? null,
|
|
@@ -70,6 +234,16 @@ var QuickHelpClient = class {
|
|
|
70
234
|
});
|
|
71
235
|
const body = await res.json().catch(() => null);
|
|
72
236
|
if (!res.ok || !body?.success || !body.data) {
|
|
237
|
+
if (res.status === 503 || body?.error?.code === "feature_not_configured") {
|
|
238
|
+
throw new CStarFeatureDisabledError(res.status, {
|
|
239
|
+
type: "feature_not_configured",
|
|
240
|
+
code: "feature_not_configured",
|
|
241
|
+
message: body?.error?.message ?? "Quick Help is not available on this team. Enable an AI Agent (Settings \u2192 AI Agents) and configure Quick Help (Settings \u2192 Quick Help) before calling .ask().",
|
|
242
|
+
doc_url: "https://cstar.help/developers/api/errors#feature-not-configured",
|
|
243
|
+
feature: "quickHelp",
|
|
244
|
+
enable_url: `${this.baseUrl}/team/${encodeURIComponent(this.teamId)}/settings?section=quickHelp`
|
|
245
|
+
});
|
|
246
|
+
}
|
|
73
247
|
const message = body?.error?.message ?? `Quick Help ask failed: ${res.status}`;
|
|
74
248
|
const err = new QuickHelpError(message, {
|
|
75
249
|
status: res.status,
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
interface QuickHelpConfig {
|
|
3
3
|
/** Your team's UUID. Required. */
|
|
4
4
|
teamId: string;
|
|
5
|
+
/**
|
|
6
|
+
* Optional publishable key (`pk_test_*` or `pk_live_*`). Sent as
|
|
7
|
+
* `Authorization: Bearer` so test-mode dev sessions can be scoped
|
|
8
|
+
* separately from live customer sessions in your analytics. Backwards-
|
|
9
|
+
* compatible: omit and the client behaves exactly as before.
|
|
10
|
+
*/
|
|
11
|
+
publishableKey?: string;
|
|
5
12
|
/** Override the base URL (defaults to https://www.cstar.help). */
|
|
6
13
|
baseUrl?: string;
|
|
7
14
|
}
|
|
@@ -61,7 +68,11 @@ interface QuickHelpAskResult {
|
|
|
61
68
|
declare class QuickHelpClient {
|
|
62
69
|
private readonly baseUrl;
|
|
63
70
|
private readonly teamId;
|
|
71
|
+
private readonly publishableKey;
|
|
72
|
+
/** Resolved mode based on the publishable-key prefix. */
|
|
73
|
+
readonly mode: 'live' | 'test';
|
|
64
74
|
constructor(config: QuickHelpConfig);
|
|
75
|
+
private authHeaders;
|
|
65
76
|
/**
|
|
66
77
|
* Fetch the sanitized public config (title, subtitle, placeholder,
|
|
67
78
|
* theme overrides). Never includes agent id or escalation contact
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
interface QuickHelpConfig {
|
|
3
3
|
/** Your team's UUID. Required. */
|
|
4
4
|
teamId: string;
|
|
5
|
+
/**
|
|
6
|
+
* Optional publishable key (`pk_test_*` or `pk_live_*`). Sent as
|
|
7
|
+
* `Authorization: Bearer` so test-mode dev sessions can be scoped
|
|
8
|
+
* separately from live customer sessions in your analytics. Backwards-
|
|
9
|
+
* compatible: omit and the client behaves exactly as before.
|
|
10
|
+
*/
|
|
11
|
+
publishableKey?: string;
|
|
5
12
|
/** Override the base URL (defaults to https://www.cstar.help). */
|
|
6
13
|
baseUrl?: string;
|
|
7
14
|
}
|
|
@@ -61,7 +68,11 @@ interface QuickHelpAskResult {
|
|
|
61
68
|
declare class QuickHelpClient {
|
|
62
69
|
private readonly baseUrl;
|
|
63
70
|
private readonly teamId;
|
|
71
|
+
private readonly publishableKey;
|
|
72
|
+
/** Resolved mode based on the publishable-key prefix. */
|
|
73
|
+
readonly mode: 'live' | 'test';
|
|
64
74
|
constructor(config: QuickHelpConfig);
|
|
75
|
+
private authHeaders;
|
|
65
76
|
/**
|
|
66
77
|
* Fetch the sanitized public config (title, subtitle, placeholder,
|
|
67
78
|
* theme overrides). Never includes agent id or escalation contact
|