effect-cf 0.12.0 → 0.13.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -10,10 +10,8 @@ import {
10
10
  OtlpTracer,
11
11
  } from "effect/unstable/observability";
12
12
 
13
- import * as DurableObject from "./DurableObject";
14
13
  import { DurableObjectState } from "./DurableObjectState";
15
14
  import { WorkerConfig, WorkerEnvironment } from "./Environment";
16
- import * as Worker from "./Worker";
17
15
 
18
16
  /** Telemetry signal groups supported by the Cloudflare OTLP layers. */
19
17
  export type Signal = "logs" | "traces" | "metrics";
@@ -516,113 +514,3 @@ export const durableObjectLayer = (options: LayerOptions & DurableObjectResource
516
514
  }),
517
515
  ),
518
516
  );
519
-
520
- const provideRpcLayer = <
521
- Rpc extends Record<string, (...args: Array<any>) => Effect.Effect<any, any, any>>,
522
- RLayer,
523
- >(
524
- rpc: Rpc | undefined,
525
- layer: Layer.Layer<never, never, RLayer>,
526
- ): Rpc | undefined => {
527
- if (rpc === undefined) {
528
- return undefined;
529
- }
530
-
531
- return new Proxy(rpc, {
532
- get(target, property, receiver) {
533
- const handler = Reflect.get(target, property, receiver);
534
- if (typeof handler !== "function") {
535
- return handler;
536
- }
537
-
538
- return (...args: Array<any>) =>
539
- Effect.suspend(() => Reflect.apply(handler, receiver, args)).pipe(Effect.provide(layer));
540
- },
541
- });
542
- };
543
-
544
- /**
545
- * Instrument Worker lifecycle handlers with event-scoped OTLP telemetry.
546
- *
547
- * Each defined handler is provided with {@link workerLayer}. Because Worker
548
- * handlers run inside `Effect.scoped`, the exporter scope closes and flushes at
549
- * the end of each Cloudflare event.
550
- */
551
- export const instrumentWorkerOptions =
552
- (options?: LayerOptions & WorkerResourceOptions) =>
553
- <ROut, Rpc extends Worker.WorkerRpc<ROut>>(
554
- handlers: Worker.WorkerOptions<ROut, Rpc>,
555
- ): Worker.WorkerOptions<ROut | WorkerEnvironment | CloudflareOtlpSettings, Rpc> => {
556
- const telemetryLayer = workerLayer(options);
557
- const queue = handlers.queue;
558
-
559
- return {
560
- ...handlers,
561
- fetch:
562
- handlers.fetch === undefined
563
- ? undefined
564
- : handlers.fetch.pipe(Effect.provide(telemetryLayer)),
565
- queue:
566
- queue === undefined
567
- ? undefined
568
- : (batch) => queue(batch).pipe(Effect.provide(telemetryLayer)),
569
- rpc: provideRpcLayer(handlers.rpc, telemetryLayer),
570
- };
571
- };
572
-
573
- /**
574
- * Instrument Durable Object lifecycle handlers with event-scoped OTLP telemetry.
575
- *
576
- * Each defined handler is provided with {@link durableObjectLayer}. Because
577
- * Durable Object handlers run inside `Effect.scoped`, the exporter scope closes
578
- * and flushes at the end of each Cloudflare event.
579
- */
580
- export const instrumentDurableObjectOptions =
581
- (options?: LayerOptions & DurableObjectResourceOptions) =>
582
- <ROut, Rpc extends DurableObject.DurableObjectRpc<ROut>>(
583
- handlers: DurableObject.DurableObjectOptions<ROut, Rpc>,
584
- ): DurableObject.DurableObjectOptions<
585
- ROut | WorkerEnvironment | DurableObjectState | CloudflareOtlpSettings,
586
- Rpc
587
- > => {
588
- const telemetryLayer = durableObjectLayer(options);
589
- const alarm = handlers.alarm;
590
- const webSocketMessage = handlers.webSocketMessage;
591
- const webSocketClose = handlers.webSocketClose;
592
- const webSocketError = handlers.webSocketError;
593
-
594
- return {
595
- ...handlers,
596
- initialize:
597
- handlers.initialize === undefined
598
- ? undefined
599
- : handlers.initialize.pipe(Effect.provide(telemetryLayer)),
600
- fetch:
601
- handlers.fetch === undefined
602
- ? undefined
603
- : handlers.fetch.pipe(Effect.provide(telemetryLayer)),
604
- alarms:
605
- handlers.alarms === undefined
606
- ? undefined
607
- : handlers.alarms.pipe(Effect.provide(telemetryLayer)),
608
- alarm:
609
- alarm === undefined
610
- ? undefined
611
- : (alarmInfo) => alarm(alarmInfo).pipe(Effect.provide(telemetryLayer)),
612
- webSocketMessage:
613
- webSocketMessage === undefined
614
- ? undefined
615
- : (socket, message) =>
616
- webSocketMessage(socket, message).pipe(Effect.provide(telemetryLayer)),
617
- webSocketClose:
618
- webSocketClose === undefined
619
- ? undefined
620
- : (socket, code, reason, wasClean) =>
621
- webSocketClose(socket, code, reason, wasClean).pipe(Effect.provide(telemetryLayer)),
622
- webSocketError:
623
- webSocketError === undefined
624
- ? undefined
625
- : (socket, error) => webSocketError(socket, error).pipe(Effect.provide(telemetryLayer)),
626
- rpc: provideRpcLayer(handlers.rpc, telemetryLayer),
627
- };
628
- };
@@ -27,6 +27,9 @@ type RuntimeContext<ROut> = DurableObjectState | WorkerEnvironment | ROut;
27
27
  type HandlerContext<ROut> = RuntimeContext<ROut> | Scope.Scope;
28
28
 
29
29
  type FetchContext<ROut> = HandlerContext<ROut> | NativeRequest;
30
+ type RunOptions = {
31
+ readonly eventLayer?: boolean;
32
+ };
30
33
 
31
34
  const RunSymbol = Symbol.for("effect-cf/DurableObject/run");
32
35
 
@@ -72,7 +75,24 @@ export type RpcHandlers<ROut, Api> = {
72
75
  /**
73
76
  * Options for creating a Durable Object class backed by Effect handlers.
74
77
  */
75
- export interface DurableObjectOptions<ROut, Rpc extends DurableObjectRpc<ROut>> {
78
+ export interface DurableObjectOptions<
79
+ RRuntime,
80
+ REvent = never,
81
+ EventLayerError = never,
82
+ Rpc extends DurableObjectRpc<RRuntime | REvent> = Record<never, never>,
83
+ > {
84
+ /**
85
+ * Layer provided around each Cloudflare event handled by this Durable Object.
86
+ *
87
+ * The layer is built inside the event's Effect scope and finalized when the
88
+ * event effect completes. It is not applied to `initialize`, which is an
89
+ * instance-load lifecycle hook rather than a platform event.
90
+ */
91
+ readonly eventLayer?: Layer.Layer<
92
+ REvent,
93
+ EventLayerError,
94
+ DurableObjectState | WorkerEnvironment | RRuntime
95
+ >;
76
96
  /**
77
97
  * Effect run when Cloudflare loads this Durable Object instance into memory.
78
98
  *
@@ -81,11 +101,11 @@ export interface DurableObjectOptions<ROut, Rpc extends DurableObjectRpc<ROut>>
81
101
  * the same Durable Object id again after eviction or restart; use Durable
82
102
  * Object storage if work must happen only once per id.
83
103
  */
84
- readonly initialize?: Effect.Effect<void, unknown, HandlerContext<ROut>>;
104
+ readonly initialize?: Effect.Effect<void, unknown, HandlerContext<RRuntime>>;
85
105
  /** Optional RPC methods exposed as Durable Object instance methods. */
86
106
  readonly rpc?: Rpc;
87
107
  /** Optional fetch handler for HTTP/WebSocket requests. */
88
- readonly fetch?: Effect.Effect<Response, unknown, FetchContext<ROut>>;
108
+ readonly fetch?: Effect.Effect<Response, unknown, FetchContext<RRuntime | REvent>>;
89
109
  /**
90
110
  * Optional logical alarm processing effect.
91
111
  *
@@ -93,24 +113,24 @@ export interface DurableObjectOptions<ROut, Rpc extends DurableObjectRpc<ROut>>
93
113
  * `DurableObjectAlarm.processDue(...)` so the reusable scheduler stays inside
94
114
  * the Durable Object's single managed runtime boundary.
95
115
  */
96
- readonly alarms?: Effect.Effect<unknown, unknown, HandlerContext<ROut>>;
116
+ readonly alarms?: Effect.Effect<unknown, unknown, HandlerContext<RRuntime | REvent>>;
97
117
  readonly alarm?: (
98
118
  alarmInfo?: globalThis.AlarmInvocationInfo,
99
- ) => Effect.Effect<void, unknown, HandlerContext<ROut>>;
119
+ ) => Effect.Effect<void, unknown, HandlerContext<RRuntime | REvent>>;
100
120
  readonly webSocketMessage?: (
101
121
  socket: DurableWebSocket,
102
122
  message: string | ArrayBuffer,
103
- ) => Effect.Effect<void, unknown, HandlerContext<ROut>>;
123
+ ) => Effect.Effect<void, unknown, HandlerContext<RRuntime | REvent>>;
104
124
  readonly webSocketClose?: (
105
125
  socket: DurableWebSocket,
106
126
  code: number,
107
127
  reason: string,
108
128
  wasClean: boolean,
109
- ) => Effect.Effect<void, unknown, HandlerContext<ROut>>;
129
+ ) => Effect.Effect<void, unknown, HandlerContext<RRuntime | REvent>>;
110
130
  readonly webSocketError?: (
111
131
  socket: DurableWebSocket,
112
132
  error: unknown,
113
- ) => Effect.Effect<void, unknown, HandlerContext<ROut>>;
133
+ ) => Effect.Effect<void, unknown, HandlerContext<RRuntime | REvent>>;
114
134
  }
115
135
 
116
136
  /**
@@ -127,11 +147,13 @@ export type DurableObjectClass<Rpc extends DurableObjectRpc<ROut>, ROut> = new (
127
147
  export const make = <
128
148
  ROut,
129
149
  LayerError,
130
- const Rpc extends DurableObjectRpc<ROut> = Record<never, never>,
150
+ REvent = never,
151
+ EventLayerError = never,
152
+ const Rpc extends DurableObjectRpc<ROut | REvent> = Record<never, never>,
131
153
  >(
132
154
  layer: Layer.Layer<ROut, LayerError, DurableObjectState | WorkerEnvironment>,
133
- options: DurableObjectOptions<ROut, Rpc> = {},
134
- ): DurableObjectClass<Rpc, ROut> => {
155
+ options: DurableObjectOptions<ROut, REvent, EventLayerError, Rpc> = {},
156
+ ): DurableObjectClass<Rpc, ROut | REvent> => {
135
157
  class EffectDurableObject extends CloudflareDurableObject<WorkerEnv> {
136
158
  readonly runtime: ManagedRuntime.ManagedRuntime<RuntimeContext<ROut>, LayerError>;
137
159
 
@@ -149,12 +171,24 @@ export const make = <
149
171
 
150
172
  const initialize = options.initialize;
151
173
  if (initialize !== undefined) {
152
- state.waitUntil(this[RunSymbol](initialize));
174
+ state.waitUntil(this[RunSymbol](initialize, { eventLayer: false }));
153
175
  }
154
176
  }
155
177
 
156
- [RunSymbol]<A, E>(effect: Effect.Effect<A, E, HandlerContext<ROut>>): Promise<A> {
157
- return this.runtime.runPromise(Effect.scoped(effect));
178
+ [RunSymbol]<A, E>(
179
+ effect: Effect.Effect<A, E, HandlerContext<ROut | REvent>>,
180
+ runOptions: RunOptions = {},
181
+ ): Promise<A> {
182
+ const effectWithEventLayer =
183
+ runOptions.eventLayer === false || options.eventLayer === undefined
184
+ ? effect
185
+ : effect.pipe(Effect.provide(options.eventLayer, { local: true }));
186
+
187
+ return this.runtime.runPromise(
188
+ Effect.scoped(
189
+ effectWithEventLayer as Effect.Effect<A, E | EventLayerError, HandlerContext<ROut>>,
190
+ ),
191
+ );
158
192
  }
159
193
 
160
194
  fetch(request: Request): Promise<Response> {
@@ -223,7 +257,9 @@ export const make = <
223
257
  (self, effect) => self[RunSymbol](effect),
224
258
  );
225
259
 
226
- return Entrypoint.assumeEntrypointClass<DurableObjectClass<Rpc, ROut>>(EffectDurableObject);
260
+ return Entrypoint.assumeEntrypointClass<DurableObjectClass<Rpc, ROut | REvent>>(
261
+ EffectDurableObject,
262
+ );
227
263
  };
228
264
 
229
265
  export type ServiceFreeSchema = S.Codec<any, any, never, never>;
@@ -285,11 +321,16 @@ export type Handlers<ROut, Self extends Definition.Any> = {
285
321
  ) => DurableObjectHandler<ROut, Method.Success<Self["methods"][Key]>>;
286
322
  };
287
323
 
288
- export interface Options<ROut, Self extends Definition.Any> extends Omit<
289
- DurableObjectOptions<ROut, Handlers<ROut, Self>>,
324
+ export interface Options<
325
+ ROut,
326
+ Self extends Definition.Any,
327
+ REvent = never,
328
+ EventLayerError = never,
329
+ > extends Omit<
330
+ DurableObjectOptions<ROut, REvent, EventLayerError, Handlers<ROut | REvent, Self>>,
290
331
  "rpc"
291
332
  > {
292
- readonly rpc: Handlers<ROut, Self>;
333
+ readonly rpc: Handlers<ROut | REvent, Self>;
293
334
  }
294
335
 
295
336
  export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Context.ServiceClass<
@@ -307,10 +348,10 @@ export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Co
307
348
  > & {
308
349
  readonly id: Id;
309
350
  readonly methods: MethodsShape;
310
- readonly make: <ROut, LayerError>(
351
+ readonly make: <ROut, LayerError, REvent = never, EventLayerError = never>(
311
352
  layer: Layer.Layer<ROut, LayerError, DurableObjectState | WorkerEnvironment>,
312
- options: Options<ROut, Definition<Id, MethodsShape>>,
313
- ) => DurableObjectClass<Handlers<ROut, Definition<Id, MethodsShape>>, ROut>;
353
+ options: Options<ROut, Definition<Id, MethodsShape>, REvent, EventLayerError>,
354
+ ) => DurableObjectClass<Handlers<ROut | REvent, Definition<Id, MethodsShape>>, ROut | REvent>;
314
355
  readonly layer: (
315
356
  options: LayerOptions,
316
357
  ) => Layer.Layer<
@@ -115,11 +115,21 @@ type BoundaryHandlers<ROut, Self extends Definition.Any> = {
115
115
  /**
116
116
  * Durable Object constructor options for a specific RPC definition.
117
117
  */
118
- export interface Options<ROut, Self extends Definition.Any> extends Omit<
119
- DurableObjectEntrypoint.DurableObjectOptions<ROut, Handlers<ROut, Self>>,
118
+ export interface Options<
119
+ ROut,
120
+ Self extends Definition.Any,
121
+ REvent = never,
122
+ EventLayerError = never,
123
+ > extends Omit<
124
+ DurableObjectEntrypoint.DurableObjectOptions<
125
+ ROut,
126
+ REvent,
127
+ EventLayerError,
128
+ Handlers<ROut | REvent, Self>
129
+ >,
120
130
  "rpc"
121
131
  > {
122
- readonly rpc: Handlers<ROut, Self>;
132
+ readonly rpc: Handlers<ROut | REvent, Self>;
123
133
  }
124
134
 
125
135
  export type LayerOptions = {
@@ -141,12 +151,12 @@ export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Co
141
151
  > & {
142
152
  readonly id: Id;
143
153
  readonly methods: MethodsShape;
144
- readonly make: <ROut, LayerError>(
154
+ readonly make: <ROut, LayerError, REvent = never, EventLayerError = never>(
145
155
  layer: Layer.Layer<ROut, LayerError, DurableObjectState | WorkerEnvironment>,
146
- options: Options<ROut, Definition<Id, MethodsShape>>,
156
+ options: Options<ROut, Definition<Id, MethodsShape>, REvent, EventLayerError>,
147
157
  ) => DurableObjectEntrypoint.DurableObjectClass<
148
- Handlers<ROut, Definition<Id, MethodsShape>>,
149
- ROut
158
+ Handlers<ROut | REvent, Definition<Id, MethodsShape>>,
159
+ ROut | REvent
150
160
  >;
151
161
  readonly layer: (
152
162
  options: LayerOptions,
@@ -195,9 +205,9 @@ const makeDefinition = <Id extends string, const MethodsShape extends Methods>(
195
205
  const definition: SelfDefinition = RpcDefinition.make(id, methods);
196
206
 
197
207
  return Object.assign(definition, {
198
- make: <ROut, LayerError>(
208
+ make: <ROut, LayerError, REvent = never, EventLayerError = never>(
199
209
  layer: Layer.Layer<ROut, LayerError, DurableObjectState | WorkerEnvironment>,
200
- options: Options<ROut, SelfDefinition>,
210
+ options: Options<ROut, SelfDefinition, REvent, EventLayerError>,
201
211
  ) =>
202
212
  DurableObjectEntrypoint.make(layer, {
203
213
  ...options,
package/src/Worker.ts CHANGED
@@ -88,6 +88,9 @@ type WorkerFetchContext<ROut> =
88
88
  type WorkerRpcContext<ROut> = WorkerBaseContext<ROut> | Scope.Scope;
89
89
 
90
90
  type RuntimeContext<ROut> = WorkerBaseContext<ROut>;
91
+ type RunOptions = {
92
+ readonly eventLayer?: boolean;
93
+ };
91
94
 
92
95
  const RunSymbol = Symbol.for("effect-cf/Worker/run");
93
96
 
@@ -127,13 +130,33 @@ export type RpcHandlers<ROut, Api> = {
127
130
  : never;
128
131
  };
129
132
 
130
- export interface WorkerOptions<ROut, Rpc extends WorkerRpc<ROut>> {
131
- readonly fetch?: Effect.Effect<WorkerFetchSuccess, unknown, WorkerFetchContext<ROut>>;
132
- readonly queue?: QueueHandler<ROut>;
133
+ export interface WorkerOptions<
134
+ RRuntime,
135
+ REvent = never,
136
+ EventLayerError = never,
137
+ Rpc extends WorkerRpc<RRuntime | REvent> = Record<never, never>,
138
+ > {
139
+ /**
140
+ * Layer provided around each Cloudflare event handled by this Worker.
141
+ *
142
+ * The layer is built inside the event's Effect scope and finalized when the
143
+ * event effect completes. Use this for event-scoped resources such as OTLP
144
+ * trace/log exporters that should flush at event completion.
145
+ */
146
+ readonly eventLayer?: Layer.Layer<REvent, EventLayerError, WorkerBaseContext<RRuntime>>;
147
+ readonly fetch?: Effect.Effect<
148
+ WorkerFetchSuccess,
149
+ unknown,
150
+ WorkerFetchContext<RRuntime | REvent>
151
+ >;
152
+ readonly queue?: QueueHandler<RRuntime | REvent>;
133
153
  readonly rpc?: Rpc;
134
154
  }
135
155
 
136
- export type FetchWorkerOptions<ROut> = Omit<WorkerOptions<ROut, Record<never, never>>, "rpc"> & {
156
+ export type FetchWorkerOptions<RRuntime, REvent = never, EventLayerError = never> = Omit<
157
+ WorkerOptions<RRuntime, REvent, EventLayerError, Record<never, never>>,
158
+ "rpc"
159
+ > & {
137
160
  readonly rpc?: never;
138
161
  };
139
162
 
@@ -173,28 +196,40 @@ const renderFetchSuccess = <E, R>(
173
196
  ),
174
197
  );
175
198
 
176
- const isWorkerOptions = <ROut, Rpc extends WorkerRpc<ROut>>(
177
- options: WorkerOptions<ROut, Rpc> | WorkerHandler<ROut>,
178
- ): options is WorkerOptions<ROut, Rpc> =>
199
+ const isWorkerOptions = <ROut, REvent, EventLayerError, Rpc extends WorkerRpc<ROut | REvent>>(
200
+ options: WorkerOptions<ROut, REvent, EventLayerError, Rpc> | WorkerHandler<ROut>,
201
+ ): options is WorkerOptions<ROut, REvent, EventLayerError, Rpc> =>
179
202
  typeof options === "object" &&
180
203
  options !== null &&
181
- ("fetch" in options || "queue" in options || "rpc" in options);
204
+ ("eventLayer" in options || "fetch" in options || "queue" in options || "rpc" in options);
182
205
 
183
206
  export function make<ROut, LayerError>(
184
207
  layer: Layer.Layer<ROut, LayerError, ExecutionContext | WorkerContext | WorkerEnvironment>,
185
208
  fetch: WorkerHandler<ROut>,
186
209
  ): WorkerClass<Record<never, never>, ROut>;
187
- export function make<ROut, LayerError, const Rpc extends WorkerRpc<ROut> = Record<never, never>>(
210
+ export function make<
211
+ ROut,
212
+ LayerError,
213
+ REvent = never,
214
+ EventLayerError = never,
215
+ const Rpc extends WorkerRpc<ROut | REvent> = Record<never, never>,
216
+ >(
188
217
  layer: Layer.Layer<ROut, LayerError, ExecutionContext | WorkerContext | WorkerEnvironment>,
189
- options: WorkerOptions<ROut, Rpc>,
190
- ): WorkerClass<Rpc, ROut>;
191
- export function make<ROut, LayerError, const Rpc extends WorkerRpc<ROut> = Record<never, never>>(
218
+ options: WorkerOptions<ROut, REvent, EventLayerError, Rpc>,
219
+ ): WorkerClass<Rpc, ROut | REvent>;
220
+ export function make<
221
+ ROut,
222
+ LayerError,
223
+ REvent = never,
224
+ EventLayerError = never,
225
+ const Rpc extends WorkerRpc<ROut | REvent> = Record<never, never>,
226
+ >(
192
227
  layer: Layer.Layer<ROut, LayerError, ExecutionContext | WorkerContext | WorkerEnvironment>,
193
- optionsOrFetch: WorkerOptions<ROut, Rpc> | WorkerHandler<ROut>,
194
- ): WorkerClass<Rpc, ROut> {
228
+ optionsOrFetch: WorkerOptions<ROut, REvent, EventLayerError, Rpc> | WorkerHandler<ROut>,
229
+ ): WorkerClass<Rpc, ROut | REvent> {
195
230
  const options = isWorkerOptions(optionsOrFetch)
196
231
  ? optionsOrFetch
197
- : ({ fetch: optionsOrFetch } as WorkerOptions<ROut, Rpc>);
232
+ : ({ fetch: optionsOrFetch } as WorkerOptions<ROut, REvent, EventLayerError, Rpc>);
198
233
 
199
234
  class EffectWorker extends CloudflareWorkerEntrypoint<WorkerEnv> {
200
235
  readonly runtime: ManagedRuntime.ManagedRuntime<RuntimeContext<ROut>, LayerError>;
@@ -226,8 +261,24 @@ export function make<ROut, LayerError, const Rpc extends WorkerRpc<ROut> = Recor
226
261
  this.runtime.runPromiseExit(effect as Effect.Effect<A, E, RuntimeContext<ROut>>);
227
262
  }
228
263
 
229
- [RunSymbol]<A, E>(effect: Effect.Effect<A, E, RuntimeContext<ROut> | Scope.Scope>): Promise<A> {
230
- return this.runtime.runPromise(Effect.scoped(effect));
264
+ [RunSymbol]<A, E>(
265
+ effect: Effect.Effect<A, E, RuntimeContext<ROut> | REvent | Scope.Scope>,
266
+ runOptions: RunOptions = {},
267
+ ): Promise<A> {
268
+ const effectWithEventLayer =
269
+ runOptions.eventLayer === false || options.eventLayer === undefined
270
+ ? effect
271
+ : effect.pipe(Effect.provide(options.eventLayer, { local: true }));
272
+
273
+ return this.runtime.runPromise(
274
+ Effect.scoped(
275
+ effectWithEventLayer as Effect.Effect<
276
+ A,
277
+ E | EventLayerError,
278
+ RuntimeContext<ROut> | Scope.Scope
279
+ >,
280
+ ),
281
+ );
231
282
  }
232
283
 
233
284
  fetch(request: Request): Promise<Response> {
@@ -246,7 +297,7 @@ export function make<ROut, LayerError, const Rpc extends WorkerRpc<ROut> = Recor
246
297
  renderFetchSuccess(fetchHandler).pipe(Effect.provide(requestServices)) as Effect.Effect<
247
298
  Response,
248
299
  unknown,
249
- RuntimeContext<ROut> | Scope.Scope
300
+ RuntimeContext<ROut> | REvent | Scope.Scope
250
301
  >,
251
302
  );
252
303
  }
@@ -272,12 +323,18 @@ export function make<ROut, LayerError, const Rpc extends WorkerRpc<ROut> = Recor
272
323
  (self, effect) => self[RunSymbol](effect),
273
324
  );
274
325
 
275
- return Entrypoint.assumeEntrypointClass<WorkerClass<Rpc, ROut>>(EffectWorker);
326
+ return Entrypoint.assumeEntrypointClass<WorkerClass<Rpc, ROut | REvent>>(EffectWorker);
276
327
  }
277
328
 
278
- export const makeFetchHandler = <ROut, LayerError, Env extends WorkerEnv = WorkerEnv>(
329
+ export const makeFetchHandler = <
330
+ ROut,
331
+ LayerError,
332
+ REvent = never,
333
+ EventLayerError = never,
334
+ Env extends WorkerEnv = WorkerEnv,
335
+ >(
279
336
  layer: Layer.Layer<ROut, LayerError, ExecutionContext | WorkerContext | WorkerEnvironment>,
280
- options: FetchWorkerOptions<ROut>,
337
+ options: FetchWorkerOptions<ROut, REvent, EventLayerError>,
281
338
  ): FetchHandler<Env> => {
282
339
  const WorkerClass = make(layer, options);
283
340
 
@@ -341,11 +398,13 @@ export type Handlers<ROut, Self extends Definition.Any> = {
341
398
  ) => WorkerRpcHandler<ROut, Method.Success<Self["methods"][Key]>>;
342
399
  };
343
400
 
344
- export interface Options<ROut, Self extends Definition.Any> extends Omit<
345
- WorkerOptions<ROut, Handlers<ROut, Self>>,
346
- "rpc"
347
- > {
348
- readonly rpc: Handlers<ROut, Self>;
401
+ export interface Options<
402
+ ROut,
403
+ Self extends Definition.Any,
404
+ REvent = never,
405
+ EventLayerError = never,
406
+ > extends Omit<WorkerOptions<ROut, REvent, EventLayerError, Handlers<ROut | REvent, Self>>, "rpc"> {
407
+ readonly rpc: Handlers<ROut | REvent, Self>;
349
408
  }
350
409
 
351
410
  export type LayerOptions = WorkerDefinition.LayerOptions;
@@ -365,10 +424,10 @@ export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Co
365
424
  > & {
366
425
  readonly id: Id;
367
426
  readonly methods: MethodsShape;
368
- readonly make: <ROut, LayerError>(
427
+ readonly make: <ROut, LayerError, REvent = never, EventLayerError = never>(
369
428
  layer: Layer.Layer<ROut, LayerError, ExecutionContext | WorkerContext | WorkerEnvironment>,
370
- options: Options<ROut, Definition<Id, MethodsShape>>,
371
- ) => WorkerClass<Handlers<ROut, Definition<Id, MethodsShape>>, ROut>;
429
+ options: Options<ROut, Definition<Id, MethodsShape>, REvent, EventLayerError>,
430
+ ) => WorkerClass<Handlers<ROut | REvent, Definition<Id, MethodsShape>>, ROut | REvent>;
372
431
  readonly layer: (
373
432
  options: LayerOptions,
374
433
  ) => Layer.Layer<
@@ -118,11 +118,16 @@ type BoundaryHandlers<ROut, Self extends Definition.Any> = {
118
118
  /**
119
119
  * Worker constructor options for a specific RPC definition.
120
120
  */
121
- export interface Options<ROut, Self extends Definition.Any> extends Omit<
122
- WorkerEntrypoint.WorkerOptions<ROut, Handlers<ROut, Self>>,
121
+ export interface Options<
122
+ ROut,
123
+ Self extends Definition.Any,
124
+ REvent = never,
125
+ EventLayerError = never,
126
+ > extends Omit<
127
+ WorkerEntrypoint.WorkerOptions<ROut, REvent, EventLayerError, Handlers<ROut | REvent, Self>>,
123
128
  "rpc"
124
129
  > {
125
- readonly rpc: Handlers<ROut, Self>;
130
+ readonly rpc: Handlers<ROut | REvent, Self>;
126
131
  }
127
132
 
128
133
  export type LayerOptions = {
@@ -144,14 +149,17 @@ export type TagClass<Self, Id extends string, MethodsShape extends Methods> = Co
144
149
  > & {
145
150
  readonly id: Id;
146
151
  readonly methods: MethodsShape;
147
- readonly make: <ROut, LayerError>(
152
+ readonly make: <ROut, LayerError, REvent = never, EventLayerError = never>(
148
153
  layer: Layer.Layer<
149
154
  ROut,
150
155
  LayerError,
151
156
  WorkerEntrypoint.ExecutionContext | WorkerEntrypoint.WorkerContext | WorkerEnvironment
152
157
  >,
153
- options: Options<ROut, Definition<Id, MethodsShape>>,
154
- ) => WorkerEntrypoint.WorkerClass<Handlers<ROut, Definition<Id, MethodsShape>>, ROut>;
158
+ options: Options<ROut, Definition<Id, MethodsShape>, REvent, EventLayerError>,
159
+ ) => WorkerEntrypoint.WorkerClass<
160
+ Handlers<ROut | REvent, Definition<Id, MethodsShape>>,
161
+ ROut | REvent
162
+ >;
155
163
  readonly layer: (
156
164
  options: LayerOptions,
157
165
  ) => Layer.Layer<
@@ -199,13 +207,13 @@ const makeDefinition = <Id extends string, const MethodsShape extends Methods>(
199
207
  const definition: SelfDefinition = RpcDefinition.make(id, methods);
200
208
 
201
209
  return Object.assign(definition, {
202
- make: <ROut, LayerError>(
210
+ make: <ROut, LayerError, REvent = never, EventLayerError = never>(
203
211
  layer: Layer.Layer<
204
212
  ROut,
205
213
  LayerError,
206
214
  WorkerEntrypoint.ExecutionContext | WorkerEntrypoint.WorkerContext | WorkerEnvironment
207
215
  >,
208
- options: Options<ROut, SelfDefinition>,
216
+ options: Options<ROut, SelfDefinition, REvent, EventLayerError>,
209
217
  ) =>
210
218
  WorkerEntrypoint.make(layer, {
211
219
  ...options,