@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 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
@@ -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 };