@dispatchtickets/sdk 0.3.0 → 0.5.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 +57 -9
- package/dist/index.cjs +397 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +509 -15
- package/dist/index.d.ts +509 -15
- package/dist/index.js +389 -67
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -7,33 +7,45 @@ var DispatchTicketsError = class extends Error {
|
|
|
7
7
|
code;
|
|
8
8
|
statusCode;
|
|
9
9
|
details;
|
|
10
|
-
|
|
10
|
+
/** Request ID for debugging with support */
|
|
11
|
+
requestId;
|
|
12
|
+
constructor(message, code, statusCode, details, requestId) {
|
|
11
13
|
super(message);
|
|
12
14
|
this.name = "DispatchTicketsError";
|
|
13
15
|
this.code = code;
|
|
14
16
|
this.statusCode = statusCode;
|
|
15
17
|
this.details = details;
|
|
18
|
+
this.requestId = requestId;
|
|
16
19
|
Object.setPrototypeOf(this, new.target.prototype);
|
|
17
20
|
}
|
|
18
21
|
};
|
|
19
22
|
var AuthenticationError = class extends DispatchTicketsError {
|
|
20
|
-
constructor(message = "Invalid or missing API key") {
|
|
21
|
-
super(message, "authentication_error", 401);
|
|
23
|
+
constructor(message = "Invalid or missing API key", requestId) {
|
|
24
|
+
super(message, "authentication_error", 401, void 0, requestId);
|
|
22
25
|
this.name = "AuthenticationError";
|
|
23
26
|
}
|
|
24
27
|
};
|
|
25
28
|
var RateLimitError = class extends DispatchTicketsError {
|
|
26
29
|
retryAfter;
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
/** Rate limit ceiling */
|
|
31
|
+
limit;
|
|
32
|
+
/** Remaining requests in current window */
|
|
33
|
+
remaining;
|
|
34
|
+
/** Unix timestamp when rate limit resets */
|
|
35
|
+
reset;
|
|
36
|
+
constructor(message = "Rate limit exceeded", retryAfter, requestId, rateLimitInfo) {
|
|
37
|
+
super(message, "rate_limit_error", 429, void 0, requestId);
|
|
29
38
|
this.name = "RateLimitError";
|
|
30
39
|
this.retryAfter = retryAfter;
|
|
40
|
+
this.limit = rateLimitInfo?.limit;
|
|
41
|
+
this.remaining = rateLimitInfo?.remaining;
|
|
42
|
+
this.reset = rateLimitInfo?.reset;
|
|
31
43
|
}
|
|
32
44
|
};
|
|
33
45
|
var ValidationError = class extends DispatchTicketsError {
|
|
34
46
|
errors;
|
|
35
|
-
constructor(message = "Validation failed", errors) {
|
|
36
|
-
super(message, "validation_error", 400, { errors });
|
|
47
|
+
constructor(message = "Validation failed", errors, requestId) {
|
|
48
|
+
super(message, "validation_error", 400, { errors }, requestId);
|
|
37
49
|
this.name = "ValidationError";
|
|
38
50
|
this.errors = errors;
|
|
39
51
|
}
|
|
@@ -41,22 +53,22 @@ var ValidationError = class extends DispatchTicketsError {
|
|
|
41
53
|
var NotFoundError = class extends DispatchTicketsError {
|
|
42
54
|
resourceType;
|
|
43
55
|
resourceId;
|
|
44
|
-
constructor(message = "Resource not found", resourceType, resourceId) {
|
|
45
|
-
super(message, "not_found", 404, { resourceType, resourceId });
|
|
56
|
+
constructor(message = "Resource not found", resourceType, resourceId, requestId) {
|
|
57
|
+
super(message, "not_found", 404, { resourceType, resourceId }, requestId);
|
|
46
58
|
this.name = "NotFoundError";
|
|
47
59
|
this.resourceType = resourceType;
|
|
48
60
|
this.resourceId = resourceId;
|
|
49
61
|
}
|
|
50
62
|
};
|
|
51
63
|
var ConflictError = class extends DispatchTicketsError {
|
|
52
|
-
constructor(message = "Resource conflict") {
|
|
53
|
-
super(message, "conflict", 409);
|
|
64
|
+
constructor(message = "Resource conflict", requestId) {
|
|
65
|
+
super(message, "conflict", 409, void 0, requestId);
|
|
54
66
|
this.name = "ConflictError";
|
|
55
67
|
}
|
|
56
68
|
};
|
|
57
69
|
var ServerError = class extends DispatchTicketsError {
|
|
58
|
-
constructor(message = "Internal server error", statusCode = 500) {
|
|
59
|
-
super(message, "server_error", statusCode);
|
|
70
|
+
constructor(message = "Internal server error", statusCode = 500, requestId) {
|
|
71
|
+
super(message, "server_error", statusCode, void 0, requestId);
|
|
60
72
|
this.name = "ServerError";
|
|
61
73
|
}
|
|
62
74
|
};
|
|
@@ -72,14 +84,68 @@ var NetworkError = class extends DispatchTicketsError {
|
|
|
72
84
|
this.name = "NetworkError";
|
|
73
85
|
}
|
|
74
86
|
};
|
|
87
|
+
function isDispatchTicketsError(error) {
|
|
88
|
+
return error instanceof DispatchTicketsError;
|
|
89
|
+
}
|
|
90
|
+
function isAuthenticationError(error) {
|
|
91
|
+
return error instanceof AuthenticationError;
|
|
92
|
+
}
|
|
93
|
+
function isRateLimitError(error) {
|
|
94
|
+
return error instanceof RateLimitError;
|
|
95
|
+
}
|
|
96
|
+
function isValidationError(error) {
|
|
97
|
+
return error instanceof ValidationError;
|
|
98
|
+
}
|
|
99
|
+
function isNotFoundError(error) {
|
|
100
|
+
return error instanceof NotFoundError;
|
|
101
|
+
}
|
|
102
|
+
function isConflictError(error) {
|
|
103
|
+
return error instanceof ConflictError;
|
|
104
|
+
}
|
|
105
|
+
function isServerError(error) {
|
|
106
|
+
return error instanceof ServerError;
|
|
107
|
+
}
|
|
108
|
+
function isTimeoutError(error) {
|
|
109
|
+
return error instanceof TimeoutError;
|
|
110
|
+
}
|
|
111
|
+
function isNetworkError(error) {
|
|
112
|
+
return error instanceof NetworkError;
|
|
113
|
+
}
|
|
75
114
|
|
|
76
115
|
// src/utils/http.ts
|
|
77
116
|
var HttpClient = class {
|
|
78
117
|
config;
|
|
79
118
|
fetchFn;
|
|
119
|
+
retryConfig;
|
|
120
|
+
/** Rate limit info from the last response */
|
|
121
|
+
_lastRateLimit;
|
|
122
|
+
/** Request ID from the last response */
|
|
123
|
+
_lastRequestId;
|
|
80
124
|
constructor(config) {
|
|
81
125
|
this.config = config;
|
|
82
126
|
this.fetchFn = config.fetch ?? fetch;
|
|
127
|
+
this.retryConfig = {
|
|
128
|
+
maxRetries: config.retry?.maxRetries ?? config.maxRetries,
|
|
129
|
+
retryableStatuses: config.retry?.retryableStatuses ?? [429, 500, 502, 503, 504],
|
|
130
|
+
retryOnNetworkError: config.retry?.retryOnNetworkError ?? true,
|
|
131
|
+
retryOnTimeout: config.retry?.retryOnTimeout ?? true,
|
|
132
|
+
initialDelayMs: config.retry?.initialDelayMs ?? 1e3,
|
|
133
|
+
maxDelayMs: config.retry?.maxDelayMs ?? 3e4,
|
|
134
|
+
backoffMultiplier: config.retry?.backoffMultiplier ?? 2,
|
|
135
|
+
jitter: config.retry?.jitter ?? 0.25
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get rate limit info from the last response
|
|
140
|
+
*/
|
|
141
|
+
get lastRateLimit() {
|
|
142
|
+
return this._lastRateLimit;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get request ID from the last response
|
|
146
|
+
*/
|
|
147
|
+
get lastRequestId() {
|
|
148
|
+
return this._lastRequestId;
|
|
83
149
|
}
|
|
84
150
|
/**
|
|
85
151
|
* Execute an HTTP request with retry logic
|
|
@@ -89,43 +155,89 @@ var HttpClient = class {
|
|
|
89
155
|
const headers = this.buildHeaders(options.headers, options.idempotencyKey);
|
|
90
156
|
let lastError;
|
|
91
157
|
let attempt = 0;
|
|
92
|
-
while (attempt <= this.
|
|
158
|
+
while (attempt <= this.retryConfig.maxRetries) {
|
|
159
|
+
const requestContext = {
|
|
160
|
+
method: options.method,
|
|
161
|
+
url,
|
|
162
|
+
headers,
|
|
163
|
+
body: options.body,
|
|
164
|
+
attempt
|
|
165
|
+
};
|
|
93
166
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
167
|
+
if (this.config.hooks?.onRequest) {
|
|
168
|
+
await this.config.hooks.onRequest(requestContext);
|
|
169
|
+
}
|
|
170
|
+
const startTime = Date.now();
|
|
171
|
+
const response = await this.executeRequest(
|
|
172
|
+
url,
|
|
173
|
+
options.method,
|
|
174
|
+
headers,
|
|
175
|
+
options.body,
|
|
176
|
+
options.signal
|
|
177
|
+
);
|
|
178
|
+
const durationMs = Date.now() - startTime;
|
|
179
|
+
const result = await this.handleResponse(response, requestContext, durationMs);
|
|
180
|
+
return result;
|
|
96
181
|
} catch (error) {
|
|
97
182
|
lastError = error;
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
if (error instanceof RateLimitError && error.retryAfter) {
|
|
103
|
-
if (attempt < this.config.maxRetries) {
|
|
104
|
-
await this.sleep(error.retryAfter * 1e3);
|
|
105
|
-
attempt++;
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (error instanceof ServerError) {
|
|
110
|
-
if (attempt < this.config.maxRetries) {
|
|
111
|
-
await this.sleep(this.calculateBackoff(attempt));
|
|
112
|
-
attempt++;
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
183
|
+
if (this.config.hooks?.onError) {
|
|
184
|
+
await this.config.hooks.onError(lastError, requestContext);
|
|
116
185
|
}
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
continue;
|
|
186
|
+
if (attempt < this.retryConfig.maxRetries && this.shouldRetry(lastError)) {
|
|
187
|
+
const delay = this.calculateDelay(lastError, attempt);
|
|
188
|
+
if (this.config.hooks?.onRetry) {
|
|
189
|
+
await this.config.hooks.onRetry(requestContext, lastError, delay);
|
|
122
190
|
}
|
|
191
|
+
await this.sleep(delay);
|
|
192
|
+
attempt++;
|
|
193
|
+
continue;
|
|
123
194
|
}
|
|
124
|
-
throw
|
|
195
|
+
throw lastError;
|
|
125
196
|
}
|
|
126
197
|
}
|
|
127
198
|
throw lastError || new NetworkError("Request failed after retries");
|
|
128
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Execute request and return response with rate limit info
|
|
202
|
+
*/
|
|
203
|
+
async requestWithRateLimit(options) {
|
|
204
|
+
const data = await this.request(options);
|
|
205
|
+
return {
|
|
206
|
+
data,
|
|
207
|
+
rateLimit: this._lastRateLimit,
|
|
208
|
+
requestId: this._lastRequestId
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
shouldRetry(error) {
|
|
212
|
+
if (error instanceof AuthenticationError || error instanceof ValidationError || error instanceof NotFoundError || error instanceof ConflictError) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (error instanceof RateLimitError) {
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
if (error instanceof ServerError && error.statusCode) {
|
|
219
|
+
return this.retryConfig.retryableStatuses.includes(error.statusCode);
|
|
220
|
+
}
|
|
221
|
+
if (error instanceof NetworkError) {
|
|
222
|
+
return this.retryConfig.retryOnNetworkError;
|
|
223
|
+
}
|
|
224
|
+
if (error instanceof TimeoutError) {
|
|
225
|
+
return this.retryConfig.retryOnTimeout;
|
|
226
|
+
}
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
calculateDelay(error, attempt) {
|
|
230
|
+
if (error instanceof RateLimitError && error.retryAfter) {
|
|
231
|
+
return error.retryAfter * 1e3;
|
|
232
|
+
}
|
|
233
|
+
const baseDelay = this.retryConfig.initialDelayMs;
|
|
234
|
+
const delay = Math.min(
|
|
235
|
+
baseDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt),
|
|
236
|
+
this.retryConfig.maxDelayMs
|
|
237
|
+
);
|
|
238
|
+
const jitter = delay * this.retryConfig.jitter * Math.random();
|
|
239
|
+
return delay + jitter;
|
|
240
|
+
}
|
|
129
241
|
buildUrl(path, query) {
|
|
130
242
|
const url = new URL(path, this.config.baseUrl);
|
|
131
243
|
if (query) {
|
|
@@ -149,9 +261,11 @@ var HttpClient = class {
|
|
|
149
261
|
}
|
|
150
262
|
return headers;
|
|
151
263
|
}
|
|
152
|
-
async executeRequest(url, method, headers, body) {
|
|
264
|
+
async executeRequest(url, method, headers, body, userSignal) {
|
|
153
265
|
const controller = new AbortController();
|
|
154
266
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
267
|
+
const abortHandler = () => controller.abort();
|
|
268
|
+
userSignal?.addEventListener("abort", abortHandler);
|
|
155
269
|
try {
|
|
156
270
|
if (this.config.debug) {
|
|
157
271
|
console.log(`[DispatchTickets] ${method} ${url}`);
|
|
@@ -159,6 +273,9 @@ var HttpClient = class {
|
|
|
159
273
|
console.log("[DispatchTickets] Body:", JSON.stringify(body, null, 2));
|
|
160
274
|
}
|
|
161
275
|
}
|
|
276
|
+
if (userSignal?.aborted) {
|
|
277
|
+
throw new Error("Request aborted");
|
|
278
|
+
}
|
|
162
279
|
const response = await this.fetchFn(url, {
|
|
163
280
|
method,
|
|
164
281
|
headers,
|
|
@@ -169,6 +286,9 @@ var HttpClient = class {
|
|
|
169
286
|
} catch (error) {
|
|
170
287
|
if (error instanceof Error) {
|
|
171
288
|
if (error.name === "AbortError") {
|
|
289
|
+
if (userSignal?.aborted) {
|
|
290
|
+
throw new NetworkError("Request aborted by user");
|
|
291
|
+
}
|
|
172
292
|
throw new TimeoutError(`Request timed out after ${this.config.timeout}ms`);
|
|
173
293
|
}
|
|
174
294
|
throw new NetworkError(error.message);
|
|
@@ -176,11 +296,42 @@ var HttpClient = class {
|
|
|
176
296
|
throw new NetworkError("Unknown network error");
|
|
177
297
|
} finally {
|
|
178
298
|
clearTimeout(timeoutId);
|
|
299
|
+
userSignal?.removeEventListener("abort", abortHandler);
|
|
179
300
|
}
|
|
180
301
|
}
|
|
181
|
-
|
|
302
|
+
extractRateLimitInfo(response) {
|
|
303
|
+
const limit = response.headers.get("x-ratelimit-limit");
|
|
304
|
+
const remaining = response.headers.get("x-ratelimit-remaining");
|
|
305
|
+
const reset = response.headers.get("x-ratelimit-reset");
|
|
306
|
+
if (limit && remaining && reset) {
|
|
307
|
+
return {
|
|
308
|
+
limit: parseInt(limit, 10),
|
|
309
|
+
remaining: parseInt(remaining, 10),
|
|
310
|
+
reset: parseInt(reset, 10)
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return void 0;
|
|
314
|
+
}
|
|
315
|
+
async handleResponse(response, requestContext, durationMs) {
|
|
182
316
|
const contentType = response.headers.get("content-type");
|
|
183
317
|
const isJson = contentType?.includes("application/json");
|
|
318
|
+
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
319
|
+
const rateLimitInfo = this.extractRateLimitInfo(response);
|
|
320
|
+
this._lastRequestId = requestId;
|
|
321
|
+
this._lastRateLimit = rateLimitInfo;
|
|
322
|
+
if (this.config.debug && requestId) {
|
|
323
|
+
console.log(`[DispatchTickets] Request ID: ${requestId}`);
|
|
324
|
+
}
|
|
325
|
+
if (response.ok && this.config.hooks?.onResponse) {
|
|
326
|
+
await this.config.hooks.onResponse({
|
|
327
|
+
request: requestContext,
|
|
328
|
+
status: response.status,
|
|
329
|
+
headers: response.headers,
|
|
330
|
+
requestId,
|
|
331
|
+
rateLimit: rateLimitInfo,
|
|
332
|
+
durationMs
|
|
333
|
+
});
|
|
334
|
+
}
|
|
184
335
|
if (response.ok) {
|
|
185
336
|
if (response.status === 204 || !isJson) {
|
|
186
337
|
return void 0;
|
|
@@ -197,31 +348,36 @@ var HttpClient = class {
|
|
|
197
348
|
const message = errorData.message || errorData.error || response.statusText;
|
|
198
349
|
switch (response.status) {
|
|
199
350
|
case 401:
|
|
200
|
-
throw new AuthenticationError(message);
|
|
351
|
+
throw new AuthenticationError(message, requestId);
|
|
201
352
|
case 400:
|
|
202
353
|
case 422:
|
|
203
|
-
throw new ValidationError(message, errorData.errors);
|
|
354
|
+
throw new ValidationError(message, errorData.errors, requestId);
|
|
204
355
|
case 404:
|
|
205
|
-
throw new NotFoundError(message);
|
|
356
|
+
throw new NotFoundError(message, void 0, void 0, requestId);
|
|
206
357
|
case 409:
|
|
207
|
-
throw new ConflictError(message);
|
|
358
|
+
throw new ConflictError(message, requestId);
|
|
208
359
|
case 429: {
|
|
209
360
|
const retryAfter = response.headers.get("retry-after");
|
|
210
|
-
throw new RateLimitError(
|
|
361
|
+
throw new RateLimitError(
|
|
362
|
+
message,
|
|
363
|
+
retryAfter ? parseInt(retryAfter, 10) : void 0,
|
|
364
|
+
requestId,
|
|
365
|
+
rateLimitInfo
|
|
366
|
+
);
|
|
211
367
|
}
|
|
212
368
|
default:
|
|
213
369
|
if (response.status >= 500) {
|
|
214
|
-
throw new ServerError(message, response.status);
|
|
370
|
+
throw new ServerError(message, response.status, requestId);
|
|
215
371
|
}
|
|
216
|
-
throw new DispatchTicketsError(
|
|
372
|
+
throw new DispatchTicketsError(
|
|
373
|
+
message,
|
|
374
|
+
"api_error",
|
|
375
|
+
response.status,
|
|
376
|
+
errorData,
|
|
377
|
+
requestId
|
|
378
|
+
);
|
|
217
379
|
}
|
|
218
380
|
}
|
|
219
|
-
calculateBackoff(attempt) {
|
|
220
|
-
const baseDelay = 1e3;
|
|
221
|
-
const maxDelay = 3e4;
|
|
222
|
-
const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
|
|
223
|
-
return delay + Math.random() * delay * 0.25;
|
|
224
|
-
}
|
|
225
381
|
sleep(ms) {
|
|
226
382
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
227
383
|
}
|
|
@@ -233,11 +389,12 @@ var BaseResource = class {
|
|
|
233
389
|
constructor(http) {
|
|
234
390
|
this.http = http;
|
|
235
391
|
}
|
|
236
|
-
async _get(path, query) {
|
|
392
|
+
async _get(path, query, options) {
|
|
237
393
|
return this.http.request({
|
|
238
394
|
method: "GET",
|
|
239
395
|
path,
|
|
240
|
-
query
|
|
396
|
+
query,
|
|
397
|
+
signal: options?.signal
|
|
241
398
|
});
|
|
242
399
|
}
|
|
243
400
|
async _post(path, body, options) {
|
|
@@ -246,28 +403,32 @@ var BaseResource = class {
|
|
|
246
403
|
path,
|
|
247
404
|
body,
|
|
248
405
|
idempotencyKey: options?.idempotencyKey,
|
|
249
|
-
query: options?.query
|
|
406
|
+
query: options?.query,
|
|
407
|
+
signal: options?.signal
|
|
250
408
|
});
|
|
251
409
|
}
|
|
252
|
-
async _patch(path, body) {
|
|
410
|
+
async _patch(path, body, options) {
|
|
253
411
|
return this.http.request({
|
|
254
412
|
method: "PATCH",
|
|
255
413
|
path,
|
|
256
|
-
body
|
|
414
|
+
body,
|
|
415
|
+
signal: options?.signal
|
|
257
416
|
});
|
|
258
417
|
}
|
|
259
|
-
async _put(path, body) {
|
|
418
|
+
async _put(path, body, options) {
|
|
260
419
|
return this.http.request({
|
|
261
420
|
method: "PUT",
|
|
262
421
|
path,
|
|
263
|
-
body
|
|
422
|
+
body,
|
|
423
|
+
signal: options?.signal
|
|
264
424
|
});
|
|
265
425
|
}
|
|
266
|
-
async _delete(path, query) {
|
|
426
|
+
async _delete(path, query, options) {
|
|
267
427
|
return this.http.request({
|
|
268
428
|
method: "DELETE",
|
|
269
429
|
path,
|
|
270
|
-
query
|
|
430
|
+
query,
|
|
431
|
+
signal: options?.signal
|
|
271
432
|
});
|
|
272
433
|
}
|
|
273
434
|
};
|
|
@@ -906,48 +1067,207 @@ var DispatchTickets = class {
|
|
|
906
1067
|
http;
|
|
907
1068
|
/**
|
|
908
1069
|
* Accounts resource for managing the current account and API keys
|
|
1070
|
+
*
|
|
1071
|
+
* @example
|
|
1072
|
+
* ```typescript
|
|
1073
|
+
* // Get current account
|
|
1074
|
+
* const account = await client.accounts.me();
|
|
1075
|
+
*
|
|
1076
|
+
* // Get usage statistics
|
|
1077
|
+
* const usage = await client.accounts.getUsage();
|
|
1078
|
+
*
|
|
1079
|
+
* // Create a new API key
|
|
1080
|
+
* const newKey = await client.accounts.createApiKey({
|
|
1081
|
+
* name: 'Production',
|
|
1082
|
+
* allBrands: true,
|
|
1083
|
+
* });
|
|
1084
|
+
* ```
|
|
909
1085
|
*/
|
|
910
1086
|
accounts;
|
|
911
1087
|
/**
|
|
912
1088
|
* Brands (workspaces) resource
|
|
1089
|
+
*
|
|
1090
|
+
* Brands are isolated containers for tickets. Each brand can have its own
|
|
1091
|
+
* email address, categories, tags, and settings.
|
|
1092
|
+
*
|
|
1093
|
+
* @example
|
|
1094
|
+
* ```typescript
|
|
1095
|
+
* // List all brands
|
|
1096
|
+
* const brands = await client.brands.list();
|
|
1097
|
+
*
|
|
1098
|
+
* // Create a new brand
|
|
1099
|
+
* const brand = await client.brands.create({
|
|
1100
|
+
* name: 'Acme Support',
|
|
1101
|
+
* slug: 'acme',
|
|
1102
|
+
* });
|
|
1103
|
+
*
|
|
1104
|
+
* // Get inbound email address
|
|
1105
|
+
* const email = client.brands.getInboundEmail('br_abc123');
|
|
1106
|
+
* // Returns: br_abc123@inbound.dispatchtickets.com
|
|
1107
|
+
* ```
|
|
913
1108
|
*/
|
|
914
1109
|
brands;
|
|
915
1110
|
/**
|
|
916
1111
|
* Tickets resource
|
|
1112
|
+
*
|
|
1113
|
+
* @example
|
|
1114
|
+
* ```typescript
|
|
1115
|
+
* // Create a ticket
|
|
1116
|
+
* const ticket = await client.tickets.create('ws_abc123', {
|
|
1117
|
+
* title: 'Issue with billing',
|
|
1118
|
+
* body: 'I was charged twice...',
|
|
1119
|
+
* priority: 'high',
|
|
1120
|
+
* });
|
|
1121
|
+
*
|
|
1122
|
+
* // Iterate through all tickets
|
|
1123
|
+
* for await (const ticket of client.tickets.list('ws_abc123', { status: 'open' })) {
|
|
1124
|
+
* console.log(ticket.title);
|
|
1125
|
+
* }
|
|
1126
|
+
* ```
|
|
917
1127
|
*/
|
|
918
1128
|
tickets;
|
|
919
1129
|
/**
|
|
920
1130
|
* Comments resource
|
|
1131
|
+
*
|
|
1132
|
+
* @example
|
|
1133
|
+
* ```typescript
|
|
1134
|
+
* // Add a comment
|
|
1135
|
+
* const comment = await client.comments.create('ws_abc123', 'tkt_xyz', {
|
|
1136
|
+
* body: 'Thanks for your patience!',
|
|
1137
|
+
* authorType: 'AGENT',
|
|
1138
|
+
* });
|
|
1139
|
+
*
|
|
1140
|
+
* // List comments
|
|
1141
|
+
* const comments = await client.comments.list('ws_abc123', 'tkt_xyz');
|
|
1142
|
+
* ```
|
|
921
1143
|
*/
|
|
922
1144
|
comments;
|
|
923
1145
|
/**
|
|
924
1146
|
* Attachments resource
|
|
1147
|
+
*
|
|
1148
|
+
* @example
|
|
1149
|
+
* ```typescript
|
|
1150
|
+
* // Simple upload
|
|
1151
|
+
* const attachment = await client.attachments.upload(
|
|
1152
|
+
* 'ws_abc123',
|
|
1153
|
+
* 'tkt_xyz',
|
|
1154
|
+
* fileBuffer,
|
|
1155
|
+
* 'document.pdf',
|
|
1156
|
+
* 'application/pdf'
|
|
1157
|
+
* );
|
|
1158
|
+
*
|
|
1159
|
+
* // Get download URL
|
|
1160
|
+
* const { downloadUrl } = await client.attachments.get('ws_abc123', 'tkt_xyz', 'att_abc');
|
|
1161
|
+
* ```
|
|
925
1162
|
*/
|
|
926
1163
|
attachments;
|
|
927
1164
|
/**
|
|
928
1165
|
* Webhooks resource
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* ```typescript
|
|
1169
|
+
* // Create a webhook
|
|
1170
|
+
* const webhook = await client.webhooks.create('ws_abc123', {
|
|
1171
|
+
* url: 'https://example.com/webhook',
|
|
1172
|
+
* secret: 'your-secret',
|
|
1173
|
+
* events: ['ticket.created', 'ticket.updated'],
|
|
1174
|
+
* });
|
|
1175
|
+
* ```
|
|
929
1176
|
*/
|
|
930
1177
|
webhooks;
|
|
931
1178
|
/**
|
|
932
1179
|
* Categories resource
|
|
1180
|
+
*
|
|
1181
|
+
* @example
|
|
1182
|
+
* ```typescript
|
|
1183
|
+
* // Create a category
|
|
1184
|
+
* await client.categories.create('ws_abc123', { name: 'Billing', color: '#ef4444' });
|
|
1185
|
+
*
|
|
1186
|
+
* // Get category stats
|
|
1187
|
+
* const stats = await client.categories.getStats('ws_abc123');
|
|
1188
|
+
* ```
|
|
933
1189
|
*/
|
|
934
1190
|
categories;
|
|
935
1191
|
/**
|
|
936
1192
|
* Tags resource
|
|
1193
|
+
*
|
|
1194
|
+
* @example
|
|
1195
|
+
* ```typescript
|
|
1196
|
+
* // Create a tag
|
|
1197
|
+
* await client.tags.create('ws_abc123', { name: 'urgent', color: '#f59e0b' });
|
|
1198
|
+
*
|
|
1199
|
+
* // Merge tags
|
|
1200
|
+
* await client.tags.merge('ws_abc123', 'tag_target', ['tag_source1', 'tag_source2']);
|
|
1201
|
+
* ```
|
|
937
1202
|
*/
|
|
938
1203
|
tags;
|
|
939
1204
|
/**
|
|
940
1205
|
* Customers resource
|
|
1206
|
+
*
|
|
1207
|
+
* @example
|
|
1208
|
+
* ```typescript
|
|
1209
|
+
* // Create a customer
|
|
1210
|
+
* const customer = await client.customers.create('ws_abc123', {
|
|
1211
|
+
* email: 'user@example.com',
|
|
1212
|
+
* name: 'Jane Doe',
|
|
1213
|
+
* });
|
|
1214
|
+
*
|
|
1215
|
+
* // Search customers
|
|
1216
|
+
* const results = await client.customers.search('ws_abc123', 'jane');
|
|
1217
|
+
* ```
|
|
941
1218
|
*/
|
|
942
1219
|
customers;
|
|
943
1220
|
/**
|
|
944
1221
|
* Custom fields resource
|
|
1222
|
+
*
|
|
1223
|
+
* @example
|
|
1224
|
+
* ```typescript
|
|
1225
|
+
* // Get all field definitions
|
|
1226
|
+
* const fields = await client.fields.getAll('ws_abc123');
|
|
1227
|
+
*
|
|
1228
|
+
* // Create a field
|
|
1229
|
+
* await client.fields.create('ws_abc123', 'ticket', {
|
|
1230
|
+
* key: 'order_id',
|
|
1231
|
+
* label: 'Order ID',
|
|
1232
|
+
* type: 'text',
|
|
1233
|
+
* required: true,
|
|
1234
|
+
* });
|
|
1235
|
+
* ```
|
|
945
1236
|
*/
|
|
946
1237
|
fields;
|
|
947
1238
|
/**
|
|
948
1239
|
* Static webhook utilities
|
|
1240
|
+
*
|
|
1241
|
+
* @example
|
|
1242
|
+
* ```typescript
|
|
1243
|
+
* // Verify webhook signature
|
|
1244
|
+
* const isValid = DispatchTickets.webhooks.verifySignature(
|
|
1245
|
+
* rawBody,
|
|
1246
|
+
* req.headers['x-dispatch-signature'],
|
|
1247
|
+
* 'your-secret'
|
|
1248
|
+
* );
|
|
1249
|
+
*
|
|
1250
|
+
* // Generate signature for testing
|
|
1251
|
+
* const signature = DispatchTickets.webhooks.generateSignature(
|
|
1252
|
+
* JSON.stringify(payload),
|
|
1253
|
+
* 'your-secret'
|
|
1254
|
+
* );
|
|
1255
|
+
* ```
|
|
949
1256
|
*/
|
|
950
1257
|
static webhooks = webhookUtils;
|
|
1258
|
+
/**
|
|
1259
|
+
* Create a new Dispatch Tickets client
|
|
1260
|
+
*
|
|
1261
|
+
* @param config - Client configuration options
|
|
1262
|
+
* @throws Error if API key is not provided
|
|
1263
|
+
*
|
|
1264
|
+
* @example
|
|
1265
|
+
* ```typescript
|
|
1266
|
+
* const client = new DispatchTickets({
|
|
1267
|
+
* apiKey: 'sk_live_...',
|
|
1268
|
+
* });
|
|
1269
|
+
* ```
|
|
1270
|
+
*/
|
|
951
1271
|
constructor(config) {
|
|
952
1272
|
if (!config.apiKey) {
|
|
953
1273
|
throw new Error("API key is required");
|
|
@@ -956,9 +1276,11 @@ var DispatchTickets = class {
|
|
|
956
1276
|
baseUrl: config.baseUrl || "https://dispatch-tickets-api.onrender.com/v1",
|
|
957
1277
|
apiKey: config.apiKey,
|
|
958
1278
|
timeout: config.timeout ?? 3e4,
|
|
959
|
-
maxRetries: config.maxRetries ?? 3,
|
|
1279
|
+
maxRetries: config.maxRetries ?? config.retry?.maxRetries ?? 3,
|
|
960
1280
|
debug: config.debug ?? false,
|
|
961
|
-
fetch: config.fetch
|
|
1281
|
+
fetch: config.fetch,
|
|
1282
|
+
retry: config.retry,
|
|
1283
|
+
hooks: config.hooks
|
|
962
1284
|
};
|
|
963
1285
|
this.http = new HttpClient(httpConfig);
|
|
964
1286
|
this.accounts = new AccountsResource(this.http);
|
|
@@ -1025,9 +1347,18 @@ exports.ServerError = ServerError;
|
|
|
1025
1347
|
exports.TimeoutError = TimeoutError;
|
|
1026
1348
|
exports.ValidationError = ValidationError;
|
|
1027
1349
|
exports.collectAll = collectAll;
|
|
1350
|
+
exports.isAuthenticationError = isAuthenticationError;
|
|
1028
1351
|
exports.isCommentCreatedEvent = isCommentCreatedEvent;
|
|
1352
|
+
exports.isConflictError = isConflictError;
|
|
1353
|
+
exports.isDispatchTicketsError = isDispatchTicketsError;
|
|
1354
|
+
exports.isNetworkError = isNetworkError;
|
|
1355
|
+
exports.isNotFoundError = isNotFoundError;
|
|
1356
|
+
exports.isRateLimitError = isRateLimitError;
|
|
1357
|
+
exports.isServerError = isServerError;
|
|
1029
1358
|
exports.isTicketCreatedEvent = isTicketCreatedEvent;
|
|
1030
1359
|
exports.isTicketUpdatedEvent = isTicketUpdatedEvent;
|
|
1360
|
+
exports.isTimeoutError = isTimeoutError;
|
|
1361
|
+
exports.isValidationError = isValidationError;
|
|
1031
1362
|
exports.parseWebhookEvent = parseWebhookEvent;
|
|
1032
1363
|
exports.webhookUtils = webhookUtils;
|
|
1033
1364
|
//# sourceMappingURL=index.cjs.map
|