runlater-js 0.10.0 → 0.12.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 +58 -2
- package/dist/index.d.mts +125 -27
- package/dist/index.d.ts +125 -27
- package/dist/index.js +149 -22
- package/dist/index.mjs +149 -22
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# runlater-js
|
|
2
2
|
|
|
3
|
-
Official Node.js SDK for [Runlater](https://runlater.eu) — delayed tasks, cron jobs, and reliable webhooks for any Node.js app. No Redis. No infrastructure. Just HTTP.
|
|
3
|
+
Official Node.js SDK for [Runlater](https://runlater.eu) — delayed tasks, cron jobs, message queues, and reliable webhooks for any Node.js app. No Redis. No infrastructure. Just HTTP.
|
|
4
4
|
|
|
5
5
|
[Documentation](https://runlater.eu/docs) | [Dashboard](https://runlater.eu) | [npm](https://www.npmjs.com/package/runlater-js)
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ const result = await rl.send("https://myapp.com/api/webhook", {
|
|
|
63
63
|
body: { key: "value" }, // automatically JSON-serialized
|
|
64
64
|
retries: 5, // default: server default
|
|
65
65
|
timeout: 30000, // ms, default: 30000
|
|
66
|
-
|
|
66
|
+
lane: "emails", // optional: serialize execution within a lane
|
|
67
67
|
callback: "https://myapp.com/api/on-complete", // optional: receive result
|
|
68
68
|
})
|
|
69
69
|
// => { task_id, execution_id, status, scheduled_for }
|
|
@@ -129,6 +129,62 @@ const executions = await rl.tasks.executions("task-id")
|
|
|
129
129
|
await rl.tasks.delete("task-id")
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
+
### Message queues
|
|
133
|
+
|
|
134
|
+
Produce and consume messages with at-least-once delivery, visibility timeout, and dead-letter support.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
// Create a queue
|
|
138
|
+
const queue = await rl.queues.create({
|
|
139
|
+
name: "order-events",
|
|
140
|
+
visibility_timeout_seconds: 30,
|
|
141
|
+
max_receives: 5,
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// Enqueue a message
|
|
145
|
+
await rl.queues.enqueue("order-events", { orderId: 123, action: "process" })
|
|
146
|
+
|
|
147
|
+
// Enqueue multiple messages
|
|
148
|
+
await rl.queues.enqueueBatch("order-events", [
|
|
149
|
+
{ orderId: 124, action: "process" },
|
|
150
|
+
{ orderId: 125, action: "process" },
|
|
151
|
+
])
|
|
152
|
+
|
|
153
|
+
// Receive messages (long-polling supported)
|
|
154
|
+
const messages = await rl.queues.receive("order-events", { max: 5, wait: 10 })
|
|
155
|
+
|
|
156
|
+
for (const msg of messages) {
|
|
157
|
+
// Process the message...
|
|
158
|
+
console.log(msg.body)
|
|
159
|
+
|
|
160
|
+
// Acknowledge when done
|
|
161
|
+
await rl.queues.ack("order-events", msg.receipt_handle)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Nack a message to release it back to the queue
|
|
165
|
+
await rl.queues.nack("order-events", msg.receipt_handle)
|
|
166
|
+
|
|
167
|
+
// Batch acknowledge
|
|
168
|
+
await rl.queues.ackBatch("order-events", ["receipt_1", "receipt_2"])
|
|
169
|
+
|
|
170
|
+
// Get queue stats
|
|
171
|
+
const stats = await rl.queues.stats("order-events")
|
|
172
|
+
// => { available, locked, completed, dead, total, avg_time_in_queue_seconds, avg_processing_time_seconds }
|
|
173
|
+
|
|
174
|
+
// List all queues
|
|
175
|
+
const queues = await rl.queues.list()
|
|
176
|
+
|
|
177
|
+
// Pause / resume
|
|
178
|
+
await rl.queues.pause("order-events")
|
|
179
|
+
await rl.queues.resume("order-events")
|
|
180
|
+
|
|
181
|
+
// Browse messages
|
|
182
|
+
const msgs = await rl.queues.messages("order-events", { status: "available", limit: 10 })
|
|
183
|
+
|
|
184
|
+
// Delete a queue
|
|
185
|
+
await rl.queues.delete("order-events")
|
|
186
|
+
```
|
|
187
|
+
|
|
132
188
|
### Monitors (dead man's switch)
|
|
133
189
|
|
|
134
190
|
```js
|
package/dist/index.d.mts
CHANGED
|
@@ -8,7 +8,7 @@ interface SendOptions {
|
|
|
8
8
|
body?: unknown;
|
|
9
9
|
retries?: number;
|
|
10
10
|
timeout?: number;
|
|
11
|
-
|
|
11
|
+
lane?: string;
|
|
12
12
|
callback?: string;
|
|
13
13
|
idempotencyKey?: string;
|
|
14
14
|
on_failure_url?: string;
|
|
@@ -31,7 +31,7 @@ interface CronOptions {
|
|
|
31
31
|
body?: unknown;
|
|
32
32
|
timeout?: number;
|
|
33
33
|
retries?: number;
|
|
34
|
-
|
|
34
|
+
lane?: string;
|
|
35
35
|
callback?: string;
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
on_failure_url?: string;
|
|
@@ -126,7 +126,7 @@ interface Task {
|
|
|
126
126
|
timeout_ms: number;
|
|
127
127
|
retry_attempts: number;
|
|
128
128
|
callback_url: string | null;
|
|
129
|
-
|
|
129
|
+
lane: string | null;
|
|
130
130
|
notify_on_failure: boolean | null;
|
|
131
131
|
notify_on_recovery: boolean | null;
|
|
132
132
|
on_failure_url: string | null;
|
|
@@ -149,7 +149,7 @@ interface Execution {
|
|
|
149
149
|
script_logs: string[];
|
|
150
150
|
}
|
|
151
151
|
interface ListOptions {
|
|
152
|
-
|
|
152
|
+
lane?: string;
|
|
153
153
|
limit?: number;
|
|
154
154
|
offset?: number;
|
|
155
155
|
}
|
|
@@ -184,10 +184,16 @@ interface Monitor {
|
|
|
184
184
|
inserted_at: string;
|
|
185
185
|
updated_at: string;
|
|
186
186
|
}
|
|
187
|
-
interface
|
|
187
|
+
interface BatchTask {
|
|
188
188
|
url: string;
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
190
|
+
headers?: Record<string, string>;
|
|
191
|
+
body?: unknown;
|
|
192
|
+
name?: string;
|
|
193
|
+
}
|
|
194
|
+
interface BatchOptions {
|
|
195
|
+
lane: string;
|
|
196
|
+
tasks: BatchTask[];
|
|
191
197
|
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
192
198
|
headers?: Record<string, string>;
|
|
193
199
|
run_at?: string | Date;
|
|
@@ -197,11 +203,11 @@ interface BatchOptions {
|
|
|
197
203
|
callback?: string;
|
|
198
204
|
}
|
|
199
205
|
interface BatchResponse {
|
|
200
|
-
|
|
206
|
+
lane: string;
|
|
201
207
|
created: number;
|
|
202
208
|
scheduled_for: string;
|
|
203
209
|
}
|
|
204
|
-
interface
|
|
210
|
+
interface CancelLaneResponse {
|
|
205
211
|
cancelled: number;
|
|
206
212
|
}
|
|
207
213
|
interface UpdateTaskOptions {
|
|
@@ -215,7 +221,7 @@ interface UpdateTaskOptions {
|
|
|
215
221
|
timeout_ms?: number;
|
|
216
222
|
retry_attempts?: number;
|
|
217
223
|
callback_url?: string;
|
|
218
|
-
|
|
224
|
+
lane?: string;
|
|
219
225
|
enabled?: boolean;
|
|
220
226
|
notify_on_failure?: boolean | null;
|
|
221
227
|
notify_on_recovery?: boolean | null;
|
|
@@ -283,7 +289,7 @@ interface Endpoint {
|
|
|
283
289
|
enabled: boolean;
|
|
284
290
|
paused: boolean;
|
|
285
291
|
retry_attempts: number;
|
|
286
|
-
|
|
292
|
+
use_lane: boolean;
|
|
287
293
|
notify_on_failure: boolean | null;
|
|
288
294
|
notify_on_recovery: boolean | null;
|
|
289
295
|
on_failure_url: string | null;
|
|
@@ -300,7 +306,7 @@ interface CreateEndpointOptions {
|
|
|
300
306
|
name: string;
|
|
301
307
|
forward_urls: string[];
|
|
302
308
|
retry_attempts?: number;
|
|
303
|
-
|
|
309
|
+
use_lane?: boolean;
|
|
304
310
|
enabled?: boolean;
|
|
305
311
|
forward_headers?: Record<string, string>;
|
|
306
312
|
forward_body?: string;
|
|
@@ -312,7 +318,7 @@ interface UpdateEndpointOptions {
|
|
|
312
318
|
name?: string;
|
|
313
319
|
forward_urls?: string[];
|
|
314
320
|
retry_attempts?: number;
|
|
315
|
-
|
|
321
|
+
use_lane?: boolean;
|
|
316
322
|
enabled?: boolean;
|
|
317
323
|
forward_headers?: Record<string, string>;
|
|
318
324
|
forward_body?: string;
|
|
@@ -329,6 +335,59 @@ interface InboundEvent {
|
|
|
329
335
|
lua_rejected: boolean;
|
|
330
336
|
lua_logs: string[];
|
|
331
337
|
}
|
|
338
|
+
interface MessageQueue {
|
|
339
|
+
id: string;
|
|
340
|
+
name: string;
|
|
341
|
+
slug: string;
|
|
342
|
+
visibility_timeout_seconds: number;
|
|
343
|
+
max_receives: number;
|
|
344
|
+
paused: boolean;
|
|
345
|
+
inserted_at: string;
|
|
346
|
+
updated_at: string;
|
|
347
|
+
}
|
|
348
|
+
interface CreateMessageQueueOptions {
|
|
349
|
+
name: string;
|
|
350
|
+
visibility_timeout_seconds?: number;
|
|
351
|
+
max_receives?: number;
|
|
352
|
+
}
|
|
353
|
+
interface UpdateMessageQueueOptions {
|
|
354
|
+
name?: string;
|
|
355
|
+
visibility_timeout_seconds?: number;
|
|
356
|
+
max_receives?: number;
|
|
357
|
+
}
|
|
358
|
+
interface MqMessage {
|
|
359
|
+
id: string;
|
|
360
|
+
body: unknown;
|
|
361
|
+
status: string;
|
|
362
|
+
receipt_handle: string | null;
|
|
363
|
+
receive_count: number;
|
|
364
|
+
locked_until: string | null;
|
|
365
|
+
first_received_at: string | null;
|
|
366
|
+
completed_at: string | null;
|
|
367
|
+
inserted_at: string;
|
|
368
|
+
}
|
|
369
|
+
interface MqStats {
|
|
370
|
+
available: number;
|
|
371
|
+
locked: number;
|
|
372
|
+
completed: number;
|
|
373
|
+
dead: number;
|
|
374
|
+
total: number;
|
|
375
|
+
avg_time_in_queue_seconds: number | null;
|
|
376
|
+
avg_processing_time_seconds: number | null;
|
|
377
|
+
}
|
|
378
|
+
interface MqReceiveOptions {
|
|
379
|
+
max?: number;
|
|
380
|
+
wait?: number;
|
|
381
|
+
}
|
|
382
|
+
interface MqListMessagesOptions {
|
|
383
|
+
status?: string;
|
|
384
|
+
limit?: number;
|
|
385
|
+
offset?: number;
|
|
386
|
+
}
|
|
387
|
+
interface MqBatchAckResponse {
|
|
388
|
+
acknowledged: number;
|
|
389
|
+
failed: number;
|
|
390
|
+
}
|
|
332
391
|
declare class RunlaterError extends Error {
|
|
333
392
|
status: number;
|
|
334
393
|
code: string;
|
|
@@ -342,6 +401,7 @@ declare class Runlater {
|
|
|
342
401
|
monitors: Monitors;
|
|
343
402
|
endpoints: Endpoints;
|
|
344
403
|
schedules: Schedules;
|
|
404
|
+
queues: MessageQueues;
|
|
345
405
|
constructor(options: RunlaterOptions | string);
|
|
346
406
|
/**
|
|
347
407
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -423,36 +483,36 @@ declare class Tasks {
|
|
|
423
483
|
update(id: string, options: UpdateTaskOptions): Promise<Task>;
|
|
424
484
|
executions(id: string, limit?: number): Promise<Execution[]>;
|
|
425
485
|
/**
|
|
426
|
-
* Create many tasks at once
|
|
486
|
+
* Create many tasks at once. Each task defines its own URL and can
|
|
487
|
+
* optionally override method, headers, body, and name. Top-level
|
|
488
|
+
* settings serve as defaults.
|
|
427
489
|
*
|
|
428
|
-
*
|
|
429
|
-
* All tasks share the same URL, method, headers, timing, and queue.
|
|
430
|
-
* Use the queue name with `cancelQueue()` to cancel them as a group.
|
|
490
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
431
491
|
*
|
|
432
492
|
* ```js
|
|
433
493
|
* await rl.tasks.batch({
|
|
434
|
-
*
|
|
435
|
-
*
|
|
494
|
+
* lane: "march-newsletter",
|
|
495
|
+
* method: "POST",
|
|
436
496
|
* run_at: "2026-03-01T09:00:00Z",
|
|
437
|
-
*
|
|
438
|
-
* {
|
|
439
|
-
* {
|
|
497
|
+
* tasks: [
|
|
498
|
+
* { url: "https://myapp.com/api/send-email", body: { to: "alice@example.com" } },
|
|
499
|
+
* { url: "https://myapp.com/api/send-sms", body: { to: "+1234567890" } },
|
|
440
500
|
* ]
|
|
441
501
|
* })
|
|
442
502
|
* ```
|
|
443
503
|
*/
|
|
444
504
|
batch(options: BatchOptions): Promise<BatchResponse>;
|
|
445
505
|
/**
|
|
446
|
-
* Cancel all tasks in a
|
|
506
|
+
* Cancel all tasks in a lane.
|
|
447
507
|
*
|
|
448
|
-
* Soft-deletes every task in the
|
|
508
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
449
509
|
*
|
|
450
510
|
* ```js
|
|
451
|
-
* const { cancelled } = await rl.tasks.
|
|
511
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
452
512
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
453
513
|
* ```
|
|
454
514
|
*/
|
|
455
|
-
|
|
515
|
+
cancelLane(lane: string): Promise<CancelLaneResponse>;
|
|
456
516
|
}
|
|
457
517
|
declare class Schedules {
|
|
458
518
|
private client;
|
|
@@ -489,5 +549,43 @@ declare class Endpoints {
|
|
|
489
549
|
pause(id: string): Promise<Endpoint>;
|
|
490
550
|
resume(id: string): Promise<Endpoint>;
|
|
491
551
|
}
|
|
552
|
+
declare class MessageQueues {
|
|
553
|
+
private client;
|
|
554
|
+
constructor(client: Runlater);
|
|
555
|
+
/** List all message queues. */
|
|
556
|
+
list(): Promise<MessageQueue[]>;
|
|
557
|
+
/** Create a new message queue. */
|
|
558
|
+
create(options: CreateMessageQueueOptions): Promise<MessageQueue>;
|
|
559
|
+
/** Get a message queue by slug. */
|
|
560
|
+
get(slug: string): Promise<MessageQueue>;
|
|
561
|
+
/** Update a message queue. */
|
|
562
|
+
update(slug: string, options: UpdateMessageQueueOptions): Promise<MessageQueue>;
|
|
563
|
+
/** Delete a message queue. */
|
|
564
|
+
delete(slug: string): Promise<void>;
|
|
565
|
+
/** Get queue statistics. */
|
|
566
|
+
stats(slug: string): Promise<MqStats>;
|
|
567
|
+
/** Enqueue a single message. */
|
|
568
|
+
enqueue(slug: string, body: unknown): Promise<MqMessage>;
|
|
569
|
+
/** Enqueue multiple messages at once. */
|
|
570
|
+
enqueueBatch(slug: string, messages: unknown[]): Promise<{
|
|
571
|
+
enqueued: number;
|
|
572
|
+
}>;
|
|
573
|
+
/** Receive messages from the queue. */
|
|
574
|
+
receive(slug: string, options?: MqReceiveOptions): Promise<MqMessage[]>;
|
|
575
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
576
|
+
ack(slug: string, receiptHandle: string): Promise<void>;
|
|
577
|
+
/** Nack (release) a message back to the queue. */
|
|
578
|
+
nack(slug: string, receiptHandle: string): Promise<void>;
|
|
579
|
+
/** Acknowledge multiple messages at once. */
|
|
580
|
+
ackBatch(slug: string, receiptHandles: string[]): Promise<MqBatchAckResponse>;
|
|
581
|
+
/** List messages in the queue with optional filtering. */
|
|
582
|
+
messages(slug: string, options?: MqListMessagesOptions): Promise<MqMessage[]>;
|
|
583
|
+
/** Get a specific message by ID. */
|
|
584
|
+
getMessage(slug: string, id: string): Promise<MqMessage>;
|
|
585
|
+
/** Pause the queue. */
|
|
586
|
+
pause(slug: string): Promise<MessageQueue>;
|
|
587
|
+
/** Resume a paused queue. */
|
|
588
|
+
resume(slug: string): Promise<MessageQueue>;
|
|
589
|
+
}
|
|
492
590
|
|
|
493
|
-
export { type BatchOptions, type BatchResponse, type
|
|
591
|
+
export { type BatchOptions, type BatchResponse, type BatchTask, type CancelLaneResponse, type CreateEndpointOptions, type CreateMessageQueueOptions, type CreateMonitorOptions, type CreateScheduleOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type MessageQueue, type Monitor, type MqBatchAckResponse, type MqListMessagesOptions, type MqMessage, type MqReceiveOptions, type MqStats, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type Schedule, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMessageQueueOptions, type UpdateMonitorOptions, type UpdateScheduleOptions, type UpdateTaskOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ interface SendOptions {
|
|
|
8
8
|
body?: unknown;
|
|
9
9
|
retries?: number;
|
|
10
10
|
timeout?: number;
|
|
11
|
-
|
|
11
|
+
lane?: string;
|
|
12
12
|
callback?: string;
|
|
13
13
|
idempotencyKey?: string;
|
|
14
14
|
on_failure_url?: string;
|
|
@@ -31,7 +31,7 @@ interface CronOptions {
|
|
|
31
31
|
body?: unknown;
|
|
32
32
|
timeout?: number;
|
|
33
33
|
retries?: number;
|
|
34
|
-
|
|
34
|
+
lane?: string;
|
|
35
35
|
callback?: string;
|
|
36
36
|
enabled?: boolean;
|
|
37
37
|
on_failure_url?: string;
|
|
@@ -126,7 +126,7 @@ interface Task {
|
|
|
126
126
|
timeout_ms: number;
|
|
127
127
|
retry_attempts: number;
|
|
128
128
|
callback_url: string | null;
|
|
129
|
-
|
|
129
|
+
lane: string | null;
|
|
130
130
|
notify_on_failure: boolean | null;
|
|
131
131
|
notify_on_recovery: boolean | null;
|
|
132
132
|
on_failure_url: string | null;
|
|
@@ -149,7 +149,7 @@ interface Execution {
|
|
|
149
149
|
script_logs: string[];
|
|
150
150
|
}
|
|
151
151
|
interface ListOptions {
|
|
152
|
-
|
|
152
|
+
lane?: string;
|
|
153
153
|
limit?: number;
|
|
154
154
|
offset?: number;
|
|
155
155
|
}
|
|
@@ -184,10 +184,16 @@ interface Monitor {
|
|
|
184
184
|
inserted_at: string;
|
|
185
185
|
updated_at: string;
|
|
186
186
|
}
|
|
187
|
-
interface
|
|
187
|
+
interface BatchTask {
|
|
188
188
|
url: string;
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
190
|
+
headers?: Record<string, string>;
|
|
191
|
+
body?: unknown;
|
|
192
|
+
name?: string;
|
|
193
|
+
}
|
|
194
|
+
interface BatchOptions {
|
|
195
|
+
lane: string;
|
|
196
|
+
tasks: BatchTask[];
|
|
191
197
|
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
192
198
|
headers?: Record<string, string>;
|
|
193
199
|
run_at?: string | Date;
|
|
@@ -197,11 +203,11 @@ interface BatchOptions {
|
|
|
197
203
|
callback?: string;
|
|
198
204
|
}
|
|
199
205
|
interface BatchResponse {
|
|
200
|
-
|
|
206
|
+
lane: string;
|
|
201
207
|
created: number;
|
|
202
208
|
scheduled_for: string;
|
|
203
209
|
}
|
|
204
|
-
interface
|
|
210
|
+
interface CancelLaneResponse {
|
|
205
211
|
cancelled: number;
|
|
206
212
|
}
|
|
207
213
|
interface UpdateTaskOptions {
|
|
@@ -215,7 +221,7 @@ interface UpdateTaskOptions {
|
|
|
215
221
|
timeout_ms?: number;
|
|
216
222
|
retry_attempts?: number;
|
|
217
223
|
callback_url?: string;
|
|
218
|
-
|
|
224
|
+
lane?: string;
|
|
219
225
|
enabled?: boolean;
|
|
220
226
|
notify_on_failure?: boolean | null;
|
|
221
227
|
notify_on_recovery?: boolean | null;
|
|
@@ -283,7 +289,7 @@ interface Endpoint {
|
|
|
283
289
|
enabled: boolean;
|
|
284
290
|
paused: boolean;
|
|
285
291
|
retry_attempts: number;
|
|
286
|
-
|
|
292
|
+
use_lane: boolean;
|
|
287
293
|
notify_on_failure: boolean | null;
|
|
288
294
|
notify_on_recovery: boolean | null;
|
|
289
295
|
on_failure_url: string | null;
|
|
@@ -300,7 +306,7 @@ interface CreateEndpointOptions {
|
|
|
300
306
|
name: string;
|
|
301
307
|
forward_urls: string[];
|
|
302
308
|
retry_attempts?: number;
|
|
303
|
-
|
|
309
|
+
use_lane?: boolean;
|
|
304
310
|
enabled?: boolean;
|
|
305
311
|
forward_headers?: Record<string, string>;
|
|
306
312
|
forward_body?: string;
|
|
@@ -312,7 +318,7 @@ interface UpdateEndpointOptions {
|
|
|
312
318
|
name?: string;
|
|
313
319
|
forward_urls?: string[];
|
|
314
320
|
retry_attempts?: number;
|
|
315
|
-
|
|
321
|
+
use_lane?: boolean;
|
|
316
322
|
enabled?: boolean;
|
|
317
323
|
forward_headers?: Record<string, string>;
|
|
318
324
|
forward_body?: string;
|
|
@@ -329,6 +335,59 @@ interface InboundEvent {
|
|
|
329
335
|
lua_rejected: boolean;
|
|
330
336
|
lua_logs: string[];
|
|
331
337
|
}
|
|
338
|
+
interface MessageQueue {
|
|
339
|
+
id: string;
|
|
340
|
+
name: string;
|
|
341
|
+
slug: string;
|
|
342
|
+
visibility_timeout_seconds: number;
|
|
343
|
+
max_receives: number;
|
|
344
|
+
paused: boolean;
|
|
345
|
+
inserted_at: string;
|
|
346
|
+
updated_at: string;
|
|
347
|
+
}
|
|
348
|
+
interface CreateMessageQueueOptions {
|
|
349
|
+
name: string;
|
|
350
|
+
visibility_timeout_seconds?: number;
|
|
351
|
+
max_receives?: number;
|
|
352
|
+
}
|
|
353
|
+
interface UpdateMessageQueueOptions {
|
|
354
|
+
name?: string;
|
|
355
|
+
visibility_timeout_seconds?: number;
|
|
356
|
+
max_receives?: number;
|
|
357
|
+
}
|
|
358
|
+
interface MqMessage {
|
|
359
|
+
id: string;
|
|
360
|
+
body: unknown;
|
|
361
|
+
status: string;
|
|
362
|
+
receipt_handle: string | null;
|
|
363
|
+
receive_count: number;
|
|
364
|
+
locked_until: string | null;
|
|
365
|
+
first_received_at: string | null;
|
|
366
|
+
completed_at: string | null;
|
|
367
|
+
inserted_at: string;
|
|
368
|
+
}
|
|
369
|
+
interface MqStats {
|
|
370
|
+
available: number;
|
|
371
|
+
locked: number;
|
|
372
|
+
completed: number;
|
|
373
|
+
dead: number;
|
|
374
|
+
total: number;
|
|
375
|
+
avg_time_in_queue_seconds: number | null;
|
|
376
|
+
avg_processing_time_seconds: number | null;
|
|
377
|
+
}
|
|
378
|
+
interface MqReceiveOptions {
|
|
379
|
+
max?: number;
|
|
380
|
+
wait?: number;
|
|
381
|
+
}
|
|
382
|
+
interface MqListMessagesOptions {
|
|
383
|
+
status?: string;
|
|
384
|
+
limit?: number;
|
|
385
|
+
offset?: number;
|
|
386
|
+
}
|
|
387
|
+
interface MqBatchAckResponse {
|
|
388
|
+
acknowledged: number;
|
|
389
|
+
failed: number;
|
|
390
|
+
}
|
|
332
391
|
declare class RunlaterError extends Error {
|
|
333
392
|
status: number;
|
|
334
393
|
code: string;
|
|
@@ -342,6 +401,7 @@ declare class Runlater {
|
|
|
342
401
|
monitors: Monitors;
|
|
343
402
|
endpoints: Endpoints;
|
|
344
403
|
schedules: Schedules;
|
|
404
|
+
queues: MessageQueues;
|
|
345
405
|
constructor(options: RunlaterOptions | string);
|
|
346
406
|
/**
|
|
347
407
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -423,36 +483,36 @@ declare class Tasks {
|
|
|
423
483
|
update(id: string, options: UpdateTaskOptions): Promise<Task>;
|
|
424
484
|
executions(id: string, limit?: number): Promise<Execution[]>;
|
|
425
485
|
/**
|
|
426
|
-
* Create many tasks at once
|
|
486
|
+
* Create many tasks at once. Each task defines its own URL and can
|
|
487
|
+
* optionally override method, headers, body, and name. Top-level
|
|
488
|
+
* settings serve as defaults.
|
|
427
489
|
*
|
|
428
|
-
*
|
|
429
|
-
* All tasks share the same URL, method, headers, timing, and queue.
|
|
430
|
-
* Use the queue name with `cancelQueue()` to cancel them as a group.
|
|
490
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
431
491
|
*
|
|
432
492
|
* ```js
|
|
433
493
|
* await rl.tasks.batch({
|
|
434
|
-
*
|
|
435
|
-
*
|
|
494
|
+
* lane: "march-newsletter",
|
|
495
|
+
* method: "POST",
|
|
436
496
|
* run_at: "2026-03-01T09:00:00Z",
|
|
437
|
-
*
|
|
438
|
-
* {
|
|
439
|
-
* {
|
|
497
|
+
* tasks: [
|
|
498
|
+
* { url: "https://myapp.com/api/send-email", body: { to: "alice@example.com" } },
|
|
499
|
+
* { url: "https://myapp.com/api/send-sms", body: { to: "+1234567890" } },
|
|
440
500
|
* ]
|
|
441
501
|
* })
|
|
442
502
|
* ```
|
|
443
503
|
*/
|
|
444
504
|
batch(options: BatchOptions): Promise<BatchResponse>;
|
|
445
505
|
/**
|
|
446
|
-
* Cancel all tasks in a
|
|
506
|
+
* Cancel all tasks in a lane.
|
|
447
507
|
*
|
|
448
|
-
* Soft-deletes every task in the
|
|
508
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
449
509
|
*
|
|
450
510
|
* ```js
|
|
451
|
-
* const { cancelled } = await rl.tasks.
|
|
511
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
452
512
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
453
513
|
* ```
|
|
454
514
|
*/
|
|
455
|
-
|
|
515
|
+
cancelLane(lane: string): Promise<CancelLaneResponse>;
|
|
456
516
|
}
|
|
457
517
|
declare class Schedules {
|
|
458
518
|
private client;
|
|
@@ -489,5 +549,43 @@ declare class Endpoints {
|
|
|
489
549
|
pause(id: string): Promise<Endpoint>;
|
|
490
550
|
resume(id: string): Promise<Endpoint>;
|
|
491
551
|
}
|
|
552
|
+
declare class MessageQueues {
|
|
553
|
+
private client;
|
|
554
|
+
constructor(client: Runlater);
|
|
555
|
+
/** List all message queues. */
|
|
556
|
+
list(): Promise<MessageQueue[]>;
|
|
557
|
+
/** Create a new message queue. */
|
|
558
|
+
create(options: CreateMessageQueueOptions): Promise<MessageQueue>;
|
|
559
|
+
/** Get a message queue by slug. */
|
|
560
|
+
get(slug: string): Promise<MessageQueue>;
|
|
561
|
+
/** Update a message queue. */
|
|
562
|
+
update(slug: string, options: UpdateMessageQueueOptions): Promise<MessageQueue>;
|
|
563
|
+
/** Delete a message queue. */
|
|
564
|
+
delete(slug: string): Promise<void>;
|
|
565
|
+
/** Get queue statistics. */
|
|
566
|
+
stats(slug: string): Promise<MqStats>;
|
|
567
|
+
/** Enqueue a single message. */
|
|
568
|
+
enqueue(slug: string, body: unknown): Promise<MqMessage>;
|
|
569
|
+
/** Enqueue multiple messages at once. */
|
|
570
|
+
enqueueBatch(slug: string, messages: unknown[]): Promise<{
|
|
571
|
+
enqueued: number;
|
|
572
|
+
}>;
|
|
573
|
+
/** Receive messages from the queue. */
|
|
574
|
+
receive(slug: string, options?: MqReceiveOptions): Promise<MqMessage[]>;
|
|
575
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
576
|
+
ack(slug: string, receiptHandle: string): Promise<void>;
|
|
577
|
+
/** Nack (release) a message back to the queue. */
|
|
578
|
+
nack(slug: string, receiptHandle: string): Promise<void>;
|
|
579
|
+
/** Acknowledge multiple messages at once. */
|
|
580
|
+
ackBatch(slug: string, receiptHandles: string[]): Promise<MqBatchAckResponse>;
|
|
581
|
+
/** List messages in the queue with optional filtering. */
|
|
582
|
+
messages(slug: string, options?: MqListMessagesOptions): Promise<MqMessage[]>;
|
|
583
|
+
/** Get a specific message by ID. */
|
|
584
|
+
getMessage(slug: string, id: string): Promise<MqMessage>;
|
|
585
|
+
/** Pause the queue. */
|
|
586
|
+
pause(slug: string): Promise<MessageQueue>;
|
|
587
|
+
/** Resume a paused queue. */
|
|
588
|
+
resume(slug: string): Promise<MessageQueue>;
|
|
589
|
+
}
|
|
492
590
|
|
|
493
|
-
export { type BatchOptions, type BatchResponse, type
|
|
591
|
+
export { type BatchOptions, type BatchResponse, type BatchTask, type CancelLaneResponse, type CreateEndpointOptions, type CreateMessageQueueOptions, type CreateMonitorOptions, type CreateScheduleOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type MessageQueue, type Monitor, type MqBatchAckResponse, type MqListMessagesOptions, type MqMessage, type MqReceiveOptions, type MqStats, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type Schedule, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMessageQueueOptions, type UpdateMonitorOptions, type UpdateScheduleOptions, type UpdateTaskOptions };
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ var Runlater = class {
|
|
|
46
46
|
monitors;
|
|
47
47
|
endpoints;
|
|
48
48
|
schedules;
|
|
49
|
+
queues;
|
|
49
50
|
constructor(options) {
|
|
50
51
|
if (typeof options === "string") {
|
|
51
52
|
this.apiKey = options;
|
|
@@ -58,6 +59,7 @@ var Runlater = class {
|
|
|
58
59
|
this.monitors = new Monitors(this);
|
|
59
60
|
this.endpoints = new Endpoints(this);
|
|
60
61
|
this.schedules = new Schedules(this);
|
|
62
|
+
this.queues = new MessageQueues(this);
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
63
65
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -142,7 +144,7 @@ var Runlater = class {
|
|
|
142
144
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
143
145
|
timeout_ms: options.timeout,
|
|
144
146
|
retry_attempts: options.retries,
|
|
145
|
-
|
|
147
|
+
lane: options.lane,
|
|
146
148
|
callback_url: options.callback,
|
|
147
149
|
enabled: options.enabled,
|
|
148
150
|
script: options.script
|
|
@@ -175,7 +177,7 @@ var Runlater = class {
|
|
|
175
177
|
body: t.body != null ? JSON.stringify(t.body) : void 0,
|
|
176
178
|
timeout_ms: t.timeout,
|
|
177
179
|
retry_attempts: t.retries,
|
|
178
|
-
|
|
180
|
+
lane: t.lane,
|
|
179
181
|
callback_url: t.callback,
|
|
180
182
|
enabled: t.enabled,
|
|
181
183
|
script: t.script
|
|
@@ -210,7 +212,7 @@ var Runlater = class {
|
|
|
210
212
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
211
213
|
timeout_ms: options.timeout,
|
|
212
214
|
retry_attempts: options.retries,
|
|
213
|
-
|
|
215
|
+
lane: options.lane,
|
|
214
216
|
callback_url: options.callback,
|
|
215
217
|
script: options.script,
|
|
216
218
|
debounce: options.debounce != null ? formatDelay(options.debounce) : void 0,
|
|
@@ -222,7 +224,7 @@ var Runlater = class {
|
|
|
222
224
|
const headers = {
|
|
223
225
|
Authorization: `Bearer ${this.apiKey}`,
|
|
224
226
|
"Content-Type": "application/json",
|
|
225
|
-
"User-Agent": "runlater-js/0.
|
|
227
|
+
"User-Agent": "runlater-js/0.12.0"
|
|
226
228
|
};
|
|
227
229
|
if (options.idempotencyKey) {
|
|
228
230
|
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
@@ -253,7 +255,7 @@ var Tasks = class {
|
|
|
253
255
|
}
|
|
254
256
|
async list(options = {}) {
|
|
255
257
|
const params = new URLSearchParams();
|
|
256
|
-
if (options.
|
|
258
|
+
if (options.lane != null) params.set("lane", options.lane);
|
|
257
259
|
if (options.limit != null) params.set("limit", String(options.limit));
|
|
258
260
|
if (options.offset != null) params.set("offset", String(options.offset));
|
|
259
261
|
const query = params.toString();
|
|
@@ -287,29 +289,34 @@ var Tasks = class {
|
|
|
287
289
|
return res.data;
|
|
288
290
|
}
|
|
289
291
|
/**
|
|
290
|
-
* Create many tasks at once
|
|
292
|
+
* Create many tasks at once. Each task defines its own URL and can
|
|
293
|
+
* optionally override method, headers, body, and name. Top-level
|
|
294
|
+
* settings serve as defaults.
|
|
291
295
|
*
|
|
292
|
-
*
|
|
293
|
-
* All tasks share the same URL, method, headers, timing, and queue.
|
|
294
|
-
* Use the queue name with `cancelQueue()` to cancel them as a group.
|
|
296
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
295
297
|
*
|
|
296
298
|
* ```js
|
|
297
299
|
* await rl.tasks.batch({
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
+
* lane: "march-newsletter",
|
|
301
|
+
* method: "POST",
|
|
300
302
|
* run_at: "2026-03-01T09:00:00Z",
|
|
301
|
-
*
|
|
302
|
-
* {
|
|
303
|
-
* {
|
|
303
|
+
* tasks: [
|
|
304
|
+
* { url: "https://myapp.com/api/send-email", body: { to: "alice@example.com" } },
|
|
305
|
+
* { url: "https://myapp.com/api/send-sms", body: { to: "+1234567890" } },
|
|
304
306
|
* ]
|
|
305
307
|
* })
|
|
306
308
|
* ```
|
|
307
309
|
*/
|
|
308
310
|
async batch(options) {
|
|
309
311
|
const body = {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
312
|
+
lane: options.lane,
|
|
313
|
+
tasks: options.tasks.map((t) => ({
|
|
314
|
+
url: t.url,
|
|
315
|
+
method: t.method,
|
|
316
|
+
headers: t.headers,
|
|
317
|
+
body: t.body != null ? typeof t.body === "string" ? t.body : JSON.stringify(t.body) : void 0,
|
|
318
|
+
name: t.name
|
|
319
|
+
})),
|
|
313
320
|
method: options.method ?? "POST",
|
|
314
321
|
headers: options.headers,
|
|
315
322
|
timeout_ms: options.timeout,
|
|
@@ -328,19 +335,19 @@ var Tasks = class {
|
|
|
328
335
|
return res.data;
|
|
329
336
|
}
|
|
330
337
|
/**
|
|
331
|
-
* Cancel all tasks in a
|
|
338
|
+
* Cancel all tasks in a lane.
|
|
332
339
|
*
|
|
333
|
-
* Soft-deletes every task in the
|
|
340
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
334
341
|
*
|
|
335
342
|
* ```js
|
|
336
|
-
* const { cancelled } = await rl.tasks.
|
|
343
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
337
344
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
338
345
|
* ```
|
|
339
346
|
*/
|
|
340
|
-
async
|
|
347
|
+
async cancelLane(lane) {
|
|
341
348
|
const res = await this.client.request(
|
|
342
349
|
"DELETE",
|
|
343
|
-
`/tasks?
|
|
350
|
+
`/tasks?lane=${encodeURIComponent(lane)}`
|
|
344
351
|
);
|
|
345
352
|
return res.data;
|
|
346
353
|
}
|
|
@@ -499,6 +506,126 @@ var Endpoints = class {
|
|
|
499
506
|
return res.data;
|
|
500
507
|
}
|
|
501
508
|
};
|
|
509
|
+
var MessageQueues = class {
|
|
510
|
+
constructor(client) {
|
|
511
|
+
this.client = client;
|
|
512
|
+
}
|
|
513
|
+
/** List all message queues. */
|
|
514
|
+
async list() {
|
|
515
|
+
const res = await this.client.request("GET", "/mq");
|
|
516
|
+
return res.data;
|
|
517
|
+
}
|
|
518
|
+
/** Create a new message queue. */
|
|
519
|
+
async create(options) {
|
|
520
|
+
const res = await this.client.request("POST", "/mq", {
|
|
521
|
+
body: options
|
|
522
|
+
});
|
|
523
|
+
return res.data;
|
|
524
|
+
}
|
|
525
|
+
/** Get a message queue by slug. */
|
|
526
|
+
async get(slug) {
|
|
527
|
+
const res = await this.client.request("GET", `/mq/${slug}`);
|
|
528
|
+
return res.data;
|
|
529
|
+
}
|
|
530
|
+
/** Update a message queue. */
|
|
531
|
+
async update(slug, options) {
|
|
532
|
+
const res = await this.client.request("PATCH", `/mq/${slug}`, {
|
|
533
|
+
body: options
|
|
534
|
+
});
|
|
535
|
+
return res.data;
|
|
536
|
+
}
|
|
537
|
+
/** Delete a message queue. */
|
|
538
|
+
async delete(slug) {
|
|
539
|
+
await this.client.request("DELETE", `/mq/${slug}`);
|
|
540
|
+
}
|
|
541
|
+
/** Get queue statistics. */
|
|
542
|
+
async stats(slug) {
|
|
543
|
+
const res = await this.client.request("GET", `/mq/${slug}/stats`);
|
|
544
|
+
return res.data;
|
|
545
|
+
}
|
|
546
|
+
/** Enqueue a single message. */
|
|
547
|
+
async enqueue(slug, body) {
|
|
548
|
+
const res = await this.client.request("POST", `/mq/${slug}/messages`, {
|
|
549
|
+
body: { body }
|
|
550
|
+
});
|
|
551
|
+
return res.data;
|
|
552
|
+
}
|
|
553
|
+
/** Enqueue multiple messages at once. */
|
|
554
|
+
async enqueueBatch(slug, messages) {
|
|
555
|
+
const res = await this.client.request(
|
|
556
|
+
"POST",
|
|
557
|
+
`/mq/${slug}/messages/batch`,
|
|
558
|
+
{ body: { messages } }
|
|
559
|
+
);
|
|
560
|
+
return res.data;
|
|
561
|
+
}
|
|
562
|
+
/** Receive messages from the queue. */
|
|
563
|
+
async receive(slug, options = {}) {
|
|
564
|
+
const params = new URLSearchParams();
|
|
565
|
+
if (options.max != null) params.set("max", String(options.max));
|
|
566
|
+
if (options.wait != null) params.set("wait", String(options.wait));
|
|
567
|
+
const query = params.toString();
|
|
568
|
+
const res = await this.client.request(
|
|
569
|
+
"GET",
|
|
570
|
+
`/mq/${slug}/receive${query ? `?${query}` : ""}`
|
|
571
|
+
);
|
|
572
|
+
return res.data;
|
|
573
|
+
}
|
|
574
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
575
|
+
async ack(slug, receiptHandle) {
|
|
576
|
+
await this.client.request("DELETE", `/mq/${slug}/ack/${receiptHandle}`);
|
|
577
|
+
}
|
|
578
|
+
/** Nack (release) a message back to the queue. */
|
|
579
|
+
async nack(slug, receiptHandle) {
|
|
580
|
+
await this.client.request("POST", `/mq/${slug}/nack/${receiptHandle}`);
|
|
581
|
+
}
|
|
582
|
+
/** Acknowledge multiple messages at once. */
|
|
583
|
+
async ackBatch(slug, receiptHandles) {
|
|
584
|
+
const res = await this.client.request(
|
|
585
|
+
"POST",
|
|
586
|
+
`/mq/${slug}/ack/batch`,
|
|
587
|
+
{ body: { receipt_handles: receiptHandles } }
|
|
588
|
+
);
|
|
589
|
+
return res.data;
|
|
590
|
+
}
|
|
591
|
+
/** List messages in the queue with optional filtering. */
|
|
592
|
+
async messages(slug, options = {}) {
|
|
593
|
+
const params = new URLSearchParams();
|
|
594
|
+
if (options.status != null) params.set("status", options.status);
|
|
595
|
+
if (options.limit != null) params.set("limit", String(options.limit));
|
|
596
|
+
if (options.offset != null) params.set("offset", String(options.offset));
|
|
597
|
+
const query = params.toString();
|
|
598
|
+
const res = await this.client.request(
|
|
599
|
+
"GET",
|
|
600
|
+
`/mq/${slug}/messages${query ? `?${query}` : ""}`
|
|
601
|
+
);
|
|
602
|
+
return res.data;
|
|
603
|
+
}
|
|
604
|
+
/** Get a specific message by ID. */
|
|
605
|
+
async getMessage(slug, id) {
|
|
606
|
+
const res = await this.client.request(
|
|
607
|
+
"GET",
|
|
608
|
+
`/mq/${slug}/messages/${id}`
|
|
609
|
+
);
|
|
610
|
+
return res.data;
|
|
611
|
+
}
|
|
612
|
+
/** Pause the queue. */
|
|
613
|
+
async pause(slug) {
|
|
614
|
+
const res = await this.client.request(
|
|
615
|
+
"POST",
|
|
616
|
+
`/mq/${slug}/pause`
|
|
617
|
+
);
|
|
618
|
+
return res.data;
|
|
619
|
+
}
|
|
620
|
+
/** Resume a paused queue. */
|
|
621
|
+
async resume(slug) {
|
|
622
|
+
const res = await this.client.request(
|
|
623
|
+
"POST",
|
|
624
|
+
`/mq/${slug}/resume`
|
|
625
|
+
);
|
|
626
|
+
return res.data;
|
|
627
|
+
}
|
|
628
|
+
};
|
|
502
629
|
function formatDelay(delay) {
|
|
503
630
|
if (typeof delay === "number") return `${delay}s`;
|
|
504
631
|
return delay;
|
package/dist/index.mjs
CHANGED
|
@@ -19,6 +19,7 @@ var Runlater = class {
|
|
|
19
19
|
monitors;
|
|
20
20
|
endpoints;
|
|
21
21
|
schedules;
|
|
22
|
+
queues;
|
|
22
23
|
constructor(options) {
|
|
23
24
|
if (typeof options === "string") {
|
|
24
25
|
this.apiKey = options;
|
|
@@ -31,6 +32,7 @@ var Runlater = class {
|
|
|
31
32
|
this.monitors = new Monitors(this);
|
|
32
33
|
this.endpoints = new Endpoints(this);
|
|
33
34
|
this.schedules = new Schedules(this);
|
|
35
|
+
this.queues = new MessageQueues(this);
|
|
34
36
|
}
|
|
35
37
|
/**
|
|
36
38
|
* Send a request immediately with reliable delivery and retries.
|
|
@@ -115,7 +117,7 @@ var Runlater = class {
|
|
|
115
117
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
116
118
|
timeout_ms: options.timeout,
|
|
117
119
|
retry_attempts: options.retries,
|
|
118
|
-
|
|
120
|
+
lane: options.lane,
|
|
119
121
|
callback_url: options.callback,
|
|
120
122
|
enabled: options.enabled,
|
|
121
123
|
script: options.script
|
|
@@ -148,7 +150,7 @@ var Runlater = class {
|
|
|
148
150
|
body: t.body != null ? JSON.stringify(t.body) : void 0,
|
|
149
151
|
timeout_ms: t.timeout,
|
|
150
152
|
retry_attempts: t.retries,
|
|
151
|
-
|
|
153
|
+
lane: t.lane,
|
|
152
154
|
callback_url: t.callback,
|
|
153
155
|
enabled: t.enabled,
|
|
154
156
|
script: t.script
|
|
@@ -183,7 +185,7 @@ var Runlater = class {
|
|
|
183
185
|
body: options.body != null ? JSON.stringify(options.body) : void 0,
|
|
184
186
|
timeout_ms: options.timeout,
|
|
185
187
|
retry_attempts: options.retries,
|
|
186
|
-
|
|
188
|
+
lane: options.lane,
|
|
187
189
|
callback_url: options.callback,
|
|
188
190
|
script: options.script,
|
|
189
191
|
debounce: options.debounce != null ? formatDelay(options.debounce) : void 0,
|
|
@@ -195,7 +197,7 @@ var Runlater = class {
|
|
|
195
197
|
const headers = {
|
|
196
198
|
Authorization: `Bearer ${this.apiKey}`,
|
|
197
199
|
"Content-Type": "application/json",
|
|
198
|
-
"User-Agent": "runlater-js/0.
|
|
200
|
+
"User-Agent": "runlater-js/0.12.0"
|
|
199
201
|
};
|
|
200
202
|
if (options.idempotencyKey) {
|
|
201
203
|
headers["Idempotency-Key"] = options.idempotencyKey;
|
|
@@ -226,7 +228,7 @@ var Tasks = class {
|
|
|
226
228
|
}
|
|
227
229
|
async list(options = {}) {
|
|
228
230
|
const params = new URLSearchParams();
|
|
229
|
-
if (options.
|
|
231
|
+
if (options.lane != null) params.set("lane", options.lane);
|
|
230
232
|
if (options.limit != null) params.set("limit", String(options.limit));
|
|
231
233
|
if (options.offset != null) params.set("offset", String(options.offset));
|
|
232
234
|
const query = params.toString();
|
|
@@ -260,29 +262,34 @@ var Tasks = class {
|
|
|
260
262
|
return res.data;
|
|
261
263
|
}
|
|
262
264
|
/**
|
|
263
|
-
* Create many tasks at once
|
|
265
|
+
* Create many tasks at once. Each task defines its own URL and can
|
|
266
|
+
* optionally override method, headers, body, and name. Top-level
|
|
267
|
+
* settings serve as defaults.
|
|
264
268
|
*
|
|
265
|
-
*
|
|
266
|
-
* All tasks share the same URL, method, headers, timing, and queue.
|
|
267
|
-
* Use the queue name with `cancelQueue()` to cancel them as a group.
|
|
269
|
+
* Use the lane name with `cancelLane()` to cancel them as a group.
|
|
268
270
|
*
|
|
269
271
|
* ```js
|
|
270
272
|
* await rl.tasks.batch({
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
+
* lane: "march-newsletter",
|
|
274
|
+
* method: "POST",
|
|
273
275
|
* run_at: "2026-03-01T09:00:00Z",
|
|
274
|
-
*
|
|
275
|
-
* {
|
|
276
|
-
* {
|
|
276
|
+
* tasks: [
|
|
277
|
+
* { url: "https://myapp.com/api/send-email", body: { to: "alice@example.com" } },
|
|
278
|
+
* { url: "https://myapp.com/api/send-sms", body: { to: "+1234567890" } },
|
|
277
279
|
* ]
|
|
278
280
|
* })
|
|
279
281
|
* ```
|
|
280
282
|
*/
|
|
281
283
|
async batch(options) {
|
|
282
284
|
const body = {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
285
|
+
lane: options.lane,
|
|
286
|
+
tasks: options.tasks.map((t) => ({
|
|
287
|
+
url: t.url,
|
|
288
|
+
method: t.method,
|
|
289
|
+
headers: t.headers,
|
|
290
|
+
body: t.body != null ? typeof t.body === "string" ? t.body : JSON.stringify(t.body) : void 0,
|
|
291
|
+
name: t.name
|
|
292
|
+
})),
|
|
286
293
|
method: options.method ?? "POST",
|
|
287
294
|
headers: options.headers,
|
|
288
295
|
timeout_ms: options.timeout,
|
|
@@ -301,19 +308,19 @@ var Tasks = class {
|
|
|
301
308
|
return res.data;
|
|
302
309
|
}
|
|
303
310
|
/**
|
|
304
|
-
* Cancel all tasks in a
|
|
311
|
+
* Cancel all tasks in a lane.
|
|
305
312
|
*
|
|
306
|
-
* Soft-deletes every task in the
|
|
313
|
+
* Soft-deletes every task in the lane and removes their pending executions.
|
|
307
314
|
*
|
|
308
315
|
* ```js
|
|
309
|
-
* const { cancelled } = await rl.tasks.
|
|
316
|
+
* const { cancelled } = await rl.tasks.cancelLane("march-newsletter")
|
|
310
317
|
* console.log(`Cancelled ${cancelled} tasks`)
|
|
311
318
|
* ```
|
|
312
319
|
*/
|
|
313
|
-
async
|
|
320
|
+
async cancelLane(lane) {
|
|
314
321
|
const res = await this.client.request(
|
|
315
322
|
"DELETE",
|
|
316
|
-
`/tasks?
|
|
323
|
+
`/tasks?lane=${encodeURIComponent(lane)}`
|
|
317
324
|
);
|
|
318
325
|
return res.data;
|
|
319
326
|
}
|
|
@@ -472,6 +479,126 @@ var Endpoints = class {
|
|
|
472
479
|
return res.data;
|
|
473
480
|
}
|
|
474
481
|
};
|
|
482
|
+
var MessageQueues = class {
|
|
483
|
+
constructor(client) {
|
|
484
|
+
this.client = client;
|
|
485
|
+
}
|
|
486
|
+
/** List all message queues. */
|
|
487
|
+
async list() {
|
|
488
|
+
const res = await this.client.request("GET", "/mq");
|
|
489
|
+
return res.data;
|
|
490
|
+
}
|
|
491
|
+
/** Create a new message queue. */
|
|
492
|
+
async create(options) {
|
|
493
|
+
const res = await this.client.request("POST", "/mq", {
|
|
494
|
+
body: options
|
|
495
|
+
});
|
|
496
|
+
return res.data;
|
|
497
|
+
}
|
|
498
|
+
/** Get a message queue by slug. */
|
|
499
|
+
async get(slug) {
|
|
500
|
+
const res = await this.client.request("GET", `/mq/${slug}`);
|
|
501
|
+
return res.data;
|
|
502
|
+
}
|
|
503
|
+
/** Update a message queue. */
|
|
504
|
+
async update(slug, options) {
|
|
505
|
+
const res = await this.client.request("PATCH", `/mq/${slug}`, {
|
|
506
|
+
body: options
|
|
507
|
+
});
|
|
508
|
+
return res.data;
|
|
509
|
+
}
|
|
510
|
+
/** Delete a message queue. */
|
|
511
|
+
async delete(slug) {
|
|
512
|
+
await this.client.request("DELETE", `/mq/${slug}`);
|
|
513
|
+
}
|
|
514
|
+
/** Get queue statistics. */
|
|
515
|
+
async stats(slug) {
|
|
516
|
+
const res = await this.client.request("GET", `/mq/${slug}/stats`);
|
|
517
|
+
return res.data;
|
|
518
|
+
}
|
|
519
|
+
/** Enqueue a single message. */
|
|
520
|
+
async enqueue(slug, body) {
|
|
521
|
+
const res = await this.client.request("POST", `/mq/${slug}/messages`, {
|
|
522
|
+
body: { body }
|
|
523
|
+
});
|
|
524
|
+
return res.data;
|
|
525
|
+
}
|
|
526
|
+
/** Enqueue multiple messages at once. */
|
|
527
|
+
async enqueueBatch(slug, messages) {
|
|
528
|
+
const res = await this.client.request(
|
|
529
|
+
"POST",
|
|
530
|
+
`/mq/${slug}/messages/batch`,
|
|
531
|
+
{ body: { messages } }
|
|
532
|
+
);
|
|
533
|
+
return res.data;
|
|
534
|
+
}
|
|
535
|
+
/** Receive messages from the queue. */
|
|
536
|
+
async receive(slug, options = {}) {
|
|
537
|
+
const params = new URLSearchParams();
|
|
538
|
+
if (options.max != null) params.set("max", String(options.max));
|
|
539
|
+
if (options.wait != null) params.set("wait", String(options.wait));
|
|
540
|
+
const query = params.toString();
|
|
541
|
+
const res = await this.client.request(
|
|
542
|
+
"GET",
|
|
543
|
+
`/mq/${slug}/receive${query ? `?${query}` : ""}`
|
|
544
|
+
);
|
|
545
|
+
return res.data;
|
|
546
|
+
}
|
|
547
|
+
/** Acknowledge (complete) a message by receipt handle. */
|
|
548
|
+
async ack(slug, receiptHandle) {
|
|
549
|
+
await this.client.request("DELETE", `/mq/${slug}/ack/${receiptHandle}`);
|
|
550
|
+
}
|
|
551
|
+
/** Nack (release) a message back to the queue. */
|
|
552
|
+
async nack(slug, receiptHandle) {
|
|
553
|
+
await this.client.request("POST", `/mq/${slug}/nack/${receiptHandle}`);
|
|
554
|
+
}
|
|
555
|
+
/** Acknowledge multiple messages at once. */
|
|
556
|
+
async ackBatch(slug, receiptHandles) {
|
|
557
|
+
const res = await this.client.request(
|
|
558
|
+
"POST",
|
|
559
|
+
`/mq/${slug}/ack/batch`,
|
|
560
|
+
{ body: { receipt_handles: receiptHandles } }
|
|
561
|
+
);
|
|
562
|
+
return res.data;
|
|
563
|
+
}
|
|
564
|
+
/** List messages in the queue with optional filtering. */
|
|
565
|
+
async messages(slug, options = {}) {
|
|
566
|
+
const params = new URLSearchParams();
|
|
567
|
+
if (options.status != null) params.set("status", options.status);
|
|
568
|
+
if (options.limit != null) params.set("limit", String(options.limit));
|
|
569
|
+
if (options.offset != null) params.set("offset", String(options.offset));
|
|
570
|
+
const query = params.toString();
|
|
571
|
+
const res = await this.client.request(
|
|
572
|
+
"GET",
|
|
573
|
+
`/mq/${slug}/messages${query ? `?${query}` : ""}`
|
|
574
|
+
);
|
|
575
|
+
return res.data;
|
|
576
|
+
}
|
|
577
|
+
/** Get a specific message by ID. */
|
|
578
|
+
async getMessage(slug, id) {
|
|
579
|
+
const res = await this.client.request(
|
|
580
|
+
"GET",
|
|
581
|
+
`/mq/${slug}/messages/${id}`
|
|
582
|
+
);
|
|
583
|
+
return res.data;
|
|
584
|
+
}
|
|
585
|
+
/** Pause the queue. */
|
|
586
|
+
async pause(slug) {
|
|
587
|
+
const res = await this.client.request(
|
|
588
|
+
"POST",
|
|
589
|
+
`/mq/${slug}/pause`
|
|
590
|
+
);
|
|
591
|
+
return res.data;
|
|
592
|
+
}
|
|
593
|
+
/** Resume a paused queue. */
|
|
594
|
+
async resume(slug) {
|
|
595
|
+
const res = await this.client.request(
|
|
596
|
+
"POST",
|
|
597
|
+
`/mq/${slug}/resume`
|
|
598
|
+
);
|
|
599
|
+
return res.data;
|
|
600
|
+
}
|
|
601
|
+
};
|
|
475
602
|
function formatDelay(delay) {
|
|
476
603
|
if (typeof delay === "number") return `${delay}s`;
|
|
477
604
|
return delay;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "runlater-js",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Delayed tasks, cron jobs, and reliable webhooks. No infrastructure required.",
|
|
3
|
+
"version": "0.12.0",
|
|
4
|
+
"description": "Delayed tasks, cron jobs, message queues, and reliable webhooks. No infrastructure required.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|