effect-inngest 0.3.0-beta.3 → 0.4.0-beta1
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 +69 -75
- package/dist/Client.js +1 -1
- package/dist/Cron.d.ts +17 -0
- package/dist/Cron.js +24 -0
- package/dist/Events.d.ts +1 -1
- package/dist/Events.js +1 -1
- package/dist/Function.d.ts +28 -26
- package/dist/Function.js +19 -11
- package/dist/Group.d.ts +7 -7
- package/dist/Group.js +1 -0
- package/dist/HttpApi.js +2 -1
- package/dist/Inngest.d.ts +60 -0
- package/dist/Inngest.js +61 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -2
- package/dist/internal/checkpoint/Abort.d.ts +1 -0
- package/dist/internal/checkpoint/Abort.js +5 -0
- package/dist/internal/checkpoint/State.d.ts +1 -1
- package/dist/internal/checkpoint/State.js +8 -1
- package/dist/internal/codec/StepResult.js +2 -12
- package/dist/internal/driver.js +1 -0
- package/dist/internal/errors.js +1 -1
- package/dist/internal/execution/ExecutionResponse.js +33 -4
- package/dist/internal/execution/HandlerRun.js +2 -1
- package/dist/internal/handler.js +37 -24
- package/dist/internal/protocol.js +3 -0
- package/dist/internal/runtime/HandlerContext.d.ts +0 -2
- package/dist/internal/runtime/HandlerContext.js +0 -3
- package/dist/internal/runtime/StepTools.d.ts +8 -16
- package/dist/internal/runtime/StepTools.js +2 -8
- package/dist/internal/runtime/steps/InvokeStep.js +1 -2
- package/dist/internal/runtime/steps/StepRun.js +25 -19
- package/dist/internal/serve/HttpApp.js +2 -1
- package/dist/internal/utils/safe-stringify.js +50 -0
- package/package.json +17 -1
- package/src/Client.ts +1 -1
- package/src/Cron.ts +33 -0
- package/src/Events.ts +1 -1
- package/src/Function.ts +58 -34
- package/src/Group.ts +10 -7
- package/src/HttpApi.ts +7 -1
- package/src/Inngest.ts +85 -0
- package/src/index.ts +21 -7
- package/src/internal/checkpoint/Abort.ts +5 -0
- package/src/internal/checkpoint/State.ts +8 -0
- package/src/internal/codec/StepResult.ts +1 -43
- package/src/internal/driver.ts +13 -2
- package/src/internal/errors.ts +1 -3
- package/src/internal/execution/ExecutionResponse.ts +44 -1
- package/src/internal/execution/HandlerRun.ts +3 -2
- package/src/internal/handler.ts +39 -34
- package/src/internal/protocol.ts +3 -0
- package/src/internal/runtime/HandlerContext.ts +2 -5
- package/src/internal/runtime/StepTools.ts +4 -31
- package/src/internal/runtime/steps/InvokeStep.ts +1 -4
- package/src/internal/runtime/steps/StepRun.ts +28 -44
- package/src/internal/serve/HttpApp.ts +1 -0
- package/src/internal/utils/safe-stringify.ts +84 -0
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
Effect Inngest brings the power of [Effect](https://effect.website) to [Inngest's](https://inngest.com) durable execution platform. Define event schemas once, and types flow automatically through triggers, handlers, and step operations — no manual annotations needed.
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
|
-
import { InngestClient, InngestEvent, InngestFunction, InngestGroup } from "effect-inngest";
|
|
28
|
+
import { InngestClient, InngestEvent, InngestFunction, InngestGroup, Inngest, InngestCron } from "effect-inngest";
|
|
29
29
|
import { Effect, Schema, Layer } from "effect";
|
|
30
30
|
|
|
31
31
|
const UserSignup = InngestEvent.make(
|
|
@@ -38,8 +38,7 @@ const UserSignup = InngestEvent.make(
|
|
|
38
38
|
|
|
39
39
|
// Create a function — event type is inferred from the trigger
|
|
40
40
|
const ProcessSignup = InngestFunction.make("process-signup", {
|
|
41
|
-
trigger:
|
|
42
|
-
success: Schema.Void,
|
|
41
|
+
trigger: UserSignup,
|
|
43
42
|
});
|
|
44
43
|
|
|
45
44
|
// Create group and implement handler
|
|
@@ -48,12 +47,12 @@ const Group = InngestGroup.make(ProcessSignup);
|
|
|
48
47
|
const UserOnboarded = InngestEvent.make("user/onboarded", Schema.Struct({ userId: Schema.String }));
|
|
49
48
|
|
|
50
49
|
const Handlers = Group.toLayer({
|
|
51
|
-
"process-signup": ({ event
|
|
50
|
+
"process-signup": ({ event }) =>
|
|
52
51
|
Effect.gen(function* () {
|
|
53
52
|
// event is typed as { name: "user/signup", data: { userId, email } }
|
|
54
|
-
yield*
|
|
55
|
-
yield*
|
|
56
|
-
yield*
|
|
53
|
+
yield* Inngest.run("send-welcome", sendWelcomeEmail(event.data.email));
|
|
54
|
+
yield* Inngest.sleep("delay", "1 hour");
|
|
55
|
+
yield* Inngest.sendEvent("notify", UserOnboarded.make({ userId: event.data.userId }));
|
|
57
56
|
}),
|
|
58
57
|
});
|
|
59
58
|
```
|
|
@@ -65,9 +64,9 @@ const Handlers = Group.toLayer({
|
|
|
65
64
|
## Features
|
|
66
65
|
|
|
67
66
|
- 🧙♂️ **Full type inference** — Payload types flow from schemas through triggers to handlers
|
|
68
|
-
- ⚡ **Effect-native steps** — `
|
|
67
|
+
- ⚡ **Effect-native steps** — `Inngest.run`, `Inngest.sleep`, `Inngest.waitForEvent` return proper Effects
|
|
69
68
|
- 🔌 **Dependency injection** — Use Effect's Layer system for services in handlers
|
|
70
|
-
- 🛡️ **
|
|
69
|
+
- 🛡️ **Event validation** — Define events once with Effect Schema, validated at the boundary
|
|
71
70
|
- 🚀 **Zero boilerplate** — No code generation, no manual type annotations
|
|
72
71
|
- 🔄 **Parallel execution** — Run steps concurrently with `Effect.all`
|
|
73
72
|
- 🌐 **Multi-runtime** — Works with Bun, Node.js, and Cloudflare Workers
|
|
@@ -109,7 +108,7 @@ import { BunHttpServer, BunRuntime } from "@effect/platform-bun";
|
|
|
109
108
|
import * as HttpMiddleware from "@effect/platform/HttpMiddleware";
|
|
110
109
|
import * as HttpServer from "@effect/platform/HttpServer";
|
|
111
110
|
import { Duration, Effect, Layer, Schema } from "effect";
|
|
112
|
-
import { InngestClient, InngestEvent, InngestFunction, InngestGroup } from "effect-inngest";
|
|
111
|
+
import { InngestClient, InngestEvent, InngestFunction, InngestGroup, Inngest, InngestCron } from "effect-inngest";
|
|
113
112
|
|
|
114
113
|
// 1. Define your Inngest event definitions
|
|
115
114
|
const UserSignup = InngestEvent.make(
|
|
@@ -124,39 +123,38 @@ const UserWelcomeSent = InngestEvent.make("user/welcome-sent", Schema.Struct({ u
|
|
|
124
123
|
|
|
125
124
|
// 2. Define your functions
|
|
126
125
|
const ProcessSignup = InngestFunction.make("process-signup", {
|
|
127
|
-
trigger:
|
|
128
|
-
success: Schema.Struct({ welcomed: Schema.Boolean }),
|
|
126
|
+
trigger: UserSignup,
|
|
129
127
|
});
|
|
130
128
|
|
|
131
129
|
const DailyDigest = InngestFunction.make("daily-digest", {
|
|
132
|
-
trigger:
|
|
133
|
-
success: Schema.Void,
|
|
130
|
+
trigger: InngestCron.make("0 9 * * *"),
|
|
134
131
|
});
|
|
135
132
|
|
|
136
133
|
// 3. Create function group and implement handlers
|
|
137
134
|
const App = InngestGroup.make(ProcessSignup, DailyDigest);
|
|
138
135
|
|
|
139
136
|
const Handlers = App.toLayer({
|
|
140
|
-
"process-signup": ({ event
|
|
137
|
+
"process-signup": ({ event }) =>
|
|
141
138
|
Effect.gen(function* () {
|
|
142
139
|
// event is typed as { name: "user/signup", data: { userId, email } }
|
|
143
140
|
yield* Effect.log(`Processing signup for ${event.data.email}`);
|
|
144
141
|
|
|
145
|
-
// Durable value-returning steps
|
|
146
|
-
const user = yield*
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
// Durable value-returning steps are normalized through JSON on the wire
|
|
143
|
+
const user = yield* Inngest.run(
|
|
144
|
+
"create-user",
|
|
145
|
+
Effect.succeed({ id: event.data.userId, email: event.data.email }),
|
|
146
|
+
);
|
|
149
147
|
|
|
150
148
|
// Sleep durably
|
|
151
|
-
yield*
|
|
149
|
+
yield* Inngest.sleep("welcome-delay", Duration.seconds(5));
|
|
152
150
|
|
|
153
151
|
// Send follow-up event
|
|
154
|
-
yield*
|
|
152
|
+
yield* Inngest.sendEvent("notify", UserWelcomeSent.make({ userId: user.id }));
|
|
155
153
|
|
|
156
154
|
return { welcomed: true };
|
|
157
155
|
}),
|
|
158
156
|
|
|
159
|
-
"daily-digest": (
|
|
157
|
+
"daily-digest": () => Inngest.run("send-digest", Effect.log("Sending daily digest...")),
|
|
160
158
|
});
|
|
161
159
|
|
|
162
160
|
// 4. Create client and start server
|
|
@@ -200,7 +198,7 @@ import { FetchHttpClient } from "@effect/platform";
|
|
|
200
198
|
import { BunHttpServer, BunRuntime } from "@effect/platform-bun";
|
|
201
199
|
import { Duration, Effect, Layer, Schema } from "effect";
|
|
202
200
|
import { InngestApiGroup, layerGroup } from "effect-inngest/HttpApi";
|
|
203
|
-
import { InngestClient, InngestEvent, InngestFunction, InngestGroup } from "effect-inngest";
|
|
201
|
+
import { InngestClient, InngestEvent, InngestFunction, InngestGroup, Inngest, InngestCron } from "effect-inngest";
|
|
204
202
|
|
|
205
203
|
// 1. Define your events
|
|
206
204
|
const UserSignup = InngestEvent.make(
|
|
@@ -215,30 +213,29 @@ const UserWelcomeSent = InngestEvent.make("user/welcome-sent", Schema.Struct({ u
|
|
|
215
213
|
|
|
216
214
|
// 2. Define functions
|
|
217
215
|
const ProcessSignup = InngestFunction.make("process-signup", {
|
|
218
|
-
trigger:
|
|
219
|
-
success: Schema.Struct({ welcomed: Schema.Boolean }),
|
|
216
|
+
trigger: UserSignup,
|
|
220
217
|
});
|
|
221
218
|
|
|
222
219
|
const DailyDigest = InngestFunction.make("daily-digest", {
|
|
223
|
-
trigger:
|
|
224
|
-
success: Schema.Void,
|
|
220
|
+
trigger: InngestCron.make("0 9 * * *"),
|
|
225
221
|
});
|
|
226
222
|
|
|
227
223
|
// 3. Create group and handlers
|
|
228
224
|
const App = InngestGroup.make(ProcessSignup, DailyDigest);
|
|
229
225
|
|
|
230
226
|
const Handlers = App.toLayer({
|
|
231
|
-
"process-signup": ({ event
|
|
227
|
+
"process-signup": ({ event }) =>
|
|
232
228
|
Effect.gen(function* () {
|
|
233
229
|
yield* Effect.log(`Processing signup for ${event.data.email}`);
|
|
234
|
-
const user = yield*
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
yield*
|
|
230
|
+
const user = yield* Inngest.run(
|
|
231
|
+
"create-user",
|
|
232
|
+
Effect.succeed({ id: event.data.userId, email: event.data.email }),
|
|
233
|
+
);
|
|
234
|
+
yield* Inngest.sleep("welcome-delay", Duration.seconds(5));
|
|
235
|
+
yield* Inngest.sendEvent("notify", UserWelcomeSent.make({ userId: user.id }));
|
|
239
236
|
return { welcomed: true };
|
|
240
237
|
}),
|
|
241
|
-
"daily-digest": (
|
|
238
|
+
"daily-digest": () => Inngest.run("send-digest", Effect.log("Sending daily digest...")),
|
|
242
239
|
});
|
|
243
240
|
|
|
244
241
|
// 4. Create client
|
|
@@ -298,46 +295,44 @@ const UserWelcomeSent = InngestEvent.make("user/welcome-sent", Schema.Struct({ u
|
|
|
298
295
|
### 2. Define your functions
|
|
299
296
|
|
|
300
297
|
```typescript
|
|
301
|
-
import { InngestFunction } from "effect-inngest";
|
|
298
|
+
import { InngestCron, InngestFunction } from "effect-inngest";
|
|
302
299
|
|
|
303
300
|
// Event-triggered function
|
|
304
301
|
const ProcessSignup = InngestFunction.make("process-signup", {
|
|
305
|
-
trigger:
|
|
306
|
-
success: Schema.Struct({ welcomeEmailSent: Schema.Boolean }),
|
|
302
|
+
trigger: UserSignup,
|
|
307
303
|
});
|
|
308
304
|
|
|
309
305
|
// Cron-triggered function
|
|
310
306
|
const DailyReport = InngestFunction.make("daily-report", {
|
|
311
|
-
trigger:
|
|
312
|
-
success: Schema.Void,
|
|
307
|
+
trigger: InngestCron.make("0 9 * * *"),
|
|
313
308
|
});
|
|
314
309
|
```
|
|
315
310
|
|
|
316
311
|
### 3. Create a function group and implement handlers
|
|
317
312
|
|
|
318
313
|
```typescript
|
|
319
|
-
import { InngestGroup } from "effect-inngest";
|
|
314
|
+
import { InngestGroup, Inngest } from "effect-inngest";
|
|
320
315
|
import { Effect, Duration } from "effect";
|
|
321
316
|
|
|
322
317
|
const AppFunctions = InngestGroup.make(ProcessSignup, DailyReport);
|
|
323
318
|
|
|
324
319
|
const HandlersLive = AppFunctions.toLayer({
|
|
325
|
-
"process-signup": ({ event
|
|
320
|
+
"process-signup": ({ event }) =>
|
|
326
321
|
Effect.gen(function* () {
|
|
327
|
-
yield*
|
|
328
|
-
yield*
|
|
329
|
-
yield*
|
|
322
|
+
yield* Inngest.run("create-user", createUser(event));
|
|
323
|
+
yield* Inngest.sleep("delay", Duration.minutes(5));
|
|
324
|
+
yield* Inngest.sendEvent("welcome", UserWelcomeSent.make({ userId: event.data.userId }));
|
|
330
325
|
return { welcomeEmailSent: true };
|
|
331
326
|
}),
|
|
332
327
|
|
|
333
|
-
"daily-report": (
|
|
328
|
+
"daily-report": () => Inngest.run("generate", Effect.log("Generating report...")),
|
|
334
329
|
});
|
|
335
330
|
```
|
|
336
331
|
|
|
337
332
|
### 4. Create a web handler
|
|
338
333
|
|
|
339
334
|
```typescript
|
|
340
|
-
import { InngestClient, InngestGroup } from "effect-inngest";
|
|
335
|
+
import { InngestClient, InngestGroup, Inngest } from "effect-inngest";
|
|
341
336
|
import { FetchHttpClient } from "@effect/platform";
|
|
342
337
|
import { Layer } from "effect";
|
|
343
338
|
|
|
@@ -363,31 +358,31 @@ Bun.serve({ port: 3000, fetch: handler });
|
|
|
363
358
|
All step operations are durable — they're memoized and survive retries:
|
|
364
359
|
|
|
365
360
|
```typescript
|
|
366
|
-
(
|
|
361
|
+
() =>
|
|
367
362
|
Effect.gen(function* () {
|
|
368
|
-
// Run an Effect with memoization.
|
|
369
|
-
const user = yield*
|
|
363
|
+
// Run an Effect with memoization. Values are replayed as normalized JSON.
|
|
364
|
+
const user = yield* Inngest.run("fetch-user", fetchUser(userId));
|
|
370
365
|
|
|
371
366
|
// Sleep for a duration
|
|
372
|
-
yield*
|
|
367
|
+
yield* Inngest.sleep("wait", Duration.hours(24));
|
|
373
368
|
|
|
374
369
|
// Sleep until a timestamp
|
|
375
|
-
yield*
|
|
370
|
+
yield* Inngest.sleepUntil("deadline", new Date("2024-12-31"));
|
|
376
371
|
|
|
377
372
|
// Wait for an event (returns Option)
|
|
378
|
-
const payment = yield*
|
|
373
|
+
const payment = yield* Inngest.waitForEvent("await-payment", PaymentReceived, {
|
|
379
374
|
timeout: Duration.days(7),
|
|
380
375
|
if: `async.data.orderId == "${orderId}"`,
|
|
381
376
|
});
|
|
382
377
|
|
|
383
378
|
// Invoke another function
|
|
384
|
-
const result = yield*
|
|
379
|
+
const result = yield* Inngest.invoke("process", {
|
|
385
380
|
function: ProcessOrder,
|
|
386
|
-
data: { orderId: "123" },
|
|
381
|
+
data: OrderPlaced.make({ orderId: "123", items: [], total: 0 }),
|
|
387
382
|
});
|
|
388
383
|
|
|
389
384
|
// Send events
|
|
390
|
-
yield*
|
|
385
|
+
yield* Inngest.sendEvent("notify", OrderShipped.make({ orderId }));
|
|
391
386
|
});
|
|
392
387
|
```
|
|
393
388
|
|
|
@@ -400,9 +395,9 @@ const [user, orders, prefs] =
|
|
|
400
395
|
yield *
|
|
401
396
|
Effect.all(
|
|
402
397
|
[
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
398
|
+
Inngest.run("user", fetchUser(id)),
|
|
399
|
+
Inngest.run("orders", fetchOrders(id)),
|
|
400
|
+
Inngest.run("prefs", fetchPreferences(id)),
|
|
406
401
|
],
|
|
407
402
|
{ concurrency: "unbounded" },
|
|
408
403
|
);
|
|
@@ -425,10 +420,10 @@ class EmailService extends Context.Tag("EmailService")<
|
|
|
425
420
|
|
|
426
421
|
// Use in handler
|
|
427
422
|
const HandlersLive = AppFunctions.toLayer({
|
|
428
|
-
"process-signup": ({ event
|
|
423
|
+
"process-signup": ({ event }) =>
|
|
429
424
|
Effect.gen(function* () {
|
|
430
425
|
const email = yield* EmailService;
|
|
431
|
-
yield*
|
|
426
|
+
yield* Inngest.run("send", email.send(event.data.email, "Welcome!"));
|
|
432
427
|
return { welcomeEmailSent: true };
|
|
433
428
|
}),
|
|
434
429
|
});
|
|
@@ -451,7 +446,7 @@ Configure retries, concurrency, rate limiting, and more:
|
|
|
451
446
|
|
|
452
447
|
```typescript
|
|
453
448
|
const ProcessOrder = InngestFunction.make("process-order", {
|
|
454
|
-
trigger:
|
|
449
|
+
trigger: OrderPlaced,
|
|
455
450
|
retries: 5,
|
|
456
451
|
concurrency: { limit: 10, key: "event.data.userId" },
|
|
457
452
|
rateLimit: { limit: 100, period: Duration.minutes(1) },
|
|
@@ -498,15 +493,14 @@ yield * Effect.fail(RetryAfterError.make({ message: "Rate limited", retryAfter:
|
|
|
498
493
|
|
|
499
494
|
### Step Methods
|
|
500
495
|
|
|
501
|
-
| Method
|
|
502
|
-
|
|
|
503
|
-
| `
|
|
504
|
-
| `
|
|
505
|
-
| `
|
|
506
|
-
| `
|
|
507
|
-
| `
|
|
508
|
-
| `
|
|
509
|
-
| `step.sendEvent(id, InngestEvent.make(payload))` | Send events to Inngest |
|
|
496
|
+
| Method | Description |
|
|
497
|
+
| --------------------------------------------------- | ---------------------------------- |
|
|
498
|
+
| `Inngest.run(id, effect)` | Execute an Effect with memoization |
|
|
499
|
+
| `Inngest.sleep(id, duration)` | Sleep for a duration |
|
|
500
|
+
| `Inngest.sleepUntil(id, timestamp)` | Sleep until a timestamp |
|
|
501
|
+
| `Inngest.waitForEvent(id, InngestEvent, opts)` | Wait for an event with timeout |
|
|
502
|
+
| `Inngest.invoke(id, opts)` | Invoke another function |
|
|
503
|
+
| `Inngest.sendEvent(id, InngestEvent.make(payload))` | Send events to Inngest |
|
|
510
504
|
|
|
511
505
|
---
|
|
512
506
|
|
|
@@ -520,11 +514,11 @@ See the [`examples/`](./examples) directory:
|
|
|
520
514
|
|
|
521
515
|
This library is under active development. The following Inngest features are **not yet supported**:
|
|
522
516
|
|
|
523
|
-
| Feature
|
|
524
|
-
|
|
|
525
|
-
| Middleware
|
|
526
|
-
| AI Steps (`
|
|
527
|
-
| Encryption
|
|
517
|
+
| Feature | Status |
|
|
518
|
+
| ------------------------- | -------------------- |
|
|
519
|
+
| Middleware | 🚧 Not yet supported |
|
|
520
|
+
| AI Steps (`Inngest.ai.*`) | 🚧 Not yet supported |
|
|
521
|
+
| Encryption | 🚧 Not yet supported |
|
|
528
522
|
|
|
529
523
|
---
|
|
530
524
|
|
package/dist/Client.js
CHANGED
|
@@ -86,7 +86,7 @@ const makeClient = (config, httpClient) => Effect.gen(function* () {
|
|
|
86
86
|
message: "Event key is required to send events in cloud mode",
|
|
87
87
|
events: events.map((e) => e.name)
|
|
88
88
|
}));
|
|
89
|
-
const key = config.eventKey
|
|
89
|
+
const key = config.eventKey || "NO_EVENT_KEY_SET";
|
|
90
90
|
const url = new URL(`e/${key}`, eventBaseUrl).toString();
|
|
91
91
|
const eventNames = events.map((e) => e.name);
|
|
92
92
|
const now = yield* Clock.currentTimeMillis;
|
package/dist/Cron.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare namespace Cron_d_exports {
|
|
2
|
+
export { CronDefinition, CronOptions, TypeId, isCron, make };
|
|
3
|
+
}
|
|
4
|
+
declare const TypeId: unique symbol;
|
|
5
|
+
type TypeId = typeof TypeId;
|
|
6
|
+
interface CronOptions {
|
|
7
|
+
readonly jitter?: string;
|
|
8
|
+
}
|
|
9
|
+
interface CronDefinition<Schedule extends string = string> {
|
|
10
|
+
readonly [TypeId]: TypeId;
|
|
11
|
+
readonly cron: Schedule;
|
|
12
|
+
readonly jitter?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function make<const Schedule extends string>(schedule: Schedule, options?: CronOptions): CronDefinition<Schedule>;
|
|
15
|
+
declare const isCron: (value: unknown) => value is CronDefinition;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CronDefinition, Cron_d_exports };
|
package/dist/Cron.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { Predicate } from "effect";
|
|
3
|
+
//#region src/Cron.ts
|
|
4
|
+
/**
|
|
5
|
+
* Public cron trigger definitions.
|
|
6
|
+
*
|
|
7
|
+
* @since 0.1.0
|
|
8
|
+
*/
|
|
9
|
+
var Cron_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
TypeId: () => TypeId,
|
|
11
|
+
isCron: () => isCron,
|
|
12
|
+
make: () => make
|
|
13
|
+
});
|
|
14
|
+
const TypeId = Symbol.for("effect-inngest/Cron");
|
|
15
|
+
function make(schedule, options) {
|
|
16
|
+
return {
|
|
17
|
+
[TypeId]: TypeId,
|
|
18
|
+
cron: schedule,
|
|
19
|
+
...Predicate.isNotUndefined(options?.jitter) ? { jitter: options.jitter } : {}
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const isCron = (value) => Predicate.hasProperty(value, TypeId) && value[TypeId] === TypeId;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { Cron_exports, isCron };
|
package/dist/Events.d.ts
CHANGED
|
@@ -65,7 +65,7 @@ declare const FunctionCancelled: EventDefinition<"inngest/function.cancelled", S
|
|
|
65
65
|
readonly correlation_id: Schema.optional<Schema.String>;
|
|
66
66
|
}>>;
|
|
67
67
|
/**
|
|
68
|
-
* Sent when a function is invoked via
|
|
68
|
+
* Sent when a function is invoked via Inngest.invoke().
|
|
69
69
|
* @since 0.1.0
|
|
70
70
|
*/
|
|
71
71
|
declare const FunctionInvoked: EventDefinition<"inngest/function.invoked", Schema.StructWithRest<Schema.Struct<{
|
package/dist/Events.js
CHANGED
|
@@ -75,7 +75,7 @@ const FunctionCancelled = make("inngest/function.cancelled", Schema.Struct({
|
|
|
75
75
|
correlation_id: Schema.optional(Schema.String)
|
|
76
76
|
}));
|
|
77
77
|
/**
|
|
78
|
-
* Sent when a function is invoked via
|
|
78
|
+
* Sent when a function is invoked via Inngest.invoke().
|
|
79
79
|
* @since 0.1.0
|
|
80
80
|
*/
|
|
81
81
|
const FunctionInvoked = make("inngest/function.invoked", Schema.StructWithRest(Schema.Struct({ _inngest: Schema.optionalKey(Schema.Record(Schema.String, Schema.Unknown)) }), [Schema.Record(Schema.String, Schema.Unknown)]));
|
package/dist/Function.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { CheckpointingOption } from "./internal/checkpoint/Config.js";
|
|
2
2
|
import { EventDefinition, EventType } from "./Event.js";
|
|
3
|
-
import {
|
|
3
|
+
import { CronDefinition } from "./Cron.js";
|
|
4
|
+
import { Duration } from "effect";
|
|
4
5
|
import { Pipeable } from "effect/Pipeable";
|
|
5
6
|
|
|
6
7
|
//#region src/Function.d.ts
|
|
7
8
|
declare namespace Function_d_exports {
|
|
8
|
-
export { BatchEventsOption, CancellationOption, CheckpointingOption, ConcurrencyOption, CronTrigger, DebounceOption, EventSchema, EventTrigger, FunctionOptions, FunctionRegistration, InngestFunction, PriorityOption, RateLimitOption, RegistrationConfig, Retries, SingletonOption, ThrottleOption, TimeoutsOption, Trigger, TriggerInput, TypeId, make };
|
|
9
|
+
export { BatchEventsOption, CancellationOption, CheckpointingOption, ConcurrencyOption, CronTrigger, DebounceOption, EventSchema, EventTrigger, FunctionOptions, FunctionRegistration, InngestFunction, PriorityOption, RateLimitOption, RegistrationConfig, Retries, SingletonOption, ThrottleOption, TimeoutsOption, Trigger, TriggerDefinition, TriggerInput, TypeId, make };
|
|
9
10
|
}
|
|
10
11
|
/**
|
|
11
12
|
* @since 0.1.0
|
|
@@ -29,6 +30,10 @@ interface EventTrigger<E extends EventSchema = EventSchema> {
|
|
|
29
30
|
readonly event: E;
|
|
30
31
|
readonly if?: string;
|
|
31
32
|
}
|
|
33
|
+
interface NormalizedEventTrigger<E extends EventSchema = EventSchema> {
|
|
34
|
+
readonly event: E;
|
|
35
|
+
readonly if?: string;
|
|
36
|
+
}
|
|
32
37
|
/**
|
|
33
38
|
* A cron-based trigger configuration.
|
|
34
39
|
*
|
|
@@ -37,6 +42,7 @@ interface EventTrigger<E extends EventSchema = EventSchema> {
|
|
|
37
42
|
*/
|
|
38
43
|
interface CronTrigger {
|
|
39
44
|
readonly cron: string;
|
|
45
|
+
readonly jitter?: string;
|
|
40
46
|
}
|
|
41
47
|
/**
|
|
42
48
|
* A trigger configuration for a function.
|
|
@@ -44,12 +50,14 @@ interface CronTrigger {
|
|
|
44
50
|
* @since 0.1.0
|
|
45
51
|
* @category triggers
|
|
46
52
|
*/
|
|
47
|
-
type
|
|
53
|
+
type NormalizedTrigger<E extends EventSchema = EventSchema> = NormalizedEventTrigger<E> | CronTrigger;
|
|
54
|
+
type Trigger<E extends EventSchema = EventSchema> = E | CronDefinition | EventTrigger<E>;
|
|
55
|
+
type TriggerDefinition<E extends EventSchema = EventSchema> = Trigger<E>;
|
|
48
56
|
/**
|
|
49
57
|
* @since 0.1.0
|
|
50
58
|
* @category triggers
|
|
51
59
|
*/
|
|
52
|
-
type TriggerInput<E extends EventSchema = EventSchema> =
|
|
60
|
+
type TriggerInput<E extends EventSchema = EventSchema> = TriggerDefinition<E> | ReadonlyArray<TriggerDefinition<E>>;
|
|
53
61
|
interface ConcurrencyOption {
|
|
54
62
|
/**
|
|
55
63
|
* The concurrency limit for this option, adding a limit on how many concurrent
|
|
@@ -305,6 +313,7 @@ interface FunctionRegistration {
|
|
|
305
313
|
event?: string;
|
|
306
314
|
cron?: string;
|
|
307
315
|
expression?: string;
|
|
316
|
+
jitter?: string;
|
|
308
317
|
}>;
|
|
309
318
|
readonly steps: {
|
|
310
319
|
readonly step: {
|
|
@@ -378,12 +387,11 @@ interface FunctionRegistration {
|
|
|
378
387
|
* @since 0.1.0
|
|
379
388
|
* @category models
|
|
380
389
|
*/
|
|
381
|
-
interface InngestFunction<Tag extends string, Triggers extends
|
|
390
|
+
interface InngestFunction<Tag extends string, Triggers extends NormalizedTrigger, Options extends FunctionOptions = FunctionOptions> extends Pipeable {
|
|
382
391
|
readonly [TypeId]: TypeId;
|
|
383
392
|
readonly _tag: Tag;
|
|
384
393
|
readonly key: string;
|
|
385
394
|
readonly triggers: ReadonlyArray<Triggers>;
|
|
386
|
-
readonly success: Success;
|
|
387
395
|
readonly options: Options;
|
|
388
396
|
readonly toRegistration: (config: RegistrationConfig) => FunctionRegistration;
|
|
389
397
|
}
|
|
@@ -392,20 +400,19 @@ interface InngestFunction<Tag extends string, Triggers extends Trigger, Success
|
|
|
392
400
|
* @category models
|
|
393
401
|
*/
|
|
394
402
|
declare namespace InngestFunction {
|
|
395
|
-
type Any = InngestFunction<string,
|
|
396
|
-
type Tag<F> = F extends InngestFunction<infer T, any, any
|
|
397
|
-
type Triggers<F> = F extends InngestFunction<any, infer T, any
|
|
398
|
-
type Events<F> = F extends InngestFunction<any, infer T, any
|
|
403
|
+
type Any = InngestFunction<string, NormalizedTrigger, FunctionOptions>;
|
|
404
|
+
type Tag<F> = F extends InngestFunction<infer T, any, any> ? T : never;
|
|
405
|
+
type Triggers<F> = F extends InngestFunction<any, infer T, any> ? T : never;
|
|
406
|
+
type Events<F> = F extends InngestFunction<any, infer T, any> ? (T extends NormalizedEventTrigger<infer E> ? E : never) : never;
|
|
399
407
|
type EventPayload<F> = EventEnvelope<Events<F>>;
|
|
400
408
|
type HasBatchEvents<O> = O extends {
|
|
401
409
|
readonly batchEvents: infer BatchEvents;
|
|
402
410
|
} ? Exclude<BatchEvents, undefined> extends BatchEventsOption ? true : false : false;
|
|
403
411
|
type EventType<F> = HasBatchEvents<Options<F>> extends true ? ReadonlyArray<EventPayload<F>> : EventPayload<F>;
|
|
404
|
-
type
|
|
405
|
-
type Success<F> = Schema.Schema.Type<SuccessSchema<F>>;
|
|
406
|
-
type Options<F> = F extends InngestFunction<any, any, any, infer O> ? O : never;
|
|
412
|
+
type Options<F> = F extends InngestFunction<any, any, infer O> ? O : never;
|
|
407
413
|
}
|
|
408
|
-
type
|
|
414
|
+
type NormalizeTrigger<T> = T extends EventSchema ? NormalizedEventTrigger<T> : T extends CronDefinition ? CronTrigger : T extends EventTrigger<infer E> ? NormalizedEventTrigger<E> : T extends CronTrigger ? T : never;
|
|
415
|
+
type NormalizeTriggers<T extends TriggerInput> = T extends ReadonlyArray<infer Item> ? NormalizeTrigger<Item> : NormalizeTrigger<T>;
|
|
409
416
|
/**
|
|
410
417
|
* @since 0.1.0
|
|
411
418
|
* @category constructors
|
|
@@ -413,35 +420,30 @@ type NormalizeTriggers<T extends TriggerInput> = T extends ReadonlyArray<Trigger
|
|
|
413
420
|
* ```ts
|
|
414
421
|
* // Event trigger
|
|
415
422
|
* const Fn1 = InngestFunction.make("Hello", {
|
|
416
|
-
* trigger:
|
|
417
|
-
* success: Schema.Void,
|
|
423
|
+
* trigger: HelloEvent,
|
|
418
424
|
* })
|
|
419
425
|
*
|
|
420
426
|
* // Event trigger with CEL filter
|
|
421
427
|
* const Fn2 = InngestFunction.make("Hello", {
|
|
422
428
|
* trigger: { event: HelloEvent, if: "event.data.name != ''" },
|
|
423
|
-
* success: Schema.Void,
|
|
424
429
|
* })
|
|
425
430
|
*
|
|
426
431
|
* // Cron trigger
|
|
427
432
|
* const Fn3 = InngestFunction.make("Scheduled", {
|
|
428
|
-
* trigger:
|
|
429
|
-
* success: Schema.Void,
|
|
433
|
+
* trigger: InngestCron.make("0 * * * *"),
|
|
430
434
|
* })
|
|
431
435
|
*
|
|
432
436
|
* // Multiple triggers
|
|
433
437
|
* const Fn4 = InngestFunction.make("Multi", {
|
|
434
438
|
* trigger: [
|
|
435
|
-
*
|
|
436
|
-
*
|
|
439
|
+
* HelloEvent,
|
|
440
|
+
* InngestCron.make("0 0 * * *"),
|
|
437
441
|
* ],
|
|
438
|
-
* success: Schema.Void,
|
|
439
442
|
* })
|
|
440
443
|
* ```
|
|
441
444
|
*/
|
|
442
|
-
declare function make<const Tag extends string, T extends TriggerInput,
|
|
445
|
+
declare function make<const Tag extends string, T extends TriggerInput, const O extends FunctionOptions = {}>(tag: Tag, options: {
|
|
443
446
|
readonly trigger: T;
|
|
444
|
-
|
|
445
|
-
} & O): InngestFunction<Tag, NormalizeTriggers<T>, S, O>;
|
|
447
|
+
} & O): InngestFunction<Tag, NormalizeTriggers<T>, O>;
|
|
446
448
|
//#endregion
|
|
447
|
-
export { BatchEventsOption, CancellationOption, type CheckpointingOption, ConcurrencyOption, CronTrigger, DebounceOption, EventSchema, EventTrigger, FunctionOptions, FunctionRegistration, Function_d_exports, InngestFunction, PriorityOption, RateLimitOption, RegistrationConfig, Retries, SingletonOption, ThrottleOption, TimeoutsOption, Trigger, TriggerInput, TypeId, make };
|
|
449
|
+
export { BatchEventsOption, CancellationOption, type CheckpointingOption, ConcurrencyOption, CronTrigger, DebounceOption, EventSchema, EventTrigger, FunctionOptions, FunctionRegistration, Function_d_exports, InngestFunction, PriorityOption, RateLimitOption, RegistrationConfig, Retries, SingletonOption, ThrottleOption, TimeoutsOption, Trigger, TriggerDefinition, TriggerInput, TypeId, make };
|
package/dist/Function.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { __exportAll } from "./_virtual/_rolldown/runtime.js";
|
|
2
2
|
import { InngestDuration } from "./internal/wire/Duration.js";
|
|
3
3
|
import { resolveConfig, toRegistration } from "./internal/checkpoint/Config.js";
|
|
4
|
+
import { isEventSchema } from "./Event.js";
|
|
5
|
+
import { isCron } from "./Cron.js";
|
|
4
6
|
import { Array, Duration, Option, Predicate, Schema } from "effect";
|
|
5
7
|
import { pipeArguments } from "effect/Pipeable";
|
|
6
8
|
//#region src/Function.ts
|
|
@@ -29,7 +31,10 @@ const Proto = {
|
|
|
29
31
|
event: t.event.identifier,
|
|
30
32
|
expression: t.if
|
|
31
33
|
});
|
|
32
|
-
else triggers.push({
|
|
34
|
+
else triggers.push({
|
|
35
|
+
cron: t.cron,
|
|
36
|
+
...Predicate.isNotUndefined(t.jitter) ? { jitter: t.jitter } : {}
|
|
37
|
+
});
|
|
33
38
|
const opts = this.options;
|
|
34
39
|
const cancel = opts.cancelOn?.map((c) => ({
|
|
35
40
|
event: c.event.identifier,
|
|
@@ -108,6 +113,14 @@ const Proto = {
|
|
|
108
113
|
};
|
|
109
114
|
}
|
|
110
115
|
};
|
|
116
|
+
const normalizeTrigger = (trigger) => {
|
|
117
|
+
if (isEventSchema(trigger)) return { event: trigger };
|
|
118
|
+
if (isCron(trigger)) return {
|
|
119
|
+
cron: trigger.cron,
|
|
120
|
+
...Predicate.isNotUndefined(trigger.jitter) ? { jitter: trigger.jitter } : {}
|
|
121
|
+
};
|
|
122
|
+
return trigger;
|
|
123
|
+
};
|
|
111
124
|
/**
|
|
112
125
|
* @since 0.1.0
|
|
113
126
|
* @category constructors
|
|
@@ -115,29 +128,25 @@ const Proto = {
|
|
|
115
128
|
* ```ts
|
|
116
129
|
* // Event trigger
|
|
117
130
|
* const Fn1 = InngestFunction.make("Hello", {
|
|
118
|
-
* trigger:
|
|
119
|
-
* success: Schema.Void,
|
|
131
|
+
* trigger: HelloEvent,
|
|
120
132
|
* })
|
|
121
133
|
*
|
|
122
134
|
* // Event trigger with CEL filter
|
|
123
135
|
* const Fn2 = InngestFunction.make("Hello", {
|
|
124
136
|
* trigger: { event: HelloEvent, if: "event.data.name != ''" },
|
|
125
|
-
* success: Schema.Void,
|
|
126
137
|
* })
|
|
127
138
|
*
|
|
128
139
|
* // Cron trigger
|
|
129
140
|
* const Fn3 = InngestFunction.make("Scheduled", {
|
|
130
|
-
* trigger:
|
|
131
|
-
* success: Schema.Void,
|
|
141
|
+
* trigger: InngestCron.make("0 * * * *"),
|
|
132
142
|
* })
|
|
133
143
|
*
|
|
134
144
|
* // Multiple triggers
|
|
135
145
|
* const Fn4 = InngestFunction.make("Multi", {
|
|
136
146
|
* trigger: [
|
|
137
|
-
*
|
|
138
|
-
*
|
|
147
|
+
* HelloEvent,
|
|
148
|
+
* InngestCron.make("0 0 * * *"),
|
|
139
149
|
* ],
|
|
140
|
-
* success: Schema.Void,
|
|
141
150
|
* })
|
|
142
151
|
* ```
|
|
143
152
|
*/
|
|
@@ -145,8 +154,7 @@ function make(tag, options) {
|
|
|
145
154
|
const fn = Object.create(Proto);
|
|
146
155
|
fn._tag = tag;
|
|
147
156
|
fn.key = `effect-inngest/Function/${tag}`;
|
|
148
|
-
fn.triggers = Array.ensure(options.trigger);
|
|
149
|
-
fn.success = options.success;
|
|
157
|
+
fn.triggers = Array.map(Array.ensure(options.trigger), normalizeTrigger);
|
|
150
158
|
fn.options = options;
|
|
151
159
|
return fn;
|
|
152
160
|
}
|