@cstar.help/js 0.1.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/index.cjs ADDED
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ CStarAuthenticationError: () => CStarAuthenticationError,
24
+ CStarClient: () => CStarClient,
25
+ CStarError: () => CStarError,
26
+ CStarNotFoundError: () => CStarNotFoundError,
27
+ CStarRateLimitError: () => CStarRateLimitError,
28
+ CStarValidationError: () => CStarValidationError,
29
+ ErrorType: () => ErrorType
30
+ });
31
+ module.exports = __toCommonJS(src_exports);
32
+
33
+ // src/errors.ts
34
+ var ErrorType = {
35
+ AUTHENTICATION_ERROR: "authentication_error",
36
+ INVALID_REQUEST_ERROR: "invalid_request_error",
37
+ NOT_FOUND_ERROR: "not_found_error",
38
+ RATE_LIMIT_ERROR: "rate_limit_error",
39
+ API_ERROR: "api_error"
40
+ };
41
+ var CStarError = class extends Error {
42
+ constructor(statusCode, body) {
43
+ super(body.message);
44
+ this.name = "CStarError";
45
+ this.type = body.type;
46
+ this.code = body.code;
47
+ this.param = body.param;
48
+ this.docUrl = body.doc_url;
49
+ this.requestId = body.request_id;
50
+ this.statusCode = statusCode;
51
+ }
52
+ };
53
+ var CStarAuthenticationError = class extends CStarError {
54
+ constructor(statusCode, body) {
55
+ super(statusCode, body);
56
+ this.name = "CStarAuthenticationError";
57
+ }
58
+ };
59
+ var CStarRateLimitError = class extends CStarError {
60
+ constructor(statusCode, body, retryAfter) {
61
+ super(statusCode, body);
62
+ this.name = "CStarRateLimitError";
63
+ this.retryAfter = retryAfter;
64
+ }
65
+ };
66
+ var CStarNotFoundError = class extends CStarError {
67
+ constructor(statusCode, body) {
68
+ super(statusCode, body);
69
+ this.name = "CStarNotFoundError";
70
+ }
71
+ };
72
+ var CStarValidationError = class extends CStarError {
73
+ constructor(statusCode, body) {
74
+ super(statusCode, body);
75
+ this.name = "CStarValidationError";
76
+ }
77
+ };
78
+ function parseError(statusCode, body, retryAfter) {
79
+ const errorBody = body?.error ?? {
80
+ type: ErrorType.API_ERROR,
81
+ code: "unknown_error",
82
+ message: `Request failed with status ${statusCode}`,
83
+ doc_url: "https://cstar.help/developers/api/errors"
84
+ };
85
+ switch (errorBody.type) {
86
+ case ErrorType.AUTHENTICATION_ERROR:
87
+ return new CStarAuthenticationError(statusCode, errorBody);
88
+ case ErrorType.RATE_LIMIT_ERROR:
89
+ return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
90
+ case ErrorType.NOT_FOUND_ERROR:
91
+ return new CStarNotFoundError(statusCode, errorBody);
92
+ case ErrorType.INVALID_REQUEST_ERROR:
93
+ return new CStarValidationError(statusCode, errorBody);
94
+ default:
95
+ return new CStarError(statusCode, errorBody);
96
+ }
97
+ }
98
+
99
+ // src/client.ts
100
+ var SDK_VERSION = "0.1.0";
101
+ var DEFAULT_BASE_URL = "https://app.cstar.help";
102
+ var DEFAULT_API_VERSION = "2026-03-01";
103
+ var DEFAULT_MAX_RETRIES = 3;
104
+ var DEFAULT_TIMEOUT = 3e4;
105
+ var HttpClient = class {
106
+ constructor(config) {
107
+ this.config = {
108
+ apiKey: config.apiKey,
109
+ teamId: config.teamId,
110
+ baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
111
+ version: config.version ?? DEFAULT_API_VERSION,
112
+ maxRetries: config.maxRetries ?? DEFAULT_MAX_RETRIES,
113
+ timeout: config.timeout ?? DEFAULT_TIMEOUT
114
+ };
115
+ this.environment = config.apiKey.startsWith("sk_test_") || config.apiKey.startsWith("pk_test_") ? "test" : "live";
116
+ }
117
+ /**
118
+ * Make an authenticated request to the cStar API.
119
+ * Automatically retries on 5xx errors and rate limits.
120
+ */
121
+ async request(method, path, options) {
122
+ const url = this.buildUrl(path, options?.query);
123
+ const headers = this.buildHeaders(options?.idempotencyKey);
124
+ const body = options?.body ? JSON.stringify(options.body) : void 0;
125
+ let lastError = null;
126
+ for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) {
127
+ if (attempt > 0 && lastError) {
128
+ const delay = lastError instanceof CStarRateLimitError ? lastError.retryAfter * 1e3 : this.getBackoffDelay(attempt);
129
+ await this.sleep(delay);
130
+ }
131
+ let response;
132
+ try {
133
+ response = await fetch(url, {
134
+ method,
135
+ headers,
136
+ body,
137
+ signal: AbortSignal.timeout(this.config.timeout)
138
+ });
139
+ } catch (err) {
140
+ lastError = err instanceof Error ? err : new Error(String(err));
141
+ if (attempt < this.config.maxRetries) continue;
142
+ throw lastError;
143
+ }
144
+ if (response.ok) {
145
+ return await response.json();
146
+ }
147
+ const errorBody = await response.json().catch(() => null);
148
+ const retryAfter = parseInt(response.headers.get("Retry-After") ?? "", 10) || void 0;
149
+ if (response.status < 500 && response.status !== 429) {
150
+ throw parseError(response.status, errorBody, retryAfter);
151
+ }
152
+ if (response.status === 429) {
153
+ lastError = parseError(429, errorBody, retryAfter);
154
+ if (attempt < this.config.maxRetries) continue;
155
+ throw lastError;
156
+ }
157
+ lastError = parseError(response.status, errorBody);
158
+ if (attempt < this.config.maxRetries) continue;
159
+ throw lastError;
160
+ }
161
+ throw lastError ?? new Error("Request failed after retries");
162
+ }
163
+ buildUrl(path, query) {
164
+ const base = `${this.config.baseUrl}/api/v1/teams/${this.config.teamId}${path}`;
165
+ if (!query) return base;
166
+ const params = new URLSearchParams();
167
+ for (const [key, value] of Object.entries(query)) {
168
+ if (value === void 0 || value === null) continue;
169
+ if (Array.isArray(value)) {
170
+ for (const v of value) {
171
+ params.append(`${key}[]`, v);
172
+ }
173
+ } else {
174
+ params.set(key, String(value));
175
+ }
176
+ }
177
+ const qs = params.toString();
178
+ return qs ? `${base}?${qs}` : base;
179
+ }
180
+ buildHeaders(idempotencyKey) {
181
+ const headers = {
182
+ "Authorization": `Bearer ${this.config.apiKey}`,
183
+ "Content-Type": "application/json",
184
+ "CStar-Version": this.config.version,
185
+ "User-Agent": `@cstar.help/js/${SDK_VERSION}`
186
+ };
187
+ if (idempotencyKey) {
188
+ headers["Idempotency-Key"] = idempotencyKey;
189
+ }
190
+ return headers;
191
+ }
192
+ /** Exponential backoff: 500ms, 1s, 2s, 4s... capped at 8s, plus jitter. */
193
+ getBackoffDelay(attempt) {
194
+ const base = Math.min(500 * Math.pow(2, attempt - 1), 8e3);
195
+ const jitter = Math.random() * 200;
196
+ return base + jitter;
197
+ }
198
+ sleep(ms) {
199
+ return new Promise((resolve) => setTimeout(resolve, ms));
200
+ }
201
+ };
202
+
203
+ // src/resources/base.ts
204
+ var BaseResource = class {
205
+ constructor(client, basePath) {
206
+ this.client = client;
207
+ this.basePath = basePath;
208
+ }
209
+ /** List resources with optional filtering and pagination. */
210
+ async list(params) {
211
+ const { idempotencyKey: _, expand, ...rest } = params ?? {};
212
+ return this.client.request("GET", this.basePath, {
213
+ query: { ...this.serializeQuery(rest), expand }
214
+ });
215
+ }
216
+ /** Get a single resource by ID. */
217
+ async get(id, options) {
218
+ return this.client.request("GET", `${this.basePath}/${id}`, {
219
+ query: options?.expand ? { expand: options.expand } : void 0
220
+ });
221
+ }
222
+ /** Create a new resource. */
223
+ async create(params, options) {
224
+ return this.client.request("POST", this.basePath, {
225
+ body: params,
226
+ idempotencyKey: options?.idempotencyKey
227
+ });
228
+ }
229
+ /** Update an existing resource. */
230
+ async update(id, params, options) {
231
+ return this.client.request("PATCH", `${this.basePath}/${id}`, {
232
+ body: params,
233
+ idempotencyKey: options?.idempotencyKey
234
+ });
235
+ }
236
+ /** Delete a resource by ID. */
237
+ async del(id) {
238
+ return this.client.request(
239
+ "DELETE",
240
+ `${this.basePath}/${id}`
241
+ );
242
+ }
243
+ /**
244
+ * Auto-paginating async iterator that yields every item across all pages.
245
+ *
246
+ * ```typescript
247
+ * for await (const ticket of cstar.tickets.listAutoPaginating({ status: 'open' })) {
248
+ * console.log(ticket.title);
249
+ * }
250
+ * ```
251
+ */
252
+ async *listAutoPaginating(params) {
253
+ let page = 1;
254
+ const pageSize = params?.pageSize;
255
+ while (true) {
256
+ const response = await this.list({ ...params, page, pageSize });
257
+ for (const item of response.data) {
258
+ yield item;
259
+ }
260
+ if (!response.pagination.hasMore) break;
261
+ page++;
262
+ }
263
+ }
264
+ /** Convert params to string values for query string serialization. */
265
+ serializeQuery(params) {
266
+ const result = {};
267
+ for (const [key, value] of Object.entries(params)) {
268
+ if (value === void 0 || value === null) continue;
269
+ if (Array.isArray(value)) {
270
+ result[key] = value.map(String);
271
+ } else if (typeof value === "boolean") {
272
+ result[key] = String(value);
273
+ } else {
274
+ result[key] = String(value);
275
+ }
276
+ }
277
+ return result;
278
+ }
279
+ };
280
+
281
+ // src/resources/tickets.ts
282
+ var TicketMessagesResource = class {
283
+ constructor(client) {
284
+ this.client = client;
285
+ }
286
+ /** List all messages on a ticket. */
287
+ async list(ticketId) {
288
+ return this.client.request(
289
+ "GET",
290
+ `/tickets/${ticketId}/messages`
291
+ );
292
+ }
293
+ /** Add a message to a ticket. */
294
+ async create(ticketId, params, options) {
295
+ return this.client.request(
296
+ "POST",
297
+ `/tickets/${ticketId}/messages`,
298
+ {
299
+ body: params,
300
+ idempotencyKey: options?.idempotencyKey
301
+ }
302
+ );
303
+ }
304
+ };
305
+ var TicketsResource = class extends BaseResource {
306
+ constructor(client) {
307
+ super(client, "/tickets");
308
+ this.messages = new TicketMessagesResource(client);
309
+ }
310
+ };
311
+
312
+ // src/resources/customers.ts
313
+ var CustomersResource = class extends BaseResource {
314
+ constructor(client) {
315
+ super(client, "/customers");
316
+ }
317
+ };
318
+
319
+ // src/resources/articles.ts
320
+ var ArticlesResource = class extends BaseResource {
321
+ constructor(client) {
322
+ super(client, "/articles");
323
+ }
324
+ };
325
+
326
+ // src/resources/webhooks.ts
327
+ var WebhooksResource = class extends BaseResource {
328
+ constructor(client) {
329
+ super(client, "/webhooks");
330
+ }
331
+ /** Send a test delivery to a webhook endpoint. */
332
+ async test(webhookId, params) {
333
+ return this.client.request(
334
+ "POST",
335
+ `/webhooks/${webhookId}/test`,
336
+ { body: params ?? {} }
337
+ );
338
+ }
339
+ };
340
+
341
+ // src/index.ts
342
+ var CStarClient = class {
343
+ constructor(config) {
344
+ this.client = new HttpClient(config);
345
+ this.tickets = new TicketsResource(this.client);
346
+ this.customers = new CustomersResource(this.client);
347
+ this.articles = new ArticlesResource(this.client);
348
+ this.webhooks = new WebhooksResource(this.client);
349
+ }
350
+ /** Whether this client is using test mode keys (sk_test_* or pk_test_*). */
351
+ get isTestMode() {
352
+ return this.client.environment === "test";
353
+ }
354
+ };
355
+ // Annotate the CommonJS export names for ESM import in node:
356
+ 0 && (module.exports = {
357
+ CStarAuthenticationError,
358
+ CStarClient,
359
+ CStarError,
360
+ CStarNotFoundError,
361
+ CStarRateLimitError,
362
+ CStarValidationError,
363
+ ErrorType
364
+ });