@xalantis/sdk 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/README.md +120 -0
- package/dist/index.d.mts +338 -0
- package/dist/index.d.ts +338 -0
- package/dist/index.js +267 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +239 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +35 -0
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# @xalantis/sdk
|
|
2
|
+
|
|
3
|
+
Official JavaScript/TypeScript SDK for the Xalantis API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @xalantis/sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Xalantis } from '@xalantis/sdk'
|
|
15
|
+
|
|
16
|
+
const client = new Xalantis({
|
|
17
|
+
apiKey: 'xal_live_...',
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Tickets
|
|
22
|
+
|
|
23
|
+
### Create a ticket
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
const { data: ticket } = await client.tickets.create({
|
|
27
|
+
subject: 'Login issue',
|
|
28
|
+
description: 'Cannot login since the latest update',
|
|
29
|
+
requester_email: 'user@example.com',
|
|
30
|
+
priority: 'high',
|
|
31
|
+
category_slug: 'technical-support', // optional
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
console.log(ticket.uuid, ticket.reference)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### List tickets
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
const { data: tickets, meta } = await client.tickets.list({
|
|
41
|
+
status: 'open',
|
|
42
|
+
priority: 'high',
|
|
43
|
+
per_page: 10,
|
|
44
|
+
sort_by: 'created_at',
|
|
45
|
+
sort_dir: 'desc',
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
console.log(`${meta.total} tickets found`)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Get a ticket
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const { data: ticket } = await client.tickets.get('ticket-uuid')
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Update a ticket
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
await client.tickets.update('ticket-uuid', {
|
|
61
|
+
status: 'resolved',
|
|
62
|
+
priority: 'low',
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Reply to a ticket
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
await client.tickets.reply('ticket-uuid', {
|
|
70
|
+
content: 'This has been fixed in v2.1.0',
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Internal note (not visible to requester)
|
|
74
|
+
await client.tickets.reply('ticket-uuid', {
|
|
75
|
+
content: 'Deployed hotfix to production',
|
|
76
|
+
is_internal: true,
|
|
77
|
+
})
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### List replies
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const { data: replies } = await client.tickets.listReplies('ticket-uuid')
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Error Handling
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
import { Xalantis, XalantisError } from '@xalantis/sdk'
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
await client.tickets.create({ ... })
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (error instanceof XalantisError) {
|
|
95
|
+
console.error(error.code) // 'VALIDATION_ERROR'
|
|
96
|
+
console.error(error.message) // 'Validation failed.'
|
|
97
|
+
console.error(error.status) // 422
|
|
98
|
+
console.error(error.details) // { subject: ['Required'] }
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## TypeScript
|
|
104
|
+
|
|
105
|
+
All types are exported:
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import type {
|
|
109
|
+
Ticket,
|
|
110
|
+
TicketPriority,
|
|
111
|
+
TicketStatus,
|
|
112
|
+
CreateTicketInput,
|
|
113
|
+
UpdateTicketInput,
|
|
114
|
+
TicketReply,
|
|
115
|
+
} from '@xalantis/sdk'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/** Configuration for the Xalantis SDK client. */
|
|
2
|
+
interface XalantisConfig {
|
|
3
|
+
/** Your Xalantis API key (e.g. `sk_live_...`). */
|
|
4
|
+
apiKey: string;
|
|
5
|
+
/** @internal For testing only. Defaults to https://xalantis.com */
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
/** Request timeout in milliseconds. Defaults to 30000 (30s). */
|
|
8
|
+
timeout?: number;
|
|
9
|
+
}
|
|
10
|
+
/** Standard API response wrapping a single resource. */
|
|
11
|
+
interface ApiResponse<T> {
|
|
12
|
+
success: boolean;
|
|
13
|
+
data: T;
|
|
14
|
+
message: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Paginated API response wrapping a list of resources. */
|
|
17
|
+
interface PaginatedResponse<T> {
|
|
18
|
+
success: boolean;
|
|
19
|
+
data: T[];
|
|
20
|
+
/** Pagination metadata. */
|
|
21
|
+
meta: {
|
|
22
|
+
current_page: number;
|
|
23
|
+
per_page: number;
|
|
24
|
+
total: number;
|
|
25
|
+
last_page: number;
|
|
26
|
+
from: number | null;
|
|
27
|
+
to: number | null;
|
|
28
|
+
};
|
|
29
|
+
/** Pagination navigation links. */
|
|
30
|
+
links: {
|
|
31
|
+
first: string | null;
|
|
32
|
+
last: string | null;
|
|
33
|
+
prev: string | null;
|
|
34
|
+
next: string | null;
|
|
35
|
+
};
|
|
36
|
+
message: string | null;
|
|
37
|
+
}
|
|
38
|
+
/** API error response structure. */
|
|
39
|
+
interface ApiError {
|
|
40
|
+
success: false;
|
|
41
|
+
error: {
|
|
42
|
+
/** Machine-readable error code (e.g. `VALIDATION_ERROR`, `NOT_FOUND`). */
|
|
43
|
+
code: string;
|
|
44
|
+
/** Human-readable error message. */
|
|
45
|
+
message: string;
|
|
46
|
+
/** Field-level validation errors, keyed by field name. */
|
|
47
|
+
details?: Record<string, string[]>;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Ticket priority levels. */
|
|
51
|
+
type TicketPriority = 'low' | 'medium' | 'high' | 'urgent';
|
|
52
|
+
/** Ticket lifecycle statuses. */
|
|
53
|
+
type TicketStatus = 'new' | 'open' | 'pending' | 'on_hold' | 'resolved' | 'closed';
|
|
54
|
+
/** Channel through which a ticket was created. */
|
|
55
|
+
type TicketChannel = 'api' | 'email' | 'phone' | 'chat' | 'web' | 'widget';
|
|
56
|
+
/** A support ticket. */
|
|
57
|
+
interface Ticket {
|
|
58
|
+
/** Unique identifier (UUID v4). */
|
|
59
|
+
uuid: string;
|
|
60
|
+
/** Human-readable reference (e.g. `TK-000042`). */
|
|
61
|
+
reference: string;
|
|
62
|
+
/** Ticket subject line. */
|
|
63
|
+
subject: string;
|
|
64
|
+
/** Ticket description / body. */
|
|
65
|
+
description: string;
|
|
66
|
+
/** Current status. */
|
|
67
|
+
status: TicketStatus;
|
|
68
|
+
/** Priority level. */
|
|
69
|
+
priority: TicketPriority;
|
|
70
|
+
/** Channel through which the ticket was created. */
|
|
71
|
+
channel: TicketChannel;
|
|
72
|
+
/** Ticket category, if assigned. */
|
|
73
|
+
category: {
|
|
74
|
+
name: string;
|
|
75
|
+
slug: string;
|
|
76
|
+
} | null;
|
|
77
|
+
/** Person who submitted the ticket. */
|
|
78
|
+
requester: {
|
|
79
|
+
type: string;
|
|
80
|
+
name: string | null;
|
|
81
|
+
email: string | null;
|
|
82
|
+
phone: string | null;
|
|
83
|
+
contact_id: string | null;
|
|
84
|
+
client_id: string | null;
|
|
85
|
+
};
|
|
86
|
+
/** Agent assigned to the ticket. */
|
|
87
|
+
assignee: {
|
|
88
|
+
name: string;
|
|
89
|
+
email: string;
|
|
90
|
+
} | null;
|
|
91
|
+
/** Custom field values. */
|
|
92
|
+
custom_fields: Record<string, unknown> | null;
|
|
93
|
+
/** Tags attached to the ticket. */
|
|
94
|
+
tags: string[];
|
|
95
|
+
/** SLA due date (ISO 8601). */
|
|
96
|
+
due_at: string | null;
|
|
97
|
+
/** Creation timestamp (ISO 8601). */
|
|
98
|
+
created_at: string;
|
|
99
|
+
/** Last update timestamp (ISO 8601). */
|
|
100
|
+
updated_at: string;
|
|
101
|
+
/** When the ticket was resolved (ISO 8601). */
|
|
102
|
+
resolved_at: string | null;
|
|
103
|
+
/** When the ticket was closed (ISO 8601). */
|
|
104
|
+
closed_at: string | null;
|
|
105
|
+
}
|
|
106
|
+
/** Input for creating a new ticket. */
|
|
107
|
+
interface CreateTicketInput {
|
|
108
|
+
/** Ticket subject (required, max 255 chars). */
|
|
109
|
+
subject: string;
|
|
110
|
+
/** Ticket description (required). */
|
|
111
|
+
description: string;
|
|
112
|
+
/** Email of the person reporting the issue (required). */
|
|
113
|
+
requester_email: string;
|
|
114
|
+
/** Name of the requester. */
|
|
115
|
+
requester_name?: string;
|
|
116
|
+
/** Priority level. Defaults to `medium`. */
|
|
117
|
+
priority?: TicketPriority;
|
|
118
|
+
/** Assign to a category by ID. */
|
|
119
|
+
category_id?: number;
|
|
120
|
+
/** Assign to a category by slug. */
|
|
121
|
+
category_slug?: string;
|
|
122
|
+
/** Channel source. Defaults to `api`. */
|
|
123
|
+
channel?: TicketChannel;
|
|
124
|
+
/** Custom field values. */
|
|
125
|
+
custom_fields?: Record<string, unknown>;
|
|
126
|
+
}
|
|
127
|
+
/** Input for updating an existing ticket. All fields are optional. */
|
|
128
|
+
interface UpdateTicketInput {
|
|
129
|
+
subject?: string;
|
|
130
|
+
description?: string;
|
|
131
|
+
status?: TicketStatus;
|
|
132
|
+
priority?: TicketPriority;
|
|
133
|
+
category_id?: number;
|
|
134
|
+
category_slug?: string;
|
|
135
|
+
/** Assign to a specific agent by ID. */
|
|
136
|
+
assignee_id?: number;
|
|
137
|
+
/** SLA due date (ISO 8601). */
|
|
138
|
+
due_at?: string;
|
|
139
|
+
custom_fields?: Record<string, unknown>;
|
|
140
|
+
}
|
|
141
|
+
/** Parameters for listing/filtering tickets. */
|
|
142
|
+
interface ListTicketsParams {
|
|
143
|
+
/** Page number (1-based). */
|
|
144
|
+
page?: number;
|
|
145
|
+
/** Results per page (default 15, max 100). */
|
|
146
|
+
per_page?: number;
|
|
147
|
+
/** Filter by status. */
|
|
148
|
+
status?: TicketStatus;
|
|
149
|
+
/** Filter by priority. */
|
|
150
|
+
priority?: TicketPriority;
|
|
151
|
+
/** Filter by assigned agent ID. */
|
|
152
|
+
assignee_id?: number;
|
|
153
|
+
/** Filter by requester email (exact match). */
|
|
154
|
+
requester_email?: string;
|
|
155
|
+
/** Full-text search on subject and description. */
|
|
156
|
+
search?: string;
|
|
157
|
+
/** Field to sort by. */
|
|
158
|
+
sort_by?: 'created_at' | 'updated_at' | 'priority' | 'status' | 'due_at' | 'reference';
|
|
159
|
+
/** Sort direction. */
|
|
160
|
+
sort_dir?: 'asc' | 'desc';
|
|
161
|
+
}
|
|
162
|
+
/** A reply or internal note on a ticket. */
|
|
163
|
+
interface TicketReply {
|
|
164
|
+
/** Unique identifier (UUID v4). */
|
|
165
|
+
uuid: string;
|
|
166
|
+
/** Reply content (HTML or plain text). */
|
|
167
|
+
content: string;
|
|
168
|
+
/** Whether this is an internal note (not visible to the requester). */
|
|
169
|
+
is_internal: boolean;
|
|
170
|
+
/** Whether this reply was auto-generated by the system. */
|
|
171
|
+
is_automated: boolean;
|
|
172
|
+
/** Agent who posted the reply, if any. */
|
|
173
|
+
user: {
|
|
174
|
+
id: number;
|
|
175
|
+
full_name: string;
|
|
176
|
+
email: string;
|
|
177
|
+
} | null;
|
|
178
|
+
/** Creation timestamp (ISO 8601). */
|
|
179
|
+
created_at: string;
|
|
180
|
+
/** Last update timestamp (ISO 8601). */
|
|
181
|
+
updated_at: string;
|
|
182
|
+
}
|
|
183
|
+
/** Input for creating a reply on a ticket. */
|
|
184
|
+
interface CreateTicketReplyInput {
|
|
185
|
+
/** Reply content (required). */
|
|
186
|
+
content: string;
|
|
187
|
+
/** Set to `true` for an internal note (not visible to the requester). */
|
|
188
|
+
is_internal?: boolean;
|
|
189
|
+
}
|
|
190
|
+
/** Parameters for listing replies. */
|
|
191
|
+
interface ListTicketRepliesParams {
|
|
192
|
+
/** Page number (1-based). */
|
|
193
|
+
page?: number;
|
|
194
|
+
/** Results per page (default 50). */
|
|
195
|
+
per_page?: number;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Error thrown when the Xalantis API returns a non-success response.
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```ts
|
|
203
|
+
* try {
|
|
204
|
+
* await client.tickets.create({ ... })
|
|
205
|
+
* } catch (error) {
|
|
206
|
+
* if (error instanceof XalantisError) {
|
|
207
|
+
* console.error(error.code) // 'VALIDATION_ERROR'
|
|
208
|
+
* console.error(error.status) // 422
|
|
209
|
+
* console.error(error.details) // { subject: ['Required'] }
|
|
210
|
+
* }
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
declare class XalantisError extends Error {
|
|
215
|
+
/** Machine-readable error code (e.g. `VALIDATION_ERROR`, `NOT_FOUND`, `UNAUTHORIZED`). */
|
|
216
|
+
code: string;
|
|
217
|
+
/** HTTP status code. */
|
|
218
|
+
status: number;
|
|
219
|
+
/** Field-level validation errors, keyed by field name. Only present for 422 responses. */
|
|
220
|
+
details?: Record<string, string[]>;
|
|
221
|
+
/** Value of `Retry-After` header when rate-limited (429). */
|
|
222
|
+
retryAfter?: number;
|
|
223
|
+
constructor(message: string, code: string, status: number, details?: Record<string, string[]>, retryAfter?: number);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Low-level HTTP client for the Xalantis API.
|
|
227
|
+
* Handles authentication, request building, and error mapping.
|
|
228
|
+
* @internal Use the `Xalantis` class instead.
|
|
229
|
+
*/
|
|
230
|
+
declare class HttpClient {
|
|
231
|
+
private baseUrl;
|
|
232
|
+
private apiKey;
|
|
233
|
+
private timeoutMs;
|
|
234
|
+
constructor(config: XalantisConfig);
|
|
235
|
+
/** @internal Prevent accidental serialization of sensitive data. */
|
|
236
|
+
toJSON(): Record<string, unknown>;
|
|
237
|
+
private request;
|
|
238
|
+
/** Send a GET request and return a single resource. */
|
|
239
|
+
get<T>(path: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
|
|
240
|
+
/** Send a GET request and return a paginated list. */
|
|
241
|
+
getPaginated<T>(path: string, params?: Record<string, unknown>): Promise<PaginatedResponse<T>>;
|
|
242
|
+
/** Send a POST request. */
|
|
243
|
+
post<T>(path: string, body: unknown): Promise<ApiResponse<T>>;
|
|
244
|
+
/** Send a PATCH request. */
|
|
245
|
+
patch<T>(path: string, body: unknown): Promise<ApiResponse<T>>;
|
|
246
|
+
/** Send a DELETE request. */
|
|
247
|
+
delete(path: string): Promise<ApiResponse<null>>;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
declare class TicketsResource {
|
|
251
|
+
private http;
|
|
252
|
+
constructor(http: HttpClient);
|
|
253
|
+
/**
|
|
254
|
+
* List tickets with optional filters and pagination.
|
|
255
|
+
*
|
|
256
|
+
* @example
|
|
257
|
+
* const tickets = await client.tickets.list({ status: 'open', per_page: 10 })
|
|
258
|
+
*/
|
|
259
|
+
list(params?: ListTicketsParams): Promise<PaginatedResponse<Ticket>>;
|
|
260
|
+
/**
|
|
261
|
+
* Get a single ticket by UUID.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* const ticket = await client.tickets.get('uuid-here')
|
|
265
|
+
*/
|
|
266
|
+
get(uuid: string): Promise<ApiResponse<Ticket>>;
|
|
267
|
+
/**
|
|
268
|
+
* Create a new ticket.
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* const ticket = await client.tickets.create({
|
|
272
|
+
* subject: 'Login issue',
|
|
273
|
+
* description: 'Cannot login since update',
|
|
274
|
+
* requester_email: 'user@example.com',
|
|
275
|
+
* priority: 'high',
|
|
276
|
+
* })
|
|
277
|
+
*/
|
|
278
|
+
create(input: CreateTicketInput): Promise<ApiResponse<Ticket>>;
|
|
279
|
+
/**
|
|
280
|
+
* Update an existing ticket.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* const ticket = await client.tickets.update('uuid-here', { status: 'resolved' })
|
|
284
|
+
*/
|
|
285
|
+
update(uuid: string, input: UpdateTicketInput): Promise<ApiResponse<Ticket>>;
|
|
286
|
+
/**
|
|
287
|
+
* List replies for a ticket.
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* const replies = await client.tickets.listReplies('uuid-here')
|
|
291
|
+
*/
|
|
292
|
+
listReplies(ticketUuid: string, params?: ListTicketRepliesParams): Promise<PaginatedResponse<TicketReply>>;
|
|
293
|
+
/**
|
|
294
|
+
* Add a reply to a ticket.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* await client.tickets.reply('uuid-here', { content: 'Thanks for reporting!' })
|
|
298
|
+
*/
|
|
299
|
+
reply(ticketUuid: string, input: CreateTicketReplyInput): Promise<ApiResponse<TicketReply>>;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Xalantis SDK Client.
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```ts
|
|
307
|
+
* import { Xalantis } from '@xalantis/sdk'
|
|
308
|
+
*
|
|
309
|
+
* const client = new Xalantis({ apiKey: 'xal_live_...' })
|
|
310
|
+
*
|
|
311
|
+
* // Create a ticket
|
|
312
|
+
* const { data: ticket } = await client.tickets.create({
|
|
313
|
+
* subject: 'Bug report',
|
|
314
|
+
* description: 'Something is broken',
|
|
315
|
+
* requester_email: 'user@example.com',
|
|
316
|
+
* })
|
|
317
|
+
*
|
|
318
|
+
* // List tickets
|
|
319
|
+
* const { data: tickets } = await client.tickets.list({ status: 'open' })
|
|
320
|
+
*
|
|
321
|
+
* // Get a ticket
|
|
322
|
+
* const { data: ticket } = await client.tickets.get('uuid-here')
|
|
323
|
+
*
|
|
324
|
+
* // Update a ticket
|
|
325
|
+
* await client.tickets.update('uuid-here', { status: 'resolved' })
|
|
326
|
+
*
|
|
327
|
+
* // Reply to a ticket
|
|
328
|
+
* await client.tickets.reply('uuid-here', { content: 'Fixed!' })
|
|
329
|
+
* ```
|
|
330
|
+
*/
|
|
331
|
+
declare class Xalantis {
|
|
332
|
+
private http;
|
|
333
|
+
/** Ticket management (create, list, get, update, reply). */
|
|
334
|
+
tickets: TicketsResource;
|
|
335
|
+
constructor(config: XalantisConfig);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export { type ApiError, type ApiResponse, type CreateTicketInput, type CreateTicketReplyInput, type ListTicketRepliesParams, type ListTicketsParams, type PaginatedResponse, type Ticket, type TicketChannel, type TicketPriority, type TicketReply, type TicketStatus, type UpdateTicketInput, Xalantis, type XalantisConfig, XalantisError };
|