@dispatchtickets/sdk 0.1.0 → 0.3.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 +111 -0
- package/dist/index.cjs +113 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +272 -6
- package/dist/index.d.ts +272 -6
- package/dist/index.js +110 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom fetch function type
|
|
3
|
+
*/
|
|
4
|
+
type FetchFunction = typeof fetch;
|
|
1
5
|
interface HttpClientConfig {
|
|
2
6
|
baseUrl: string;
|
|
3
7
|
apiKey: string;
|
|
4
8
|
timeout: number;
|
|
5
9
|
maxRetries: number;
|
|
6
10
|
debug?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Custom fetch implementation for testing/mocking
|
|
13
|
+
*/
|
|
14
|
+
fetch?: FetchFunction;
|
|
7
15
|
}
|
|
8
16
|
interface RequestOptions {
|
|
9
17
|
method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
|
|
@@ -18,6 +26,7 @@ interface RequestOptions {
|
|
|
18
26
|
*/
|
|
19
27
|
declare class HttpClient {
|
|
20
28
|
private readonly config;
|
|
29
|
+
private readonly fetchFn;
|
|
21
30
|
constructor(config: HttpClientConfig);
|
|
22
31
|
/**
|
|
23
32
|
* Execute an HTTP request with retry logic
|
|
@@ -47,6 +56,104 @@ declare abstract class BaseResource {
|
|
|
47
56
|
protected _delete<T>(path: string, query?: RequestOptions['query']): Promise<T>;
|
|
48
57
|
}
|
|
49
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Account represents the organization/company using Dispatch Tickets
|
|
61
|
+
*/
|
|
62
|
+
interface Account {
|
|
63
|
+
id: string;
|
|
64
|
+
stackbeCustomerId: string;
|
|
65
|
+
stackbeOrganizationId: string;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
updatedAt: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Usage statistics for the account
|
|
71
|
+
*/
|
|
72
|
+
interface AccountUsage {
|
|
73
|
+
ticketsThisMonth: number;
|
|
74
|
+
ticketsTotal: number;
|
|
75
|
+
brandsCount: number;
|
|
76
|
+
plan?: {
|
|
77
|
+
name: string;
|
|
78
|
+
ticketLimit: number;
|
|
79
|
+
brandLimit: number | null;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* API key for programmatic access
|
|
84
|
+
*/
|
|
85
|
+
interface ApiKey {
|
|
86
|
+
id: string;
|
|
87
|
+
name: string;
|
|
88
|
+
keyPreview: string;
|
|
89
|
+
allBrands: boolean;
|
|
90
|
+
brandIds: string[];
|
|
91
|
+
lastUsedAt: string | null;
|
|
92
|
+
createdAt: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* API key with the full key value (only returned on creation)
|
|
96
|
+
*/
|
|
97
|
+
interface ApiKeyWithSecret extends ApiKey {
|
|
98
|
+
key: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Input for creating an API key
|
|
102
|
+
*/
|
|
103
|
+
interface CreateApiKeyInput {
|
|
104
|
+
name: string;
|
|
105
|
+
/**
|
|
106
|
+
* If true, the API key can access all brands (current and future)
|
|
107
|
+
*/
|
|
108
|
+
allBrands?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Specific brand IDs this key can access (ignored if allBrands is true)
|
|
111
|
+
*/
|
|
112
|
+
brandIds?: string[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Input for updating API key scope
|
|
116
|
+
*/
|
|
117
|
+
interface UpdateApiKeyScopeInput {
|
|
118
|
+
allBrands?: boolean;
|
|
119
|
+
brandIds?: string[];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Accounts resource for managing the current account
|
|
124
|
+
*/
|
|
125
|
+
declare class AccountsResource extends BaseResource {
|
|
126
|
+
/**
|
|
127
|
+
* Get the current account
|
|
128
|
+
*/
|
|
129
|
+
me(): Promise<Account>;
|
|
130
|
+
/**
|
|
131
|
+
* Get usage statistics for the current account
|
|
132
|
+
*/
|
|
133
|
+
getUsage(): Promise<AccountUsage>;
|
|
134
|
+
/**
|
|
135
|
+
* List all API keys for the current account
|
|
136
|
+
*/
|
|
137
|
+
listApiKeys(): Promise<ApiKey[]>;
|
|
138
|
+
/**
|
|
139
|
+
* Create a new API key
|
|
140
|
+
*
|
|
141
|
+
* Note: The full key value is only returned once on creation.
|
|
142
|
+
* Store it securely as it cannot be retrieved again.
|
|
143
|
+
*/
|
|
144
|
+
createApiKey(data: CreateApiKeyInput): Promise<ApiKeyWithSecret>;
|
|
145
|
+
/**
|
|
146
|
+
* Update the brand scope for an API key
|
|
147
|
+
*/
|
|
148
|
+
updateApiKeyScope(keyId: string, data: UpdateApiKeyScopeInput): Promise<{
|
|
149
|
+
success: boolean;
|
|
150
|
+
}>;
|
|
151
|
+
/**
|
|
152
|
+
* Revoke an API key
|
|
153
|
+
*/
|
|
154
|
+
revokeApiKey(keyId: string): Promise<void>;
|
|
155
|
+
}
|
|
156
|
+
|
|
50
157
|
/**
|
|
51
158
|
* Brand (workspace) resource
|
|
52
159
|
*/
|
|
@@ -144,6 +251,26 @@ declare class BrandsResource extends BaseResource {
|
|
|
144
251
|
* Update the ticket schema for a brand
|
|
145
252
|
*/
|
|
146
253
|
updateSchema(brandId: string, schema: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
254
|
+
/**
|
|
255
|
+
* Get the inbound email address for a brand
|
|
256
|
+
*
|
|
257
|
+
* Emails sent to this address will automatically create tickets.
|
|
258
|
+
*
|
|
259
|
+
* @param brandId - The brand ID
|
|
260
|
+
* @param domain - Optional custom inbound domain (default: inbound.dispatchtickets.com)
|
|
261
|
+
* @returns The inbound email address
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const email = client.brands.getInboundEmail('br_abc123');
|
|
266
|
+
* // Returns: br_abc123@inbound.dispatchtickets.com
|
|
267
|
+
*
|
|
268
|
+
* // With custom domain:
|
|
269
|
+
* const customEmail = client.brands.getInboundEmail('br_abc123', 'support.mycompany.com');
|
|
270
|
+
* // Returns: br_abc123@support.mycompany.com
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
getInboundEmail(brandId: string, domain?: string): string;
|
|
147
274
|
}
|
|
148
275
|
|
|
149
276
|
/**
|
|
@@ -185,9 +312,10 @@ type AuthorType = 'CUSTOMER' | 'AGENT' | 'SYSTEM';
|
|
|
185
312
|
*/
|
|
186
313
|
type AttachmentStatus = 'PENDING' | 'UPLOADED' | 'FAILED';
|
|
187
314
|
/**
|
|
188
|
-
* Webhook event
|
|
315
|
+
* Webhook event type strings (for subscription)
|
|
316
|
+
* @deprecated Use WebhookEventType from events.ts for typed event handling
|
|
189
317
|
*/
|
|
190
|
-
type
|
|
318
|
+
type WebhookEventName = 'ticket.created' | 'ticket.updated' | 'ticket.deleted' | 'ticket.comment.created' | 'comment.created' | 'comment.updated' | 'comment.deleted' | 'attachment.created' | 'attachment.deleted';
|
|
191
319
|
/**
|
|
192
320
|
* Custom field types
|
|
193
321
|
*/
|
|
@@ -655,7 +783,7 @@ interface Webhook {
|
|
|
655
783
|
id: string;
|
|
656
784
|
brandId: string;
|
|
657
785
|
url: string;
|
|
658
|
-
events:
|
|
786
|
+
events: WebhookEventName[];
|
|
659
787
|
enabled: boolean;
|
|
660
788
|
failureCount: number;
|
|
661
789
|
lastTriggered?: string;
|
|
@@ -669,7 +797,7 @@ interface Webhook {
|
|
|
669
797
|
interface CreateWebhookInput {
|
|
670
798
|
url: string;
|
|
671
799
|
secret: string;
|
|
672
|
-
events:
|
|
800
|
+
events: WebhookEventName[];
|
|
673
801
|
}
|
|
674
802
|
/**
|
|
675
803
|
* Webhook delivery record
|
|
@@ -677,7 +805,7 @@ interface CreateWebhookInput {
|
|
|
677
805
|
interface WebhookDelivery {
|
|
678
806
|
id: string;
|
|
679
807
|
webhookId: string;
|
|
680
|
-
event:
|
|
808
|
+
event: WebhookEventName;
|
|
681
809
|
payload: Record<string, unknown>;
|
|
682
810
|
status: 'PENDING' | 'SUCCESS' | 'FAILED' | 'RETRYING';
|
|
683
811
|
attempts: number;
|
|
@@ -922,6 +1050,10 @@ interface DispatchTicketsConfig {
|
|
|
922
1050
|
* @default false
|
|
923
1051
|
*/
|
|
924
1052
|
debug?: boolean;
|
|
1053
|
+
/**
|
|
1054
|
+
* Custom fetch implementation for testing/mocking
|
|
1055
|
+
*/
|
|
1056
|
+
fetch?: FetchFunction;
|
|
925
1057
|
}
|
|
926
1058
|
/**
|
|
927
1059
|
* Dispatch Tickets SDK client
|
|
@@ -951,6 +1083,10 @@ interface DispatchTicketsConfig {
|
|
|
951
1083
|
*/
|
|
952
1084
|
declare class DispatchTickets {
|
|
953
1085
|
private readonly http;
|
|
1086
|
+
/**
|
|
1087
|
+
* Accounts resource for managing the current account and API keys
|
|
1088
|
+
*/
|
|
1089
|
+
readonly accounts: AccountsResource;
|
|
954
1090
|
/**
|
|
955
1091
|
* Brands (workspaces) resource
|
|
956
1092
|
*/
|
|
@@ -1065,6 +1201,136 @@ declare class NetworkError extends DispatchTicketsError {
|
|
|
1065
1201
|
constructor(message?: string);
|
|
1066
1202
|
}
|
|
1067
1203
|
|
|
1204
|
+
/**
|
|
1205
|
+
* All supported webhook event types
|
|
1206
|
+
*/
|
|
1207
|
+
type WebhookEventType = 'ticket.created' | 'ticket.updated' | 'ticket.comment.created';
|
|
1208
|
+
/**
|
|
1209
|
+
* Base webhook event envelope
|
|
1210
|
+
*/
|
|
1211
|
+
interface WebhookEventEnvelope<T extends WebhookEventType, D> {
|
|
1212
|
+
/** Unique event ID */
|
|
1213
|
+
id: string;
|
|
1214
|
+
/** Event type */
|
|
1215
|
+
event: T;
|
|
1216
|
+
/** Brand ID that triggered the event */
|
|
1217
|
+
brand_id: string;
|
|
1218
|
+
/** Event data */
|
|
1219
|
+
data: D;
|
|
1220
|
+
/** ISO timestamp when event was created */
|
|
1221
|
+
timestamp: string;
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Customer info included in events
|
|
1225
|
+
*/
|
|
1226
|
+
interface EventCustomerInfo {
|
|
1227
|
+
customerId: string | null;
|
|
1228
|
+
customerEmail: string | null;
|
|
1229
|
+
customerName: string | null;
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Payload for ticket.created event
|
|
1233
|
+
*/
|
|
1234
|
+
interface TicketCreatedData extends EventCustomerInfo {
|
|
1235
|
+
id: string;
|
|
1236
|
+
ticketNumber: number;
|
|
1237
|
+
title: string;
|
|
1238
|
+
status: TicketStatus;
|
|
1239
|
+
priority: TicketPriority;
|
|
1240
|
+
source: TicketSource;
|
|
1241
|
+
createdAt: string;
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Payload for ticket.updated event
|
|
1245
|
+
*/
|
|
1246
|
+
interface TicketUpdatedData extends EventCustomerInfo {
|
|
1247
|
+
id: string;
|
|
1248
|
+
ticketNumber: number;
|
|
1249
|
+
title: string;
|
|
1250
|
+
status: TicketStatus;
|
|
1251
|
+
priority: TicketPriority;
|
|
1252
|
+
assigneeId: string | null;
|
|
1253
|
+
updatedAt: string;
|
|
1254
|
+
/** List of field names that were changed */
|
|
1255
|
+
changes: string[];
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Comment data in ticket.comment.created event
|
|
1259
|
+
*/
|
|
1260
|
+
interface EventCommentData {
|
|
1261
|
+
id: string;
|
|
1262
|
+
body: string;
|
|
1263
|
+
authorId: string | null;
|
|
1264
|
+
authorType: AuthorType;
|
|
1265
|
+
createdAt: string;
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Payload for ticket.comment.created event
|
|
1269
|
+
*/
|
|
1270
|
+
interface CommentCreatedData extends EventCustomerInfo {
|
|
1271
|
+
ticketId: string;
|
|
1272
|
+
/** Formatted ticket number (e.g., "ACME-123") */
|
|
1273
|
+
ticketNumber: string;
|
|
1274
|
+
comment: EventCommentData;
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Ticket created webhook event
|
|
1278
|
+
*/
|
|
1279
|
+
type TicketCreatedEvent = WebhookEventEnvelope<'ticket.created', TicketCreatedData>;
|
|
1280
|
+
/**
|
|
1281
|
+
* Ticket updated webhook event
|
|
1282
|
+
*/
|
|
1283
|
+
type TicketUpdatedEvent = WebhookEventEnvelope<'ticket.updated', TicketUpdatedData>;
|
|
1284
|
+
/**
|
|
1285
|
+
* Comment created webhook event
|
|
1286
|
+
*/
|
|
1287
|
+
type CommentCreatedEvent = WebhookEventEnvelope<'ticket.comment.created', CommentCreatedData>;
|
|
1288
|
+
/**
|
|
1289
|
+
* Union of all webhook events
|
|
1290
|
+
*/
|
|
1291
|
+
type WebhookEvent = TicketCreatedEvent | TicketUpdatedEvent | CommentCreatedEvent;
|
|
1292
|
+
/**
|
|
1293
|
+
* Map of event types to their data types
|
|
1294
|
+
*/
|
|
1295
|
+
interface WebhookEventMap {
|
|
1296
|
+
'ticket.created': TicketCreatedEvent;
|
|
1297
|
+
'ticket.updated': TicketUpdatedEvent;
|
|
1298
|
+
'ticket.comment.created': CommentCreatedEvent;
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Type guard to check if event is a ticket.created event
|
|
1302
|
+
*/
|
|
1303
|
+
declare function isTicketCreatedEvent(event: WebhookEvent): event is TicketCreatedEvent;
|
|
1304
|
+
/**
|
|
1305
|
+
* Type guard to check if event is a ticket.updated event
|
|
1306
|
+
*/
|
|
1307
|
+
declare function isTicketUpdatedEvent(event: WebhookEvent): event is TicketUpdatedEvent;
|
|
1308
|
+
/**
|
|
1309
|
+
* Type guard to check if event is a ticket.comment.created event
|
|
1310
|
+
*/
|
|
1311
|
+
declare function isCommentCreatedEvent(event: WebhookEvent): event is CommentCreatedEvent;
|
|
1312
|
+
/**
|
|
1313
|
+
* Parse and validate a webhook payload
|
|
1314
|
+
*
|
|
1315
|
+
* @param payload - Raw JSON payload string or parsed object
|
|
1316
|
+
* @returns Typed webhook event
|
|
1317
|
+
* @throws Error if payload is invalid
|
|
1318
|
+
*
|
|
1319
|
+
* @example
|
|
1320
|
+
* ```typescript
|
|
1321
|
+
* import { parseWebhookEvent, isTicketCreatedEvent } from '@dispatchtickets/sdk';
|
|
1322
|
+
*
|
|
1323
|
+
* app.post('/webhooks', (req, res) => {
|
|
1324
|
+
* const event = parseWebhookEvent(req.body);
|
|
1325
|
+
*
|
|
1326
|
+
* if (isTicketCreatedEvent(event)) {
|
|
1327
|
+
* console.log('New ticket:', event.data.title);
|
|
1328
|
+
* }
|
|
1329
|
+
* });
|
|
1330
|
+
* ```
|
|
1331
|
+
*/
|
|
1332
|
+
declare function parseWebhookEvent(payload: string | object): WebhookEvent;
|
|
1333
|
+
|
|
1068
1334
|
/**
|
|
1069
1335
|
* Webhook signature verification utilities
|
|
1070
1336
|
*/
|
|
@@ -1113,4 +1379,4 @@ declare const webhookUtils: {
|
|
|
1113
1379
|
*/
|
|
1114
1380
|
declare function collectAll<T>(iterable: AsyncIterable<T>): Promise<T[]>;
|
|
1115
1381
|
|
|
1116
|
-
export { type Attachment, type AttachmentStatus, type AttachmentWithUrl, AuthenticationError, type AuthorType, type Brand, type BulkAction, type BulkActionResult, type Category, type CategoryStats, type Comment, type Company, ConflictError, type CreateBrandInput, type CreateCategoryInput, type CreateCommentInput, type CreateCommentOptions, type CreateCustomerInput, type CreateFieldInput, type CreateTagInput, type CreateTicketInput, type CreateTicketOptions, type CreateWebhookInput, type Customer, type DeleteBrandPreview, DispatchTickets, type DispatchTicketsConfig, DispatchTicketsError, type EntityType, type FieldDefinition, type FieldDefinitions, type FieldType, type InitiateUploadInput, type InitiateUploadResponse, type Link, type ListCustomersFilters, type ListTicketsFilters, type MergeTagsInput, type MergeTicketsInput, NetworkError, NotFoundError, type PaginatedResponse, RateLimitError, ServerError, type SortOrder, type Tag, type Ticket, type TicketPriority, type TicketSource, type TicketStatus, TimeoutError, type UpdateBrandInput, type UpdateCategoryInput, type UpdateCommentInput, type UpdateCustomerInput, type UpdateFieldInput, type UpdateTagInput, type UpdateTicketInput, ValidationError, type Webhook, type WebhookDelivery, type WebhookEvent, collectAll, webhookUtils };
|
|
1382
|
+
export { type Account, type AccountUsage, type ApiKey, type ApiKeyWithSecret, type Attachment, type AttachmentStatus, type AttachmentWithUrl, AuthenticationError, type AuthorType, type Brand, type BulkAction, type BulkActionResult, type Category, type CategoryStats, type Comment, type CommentCreatedData, type CommentCreatedEvent, type Company, ConflictError, type CreateApiKeyInput, type CreateBrandInput, type CreateCategoryInput, type CreateCommentInput, type CreateCommentOptions, type CreateCustomerInput, type CreateFieldInput, type CreateTagInput, type CreateTicketInput, type CreateTicketOptions, type CreateWebhookInput, type Customer, type DeleteBrandPreview, DispatchTickets, type DispatchTicketsConfig, DispatchTicketsError, type EntityType, type EventCommentData, type EventCustomerInfo, type FieldDefinition, type FieldDefinitions, type FieldType, type InitiateUploadInput, type InitiateUploadResponse, type Link, type ListCustomersFilters, type ListTicketsFilters, type MergeTagsInput, type MergeTicketsInput, NetworkError, NotFoundError, type PaginatedResponse, RateLimitError, ServerError, type SortOrder, type Tag, type Ticket, type TicketCreatedData, type TicketCreatedEvent, type TicketPriority, type TicketSource, type TicketStatus, type TicketUpdatedData, type TicketUpdatedEvent, TimeoutError, type UpdateApiKeyScopeInput, type UpdateBrandInput, type UpdateCategoryInput, type UpdateCommentInput, type UpdateCustomerInput, type UpdateFieldInput, type UpdateTagInput, type UpdateTicketInput, ValidationError, type Webhook, type WebhookDelivery, type WebhookEvent, type WebhookEventEnvelope, type WebhookEventMap, type WebhookEventName, type WebhookEventType, collectAll, isCommentCreatedEvent, isTicketCreatedEvent, isTicketUpdatedEvent, parseWebhookEvent, webhookUtils };
|
package/dist/index.js
CHANGED
|
@@ -74,8 +74,10 @@ var NetworkError = class extends DispatchTicketsError {
|
|
|
74
74
|
// src/utils/http.ts
|
|
75
75
|
var HttpClient = class {
|
|
76
76
|
config;
|
|
77
|
+
fetchFn;
|
|
77
78
|
constructor(config) {
|
|
78
79
|
this.config = config;
|
|
80
|
+
this.fetchFn = config.fetch ?? fetch;
|
|
79
81
|
}
|
|
80
82
|
/**
|
|
81
83
|
* Execute an HTTP request with retry logic
|
|
@@ -155,7 +157,7 @@ var HttpClient = class {
|
|
|
155
157
|
console.log("[DispatchTickets] Body:", JSON.stringify(body, null, 2));
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
|
-
const response = await
|
|
160
|
+
const response = await this.fetchFn(url, {
|
|
159
161
|
method,
|
|
160
162
|
headers,
|
|
161
163
|
body: body ? JSON.stringify(body) : void 0,
|
|
@@ -268,6 +270,52 @@ var BaseResource = class {
|
|
|
268
270
|
}
|
|
269
271
|
};
|
|
270
272
|
|
|
273
|
+
// src/resources/accounts.ts
|
|
274
|
+
var AccountsResource = class extends BaseResource {
|
|
275
|
+
/**
|
|
276
|
+
* Get the current account
|
|
277
|
+
*/
|
|
278
|
+
async me() {
|
|
279
|
+
return this._get("/accounts/me");
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get usage statistics for the current account
|
|
283
|
+
*/
|
|
284
|
+
async getUsage() {
|
|
285
|
+
return this._get("/accounts/me/usage");
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* List all API keys for the current account
|
|
289
|
+
*/
|
|
290
|
+
async listApiKeys() {
|
|
291
|
+
return this._get("/accounts/me/api-keys");
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Create a new API key
|
|
295
|
+
*
|
|
296
|
+
* Note: The full key value is only returned once on creation.
|
|
297
|
+
* Store it securely as it cannot be retrieved again.
|
|
298
|
+
*/
|
|
299
|
+
async createApiKey(data) {
|
|
300
|
+
return this._post("/accounts/me/api-keys", data);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Update the brand scope for an API key
|
|
304
|
+
*/
|
|
305
|
+
async updateApiKeyScope(keyId, data) {
|
|
306
|
+
return this._patch(
|
|
307
|
+
`/accounts/me/api-keys/${keyId}/scope`,
|
|
308
|
+
data
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Revoke an API key
|
|
313
|
+
*/
|
|
314
|
+
async revokeApiKey(keyId) {
|
|
315
|
+
await this._delete(`/accounts/me/api-keys/${keyId}`);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
271
319
|
// src/resources/brands.ts
|
|
272
320
|
var BrandsResource = class extends BaseResource {
|
|
273
321
|
/**
|
|
@@ -318,6 +366,28 @@ var BrandsResource = class extends BaseResource {
|
|
|
318
366
|
async updateSchema(brandId, schema) {
|
|
319
367
|
return this._put(`/brands/${brandId}/schema`, schema);
|
|
320
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* Get the inbound email address for a brand
|
|
371
|
+
*
|
|
372
|
+
* Emails sent to this address will automatically create tickets.
|
|
373
|
+
*
|
|
374
|
+
* @param brandId - The brand ID
|
|
375
|
+
* @param domain - Optional custom inbound domain (default: inbound.dispatchtickets.com)
|
|
376
|
+
* @returns The inbound email address
|
|
377
|
+
*
|
|
378
|
+
* @example
|
|
379
|
+
* ```typescript
|
|
380
|
+
* const email = client.brands.getInboundEmail('br_abc123');
|
|
381
|
+
* // Returns: br_abc123@inbound.dispatchtickets.com
|
|
382
|
+
*
|
|
383
|
+
* // With custom domain:
|
|
384
|
+
* const customEmail = client.brands.getInboundEmail('br_abc123', 'support.mycompany.com');
|
|
385
|
+
* // Returns: br_abc123@support.mycompany.com
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
getInboundEmail(brandId, domain = "inbound.dispatchtickets.com") {
|
|
389
|
+
return `${brandId}@${domain}`;
|
|
390
|
+
}
|
|
321
391
|
};
|
|
322
392
|
|
|
323
393
|
// src/resources/tickets.ts
|
|
@@ -832,6 +902,10 @@ var webhookUtils = {
|
|
|
832
902
|
// src/client.ts
|
|
833
903
|
var DispatchTickets = class {
|
|
834
904
|
http;
|
|
905
|
+
/**
|
|
906
|
+
* Accounts resource for managing the current account and API keys
|
|
907
|
+
*/
|
|
908
|
+
accounts;
|
|
835
909
|
/**
|
|
836
910
|
* Brands (workspaces) resource
|
|
837
911
|
*/
|
|
@@ -881,9 +955,11 @@ var DispatchTickets = class {
|
|
|
881
955
|
apiKey: config.apiKey,
|
|
882
956
|
timeout: config.timeout ?? 3e4,
|
|
883
957
|
maxRetries: config.maxRetries ?? 3,
|
|
884
|
-
debug: config.debug ?? false
|
|
958
|
+
debug: config.debug ?? false,
|
|
959
|
+
fetch: config.fetch
|
|
885
960
|
};
|
|
886
961
|
this.http = new HttpClient(httpConfig);
|
|
962
|
+
this.accounts = new AccountsResource(this.http);
|
|
887
963
|
this.brands = new BrandsResource(this.http);
|
|
888
964
|
this.tickets = new TicketsResource(this.http);
|
|
889
965
|
this.comments = new CommentsResource(this.http);
|
|
@@ -896,6 +972,37 @@ var DispatchTickets = class {
|
|
|
896
972
|
}
|
|
897
973
|
};
|
|
898
974
|
|
|
975
|
+
// src/types/events.ts
|
|
976
|
+
function isTicketCreatedEvent(event) {
|
|
977
|
+
return event.event === "ticket.created";
|
|
978
|
+
}
|
|
979
|
+
function isTicketUpdatedEvent(event) {
|
|
980
|
+
return event.event === "ticket.updated";
|
|
981
|
+
}
|
|
982
|
+
function isCommentCreatedEvent(event) {
|
|
983
|
+
return event.event === "ticket.comment.created";
|
|
984
|
+
}
|
|
985
|
+
function parseWebhookEvent(payload) {
|
|
986
|
+
const event = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
987
|
+
if (!event || typeof event !== "object") {
|
|
988
|
+
throw new Error("Invalid webhook payload: expected object");
|
|
989
|
+
}
|
|
990
|
+
if (!event.event || typeof event.event !== "string") {
|
|
991
|
+
throw new Error("Invalid webhook payload: missing event type");
|
|
992
|
+
}
|
|
993
|
+
if (!event.id || typeof event.id !== "string") {
|
|
994
|
+
throw new Error("Invalid webhook payload: missing event id");
|
|
995
|
+
}
|
|
996
|
+
if (!event.data || typeof event.data !== "object") {
|
|
997
|
+
throw new Error("Invalid webhook payload: missing data");
|
|
998
|
+
}
|
|
999
|
+
const validEvents = ["ticket.created", "ticket.updated", "ticket.comment.created"];
|
|
1000
|
+
if (!validEvents.includes(event.event)) {
|
|
1001
|
+
throw new Error(`Invalid webhook payload: unknown event type "${event.event}"`);
|
|
1002
|
+
}
|
|
1003
|
+
return event;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
899
1006
|
// src/utils/pagination.ts
|
|
900
1007
|
async function collectAll(iterable) {
|
|
901
1008
|
const items = [];
|
|
@@ -905,6 +1012,6 @@ async function collectAll(iterable) {
|
|
|
905
1012
|
return items;
|
|
906
1013
|
}
|
|
907
1014
|
|
|
908
|
-
export { AuthenticationError, ConflictError, DispatchTickets, DispatchTicketsError, NetworkError, NotFoundError, RateLimitError, ServerError, TimeoutError, ValidationError, collectAll, webhookUtils };
|
|
1015
|
+
export { AuthenticationError, ConflictError, DispatchTickets, DispatchTicketsError, NetworkError, NotFoundError, RateLimitError, ServerError, TimeoutError, ValidationError, collectAll, isCommentCreatedEvent, isTicketCreatedEvent, isTicketUpdatedEvent, parseWebhookEvent, webhookUtils };
|
|
909
1016
|
//# sourceMappingURL=index.js.map
|
|
910
1017
|
//# sourceMappingURL=index.js.map
|