effect-cf 0.40.1 → 0.40.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # effect-cf
2
2
 
3
+ ## 0.40.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#157](https://github.com/danieljvdm/effect-cf/pull/157) [`279eecd`](https://github.com/danieljvdm/effect-cf/commit/279eecd1a5ea9112e727497e0aac666142e7a7f8) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Prevent Durable Object SQLite transactions from stalling when a blocked owner timer precedes an Effect scheduler yield. Keep transaction isolation, rollback, and the caller's scheduler after the transaction completes.
8
+
9
+ ## 0.40.2
10
+
11
+ ### Patch Changes
12
+
13
+ - [#155](https://github.com/danieljvdm/effect-cf/pull/155) [`c23dd31`](https://github.com/danieljvdm/effect-cf/commit/c23dd319f7ea018f803de31095937c2ca69eb0ed) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Fix initialization failures when importing Queue or Workflow definitions from the published ES modules. Their factory exports remain the same functions regardless of module evaluation order.
14
+
3
15
  ## 0.40.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -8,6 +8,8 @@ npm install effect-cf "effect@^4.0.0-rc.112"
8
8
 
9
9
  The repository tests against workerd `1.20260825.1` and `@cloudflare/workers-types@5.20260825.1`. Use `compatibility_date: "2026-08-25"` in Wrangler.
10
10
 
11
+ See the [runtime performance guide](https://github.com/danieljvdm/effect-cf/blob/main/docs/runtime-performance.md) for measured alarm batching and telemetry configuration guidance.
12
+
11
13
  ## Worker
12
14
 
13
15
  ```ts
package/dist/D1.d.mts CHANGED
@@ -2,8 +2,8 @@ import { WorkerEnvironment } from "./Environment.mjs";
2
2
  import { BindingNotFoundError, BindingService, BindingValidationError } from "./Binding.mjs";
3
3
  import * as Layer$1 from "effect/Layer";
4
4
  import { D1Client } from "@effect/sql-d1";
5
- import { Config } from "effect";
6
5
  import { SqlClient } from "effect/unstable/sql";
6
+ import { Config } from "effect";
7
7
  declare namespace D1_d_exports {
8
8
  export { D1Definition, D1Service, D1SqlLayerOptions, Service, TypeId, make };
9
9
  }
@@ -1,16 +1,25 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { DurableObjectState } from "./DurableObjectState.mjs";
3
+ import * as Context from "effect/Context";
3
4
  import * as Effect from "effect/Effect";
4
5
  import * as Layer from "effect/Layer";
5
6
  import { SqliteClient } from "@effect/sql-sqlite-do";
7
+ import * as Scheduler from "effect/Scheduler";
8
+ import * as Reactivity from "effect/unstable/reactivity/Reactivity";
9
+ import { SqlClient } from "effect/unstable/sql";
6
10
  //#region src/DurableObjectSqlite.ts
7
11
  var DurableObjectSqlite_exports = /* @__PURE__ */ __exportAll({ layer: () => layer });
8
- const layer = (options) => Layer.unwrap(Effect.gen(function* () {
12
+ const layer = (options) => Layer.effectContext(Effect.gen(function* () {
9
13
  const state = yield* DurableObjectState;
10
- return SqliteClient.layer({
14
+ const client = yield* SqliteClient.make({
11
15
  ...options,
12
16
  storage: state.raw.storage
13
17
  });
14
- }));
18
+ const original = client.withTransaction;
19
+ const scheduler = new Scheduler.MixedScheduler("sync");
20
+ const withTransaction = (body) => original(body).pipe(Effect.provideService(Scheduler.Scheduler, scheduler));
21
+ Object.assign(client, { withTransaction });
22
+ return Context.make(SqliteClient.SqliteClient, client).pipe(Context.add(SqlClient.SqlClient, client));
23
+ })).pipe(Layer.provide(Reactivity.layer));
15
24
  //#endregion
16
25
  export { DurableObjectSqlite_exports, layer };
@@ -2,8 +2,8 @@ import { WorkerEnvironment } from "./Environment.mjs";
2
2
  import { BindingNotFoundError, BindingValidationError } from "./Binding.mjs";
3
3
  import { LayerOptions, TagClass } from "./Hyperdrive.mjs";
4
4
  import * as Layer from "effect/Layer";
5
- import { PgClient } from "@effect/sql-pg";
6
5
  import { SqlClient, SqlError } from "effect/unstable/sql";
6
+ import { PgClient } from "@effect/sql-pg";
7
7
  //#region src/HyperdrivePg.d.ts
8
8
  type PgLayerOptions = Omit<Parameters<typeof PgClient.makeClient>[0], "url" | "host" | "port" | "path" | "ssl" | "database" | "username" | "password" | "stream">;
9
9
  declare const layer: <Self, Id extends string>(tag: TagClass<Self, Id>, binding: LayerOptions, options?: PgLayerOptions) => Layer.Layer<PgClient.PgClient | SqlClient.SqlClient, BindingNotFoundError | BindingValidationError | SqlError.SqlError, WorkerEnvironment>;
package/dist/Queue.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { WorkerEnvironment } from "./Environment.mjs";
2
- import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, TagClass as TagClass$1, implement as implement$1 } from "./QueueDefinition.mjs";
2
+ import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, Tag, TagClass as TagClass$1, implement } from "./QueueDefinition.mjs";
3
3
  import { ExecutionContext, WorkerContext } from "./Worker.mjs";
4
4
  import * as Effect from "effect/Effect";
5
5
  import { Scope } from "effect";
@@ -58,10 +58,6 @@ declare namespace Definition {
58
58
  }
59
59
  type LayerOptions = LayerOptions$1;
60
60
  type TagClass<Self, Id extends string, Message extends Definition$1.Any["message"]> = TagClass$1<Self, Id, Message>;
61
- declare const Tag: <Self>() => <Id extends string, Message extends Definition$1.Any["message"]>(id: Id, definition: {
62
- readonly message: Message;
63
- }) => TagClass<Self, Id, Message>;
64
- declare const implement: typeof implement$1;
65
61
  type Handler<ROut, Self extends Definition$1.Any> = Handler$1<ROut, Self>;
66
62
  type Options<ROut, Self extends Definition$1.Any> = Options$1<ROut, Self>;
67
63
  //#endregion
package/dist/Queue.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { causeMessage } from "./internal/ErrorMessage.mjs";
3
- import { Tag as Tag$1, implement as implement$1 } from "./QueueDefinition.mjs";
3
+ import { Tag, implement } from "./QueueDefinition.mjs";
4
4
  import * as Data from "effect/Data";
5
5
  import * as Effect from "effect/Effect";
6
6
  //#region src/Queue.ts
@@ -48,7 +48,5 @@ const decodeBatch = (batch, decodeBody) => Effect.gen(function* () {
48
48
  }
49
49
  return fromMessageBatch(batch, messages);
50
50
  });
51
- const Tag = Tag$1;
52
- const implement = implement$1;
53
51
  //#endregion
54
52
  export { QueueMessageDecodeError, Queue_exports, Tag, decodeBatch, fromMessage, fromMessageBatch, implement };
@@ -1,6 +1,6 @@
1
1
  import { WorkerEnv, WorkerEnvironment } from "./Environment.mjs";
2
2
  import { ExecutionContext, WorkerContext } from "./Worker.mjs";
3
- import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, TagClass as TagClass$1, implement as implement$1 } from "./WorkflowDefinition.mjs";
3
+ import { Definition as Definition$1, Handler as Handler$1, LayerOptions as LayerOptions$1, Options as Options$1, Tag, TagClass as TagClass$1, implement } from "./WorkflowDefinition.mjs";
4
4
  import * as Context$1 from "effect/Context";
5
5
  import * as Effect from "effect/Effect";
6
6
  import * as Layer$1 from "effect/Layer";
@@ -80,11 +80,6 @@ declare namespace Definition {
80
80
  }
81
81
  type LayerOptions = LayerOptions$1;
82
82
  type TagClass<Self, Id extends string, Payload extends Definition$1.Any["payload"], Result extends Definition$1.Any["result"]> = TagClass$1<Self, Id, Payload, Result>;
83
- declare const Tag: <Self>() => <Id extends string, Payload extends Definition$1.Any["payload"], Result extends Definition$1.Any["result"]>(id: Id, definition: {
84
- readonly payload: Payload;
85
- readonly result: Result;
86
- }) => TagClass<Self, Id, Payload, Result>;
87
- declare const implement: typeof implement$1;
88
83
  type Handler<ROut, Self extends Definition$1.Any> = Handler$1<ROut, Self>;
89
84
  type Options<ROut, Self extends Definition$1.Any> = Options$1<ROut, Self>;
90
85
  //#endregion
package/dist/Workflow.mjs CHANGED
@@ -4,7 +4,7 @@ import { fromExecutionContext } from "./internal/WorkerContext.mjs";
4
4
  import { assumeEntrypointClass } from "./internal/Entrypoint.mjs";
5
5
  import { makeEntrypointRuntime, runEventPromise } from "./internal/Runtime.mjs";
6
6
  import { ExecutionContext, WorkerContext } from "./Worker.mjs";
7
- import { Tag as Tag$1, implement as implement$1 } from "./WorkflowDefinition.mjs";
7
+ import { Tag, implement } from "./WorkflowDefinition.mjs";
8
8
  import * as Context from "effect/Context";
9
9
  import * as Data from "effect/Data";
10
10
  import * as Effect from "effect/Effect";
@@ -133,7 +133,5 @@ const step = (name, effect, config) => Effect.flatMap(WorkflowStep$1, (workflowS
133
133
  const sleep = (name, duration) => Effect.flatMap(WorkflowStep$1, (workflowStep) => workflowStep.sleep(name, duration));
134
134
  const sleepUntil = (name, timestamp) => Effect.flatMap(WorkflowStep$1, (workflowStep) => workflowStep.sleepUntil(name, timestamp));
135
135
  const waitForEvent = (name, options) => Effect.flatMap(WorkflowStep$1, (workflowStep) => workflowStep.waitForEvent(name, options));
136
- const Tag = Tag$1;
137
- const implement = implement$1;
138
136
  //#endregion
139
137
  export { Tag, WorkflowEvent$1 as WorkflowEvent, WorkflowStep$1 as WorkflowStep, WorkflowStepContext$1 as WorkflowStepContext, WorkflowStepError, WorkflowStepNonRetryableError, Workflow_exports, implement, make, sleep, sleepUntil, step, waitForEvent };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.40.1",
3
+ "version": "0.40.3",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,7 +1,10 @@
1
1
  import { SqliteClient } from "@effect/sql-sqlite-do";
2
+ import * as Context from "effect/Context";
2
3
  import * as Effect from "effect/Effect";
3
4
  import * as Layer from "effect/Layer";
4
- import type { SqlClient } from "effect/unstable/sql";
5
+ import * as Scheduler from "effect/Scheduler";
6
+ import * as Reactivity from "effect/unstable/reactivity/Reactivity";
7
+ import { SqlClient } from "effect/unstable/sql";
5
8
 
6
9
  import { DurableObjectState } from "./DurableObjectState";
7
10
 
@@ -10,10 +13,22 @@ export type SqliteLayerOptions = Omit<SqliteClient.SqliteClientConfig, "db" | "s
10
13
  export const layer = (
11
14
  options?: SqliteLayerOptions,
12
15
  ): Layer.Layer<SqliteClient.SqliteClient | SqlClient.SqlClient, never, DurableObjectState> =>
13
- Layer.unwrap(
16
+ Layer.effectContext(
14
17
  Effect.gen(function* () {
15
18
  const state = yield* DurableObjectState;
19
+ const client = yield* SqliteClient.make({ ...options, storage: state.raw.storage });
20
+ const original = client.withTransaction;
21
+ const scheduler = new Scheduler.MixedScheduler("sync");
22
+ const withTransaction: SqliteClient.SqliteClient["withTransaction"] = (body) =>
23
+ original(body).pipe(Effect.provideService(Scheduler.Scheduler, scheduler));
16
24
 
17
- return SqliteClient.layer({ ...options, storage: state.raw.storage });
25
+ // Native timers retain their input gate. A blocked parent timer can prevent
26
+ // a transaction's later timer from running, so yield through microtasks until
27
+ // the native transaction settles. Keep the original client and SQL permit.
28
+ Object.assign(client, { withTransaction });
29
+
30
+ return Context.make(SqliteClient.SqliteClient, client).pipe(
31
+ Context.add(SqlClient.SqlClient, client),
32
+ );
18
33
  }),
19
- );
34
+ ).pipe(Layer.provide(Reactivity.layer));
package/src/Queue.ts CHANGED
@@ -4,7 +4,7 @@ import type { Scope } from "effect";
4
4
 
5
5
  import type { ExecutionContext, WorkerContext } from "./Worker";
6
6
  import type { WorkerEnvironment } from "./Environment";
7
- import * as QueueDefinition from "./QueueDefinition";
7
+ import type * as QueueDefinition from "./QueueDefinition";
8
8
  import * as ErrorMessage from "./internal/ErrorMessage";
9
9
 
10
10
  export interface QueueMessage<Body> {
@@ -117,15 +117,7 @@ export type TagClass<
117
117
  Message extends QueueDefinition.Definition.Any["message"],
118
118
  > = QueueDefinition.TagClass<Self, Id, Message>;
119
119
 
120
- export const Tag: <Self>() => <
121
- Id extends string,
122
- Message extends QueueDefinition.Definition.Any["message"],
123
- >(
124
- id: Id,
125
- definition: { readonly message: Message },
126
- ) => TagClass<Self, Id, Message> = QueueDefinition.Tag;
127
-
128
- export const implement = QueueDefinition.implement;
120
+ export { implement, Tag } from "./QueueDefinition";
129
121
 
130
122
  export type Handler<ROut, Self extends QueueDefinition.Definition.Any> = QueueDefinition.Handler<
131
123
  ROut,
package/src/Workflow.ts CHANGED
@@ -20,7 +20,7 @@ import type { ManagedRuntime, Scope } from "effect";
20
20
 
21
21
  import { WorkerEnvironment, type WorkerEnv } from "./Environment";
22
22
  import { ExecutionContext, WorkerContext } from "./Worker";
23
- import * as WorkflowDefinition from "./WorkflowDefinition";
23
+ import type * as WorkflowDefinition from "./WorkflowDefinition";
24
24
  import * as Entrypoint from "./internal/Entrypoint";
25
25
  import * as ErrorMessage from "./internal/ErrorMessage";
26
26
  import * as Runtime from "./internal/Runtime";
@@ -318,19 +318,7 @@ export type TagClass<
318
318
  Result extends WorkflowDefinition.Definition.Any["result"],
319
319
  > = WorkflowDefinition.TagClass<Self, Id, Payload, Result>;
320
320
 
321
- export const Tag: <Self>() => <
322
- Id extends string,
323
- Payload extends WorkflowDefinition.Definition.Any["payload"],
324
- Result extends WorkflowDefinition.Definition.Any["result"],
325
- >(
326
- id: Id,
327
- definition: {
328
- readonly payload: Payload;
329
- readonly result: Result;
330
- },
331
- ) => TagClass<Self, Id, Payload, Result> = WorkflowDefinition.Tag;
332
-
333
- export const implement = WorkflowDefinition.implement;
321
+ export { implement, Tag } from "./WorkflowDefinition";
334
322
 
335
323
  export type Handler<
336
324
  ROut,