@durable-effect/jobs 0.0.1-next.1

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.
Files changed (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +490 -0
  3. package/dist/client/client.d.ts +34 -0
  4. package/dist/client/client.d.ts.map +1 -0
  5. package/dist/client/client.js +427 -0
  6. package/dist/client/client.js.map +1 -0
  7. package/dist/client/index.d.ts +4 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +4 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/response.d.ts +99 -0
  12. package/dist/client/response.d.ts.map +1 -0
  13. package/dist/client/response.js +92 -0
  14. package/dist/client/response.js.map +1 -0
  15. package/dist/client/types.d.ts +242 -0
  16. package/dist/client/types.d.ts.map +1 -0
  17. package/dist/client/types.js +3 -0
  18. package/dist/client/types.js.map +1 -0
  19. package/dist/definitions/continuous.d.ts +110 -0
  20. package/dist/definitions/continuous.d.ts.map +1 -0
  21. package/dist/definitions/continuous.js +79 -0
  22. package/dist/definitions/continuous.js.map +1 -0
  23. package/dist/definitions/debounce.d.ts +67 -0
  24. package/dist/definitions/debounce.d.ts.map +1 -0
  25. package/dist/definitions/debounce.js +28 -0
  26. package/dist/definitions/debounce.js.map +1 -0
  27. package/dist/definitions/index.d.ts +4 -0
  28. package/dist/definitions/index.d.ts.map +1 -0
  29. package/dist/definitions/index.js +5 -0
  30. package/dist/definitions/index.js.map +1 -0
  31. package/dist/definitions/task.d.ts +234 -0
  32. package/dist/definitions/task.d.ts.map +1 -0
  33. package/dist/definitions/task.js +106 -0
  34. package/dist/definitions/task.js.map +1 -0
  35. package/dist/engine/engine.d.ts +60 -0
  36. package/dist/engine/engine.d.ts.map +1 -0
  37. package/dist/engine/engine.js +89 -0
  38. package/dist/engine/engine.js.map +1 -0
  39. package/dist/engine/index.d.ts +3 -0
  40. package/dist/engine/index.d.ts.map +1 -0
  41. package/dist/engine/index.js +3 -0
  42. package/dist/engine/index.js.map +1 -0
  43. package/dist/engine/types.d.ts +53 -0
  44. package/dist/engine/types.d.ts.map +1 -0
  45. package/dist/engine/types.js +3 -0
  46. package/dist/engine/types.js.map +1 -0
  47. package/dist/errors.d.ts +119 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +80 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/factory.d.ts +97 -0
  52. package/dist/factory.d.ts.map +1 -0
  53. package/dist/factory.js +94 -0
  54. package/dist/factory.js.map +1 -0
  55. package/dist/handlers/continuous/context.d.ts +25 -0
  56. package/dist/handlers/continuous/context.d.ts.map +1 -0
  57. package/dist/handlers/continuous/context.js +38 -0
  58. package/dist/handlers/continuous/context.js.map +1 -0
  59. package/dist/handlers/continuous/executor.d.ts +10 -0
  60. package/dist/handlers/continuous/executor.d.ts.map +1 -0
  61. package/dist/handlers/continuous/executor.js +83 -0
  62. package/dist/handlers/continuous/executor.js.map +1 -0
  63. package/dist/handlers/continuous/handler.d.ts +14 -0
  64. package/dist/handlers/continuous/handler.d.ts.map +1 -0
  65. package/dist/handlers/continuous/handler.js +283 -0
  66. package/dist/handlers/continuous/handler.js.map +1 -0
  67. package/dist/handlers/continuous/index.d.ts +4 -0
  68. package/dist/handlers/continuous/index.d.ts.map +1 -0
  69. package/dist/handlers/continuous/index.js +4 -0
  70. package/dist/handlers/continuous/index.js.map +1 -0
  71. package/dist/handlers/continuous/types.d.ts +36 -0
  72. package/dist/handlers/continuous/types.d.ts.map +1 -0
  73. package/dist/handlers/continuous/types.js +3 -0
  74. package/dist/handlers/continuous/types.js.map +1 -0
  75. package/dist/handlers/debounce/handler.d.ts +14 -0
  76. package/dist/handlers/debounce/handler.d.ts.map +1 -0
  77. package/dist/handlers/debounce/handler.js +261 -0
  78. package/dist/handlers/debounce/handler.js.map +1 -0
  79. package/dist/handlers/debounce/index.d.ts +3 -0
  80. package/dist/handlers/debounce/index.d.ts.map +1 -0
  81. package/dist/handlers/debounce/index.js +3 -0
  82. package/dist/handlers/debounce/index.js.map +1 -0
  83. package/dist/handlers/debounce/types.d.ts +10 -0
  84. package/dist/handlers/debounce/types.d.ts.map +1 -0
  85. package/dist/handlers/debounce/types.js +3 -0
  86. package/dist/handlers/debounce/types.js.map +1 -0
  87. package/dist/handlers/index.d.ts +14 -0
  88. package/dist/handlers/index.d.ts.map +1 -0
  89. package/dist/handlers/index.js +25 -0
  90. package/dist/handlers/index.js.map +1 -0
  91. package/dist/handlers/task/context.d.ts +35 -0
  92. package/dist/handlers/task/context.d.ts.map +1 -0
  93. package/dist/handlers/task/context.js +156 -0
  94. package/dist/handlers/task/context.js.map +1 -0
  95. package/dist/handlers/task/handler.d.ts +13 -0
  96. package/dist/handlers/task/handler.d.ts.map +1 -0
  97. package/dist/handlers/task/handler.js +280 -0
  98. package/dist/handlers/task/handler.js.map +1 -0
  99. package/dist/handlers/task/index.d.ts +3 -0
  100. package/dist/handlers/task/index.d.ts.map +1 -0
  101. package/dist/handlers/task/index.js +2 -0
  102. package/dist/handlers/task/index.js.map +1 -0
  103. package/dist/handlers/task/types.d.ts +10 -0
  104. package/dist/handlers/task/types.d.ts.map +1 -0
  105. package/dist/handlers/task/types.js +3 -0
  106. package/dist/handlers/task/types.js.map +1 -0
  107. package/dist/index.d.ts +28 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +79 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/registry/index.d.ts +5 -0
  112. package/dist/registry/index.d.ts.map +1 -0
  113. package/dist/registry/index.js +4 -0
  114. package/dist/registry/index.js.map +1 -0
  115. package/dist/registry/registry.d.ts +74 -0
  116. package/dist/registry/registry.d.ts.map +1 -0
  117. package/dist/registry/registry.js +159 -0
  118. package/dist/registry/registry.js.map +1 -0
  119. package/dist/registry/typed.d.ts +146 -0
  120. package/dist/registry/typed.d.ts.map +1 -0
  121. package/dist/registry/typed.js +29 -0
  122. package/dist/registry/typed.js.map +1 -0
  123. package/dist/registry/types.d.ts +497 -0
  124. package/dist/registry/types.d.ts.map +1 -0
  125. package/dist/registry/types.js +3 -0
  126. package/dist/registry/types.js.map +1 -0
  127. package/dist/retry/errors.d.ts +31 -0
  128. package/dist/retry/errors.d.ts.map +1 -0
  129. package/dist/retry/errors.js +22 -0
  130. package/dist/retry/errors.js.map +1 -0
  131. package/dist/retry/executor.d.ts +53 -0
  132. package/dist/retry/executor.d.ts.map +1 -0
  133. package/dist/retry/executor.js +112 -0
  134. package/dist/retry/executor.js.map +1 -0
  135. package/dist/retry/index.d.ts +4 -0
  136. package/dist/retry/index.d.ts.map +1 -0
  137. package/dist/retry/index.js +4 -0
  138. package/dist/retry/index.js.map +1 -0
  139. package/dist/retry/types.d.ts +29 -0
  140. package/dist/retry/types.d.ts.map +1 -0
  141. package/dist/retry/types.js +3 -0
  142. package/dist/retry/types.js.map +1 -0
  143. package/dist/runtime/dispatcher.d.ts +39 -0
  144. package/dist/runtime/dispatcher.d.ts.map +1 -0
  145. package/dist/runtime/dispatcher.js +76 -0
  146. package/dist/runtime/dispatcher.js.map +1 -0
  147. package/dist/runtime/index.d.ts +4 -0
  148. package/dist/runtime/index.d.ts.map +1 -0
  149. package/dist/runtime/index.js +6 -0
  150. package/dist/runtime/index.js.map +1 -0
  151. package/dist/runtime/runtime.d.ts +88 -0
  152. package/dist/runtime/runtime.d.ts.map +1 -0
  153. package/dist/runtime/runtime.js +116 -0
  154. package/dist/runtime/runtime.js.map +1 -0
  155. package/dist/runtime/types.d.ts +182 -0
  156. package/dist/runtime/types.d.ts.map +1 -0
  157. package/dist/runtime/types.js +3 -0
  158. package/dist/runtime/types.js.map +1 -0
  159. package/dist/services/alarm.d.ts +37 -0
  160. package/dist/services/alarm.d.ts.map +1 -0
  161. package/dist/services/alarm.js +39 -0
  162. package/dist/services/alarm.js.map +1 -0
  163. package/dist/services/cleanup.d.ts +27 -0
  164. package/dist/services/cleanup.d.ts.map +1 -0
  165. package/dist/services/cleanup.js +25 -0
  166. package/dist/services/cleanup.js.map +1 -0
  167. package/dist/services/entity-state.d.ts +49 -0
  168. package/dist/services/entity-state.d.ts.map +1 -0
  169. package/dist/services/entity-state.js +72 -0
  170. package/dist/services/entity-state.js.map +1 -0
  171. package/dist/services/execution.d.ts +70 -0
  172. package/dist/services/execution.d.ts.map +1 -0
  173. package/dist/services/execution.js +159 -0
  174. package/dist/services/execution.js.map +1 -0
  175. package/dist/services/execution_test.d.ts +13 -0
  176. package/dist/services/execution_test.d.ts.map +1 -0
  177. package/dist/services/execution_test.js +11 -0
  178. package/dist/services/execution_test.js.map +1 -0
  179. package/dist/services/idempotency.d.ts +36 -0
  180. package/dist/services/idempotency.d.ts.map +1 -0
  181. package/dist/services/idempotency.js +48 -0
  182. package/dist/services/idempotency.js.map +1 -0
  183. package/dist/services/index.d.ts +19 -0
  184. package/dist/services/index.d.ts.map +1 -0
  185. package/dist/services/index.js +33 -0
  186. package/dist/services/index.js.map +1 -0
  187. package/dist/services/metadata.d.ts +64 -0
  188. package/dist/services/metadata.d.ts.map +1 -0
  189. package/dist/services/metadata.js +56 -0
  190. package/dist/services/metadata.js.map +1 -0
  191. package/dist/services/registry.d.ts +19 -0
  192. package/dist/services/registry.d.ts.map +1 -0
  193. package/dist/services/registry.js +17 -0
  194. package/dist/services/registry.js.map +1 -0
  195. package/dist/storage-keys.d.ts +38 -0
  196. package/dist/storage-keys.d.ts.map +1 -0
  197. package/dist/storage-keys.js +47 -0
  198. package/dist/storage-keys.js.map +1 -0
  199. package/package.json +35 -0
@@ -0,0 +1,5 @@
1
+ // packages/jobs/src/definitions/index.ts
2
+ export { Continuous, } from "./continuous";
3
+ export { Debounce, } from "./debounce";
4
+ export { Task, } from "./task";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AAEzC,OAAO,EACL,UAAU,GAGX,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,QAAQ,GAGT,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,IAAI,GAGL,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,234 @@
1
+ import type { Effect, Schema } from "effect";
2
+ import type { UnregisteredTaskDefinition, TaskEventContext, TaskExecuteContext, TaskIdleContext, TaskErrorContext } from "../registry/types";
3
+ /**
4
+ * Configuration for creating a task job definition.
5
+ *
6
+ * Task provides user-controlled durable state machines where:
7
+ * - Events update state and optionally schedule execution
8
+ * - Execute runs when alarm fires
9
+ * - User controls the full lifecycle via schedule/clear
10
+ *
11
+ * @typeParam S - State type (inferred from stateSchema)
12
+ * @typeParam E - Event type (inferred from eventSchema)
13
+ * @typeParam Err - Error type (inferred from handlers)
14
+ * @typeParam R - Effect requirements (inferred from handlers)
15
+ */
16
+ export interface TaskMakeConfig<S, E, Err, R> {
17
+ /**
18
+ * Schema for validating and serializing state.
19
+ * State is persisted durably and survives restarts.
20
+ */
21
+ readonly stateSchema: Schema.Schema<S, any, never>;
22
+ /**
23
+ * Schema for validating incoming events.
24
+ * Events are validated before being passed to onEvent.
25
+ */
26
+ readonly eventSchema: Schema.Schema<E, any, never>;
27
+ /**
28
+ * Handler called for each incoming event.
29
+ *
30
+ * The event is passed as the first parameter (not on ctx) to make it
31
+ * clear that it's a direct value, not an Effect that needs yielding.
32
+ *
33
+ * Responsibilities:
34
+ * - Update state based on the event (via ctx.setState or ctx.updateState)
35
+ * - Schedule execution if needed (via ctx.schedule)
36
+ * - Optionally clear the task if complete (via ctx.clear)
37
+ *
38
+ * @param event - The incoming event (already validated against eventSchema)
39
+ * @param ctx - Context for state access, scheduling, and metadata
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * onEvent: (event, ctx) => Effect.gen(function* () {
44
+ * // event is a direct value - no yield needed!
45
+ * console.log("Received:", event);
46
+ *
47
+ * // Initialize state on first event
48
+ * if (ctx.state === null) {
49
+ * yield* ctx.setState({ items: [event], createdAt: Date.now() });
50
+ * } else {
51
+ * // Update state based on event
52
+ * yield* ctx.updateState(s => ({
53
+ * ...s,
54
+ * items: [...s.items, event]
55
+ * }));
56
+ * }
57
+ *
58
+ * // Schedule processing in 5 seconds
59
+ * yield* ctx.schedule(Duration.seconds(5));
60
+ * })
61
+ * ```
62
+ */
63
+ onEvent(event: E, ctx: TaskEventContext<S>): Effect.Effect<void, Err, R>;
64
+ /**
65
+ * Handler called when the scheduled alarm fires.
66
+ *
67
+ * Responsibilities:
68
+ * - Process the current state
69
+ * - Schedule next execution if needed
70
+ * - Clear the task when work is complete
71
+ *
72
+ * @example
73
+ * ```ts
74
+ * execute: (ctx) => Effect.gen(function* () {
75
+ * const state = yield* ctx.state;
76
+ * if (state === null) return;
77
+ *
78
+ * // Process items
79
+ * yield* processItems(state.items);
80
+ *
81
+ * // Clear when done
82
+ * yield* ctx.clear();
83
+ * })
84
+ * ```
85
+ */
86
+ execute(ctx: TaskExecuteContext<S>): Effect.Effect<void, Err, R>;
87
+ /**
88
+ * Optional handler called when either `onEvent` or `execute` completes
89
+ * and no alarm is scheduled.
90
+ *
91
+ * Use this to:
92
+ * - Schedule delayed cleanup
93
+ * - Log idle state
94
+ * - Trigger maintenance tasks
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * onIdle: (ctx) => Effect.gen(function* () {
99
+ * // Schedule cleanup in 1 hour if nothing happens
100
+ * yield* ctx.schedule(Duration.hours(1));
101
+ * })
102
+ * ```
103
+ */
104
+ readonly onIdle?: (ctx: TaskIdleContext<S>) => Effect.Effect<void, never, R>;
105
+ /**
106
+ * Optional error handler for onEvent/execute failures.
107
+ *
108
+ * Use this to:
109
+ * - Log errors
110
+ * - Update state to track failures
111
+ * - Schedule retries
112
+ * - Clear the task on fatal errors
113
+ *
114
+ * If not provided, errors are logged and the task continues.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * onError: (error, ctx) => Effect.gen(function* () {
119
+ * yield* Effect.logError("Task failed", error);
120
+ *
121
+ * // Track error in state
122
+ * yield* ctx.updateState(s => ({
123
+ * ...s,
124
+ * errorCount: (s.errorCount ?? 0) + 1
125
+ * }));
126
+ *
127
+ * // Retry in 30 seconds
128
+ * yield* ctx.schedule(Duration.seconds(30));
129
+ * })
130
+ * ```
131
+ */
132
+ readonly onError?: (error: Err, ctx: TaskErrorContext<S>) => Effect.Effect<void, never, R>;
133
+ }
134
+ /**
135
+ * Namespace for creating task job definitions.
136
+ *
137
+ * Task is a user-controlled durable state machine that provides:
138
+ * - Event-driven state updates
139
+ * - Scheduled execution via alarms
140
+ * - Full lifecycle control (schedule, cancel, clear)
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * import { Task } from "@durable-effect/jobs";
145
+ * import { Schema, Effect, Duration } from "effect";
146
+ *
147
+ * // Order processing task
148
+ * const orderProcessor = Task.make({
149
+ * stateSchema: Schema.Struct({
150
+ * orderId: Schema.String,
151
+ * status: Schema.Literal("pending", "processing", "shipped", "delivered"),
152
+ * lastUpdated: Schema.Number,
153
+ * }),
154
+ *
155
+ * eventSchema: Schema.Union(
156
+ * Schema.Struct({ _tag: Schema.Literal("OrderPlaced"), orderId: Schema.String }),
157
+ * Schema.Struct({ _tag: Schema.Literal("PaymentReceived") }),
158
+ * Schema.Struct({ _tag: Schema.Literal("Shipped"), trackingNumber: Schema.String }),
159
+ * ),
160
+ *
161
+ * // event is passed as first parameter - clear it's a direct value!
162
+ * onEvent: (event, ctx) => Effect.gen(function* () {
163
+ * switch (event._tag) {
164
+ * case "OrderPlaced":
165
+ * yield* ctx.setState({
166
+ * orderId: event.orderId,
167
+ * status: "pending",
168
+ * lastUpdated: Date.now(),
169
+ * });
170
+ * // Check payment status in 5 minutes
171
+ * yield* ctx.schedule(Duration.minutes(5));
172
+ * break;
173
+ *
174
+ * case "PaymentReceived":
175
+ * yield* ctx.updateState(s => ({ ...s, status: "processing", lastUpdated: Date.now() }));
176
+ * break;
177
+ *
178
+ * case "Shipped":
179
+ * yield* ctx.updateState(s => ({ ...s, status: "shipped", lastUpdated: Date.now() }));
180
+ * // Check delivery in 24 hours
181
+ * yield* ctx.schedule(Duration.hours(24));
182
+ * break;
183
+ * }
184
+ * }),
185
+ *
186
+ * execute: (ctx) => Effect.gen(function* () {
187
+ * const state = yield* ctx.state;
188
+ * if (state === null) return;
189
+ *
190
+ * if (state.status === "shipped") {
191
+ * // Check if delivered
192
+ * const delivered = yield* checkDeliveryStatus(state.orderId);
193
+ * if (delivered) {
194
+ * yield* ctx.updateState(s => ({ ...s, status: "delivered", lastUpdated: Date.now() }));
195
+ * yield* ctx.clear(); // Order complete
196
+ * } else {
197
+ * yield* ctx.schedule(Duration.hours(24)); // Check again tomorrow
198
+ * }
199
+ * }
200
+ * }),
201
+ * });
202
+ *
203
+ * // Register with createDurableJobs - name comes from key
204
+ * const { Jobs, client } = createDurableJobs({
205
+ * jobs: { orderProcessor },
206
+ * binding: env.JOBS,
207
+ * });
208
+ *
209
+ * // Send events
210
+ * await Effect.runPromise(
211
+ * client.task("orderProcessor").send({
212
+ * id: "order-123",
213
+ * event: { _tag: "OrderPlaced", orderId: "order-123" }
214
+ * })
215
+ * );
216
+ * ```
217
+ */
218
+ export declare const Task: {
219
+ /**
220
+ * Create a task job definition.
221
+ *
222
+ * The name is NOT provided here - it comes from the key when you
223
+ * register the job via createDurableJobs().
224
+ *
225
+ * @param config - Configuration for the task
226
+ * @returns An UnregisteredTaskDefinition that can be registered
227
+ */
228
+ readonly make: <S, E, Err = never, R = never>(config: TaskMakeConfig<S, E, Err, R>) => UnregisteredTaskDefinition<S, E, Err, R>;
229
+ };
230
+ /**
231
+ * Type alias for the Task namespace.
232
+ */
233
+ export type TaskNamespace = typeof Task;
234
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/definitions/task.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EACV,0BAA0B,EAC1B,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAM3B;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;IAC1C;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAEnD;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAEzE;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IAEjE;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,CACjB,KAAK,EAAE,GAAG,EACV,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACrB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AACH,eAAO,MAAM,IAAI;IACf;;;;;;;;OAQG;oBACI,CAAC,EAAE,CAAC,EAAE,GAAG,UAAU,CAAC,kBACjB,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,KACnC,0BAA0B,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;CASnC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,IAAI,CAAC"}
@@ -0,0 +1,106 @@
1
+ // packages/jobs/src/definitions/task.ts
2
+ /**
3
+ * Namespace for creating task job definitions.
4
+ *
5
+ * Task is a user-controlled durable state machine that provides:
6
+ * - Event-driven state updates
7
+ * - Scheduled execution via alarms
8
+ * - Full lifecycle control (schedule, cancel, clear)
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { Task } from "@durable-effect/jobs";
13
+ * import { Schema, Effect, Duration } from "effect";
14
+ *
15
+ * // Order processing task
16
+ * const orderProcessor = Task.make({
17
+ * stateSchema: Schema.Struct({
18
+ * orderId: Schema.String,
19
+ * status: Schema.Literal("pending", "processing", "shipped", "delivered"),
20
+ * lastUpdated: Schema.Number,
21
+ * }),
22
+ *
23
+ * eventSchema: Schema.Union(
24
+ * Schema.Struct({ _tag: Schema.Literal("OrderPlaced"), orderId: Schema.String }),
25
+ * Schema.Struct({ _tag: Schema.Literal("PaymentReceived") }),
26
+ * Schema.Struct({ _tag: Schema.Literal("Shipped"), trackingNumber: Schema.String }),
27
+ * ),
28
+ *
29
+ * // event is passed as first parameter - clear it's a direct value!
30
+ * onEvent: (event, ctx) => Effect.gen(function* () {
31
+ * switch (event._tag) {
32
+ * case "OrderPlaced":
33
+ * yield* ctx.setState({
34
+ * orderId: event.orderId,
35
+ * status: "pending",
36
+ * lastUpdated: Date.now(),
37
+ * });
38
+ * // Check payment status in 5 minutes
39
+ * yield* ctx.schedule(Duration.minutes(5));
40
+ * break;
41
+ *
42
+ * case "PaymentReceived":
43
+ * yield* ctx.updateState(s => ({ ...s, status: "processing", lastUpdated: Date.now() }));
44
+ * break;
45
+ *
46
+ * case "Shipped":
47
+ * yield* ctx.updateState(s => ({ ...s, status: "shipped", lastUpdated: Date.now() }));
48
+ * // Check delivery in 24 hours
49
+ * yield* ctx.schedule(Duration.hours(24));
50
+ * break;
51
+ * }
52
+ * }),
53
+ *
54
+ * execute: (ctx) => Effect.gen(function* () {
55
+ * const state = yield* ctx.state;
56
+ * if (state === null) return;
57
+ *
58
+ * if (state.status === "shipped") {
59
+ * // Check if delivered
60
+ * const delivered = yield* checkDeliveryStatus(state.orderId);
61
+ * if (delivered) {
62
+ * yield* ctx.updateState(s => ({ ...s, status: "delivered", lastUpdated: Date.now() }));
63
+ * yield* ctx.clear(); // Order complete
64
+ * } else {
65
+ * yield* ctx.schedule(Duration.hours(24)); // Check again tomorrow
66
+ * }
67
+ * }
68
+ * }),
69
+ * });
70
+ *
71
+ * // Register with createDurableJobs - name comes from key
72
+ * const { Jobs, client } = createDurableJobs({
73
+ * jobs: { orderProcessor },
74
+ * binding: env.JOBS,
75
+ * });
76
+ *
77
+ * // Send events
78
+ * await Effect.runPromise(
79
+ * client.task("orderProcessor").send({
80
+ * id: "order-123",
81
+ * event: { _tag: "OrderPlaced", orderId: "order-123" }
82
+ * })
83
+ * );
84
+ * ```
85
+ */
86
+ export const Task = {
87
+ /**
88
+ * Create a task job definition.
89
+ *
90
+ * The name is NOT provided here - it comes from the key when you
91
+ * register the job via createDurableJobs().
92
+ *
93
+ * @param config - Configuration for the task
94
+ * @returns An UnregisteredTaskDefinition that can be registered
95
+ */
96
+ make: (config) => ({
97
+ _tag: "TaskDefinition",
98
+ stateSchema: config.stateSchema,
99
+ eventSchema: config.eventSchema,
100
+ onEvent: config.onEvent,
101
+ execute: config.execute,
102
+ onIdle: config.onIdle,
103
+ onError: config.onError,
104
+ }),
105
+ };
106
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/definitions/task.ts"],"names":[],"mappings":"AAAA,wCAAwC;AA2JxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB;;;;;;;;OAQG;IACH,IAAI,EAAE,CACJ,MAAoC,EACM,EAAE,CAAC,CAAC;QAC9C,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;KACxB,CAAC;CACM,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { DurableObject } from "cloudflare:workers";
2
+ import type { JobRequest, JobResponse } from "../runtime/types";
3
+ import type { DurableJobsEngineInterface, JobsEngineConfig } from "./types";
4
+ /**
5
+ * The Durable Object class for jobs.
6
+ *
7
+ * This is a THIN SHELL that:
8
+ * 1. Creates the runtime in constructor
9
+ * 2. Delegates `call()` to `runtime.handle()`
10
+ * 3. Delegates `alarm()` to `runtime.handleAlarm()`
11
+ * 4. Flushes events via `ctx.waitUntil()`
12
+ *
13
+ * The engine knows NOTHING about job types. It just:
14
+ * - Creates the runtime
15
+ * - Delegates to runtime.handle() and runtime.handleAlarm()
16
+ * - Flushes events
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * // In your worker's wrangler.toml:
21
+ * // [[durable_objects.bindings]]
22
+ * // name = "JOBS"
23
+ * // class_name = "DurableJobsEngine"
24
+ *
25
+ * // The engine is created via createDurableJobs():
26
+ * const { Jobs } = createDurableJobs({
27
+ * jobs: { tokenRefresher, webhookDebounce, emailWorkerPool },
28
+ * });
29
+ *
30
+ * export { Jobs };
31
+ * ```
32
+ */
33
+ export declare class DurableJobsEngine extends DurableObject implements DurableJobsEngineInterface {
34
+ #private;
35
+ /**
36
+ * Create a new jobs engine instance.
37
+ *
38
+ * @param state - Durable Object state (provides storage + alarm)
39
+ * @param env - Environment with config injected
40
+ */
41
+ constructor(state: DurableObjectState, env: JobsEngineConfig);
42
+ /**
43
+ * Handle a job request.
44
+ *
45
+ * ONE generic RPC method - NOT one per job operation.
46
+ * The DO doesn't know about job types.
47
+ *
48
+ * @param request - The typed request from the client
49
+ * @returns The typed response
50
+ */
51
+ call(request: JobRequest): Promise<JobResponse>;
52
+ /**
53
+ * Handle an alarm.
54
+ *
55
+ * The runtime reads metadata to determine job type,
56
+ * then delegates to the appropriate handler.
57
+ */
58
+ alarm(): Promise<void>;
59
+ }
60
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAM5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,iBACX,SAAQ,aACR,YAAW,0BAA0B;;IAOrC;;;;;OAKG;gBACS,KAAK,EAAE,kBAAkB,EAAE,GAAG,EAAE,gBAAgB;IAe5D;;;;;;;;OAQG;IACG,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IAUrD;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
@@ -0,0 +1,89 @@
1
+ // packages/jobs/src/engine/engine.ts
2
+ import { DurableObject } from "cloudflare:workers";
3
+ import { createJobsRuntime } from "../runtime/runtime";
4
+ // =============================================================================
5
+ // Durable Jobs Engine
6
+ // =============================================================================
7
+ /**
8
+ * The Durable Object class for jobs.
9
+ *
10
+ * This is a THIN SHELL that:
11
+ * 1. Creates the runtime in constructor
12
+ * 2. Delegates `call()` to `runtime.handle()`
13
+ * 3. Delegates `alarm()` to `runtime.handleAlarm()`
14
+ * 4. Flushes events via `ctx.waitUntil()`
15
+ *
16
+ * The engine knows NOTHING about job types. It just:
17
+ * - Creates the runtime
18
+ * - Delegates to runtime.handle() and runtime.handleAlarm()
19
+ * - Flushes events
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // In your worker's wrangler.toml:
24
+ * // [[durable_objects.bindings]]
25
+ * // name = "JOBS"
26
+ * // class_name = "DurableJobsEngine"
27
+ *
28
+ * // The engine is created via createDurableJobs():
29
+ * const { Jobs } = createDurableJobs({
30
+ * jobs: { tokenRefresher, webhookDebounce, emailWorkerPool },
31
+ * });
32
+ *
33
+ * export { Jobs };
34
+ * ```
35
+ */
36
+ export class DurableJobsEngine extends DurableObject {
37
+ /**
38
+ * The runtime that handles all job operations.
39
+ */
40
+ #runtime;
41
+ /**
42
+ * Create a new jobs engine instance.
43
+ *
44
+ * @param state - Durable Object state (provides storage + alarm)
45
+ * @param env - Environment with config injected
46
+ */
47
+ constructor(state, env) {
48
+ super(state, env);
49
+ state.storage.deleteAll;
50
+ if (!env.__JOB_REGISTRY__) {
51
+ throw new Error("DurableJobsEngine requires __JOB_REGISTRY__ in env");
52
+ }
53
+ // Create the runtime with DO state and registry
54
+ // The runtime handles all Effect complexity
55
+ this.#runtime = createJobsRuntime({
56
+ doState: state,
57
+ registry: env.__JOB_REGISTRY__,
58
+ });
59
+ }
60
+ /**
61
+ * Handle a job request.
62
+ *
63
+ * ONE generic RPC method - NOT one per job operation.
64
+ * The DO doesn't know about job types.
65
+ *
66
+ * @param request - The typed request from the client
67
+ * @returns The typed response
68
+ */
69
+ async call(request) {
70
+ // Delegate to runtime
71
+ const result = await this.#runtime.handle(request);
72
+ // Fire-and-forget event flushing - don't block response
73
+ this.ctx.waitUntil(this.#runtime.flush());
74
+ return result;
75
+ }
76
+ /**
77
+ * Handle an alarm.
78
+ *
79
+ * The runtime reads metadata to determine job type,
80
+ * then delegates to the appropriate handler.
81
+ */
82
+ async alarm() {
83
+ // Delegate to runtime
84
+ await this.#runtime.handleAlarm();
85
+ // Fire-and-forget event flushing
86
+ this.ctx.waitUntil(this.#runtime.flush());
87
+ }
88
+ }
89
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAoB,MAAM,oBAAoB,CAAC;AAIzE,gFAAgF;AAChF,sBAAsB;AACtB,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,OAAO,iBACX,SAAQ,aAAa;IAGrB;;OAEG;IACM,QAAQ,CAAc;IAE/B;;;;;OAKG;IACH,YAAY,KAAyB,EAAE,GAAqB;QAC1D,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClB,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QAED,gDAAgD;QAChD,4CAA4C;QAC5C,IAAI,CAAC,QAAQ,GAAG,iBAAiB,CAAC;YAChC,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,GAAG,CAAC,gBAAgB;SAC/B,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,IAAI,CAAC,OAAmB;QAC5B,sBAAsB;QACtB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnD,wDAAwD;QACxD,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAK;QACT,sBAAsB;QACtB,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAElC,iCAAiC;QACjC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export { DurableJobsEngine } from "./engine";
2
+ export type { DurableJobsEngineInterface, JobsEngineConfig, JobsEnv, } from "./types";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,YAAY,EACV,0BAA0B,EAC1B,gBAAgB,EAChB,OAAO,GACR,MAAM,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ // packages/jobs/src/engine/index.ts
2
+ export { DurableJobsEngine } from "./engine";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA,oCAAoC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,53 @@
1
+ import type { JobRequest, JobResponse } from "../runtime/types";
2
+ import type { RuntimeJobRegistry } from "../registry/typed";
3
+ /**
4
+ * Configuration for the jobs engine.
5
+ *
6
+ * This is passed to the engine via the Cloudflare environment binding.
7
+ */
8
+ export interface JobsEngineConfig {
9
+ /**
10
+ * The job registry containing all registered jobs.
11
+ */
12
+ readonly __JOB_REGISTRY__: RuntimeJobRegistry;
13
+ }
14
+ /**
15
+ * The Durable Object interface for the jobs engine.
16
+ *
17
+ * This is a thin shell that delegates all operations to the runtime.
18
+ * It has ONE generic RPC method `call()` and `alarm()` - nothing else.
19
+ */
20
+ export interface DurableJobsEngineInterface {
21
+ /**
22
+ * Handle a job request.
23
+ *
24
+ * This is the ONLY RPC method for jobs. The client sends typed
25
+ * requests and receives typed responses. The engine doesn't know
26
+ * about specific job operations - it just delegates to the runtime.
27
+ *
28
+ * @param request - The job request to handle
29
+ * @returns The response from the job handler
30
+ */
31
+ call(request: JobRequest): Promise<JobResponse>;
32
+ /**
33
+ * Handle an alarm.
34
+ *
35
+ * The alarm handler reads metadata to determine which job type
36
+ * owns this instance, then delegates to the appropriate handler.
37
+ */
38
+ alarm(): Promise<void>;
39
+ }
40
+ /**
41
+ * Type helper for Cloudflare worker environment with jobs binding.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * interface Env extends JobsEnv<"JOBS"> {
46
+ * // Other bindings...
47
+ * }
48
+ * ```
49
+ */
50
+ export type JobsEnv<BindingName extends string = "JOBS"> = {
51
+ [K in BindingName]: DurableObjectNamespace;
52
+ };
53
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAM5D;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CAAC,gBAAgB,EAAE,kBAAkB,CAAC;CAC/C;AAMD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;OASG;IACH,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEhD;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAMD;;;;;;;;;GASG;AACH,MAAM,MAAM,OAAO,CAAC,WAAW,SAAS,MAAM,GAAG,MAAM,IAAI;KACxD,CAAC,IAAI,WAAW,GAAG,sBAAsB;CAC3C,CAAC"}
@@ -0,0 +1,3 @@
1
+ // packages/jobs/src/engine/types.ts
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/engine/types.ts"],"names":[],"mappings":"AAAA,oCAAoC"}