runlater-js 0.3.0 → 0.5.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 CHANGED
@@ -151,6 +151,46 @@ const pings = await rl.monitors.pings("monitor-id", 20)
151
151
  await rl.monitors.ping("pm_your_token_here")
152
152
  ```
153
153
 
154
+ ### Endpoints (webhook gateway)
155
+
156
+ ```js
157
+ // Create an endpoint with Lua scripting
158
+ const endpoint = await rl.endpoints.create({
159
+ name: "Stripe webhooks",
160
+ forward_urls: ["https://myapp.com/webhooks/stripe"],
161
+ script: `
162
+ function verify(event, secrets)
163
+ local sig = event.headers["stripe-signature"]
164
+ if not sig then return false end
165
+ local ts, hash = sig:match("t=(%d+),v1=(%S+)")
166
+ if not ts or not hash then return false end
167
+ local expected = hmac_sha256(secrets.signing_key, ts .. "." .. event.body)
168
+ return expected == hash
169
+ end
170
+ `,
171
+ secrets: { signing_key: "whsec_..." },
172
+ })
173
+
174
+ console.log(endpoint.inbound_url) // Give this URL to Stripe
175
+
176
+ // List endpoints
177
+ const { data } = await rl.endpoints.list()
178
+
179
+ // Update script
180
+ await rl.endpoints.update("endpoint-id", {
181
+ script: "function filter(event) return true end",
182
+ })
183
+
184
+ // View events
185
+ const events = await rl.endpoints.events("endpoint-id")
186
+
187
+ // Replay an event
188
+ await rl.endpoints.replay("endpoint-id", "event-id")
189
+
190
+ // Delete
191
+ await rl.endpoints.delete("endpoint-id")
192
+ ```
193
+
154
194
  ### Declarative sync
155
195
 
156
196
  Push your task configuration from code. Matched by name.
package/dist/index.d.mts CHANGED
@@ -11,6 +11,8 @@ interface SendOptions {
11
11
  queue?: string;
12
12
  callback?: string;
13
13
  idempotencyKey?: string;
14
+ on_failure_url?: string;
15
+ on_recovery_url?: string;
14
16
  }
15
17
  interface DelayOptions extends SendOptions {
16
18
  delay: string | number;
@@ -29,6 +31,8 @@ interface CronOptions {
29
31
  queue?: string;
30
32
  callback?: string;
31
33
  enabled?: boolean;
34
+ on_failure_url?: string;
35
+ on_recovery_url?: string;
32
36
  }
33
37
  interface TaskResponse {
34
38
  task_id: string;
@@ -64,6 +68,8 @@ interface Task {
64
68
  queue: string | null;
65
69
  notify_on_failure: boolean | null;
66
70
  notify_on_recovery: boolean | null;
71
+ on_failure_url: string | null;
72
+ on_recovery_url: string | null;
67
73
  next_run_at: string | null;
68
74
  inserted_at: string;
69
75
  updated_at: string;
@@ -108,6 +114,8 @@ interface Monitor {
108
114
  enabled: boolean;
109
115
  notify_on_failure: boolean | null;
110
116
  notify_on_recovery: boolean | null;
117
+ on_failure_url: string | null;
118
+ on_recovery_url: string | null;
111
119
  last_ping_at: string | null;
112
120
  next_expected_at: string | null;
113
121
  inserted_at: string;
@@ -148,6 +156,8 @@ interface UpdateTaskOptions {
148
156
  enabled?: boolean;
149
157
  notify_on_failure?: boolean | null;
150
158
  notify_on_recovery?: boolean | null;
159
+ on_failure_url?: string;
160
+ on_recovery_url?: string;
151
161
  expected_status_codes?: string;
152
162
  expected_body_pattern?: string;
153
163
  }
@@ -157,6 +167,8 @@ interface CreateMonitorOptions {
157
167
  interval?: number;
158
168
  grace?: number;
159
169
  enabled?: boolean;
170
+ on_failure_url?: string;
171
+ on_recovery_url?: string;
160
172
  }
161
173
  interface UpdateMonitorOptions {
162
174
  name?: string;
@@ -167,6 +179,8 @@ interface UpdateMonitorOptions {
167
179
  enabled?: boolean;
168
180
  notify_on_failure?: boolean | null;
169
181
  notify_on_recovery?: boolean | null;
182
+ on_failure_url?: string;
183
+ on_recovery_url?: string;
170
184
  }
171
185
  interface Ping {
172
186
  id: string;
@@ -196,6 +210,60 @@ interface SyncResponse {
196
210
  updated_count: number;
197
211
  deleted_count: number;
198
212
  }
213
+ interface Endpoint {
214
+ id: string;
215
+ name: string;
216
+ slug: string;
217
+ inbound_url: string;
218
+ forward_urls: string[];
219
+ enabled: boolean;
220
+ retry_attempts: number;
221
+ use_queue: boolean;
222
+ notify_on_failure: boolean | null;
223
+ notify_on_recovery: boolean | null;
224
+ on_failure_url: string | null;
225
+ on_recovery_url: string | null;
226
+ forward_headers: Record<string, string> | null;
227
+ forward_body: string | null;
228
+ forward_method: string | null;
229
+ script: string | null;
230
+ secrets_keys: string[];
231
+ inserted_at: string;
232
+ updated_at: string;
233
+ }
234
+ interface CreateEndpointOptions {
235
+ name: string;
236
+ forward_urls: string[];
237
+ retry_attempts?: number;
238
+ use_queue?: boolean;
239
+ enabled?: boolean;
240
+ forward_headers?: Record<string, string>;
241
+ forward_body?: string;
242
+ forward_method?: string;
243
+ script?: string;
244
+ secrets?: Record<string, string>;
245
+ }
246
+ interface UpdateEndpointOptions {
247
+ name?: string;
248
+ forward_urls?: string[];
249
+ retry_attempts?: number;
250
+ use_queue?: boolean;
251
+ enabled?: boolean;
252
+ forward_headers?: Record<string, string>;
253
+ forward_body?: string;
254
+ forward_method?: string;
255
+ script?: string;
256
+ secrets?: Record<string, string>;
257
+ }
258
+ interface InboundEvent {
259
+ id: string;
260
+ method: string;
261
+ source_ip: string;
262
+ received_at: string;
263
+ task_ids: string[];
264
+ lua_rejected: boolean;
265
+ lua_logs: string[];
266
+ }
199
267
  declare class RunlaterError extends Error {
200
268
  status: number;
201
269
  code: string;
@@ -207,6 +275,7 @@ declare class Runlater {
207
275
  private baseUrl;
208
276
  tasks: Tasks;
209
277
  monitors: Monitors;
278
+ endpoints: Endpoints;
210
279
  constructor(options: RunlaterOptions | string);
211
280
  /**
212
281
  * Send a request immediately with reliable delivery and retries.
@@ -330,5 +399,16 @@ declare class Monitors {
330
399
  pings(id: string, limit?: number): Promise<Ping[]>;
331
400
  ping(token: string): Promise<PingResponse>;
332
401
  }
402
+ declare class Endpoints {
403
+ private client;
404
+ constructor(client: Runlater);
405
+ list(): Promise<ListResponse<Endpoint>>;
406
+ get(id: string): Promise<Endpoint>;
407
+ create(options: CreateEndpointOptions): Promise<Endpoint>;
408
+ update(id: string, options: UpdateEndpointOptions): Promise<Endpoint>;
409
+ delete(id: string): Promise<void>;
410
+ events(id: string, limit?: number): Promise<InboundEvent[]>;
411
+ replay(endpointId: string, eventId: string): Promise<void>;
412
+ }
333
413
 
334
- export { type BatchOptions, type BatchResponse, type CancelQueueResponse, type CreateMonitorOptions, type CronOptions, type CronResponse, type DelayOptions, type Execution, type ListOptions, type ListResponse, type Monitor, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateMonitorOptions, type UpdateTaskOptions };
414
+ export { type BatchOptions, type BatchResponse, type CancelQueueResponse, type CreateEndpointOptions, type CreateMonitorOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type Monitor, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMonitorOptions, type UpdateTaskOptions };
package/dist/index.d.ts CHANGED
@@ -11,6 +11,8 @@ interface SendOptions {
11
11
  queue?: string;
12
12
  callback?: string;
13
13
  idempotencyKey?: string;
14
+ on_failure_url?: string;
15
+ on_recovery_url?: string;
14
16
  }
15
17
  interface DelayOptions extends SendOptions {
16
18
  delay: string | number;
@@ -29,6 +31,8 @@ interface CronOptions {
29
31
  queue?: string;
30
32
  callback?: string;
31
33
  enabled?: boolean;
34
+ on_failure_url?: string;
35
+ on_recovery_url?: string;
32
36
  }
33
37
  interface TaskResponse {
34
38
  task_id: string;
@@ -64,6 +68,8 @@ interface Task {
64
68
  queue: string | null;
65
69
  notify_on_failure: boolean | null;
66
70
  notify_on_recovery: boolean | null;
71
+ on_failure_url: string | null;
72
+ on_recovery_url: string | null;
67
73
  next_run_at: string | null;
68
74
  inserted_at: string;
69
75
  updated_at: string;
@@ -108,6 +114,8 @@ interface Monitor {
108
114
  enabled: boolean;
109
115
  notify_on_failure: boolean | null;
110
116
  notify_on_recovery: boolean | null;
117
+ on_failure_url: string | null;
118
+ on_recovery_url: string | null;
111
119
  last_ping_at: string | null;
112
120
  next_expected_at: string | null;
113
121
  inserted_at: string;
@@ -148,6 +156,8 @@ interface UpdateTaskOptions {
148
156
  enabled?: boolean;
149
157
  notify_on_failure?: boolean | null;
150
158
  notify_on_recovery?: boolean | null;
159
+ on_failure_url?: string;
160
+ on_recovery_url?: string;
151
161
  expected_status_codes?: string;
152
162
  expected_body_pattern?: string;
153
163
  }
@@ -157,6 +167,8 @@ interface CreateMonitorOptions {
157
167
  interval?: number;
158
168
  grace?: number;
159
169
  enabled?: boolean;
170
+ on_failure_url?: string;
171
+ on_recovery_url?: string;
160
172
  }
161
173
  interface UpdateMonitorOptions {
162
174
  name?: string;
@@ -167,6 +179,8 @@ interface UpdateMonitorOptions {
167
179
  enabled?: boolean;
168
180
  notify_on_failure?: boolean | null;
169
181
  notify_on_recovery?: boolean | null;
182
+ on_failure_url?: string;
183
+ on_recovery_url?: string;
170
184
  }
171
185
  interface Ping {
172
186
  id: string;
@@ -196,6 +210,60 @@ interface SyncResponse {
196
210
  updated_count: number;
197
211
  deleted_count: number;
198
212
  }
213
+ interface Endpoint {
214
+ id: string;
215
+ name: string;
216
+ slug: string;
217
+ inbound_url: string;
218
+ forward_urls: string[];
219
+ enabled: boolean;
220
+ retry_attempts: number;
221
+ use_queue: boolean;
222
+ notify_on_failure: boolean | null;
223
+ notify_on_recovery: boolean | null;
224
+ on_failure_url: string | null;
225
+ on_recovery_url: string | null;
226
+ forward_headers: Record<string, string> | null;
227
+ forward_body: string | null;
228
+ forward_method: string | null;
229
+ script: string | null;
230
+ secrets_keys: string[];
231
+ inserted_at: string;
232
+ updated_at: string;
233
+ }
234
+ interface CreateEndpointOptions {
235
+ name: string;
236
+ forward_urls: string[];
237
+ retry_attempts?: number;
238
+ use_queue?: boolean;
239
+ enabled?: boolean;
240
+ forward_headers?: Record<string, string>;
241
+ forward_body?: string;
242
+ forward_method?: string;
243
+ script?: string;
244
+ secrets?: Record<string, string>;
245
+ }
246
+ interface UpdateEndpointOptions {
247
+ name?: string;
248
+ forward_urls?: string[];
249
+ retry_attempts?: number;
250
+ use_queue?: boolean;
251
+ enabled?: boolean;
252
+ forward_headers?: Record<string, string>;
253
+ forward_body?: string;
254
+ forward_method?: string;
255
+ script?: string;
256
+ secrets?: Record<string, string>;
257
+ }
258
+ interface InboundEvent {
259
+ id: string;
260
+ method: string;
261
+ source_ip: string;
262
+ received_at: string;
263
+ task_ids: string[];
264
+ lua_rejected: boolean;
265
+ lua_logs: string[];
266
+ }
199
267
  declare class RunlaterError extends Error {
200
268
  status: number;
201
269
  code: string;
@@ -207,6 +275,7 @@ declare class Runlater {
207
275
  private baseUrl;
208
276
  tasks: Tasks;
209
277
  monitors: Monitors;
278
+ endpoints: Endpoints;
210
279
  constructor(options: RunlaterOptions | string);
211
280
  /**
212
281
  * Send a request immediately with reliable delivery and retries.
@@ -330,5 +399,16 @@ declare class Monitors {
330
399
  pings(id: string, limit?: number): Promise<Ping[]>;
331
400
  ping(token: string): Promise<PingResponse>;
332
401
  }
402
+ declare class Endpoints {
403
+ private client;
404
+ constructor(client: Runlater);
405
+ list(): Promise<ListResponse<Endpoint>>;
406
+ get(id: string): Promise<Endpoint>;
407
+ create(options: CreateEndpointOptions): Promise<Endpoint>;
408
+ update(id: string, options: UpdateEndpointOptions): Promise<Endpoint>;
409
+ delete(id: string): Promise<void>;
410
+ events(id: string, limit?: number): Promise<InboundEvent[]>;
411
+ replay(endpointId: string, eventId: string): Promise<void>;
412
+ }
333
413
 
334
- export { type BatchOptions, type BatchResponse, type CancelQueueResponse, type CreateMonitorOptions, type CronOptions, type CronResponse, type DelayOptions, type Execution, type ListOptions, type ListResponse, type Monitor, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateMonitorOptions, type UpdateTaskOptions };
414
+ export { type BatchOptions, type BatchResponse, type CancelQueueResponse, type CreateEndpointOptions, type CreateMonitorOptions, type CronOptions, type CronResponse, type DelayOptions, type Endpoint, type Execution, type InboundEvent, type ListOptions, type ListResponse, type Monitor, type Ping, type PingResponse, Runlater, RunlaterError, type RunlaterOptions, type ScheduleOptions, type SendOptions, type SyncOptions, type SyncResponse, type Task, type TaskResponse, type TriggerResponse, type UpdateEndpointOptions, type UpdateMonitorOptions, type UpdateTaskOptions };
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ var Runlater = class {
44
44
  baseUrl;
45
45
  tasks;
46
46
  monitors;
47
+ endpoints;
47
48
  constructor(options) {
48
49
  if (typeof options === "string") {
49
50
  this.apiKey = options;
@@ -54,6 +55,7 @@ var Runlater = class {
54
55
  }
55
56
  this.tasks = new Tasks(this);
56
57
  this.monitors = new Monitors(this);
58
+ this.endpoints = new Endpoints(this);
57
59
  }
58
60
  /**
59
61
  * Send a request immediately with reliable delivery and retries.
@@ -386,6 +388,43 @@ var Monitors = class {
386
388
  return await response.json();
387
389
  }
388
390
  };
391
+ var Endpoints = class {
392
+ constructor(client) {
393
+ this.client = client;
394
+ }
395
+ async list() {
396
+ return this.client.request("GET", "/endpoints");
397
+ }
398
+ async get(id) {
399
+ const res = await this.client.request("GET", `/endpoints/${id}`);
400
+ return res.data;
401
+ }
402
+ async create(options) {
403
+ const res = await this.client.request("POST", "/endpoints", {
404
+ body: options
405
+ });
406
+ return res.data;
407
+ }
408
+ async update(id, options) {
409
+ const res = await this.client.request("PUT", `/endpoints/${id}`, {
410
+ body: options
411
+ });
412
+ return res.data;
413
+ }
414
+ async delete(id) {
415
+ await this.client.request("DELETE", `/endpoints/${id}`);
416
+ }
417
+ async events(id, limit = 50) {
418
+ const res = await this.client.request(
419
+ "GET",
420
+ `/endpoints/${id}/events?limit=${limit}`
421
+ );
422
+ return res.data;
423
+ }
424
+ async replay(endpointId, eventId) {
425
+ await this.client.request("POST", `/endpoints/${endpointId}/events/${eventId}/replay`);
426
+ }
427
+ };
389
428
  function formatDelay(delay) {
390
429
  if (typeof delay === "number") return `${delay}s`;
391
430
  return delay;
package/dist/index.mjs CHANGED
@@ -17,6 +17,7 @@ var Runlater = class {
17
17
  baseUrl;
18
18
  tasks;
19
19
  monitors;
20
+ endpoints;
20
21
  constructor(options) {
21
22
  if (typeof options === "string") {
22
23
  this.apiKey = options;
@@ -27,6 +28,7 @@ var Runlater = class {
27
28
  }
28
29
  this.tasks = new Tasks(this);
29
30
  this.monitors = new Monitors(this);
31
+ this.endpoints = new Endpoints(this);
30
32
  }
31
33
  /**
32
34
  * Send a request immediately with reliable delivery and retries.
@@ -359,6 +361,43 @@ var Monitors = class {
359
361
  return await response.json();
360
362
  }
361
363
  };
364
+ var Endpoints = class {
365
+ constructor(client) {
366
+ this.client = client;
367
+ }
368
+ async list() {
369
+ return this.client.request("GET", "/endpoints");
370
+ }
371
+ async get(id) {
372
+ const res = await this.client.request("GET", `/endpoints/${id}`);
373
+ return res.data;
374
+ }
375
+ async create(options) {
376
+ const res = await this.client.request("POST", "/endpoints", {
377
+ body: options
378
+ });
379
+ return res.data;
380
+ }
381
+ async update(id, options) {
382
+ const res = await this.client.request("PUT", `/endpoints/${id}`, {
383
+ body: options
384
+ });
385
+ return res.data;
386
+ }
387
+ async delete(id) {
388
+ await this.client.request("DELETE", `/endpoints/${id}`);
389
+ }
390
+ async events(id, limit = 50) {
391
+ const res = await this.client.request(
392
+ "GET",
393
+ `/endpoints/${id}/events?limit=${limit}`
394
+ );
395
+ return res.data;
396
+ }
397
+ async replay(endpointId, eventId) {
398
+ await this.client.request("POST", `/endpoints/${endpointId}/events/${eventId}/replay`);
399
+ }
400
+ };
362
401
  function formatDelay(delay) {
363
402
  if (typeof delay === "number") return `${delay}s`;
364
403
  return delay;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runlater-js",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Delayed tasks, cron jobs, and reliable webhooks. No infrastructure required.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",