@zizq-labs/zizq 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.
@@ -0,0 +1,747 @@
1
+ /**
2
+ * Low-level HTTP client for the Zizq job queue server.
3
+ *
4
+ * @example Basic usage
5
+ * ```ts
6
+ * import { Client } from "@zizq-labs/zizq";
7
+ *
8
+ * const client = new Client({ url: "http://localhost:7890" });
9
+ *
10
+ * // Enqueue a job
11
+ * const job = await client.enqueue({
12
+ * type: "send_email",
13
+ * queue: "emails",
14
+ * payload: { to: "user@example.com", subject: "Hello" },
15
+ * });
16
+ * console.log(job.id); // "03fvqh..."
17
+ *
18
+ * // Take and process jobs (streaming)
19
+ * for await (const job of client.take({ prefetch: 5, queues: ["emails"] })) {
20
+ * try {
21
+ * await processJob(job);
22
+ * await client.reportSuccess(job.id);
23
+ * } catch (err) {
24
+ * await client.reportFailure(job.id, { message: err.message });
25
+ * }
26
+ * }
27
+ *
28
+ * await client.close();
29
+ * ```
30
+ *
31
+ * @module
32
+ */
33
+ import { type Dispatcher } from "undici";
34
+ import { Job, JobPage, ErrorRecord, ErrorPage } from "./resources.ts";
35
+ import { JobQuery, type JobQueryOptions } from "./query.ts";
36
+ /** Lifecycle status of a job. */
37
+ export type JobStatus = "ready" | "in_flight" | "scheduled" | "completed" | "dead";
38
+ /** Sort direction for paginated listings. */
39
+ export type SortDirection = "asc" | "desc";
40
+ /** Uniqueness scope for deduplication. */
41
+ export type UniqueScope = "queued" | "active" | "exists";
42
+ export { Job, JobPage, ErrorRecord, ErrorPage, type JobData, type ErrorRecordData } from "./resources.ts";
43
+ /**
44
+ * Backoff configuration for retry delays.
45
+ *
46
+ * This is used in the following formula:
47
+ *
48
+ * ```
49
+ * t = baseMs + (attempts ** exponent) + (attempts * random() * jitterMs)
50
+ * ```
51
+ *
52
+ * The random jitter is designed to ensure clusters of failed jobs do not all
53
+ * retry at the same time but are instead randomly spread out.
54
+ */
55
+ export interface BackoffConfig {
56
+ /** Base delay in milliseconds, applied to all retries. */
57
+ baseMs: number;
58
+ /** Backoff curve steepness (attempts ** exponent). */
59
+ exponent: number;
60
+ /** Maximum random jitter in milliseconds per attempt multiplier. */
61
+ jitterMs: number;
62
+ }
63
+ /**
64
+ * Retention configuration controlling how long jobs in terminal statuses are kept.
65
+ *
66
+ * The terminal statuses are "completed" and "dead".
67
+ */
68
+ export interface RetentionConfig {
69
+ /** How long completed jobs remain visible (ms). `null` clears to server default. */
70
+ completedMs?: number | null;
71
+ /** How long dead jobs remain visible (ms). `null` clears to server default. */
72
+ deadMs?: number | null;
73
+ }
74
+ /**
75
+ * Options for enqueueing a single job.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * await client.enqueue({
80
+ * type: "generate_report",
81
+ * queue: "reports",
82
+ * payload: { reportId: 42 },
83
+ * priority: 100, // optional, lower = higher priority
84
+ * readyAt: Date.now() + 60000, // optional, delay by 1 minute
85
+ * });
86
+ * ```
87
+ */
88
+ export interface EnqueueOptions {
89
+ /** Job type identifier. */
90
+ type: string;
91
+ /**
92
+ * Target queue name.
93
+ *
94
+ * Must be valid UTF-8 and must not contain any of the following reserved
95
+ * characters: ",", "?", "*", "[", "]", "{", "}", "!".
96
+ */
97
+ queue: string;
98
+ /**
99
+ * Arbitrary payload delivered to the worker.
100
+ */
101
+ payload: unknown;
102
+ /**
103
+ * Optional priority (lower = higher priority).
104
+ *
105
+ * Valid range is 0 to 65536. Default: 32768.
106
+ */
107
+ priority?: number;
108
+ /**
109
+ * Optional timestamp (ms since epoch) when the job becomes eligible.
110
+ *
111
+ * When set to a future timestamp the job is created in the "scheduled"
112
+ * status. Otherwise the job is created in the "ready" status.
113
+ */
114
+ readyAt?: number;
115
+ /**
116
+ * Optional per-job retry limit.
117
+ *
118
+ * When not set the server default value applies.
119
+ */
120
+ retryLimit?: number;
121
+ /** Optional per-job backoff configuration. */
122
+ backoff?: BackoffConfig;
123
+ /** Optional per-job retention configuration. */
124
+ retention?: RetentionConfig;
125
+ /**
126
+ * Optional unique key for enqueue-time deduplication.
127
+ *
128
+ * Requires a pro license on the server.
129
+ *
130
+ * The key is global across all queues and job types. Prefix with the job
131
+ * type to make it unique per job type.
132
+ */
133
+ uniqueKey?: string;
134
+ /**
135
+ * Uniqueness scope. Only valid when `uniqueKey` is set.
136
+ *
137
+ * When set to "queued" other jobs with the same key will not be enqueued as
138
+ * long as this job is in the "scheduled" or "ready" statuses.
139
+ *
140
+ * When set to "active" other jobs with the same key will not be enqueued
141
+ * while this job is in the "scheduled", "ready" or "in_flight" statuses.
142
+ *
143
+ * When set to "exists" other jobs with the same key will not be enqueued
144
+ * for as long as this job remains on the server (i.e. until it is eventually
145
+ * reaped, based on the retention policy).
146
+ */
147
+ uniqueWhile?: UniqueScope;
148
+ }
149
+ /** Options for reporting a job failure. */
150
+ export interface FailureOptions {
151
+ /** Error message describing what went wrong. */
152
+ message: string;
153
+ /** Optional error class name, e.g. "TimeoutError". */
154
+ errorType?: string;
155
+ /** Optional stack trace from the worker. */
156
+ backtrace?: string;
157
+ /** Optional forced retry time (ms since epoch), bypassing backoff. */
158
+ retryAt?: number;
159
+ /**
160
+ * Kill the job immediately regardless of retry limit.
161
+ *
162
+ * Note: passing false does nothing.
163
+ */
164
+ kill?: boolean;
165
+ }
166
+ /**
167
+ * Options for the streaming take endpoint.
168
+ *
169
+ * Returns an async generator which never terminates as long as the connection
170
+ * to the server remains open. Clients should use `break` to explicitly
171
+ * disconnect from the endpoint and stop receiving jobs.
172
+ *
173
+ * When no jobs are available, the generator waits until new jobs are enqueued.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * // Take up to 10 jobs at a time from specific queues
178
+ * for await (const job of client.take({ prefetch: 10, queues: ["emails", "webhooks"] })) {
179
+ * // process job...
180
+ * }
181
+ * ```
182
+ */
183
+ export interface TakeOptions {
184
+ /**
185
+ * Maximum number of "in_flight", unacknowledged jobs the server will send.
186
+ *
187
+ * The default is 1, meaning the client must acknowledge or fail the job
188
+ * before the server sends the next, and so on.
189
+ */
190
+ prefetch?: number;
191
+ /** Only take jobs from these queues. Empty means all queues. */
192
+ queues?: string[];
193
+ /** AbortSignal to cancel the streaming connection. */
194
+ signal?: AbortSignal;
195
+ }
196
+ /**
197
+ * Options for listing jobs with cursor-based pagination.
198
+ *
199
+ * @example
200
+ * ```ts
201
+ * const page = await client.listJobs({
202
+ * queue: "emails",
203
+ * status: ["ready", "in_flight"],
204
+ * limit: 20,
205
+ * });
206
+ * ```
207
+ */
208
+ export interface ListJobsOptions {
209
+ /** Cursor: start after this job ID (exclusive). */
210
+ from?: string;
211
+ /** Sort order. Default: "asc" (oldest first). */
212
+ order?: SortDirection;
213
+ /** Maximum number of jobs per page (1–2000, default 50). */
214
+ limit?: number;
215
+ /** Filter by status. Accepts a single value or an array. */
216
+ status?: JobStatus | JobStatus[];
217
+ /** Filter by queue name. Accepts a single value or an array. */
218
+ queue?: string | string[];
219
+ /** Filter by job type. Accepts a single value or an array. */
220
+ type?: string | string[];
221
+ /** Filter by job ID. Accepts a single value or an array. */
222
+ id?: string | string[];
223
+ /** jq expression to filter jobs by payload. */
224
+ filter?: string;
225
+ }
226
+ /**
227
+ * Options for listing error records for a job.
228
+ *
229
+ * @example
230
+ * ```ts
231
+ * const page = await client.listErrors("job-id", { order: "desc", limit: 10 });
232
+ * ```
233
+ */
234
+ export interface ListErrorsOptions {
235
+ /** Cursor: start after this attempt number (exclusive). */
236
+ from?: number;
237
+ /** Sort order. Default: "asc" (oldest first). */
238
+ order?: SortDirection;
239
+ /** Maximum number of error records per page (1–2000, default 50). */
240
+ limit?: number;
241
+ }
242
+ /**
243
+ * Mutable fields for updating a job.
244
+ *
245
+ * Field semantics:
246
+ * - **omitted or `undefined`** — leave unchanged
247
+ * - **`null`** — clear the field (only valid for nullable fields)
248
+ * - **a value** — update to that value
249
+ *
250
+ * Nullable fields: `readyAt`, `retryLimit`, `backoff`, `retention`.
251
+ * Non-nullable fields: `queue`, `priority`.
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * // Change priority and clear retry limit (use server default)
256
+ * await client.updateJob("job-id", {
257
+ * priority: 100,
258
+ * retryLimit: null,
259
+ * });
260
+ * ```
261
+ */
262
+ export interface UpdateJobOptions {
263
+ /** Move the job to a different queue. */
264
+ queue?: string;
265
+ /** Change the job's priority. */
266
+ priority?: number;
267
+ /** Change when the job becomes ready (ms since epoch). `null` clears to immediately ready. */
268
+ readyAt?: number | null;
269
+ /** Override the retry limit. `null` clears to server default. */
270
+ retryLimit?: number | null;
271
+ /** Override the backoff config. `null` clears to server default. */
272
+ backoff?: BackoffConfig | null;
273
+ /** Override the retention config. `null` clears to server default. */
274
+ retention?: RetentionConfig | null;
275
+ }
276
+ /**
277
+ * Options for bulk-updating jobs.
278
+ *
279
+ * Has two parts:
280
+ * - `where` — filter selecting which jobs to update (same as `deleteAllJobs`)
281
+ * - `apply` — fields to update on the matching jobs (same as `updateJob`)
282
+ *
283
+ * An empty array filter (e.g. `where.id: []`) short-circuits to 0 jobs updated.
284
+ *
285
+ * @example
286
+ * ```ts
287
+ * // Lower the priority of all dead jobs in the emails queue
288
+ * const count = await client.updateAllJobs({
289
+ * where: { queue: "emails", status: "dead" },
290
+ * apply: { priority: 1000 },
291
+ * });
292
+ * ```
293
+ */
294
+ export interface UpdateAllJobsOptions {
295
+ /** Filter selecting which jobs to update. */
296
+ where?: JobFilter;
297
+ /** Fields to update on the matching jobs. */
298
+ apply: UpdateJobOptions;
299
+ }
300
+ /**
301
+ * Filter for selecting jobs in bulk operations.
302
+ *
303
+ * Used by `deleteAllJobs` and `updateAllJobs` to scope which jobs are
304
+ * affected. An empty filter selects all jobs.
305
+ *
306
+ * Multi-value fields accept either a single value or an array.
307
+ */
308
+ export interface JobFilter {
309
+ /** Filter by job ID. Accepts a single value or an array. */
310
+ id?: string | string[];
311
+ /** Filter by status. Accepts a single value or an array. */
312
+ status?: JobStatus | JobStatus[];
313
+ /** Filter by queue name. Accepts a single value or an array. */
314
+ queue?: string | string[];
315
+ /** Filter by job type. Accepts a single value or an array. */
316
+ type?: string | string[];
317
+ /** jq expression to filter jobs by payload. */
318
+ filter?: string;
319
+ }
320
+ /**
321
+ * Options for bulk-deleting jobs.
322
+ *
323
+ * An empty `where` filter deletes all jobs.
324
+ *
325
+ * @example
326
+ * ```ts
327
+ * // Delete all dead jobs in the emails queue
328
+ * const count = await client.deleteAllJobs({
329
+ * where: { queue: "emails", status: "dead" },
330
+ * });
331
+ * ```
332
+ */
333
+ export interface DeleteAllJobsOptions {
334
+ /** Filter selecting which jobs to delete. */
335
+ where?: JobFilter;
336
+ }
337
+ /** Response shape for `GET /health`. */
338
+ interface HealthResponse {
339
+ status: string;
340
+ }
341
+ /**
342
+ * TLS configuration for connecting to the Zizq server over HTTPS.
343
+ *
344
+ * Values are PEM-encoded strings or Buffers. If loading from files,
345
+ * use `fs.readFileSync()`.
346
+ *
347
+ * @example
348
+ * ```ts
349
+ * import fs from "node:fs";
350
+ *
351
+ * const client = new Client({
352
+ * url: "https://localhost:7890",
353
+ * tls: {
354
+ * ca: fs.readFileSync("/path/to/ca.pem"),
355
+ * cert: fs.readFileSync("/path/to/client.pem"),
356
+ * key: fs.readFileSync("/path/to/client-key.pem"),
357
+ * },
358
+ * });
359
+ * ```
360
+ */
361
+ export interface TlsOptions {
362
+ /** PEM-encoded CA certificate(s) for verifying the server. */
363
+ ca?: string | Buffer;
364
+ /** PEM-encoded client certificate for mTLS. Must be paired with `key`. */
365
+ cert?: string | Buffer;
366
+ /** PEM-encoded client private key for mTLS. Must be paired with `cert`. */
367
+ key?: string | Buffer;
368
+ }
369
+ /** Serialization format for client-server communication. */
370
+ export type Format = "json" | "msgpack";
371
+ /** Options for constructing a {@link Client}. */
372
+ export interface ClientOptions {
373
+ /** Base URL of the Zizq server, e.g. "http://localhost:7890". */
374
+ url: string;
375
+ /**
376
+ * Serialization format for request and response bodies.
377
+ *
378
+ * Default: "json".
379
+ */
380
+ format?: Format;
381
+ /** TLS configuration for HTTPS connections. */
382
+ tls?: TlsOptions;
383
+ /** @internal For testing — override the HTTP dispatcher. */
384
+ dispatcher?: Dispatcher;
385
+ }
386
+ /** Base error class for all Zizq errors. */
387
+ export declare class ZizqError extends Error {
388
+ constructor(message: string);
389
+ }
390
+ /**
391
+ * Network-level failure (connection refused, DNS, timeout, etc.).
392
+ *
393
+ * These are always transient and safe to retry.
394
+ */
395
+ export declare class ConnectionError extends ZizqError {
396
+ constructor(message: string);
397
+ }
398
+ /**
399
+ * HTTP error — the server returned a non-success status code.
400
+ *
401
+ * Carries the HTTP status code and (when available) the parsed response
402
+ * body, which typically contains an `error` field with a human-readable
403
+ * message from the server.
404
+ */
405
+ export declare class ResponseError extends ZizqError {
406
+ /** HTTP status code from the server. */
407
+ status: number;
408
+ /** Parsed response body, if available. */
409
+ body?: unknown;
410
+ constructor(message: string, status: number, body?: unknown);
411
+ }
412
+ /** 4xx client error — the request was invalid. Not retryable. */
413
+ export declare class ClientError extends ResponseError {
414
+ constructor(message: string, status: number, body?: unknown);
415
+ }
416
+ /** 404 specifically — job not found, etc. */
417
+ export declare class NotFoundError extends ClientError {
418
+ constructor(message: string, body?: unknown);
419
+ }
420
+ /** 5xx server error — something went wrong on the server. Retryable. */
421
+ export declare class ServerError extends ResponseError {
422
+ constructor(message: string, status: number, body?: unknown);
423
+ }
424
+ /**
425
+ * Low-level HTTP client for the Zizq job queue server.
426
+ *
427
+ * Maintains a persistent connection (HTTP/2 when available) for efficient
428
+ * request multiplexing. All methods map directly to server API endpoints.
429
+ *
430
+ * Call {@link close} when done to wait for in-flight requests to complete and
431
+ * release the underlying connection.
432
+ *
433
+ * @example
434
+ * ```ts
435
+ * const client = new Client({ url: "http://localhost:7890" });
436
+ *
437
+ * const job = await client.enqueue({
438
+ * type: "send_email",
439
+ * queue: "emails",
440
+ * payload: { to: "user@example.com" },
441
+ * });
442
+ *
443
+ * await client.close();
444
+ * ```
445
+ */
446
+ export declare class Client {
447
+ /** Pool for request/response traffic (enqueue, ack, failure, get). */
448
+ private http;
449
+ /** Separate pool for long-lived streaming connections (take). */
450
+ private streamHttp;
451
+ /** The base URL of the Zizq server. */
452
+ readonly url: string;
453
+ /** Serialization format. */
454
+ private format;
455
+ /** Content-type for requests. */
456
+ private contentType;
457
+ /** Accept header for request/response endpoints. */
458
+ private accept;
459
+ /** Accept header for the streaming take endpoint. */
460
+ private streamAccept;
461
+ constructor(options: ClientOptions);
462
+ /**
463
+ * Enqueue a single job.
464
+ *
465
+ * @returns The created job, including its server-assigned `id` and `status`.
466
+ * @throws {ZizqError} If the server rejects the request (e.g. invalid queue name).
467
+ *
468
+ * @example
469
+ * ```ts
470
+ * const job = await client.enqueue({
471
+ * type: "send_email",
472
+ * queue: "emails",
473
+ * payload: { to: "user@example.com" },
474
+ * });
475
+ * ```
476
+ */
477
+ enqueue(options: EnqueueOptions): Promise<Job>;
478
+ /**
479
+ * Enqueue multiple jobs in a single request.
480
+ *
481
+ * @returns An array of created jobs in the same order as the input.
482
+ *
483
+ * @example
484
+ * ```ts
485
+ * const jobs = await client.enqueueBulk([
486
+ * { type: "send_email", queue: "emails", payload: { to: "a@b.com" } },
487
+ * { type: "send_email", queue: "emails", payload: { to: "c@d.com" } },
488
+ * ]);
489
+ * ```
490
+ */
491
+ enqueueBulk(jobs: EnqueueOptions[]): Promise<Job[]>;
492
+ /**
493
+ * Acknowledge a job as successfully completed.
494
+ *
495
+ * @param id - The job ID to acknowledge.
496
+ * @throws {ZizqError} If the job is not found or not in-flight.
497
+ */
498
+ reportSuccess(id: string): Promise<void>;
499
+ /**
500
+ * Acknowledge multiple jobs as successfully completed in a single request.
501
+ *
502
+ * Jobs that have already been acknowledged or that don't exist are
503
+ * silently ignored (the server returns 422 but the client treats it
504
+ * as success).
505
+ *
506
+ * @param ids - Array of job IDs to acknowledge.
507
+ */
508
+ reportSuccessBulk(ids: string[]): Promise<void>;
509
+ /**
510
+ * Report a job as failed.
511
+ *
512
+ * The server will either reschedule the job with backoff or move it to
513
+ * the dead list if the retry limit has been exceeded.
514
+ *
515
+ * @param id - The job ID to report failure for.
516
+ * @param options - Error details (message, stack trace, etc.).
517
+ * @returns The updated job with its new status and attempt count.
518
+ */
519
+ reportFailure(id: string, options: FailureOptions): Promise<Job>;
520
+ /**
521
+ * Fetch a single job by ID.
522
+ *
523
+ * @param id - The job ID to fetch.
524
+ * @returns The full job data including payload.
525
+ * @throws {ZizqError} If the job is not found (404).
526
+ */
527
+ getJob(id: string): Promise<Job>;
528
+ /**
529
+ * Delete a single job by ID.
530
+ *
531
+ * @param id - The job ID to delete.
532
+ * @throws {NotFoundError} If the job is not found.
533
+ */
534
+ deleteJob(id: string): Promise<void>;
535
+ /**
536
+ * Delete jobs matching the given filters.
537
+ *
538
+ * An empty options object deletes all jobs.
539
+ *
540
+ * @returns The number of deleted jobs.
541
+ *
542
+ * @example
543
+ * ```ts
544
+ * const count = await client.deleteAllJobs({ queue: "emails", status: "dead" });
545
+ * ```
546
+ */
547
+ deleteAllJobs(options?: DeleteAllJobsOptions): Promise<number>;
548
+ /**
549
+ * Update a single job's mutable fields.
550
+ *
551
+ * Field semantics:
552
+ * - **omitted or `undefined`** — leave unchanged
553
+ * - **`null`** — clear the field (only valid for nullable fields)
554
+ * - **a value** — update to that value
555
+ *
556
+ * @param id - The job ID to update.
557
+ * @param options - Fields to update.
558
+ * @returns The updated job.
559
+ * @throws {NotFoundError} If the job is not found.
560
+ *
561
+ * @example
562
+ * ```ts
563
+ * // Change priority and clear the retry limit
564
+ * await client.updateJob("job-id", {
565
+ * priority: 100,
566
+ * retryLimit: null,
567
+ * });
568
+ * ```
569
+ */
570
+ updateJob(id: string, options: UpdateJobOptions): Promise<Job>;
571
+ /**
572
+ * Bulk update jobs matching a filter.
573
+ *
574
+ * @returns The number of updated jobs.
575
+ *
576
+ * @example
577
+ * ```ts
578
+ * const count = await client.updateAllJobs({
579
+ * where: { queue: "emails", status: "ready" },
580
+ * apply: { priority: 1000 },
581
+ * });
582
+ * ```
583
+ */
584
+ updateAllJobs(options: UpdateAllJobsOptions): Promise<number>;
585
+ /**
586
+ * List jobs with cursor-based pagination.
587
+ *
588
+ * Returns a single page of jobs. Use `page.nextPage()` and
589
+ * `page.prevPage()` to navigate between pages.
590
+ *
591
+ * @example
592
+ * ```ts
593
+ * const page = await client.listJobs({ queue: ["emails"], limit: 10 });
594
+ * for (const job of page.jobs) {
595
+ * console.log(job.id, job.status);
596
+ * }
597
+ * if (page.hasNext) {
598
+ * const next = await page.nextPage();
599
+ * }
600
+ * ```
601
+ */
602
+ listJobs(options?: ListJobsOptions): Promise<JobPage>;
603
+ /**
604
+ * Fetch a page of jobs by a raw path (used internally for pagination links).
605
+ *
606
+ * @internal
607
+ */
608
+ listJobsByPath(path: string): Promise<JobPage>;
609
+ /**
610
+ * Health check.
611
+ *
612
+ * @returns The parsed response body, e.g. `{ status: "ok" }`.
613
+ */
614
+ health(): Promise<HealthResponse>;
615
+ /**
616
+ * Server version.
617
+ *
618
+ * @returns The server's version string.
619
+ */
620
+ serverVersion(): Promise<string>;
621
+ /**
622
+ * Start a composable, lazy query over jobs.
623
+ *
624
+ * Returns a {@link JobQuery} that can be chained with filter and
625
+ * ordering methods, then iterated or used with terminal methods like
626
+ * `first()`, `toArray()`, `updateAll()`, and `deleteAll()`.
627
+ *
628
+ * No HTTP request is made until the query is consumed.
629
+ *
630
+ * Accepts an optional {@link JobQueryOptions} to seed the query's initial
631
+ * filter, order, limit, and page size — handy as a shorthand for
632
+ * `client.jobs().byQueue(...).limit(...)` etc.
633
+ *
634
+ * @example
635
+ * ```ts
636
+ * const dead = await client.jobs()
637
+ * .byQueue("emails")
638
+ * .byStatus("dead")
639
+ * .toArray();
640
+ *
641
+ * // Shorthand with seeded options
642
+ * const ready = await client.jobs({ queue: "emails", status: "ready" }).toArray();
643
+ *
644
+ * for await (const job of client.jobs().byStatus("ready")) {
645
+ * console.log(job.id);
646
+ * }
647
+ * ```
648
+ */
649
+ jobs(options?: JobQueryOptions): JobQuery;
650
+ /**
651
+ * List all distinct queue names on the server.
652
+ *
653
+ * @returns An array of queue name strings, sorted alphabetically.
654
+ */
655
+ queues(): Promise<string[]>;
656
+ /**
657
+ * List error records for a job with cursor-based pagination.
658
+ *
659
+ * @param id - The job ID to list errors for.
660
+ * @param options - Pagination and ordering options.
661
+ *
662
+ * @example
663
+ * ```ts
664
+ * const page = await client.listErrors("job-id", { order: "desc" });
665
+ * for (const error of page) {
666
+ * console.log(`Attempt ${error.attempt}: ${error.message}`);
667
+ * }
668
+ * ```
669
+ */
670
+ listErrors(id: string, options?: ListErrorsOptions): Promise<ErrorPage>;
671
+ /**
672
+ * Fetch a page of errors by a raw path (used internally for pagination links).
673
+ *
674
+ * @internal
675
+ */
676
+ listErrorsByPath(path: string): Promise<ErrorPage>;
677
+ /**
678
+ * Fetch a single error record for a job by attempt number.
679
+ *
680
+ * @param id - The job ID.
681
+ * @param attempt - The attempt number (1-based).
682
+ * @returns The error record for that attempt.
683
+ * @throws {NotFoundError} If the job or attempt is not found.
684
+ */
685
+ getError(id: string, attempt: number): Promise<ErrorRecord>;
686
+ /**
687
+ * Connect to the streaming take endpoint and return an async generator
688
+ * of jobs.
689
+ *
690
+ * The returned promise resolves once the HTTP connection is established.
691
+ * The async generator then yields jobs as they arrive. Heartbeats in
692
+ * the stream are silently skipped.
693
+ *
694
+ * The generator completes when the server closes the connection. The
695
+ * caller may also break out of the loop explicitly to end the stream,
696
+ * or provide an AbortSignal to explicitly signal cancellation.
697
+ *
698
+ * @example
699
+ * ```ts
700
+ * for await (const job of await client.take({ prefetch: 5, queues: ["emails"] })) {
701
+ * await processJob(job.payload);
702
+ * await client.reportSuccess(job.id);
703
+ * }
704
+ * ```
705
+ */
706
+ take(options?: TakeOptions): Promise<AsyncGenerator<Job>>;
707
+ /** Parse an NDJSON stream, yielding jobs. Empty lines are heartbeats. */
708
+ private iterateNdjson;
709
+ /**
710
+ * Parse a length-prefixed MessagePack stream, yielding jobs.
711
+ *
712
+ * Frame format: [4-byte big-endian length][MessagePack payload].
713
+ * A zero-length frame is a heartbeat and is silently skipped.
714
+ */
715
+ private iterateMsgpackStream;
716
+ /** Wrap raw API data as a Job instance. */
717
+ private wrapJob;
718
+ /** Wrap raw API data as an ErrorRecord instance. */
719
+ private wrapError;
720
+ /**
721
+ * Gracefully close the underlying HTTP connection.
722
+ *
723
+ * Waits for in-flight requests to complete. If a streaming `take()`
724
+ * connection is open, this will block until it ends — use
725
+ * {@link destroy} for hard immediate shutdown.
726
+ */
727
+ close(): Promise<void>;
728
+ /**
729
+ * Forcefully destroy the underlying HTTP connection.
730
+ *
731
+ * Immediately terminates all in-flight requests including any open
732
+ * `take()` stream. Use this when `close()` would block (e.g. after
733
+ * an unclean interruption in the REPL).
734
+ */
735
+ destroy(): Promise<void>;
736
+ private request;
737
+ private post;
738
+ private patch;
739
+ private requestWithBody;
740
+ /** Encode a value in the configured format. */
741
+ private encode;
742
+ private handleResponse;
743
+ private throwOnError;
744
+ /** Read and decode a response body, using the content-type header to
745
+ * pick the correct decoder rather than assuming the requested format. */
746
+ private readBody;
747
+ }