effect-cf 0.20.1 → 0.23.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.
Files changed (53) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +27 -3
  3. package/dist/{Hyperdrive-RTjgirMV.d.mts → Hyperdrive-COyg7R26.d.mts} +40 -13
  4. package/dist/HyperdrivePg.d.mts +13 -5
  5. package/dist/HyperdrivePg.mjs +12 -7
  6. package/dist/index.d.mts +1113 -922
  7. package/dist/index.mjs +980 -604
  8. package/package.json +10 -5
  9. package/src/AiGateway.ts +82 -47
  10. package/src/AnalyticsEngine.ts +74 -58
  11. package/src/Binding.ts +66 -13
  12. package/src/BrowserRendering.ts +30 -7
  13. package/src/Cache.ts +32 -8
  14. package/src/CloudflareOtlp.ts +32 -9
  15. package/src/ContainerNamespace.ts +251 -80
  16. package/src/D1.ts +13 -3
  17. package/src/DurableObject.ts +27 -164
  18. package/src/DurableObjectAlarm.ts +30 -9
  19. package/src/DurableObjectDefinition.ts +58 -54
  20. package/src/DurableObjectNamespace.ts +99 -96
  21. package/src/DurableObjectRpcWebSocket.ts +14 -6
  22. package/src/DurableObjectSqlite.ts +6 -3
  23. package/src/DurableObjectState.ts +63 -39
  24. package/src/DurableObjectStorage.ts +7 -1
  25. package/src/DurableObjectWebSocket.ts +51 -41
  26. package/src/Email.ts +40 -13
  27. package/src/Environment.ts +26 -6
  28. package/src/Hyperdrive.ts +2 -2
  29. package/src/HyperdrivePg.ts +25 -13
  30. package/src/Images.ts +77 -82
  31. package/src/Kv.ts +37 -27
  32. package/src/Queue.ts +6 -1
  33. package/src/QueueBinding.ts +18 -21
  34. package/src/QueueDefinition.ts +15 -14
  35. package/src/R2.ts +107 -29
  36. package/src/Rpc.ts +3 -1
  37. package/src/RpcDefinition.ts +177 -133
  38. package/src/ServiceBinding.ts +112 -108
  39. package/src/Vectorize.ts +59 -14
  40. package/src/Worker.ts +172 -192
  41. package/src/WorkerDefinition.ts +5 -10
  42. package/src/WorkersAi.ts +27 -17
  43. package/src/Workflow.ts +54 -49
  44. package/src/WorkflowBinding.ts +19 -11
  45. package/src/WorkflowDefinition.ts +24 -27
  46. package/src/index.ts +4 -3
  47. package/src/internal/Entrypoint.ts +3 -1
  48. package/src/internal/ErrorMessage.ts +24 -0
  49. package/src/internal/RpcInvocation.ts +11 -8
  50. package/src/internal/Runtime.ts +52 -0
  51. package/src/internal/WorkerContext.ts +39 -17
  52. package/src/Entry.ts +0 -259
  53. package/src/internal/Clock.ts +0 -37
package/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # effect-cf
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#78](https://github.com/danieljvdm/effect-cf/pull/78) [`f753742`](https://github.com/danieljvdm/effect-cf/commit/f753742500603ea604f4f11d4c7840a41efb849b) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Extend the `ContainerNamespace` client with the remaining caller-side Container primitives: `waitForPort` (preserving the native retry-count result), the runtime host-policy operations (`setAllowedHosts`, `setDeniedHosts`, `allowHost`, `denyHost`, `removeAllowedHost`, `removeDeniedHost`), and numeric stop signals alongside the named ones. `ContainerNamespace.Tag` now accepts an optional exact native namespace type (for example `DurableObjectNamespace<CodexSandbox>`) so `rawUnsafe` on the namespace and on named instances preserves the exact native namespace and stub types, including extra subclass methods. Existing consumers compile unchanged via default type parameters.
8
+
9
+ - [#78](https://github.com/danieljvdm/effect-cf/pull/78) [`f753742`](https://github.com/danieljvdm/effect-cf/commit/f753742500603ea604f4f11d4c7840a41efb849b) Thanks [@danieljvdm](https://github.com/danieljvdm)! - `DurableObjectState.waitUntil` now also accepts an Effect, running it in the background with the caller's Effect context and the same failure modes as `WorkerContext.waitUntil` (`"observe"` logs or routes failures to `onFailure`; `"propagate"` also rejects the native `waitUntil` promise). The existing Promise form is unchanged, so Durable Objects no longer need to capture a Context and call `Effect.runPromiseWith` to schedule background Effects.
10
+
11
+ ## 0.22.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#73](https://github.com/danieljvdm/effect-cf/pull/73) [`9096e1e`](https://github.com/danieljvdm/effect-cf/commit/9096e1e6801bb9ac29ce8de0fa30902d9e210983) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Encode RPC method schemas through their canonical JSON codec at the Workers RPC boundary. Declaration schemas such as `Schema.Result` keep their container instance in their encoded form, so Durable Object, Worker entrypoint, and service binding RPC methods declared with them crashed in production with `DataCloneError` even though local same-isolate calls worked. Wire values are now plain JSON in both directions: clients encode arguments and decode results back into real instances, servers decode arguments and encode results, and codec failures still surface as tagged errors naming the definition and method. The `Method.EncodedArgs` and `Method.EncodedSuccess` utility types now report the JSON wire form.
16
+
17
+ ## 0.21.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [#69](https://github.com/danieljvdm/effect-cf/pull/69) [`16d6190`](https://github.com/danieljvdm/effect-cf/commit/16d6190bc022f040b6e9ddb1f583a973357598c3) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Align effect-cf with effect 4.0.0-beta.105 canonical APIs. This release contains breaking renames alongside behavior fixes surfaced by a full audit of the beta.65 → beta.105 upgrade.
22
+
23
+ Breaking changes:
24
+
25
+ - `unsafeRaw` is now `rawUnsafe` on every binding client and definition tag, following the effect v4 `Unsafe`-suffix convention. Definition tag statics are now Effect properties (matching the client shape) rather than zero-arg functions.
26
+ - `Kv` clients: `remove` is now `delete`.
27
+ - Layer variants renamed: `AnalyticsEngine.queryFetchLayer`/`queryFetchLayerConfig` → `layerFetch`/`layerFetchConfig` (tag fields `fetchLayer`/`fetchLayerConfig` likewise); `CloudflareOtlp.workerLayer`/`durableObjectLayer` → `layerWorker`/`layerDurableObject`.
28
+ - Definition tags (Durable Objects, Queues, Workflows, Containers, Bindings) are keyed as `effect-cf/<Module>/<id>` instead of the bare user id, so a definition named `"X"` no longer silently collides with an unrelated service keyed `"X"`. `definition.id` is unchanged.
29
+ - Queue producers must provide `sendBatch`; the silent sequential-send fallback (which lost batch atomicity) was removed and now fails with `QueueOperationError`.
30
+ - `Worker.renderHttpResponse` removed — return `HttpServerResponse` values directly from fetch handlers to get canonical response handling, including streaming-scope transfer.
31
+ - `RpcDefinition`: the plain-Error `ReservedMethodNameError` and `assertNoReservedMethodNames` were removed (use `assertNoReservedMethods`, which now throws the tagged `RpcReservedMethodNameError`); the `index` field was removed from argument encode/decode errors (positional info lives in the schema issue path).
32
+ - `Worker.TagFactory` / `DurableObject.TagFactory` types removed; the definition type surface is now re-exported from `WorkerDefinition`/`DurableObjectDefinition`.
33
+ - The unexported legacy `Entry` module and the internal Cloudflare clock were deleted; the effect default clock is used (its epoch time is monotonic-anchored, so it may skew from `Date.now()` by microseconds).
34
+ - effect peer dependencies are pinned exactly to `4.0.0-beta.105` while the package depends on `effect/unstable/*` modules.
35
+
36
+ Fixes:
37
+
38
+ - `DurableObjectSqlite.layer` now passes Durable Object storage to the SQL client, so `sql.withTransaction` works — previously every transaction failed at runtime.
39
+ - `CloudflareOtlp` layers now expose `OtlpExporter.Flusher`, and Worker fetch handlers automatically flush buffered telemetry via `ctx.waitUntil` after each response — telemetry is no longer lost when the isolate freezes after responding.
40
+ - Worker fetch handlers built with `makeFetchHandler` cache the runtime per environment instead of rebuilding every layer on each request.
41
+ - RPC method errors keep their tags across the Workers RPC wire: `RpcArgumentCountError`, `RpcArgumentDecodeError`, and `RpcSuccessEncodeError` are schema-serialized at the entrypoint and rehydrated as tagged instances on the caller side.
42
+ - The Durable Object RPC WebSocket transport closes the socket with code 1009 when a frame exceeds the serialization buffer limit instead of leaving the connection in a poisoned state.
43
+ - `DurableObjectWebSocket.acceptUpgrade` fails with a typed `DurableWebSocketAttachmentError` for non-serializable attachments instead of an untyped defect.
44
+ - Cloudflare Workflow steps fail with a typed `WorkflowStepError` carrying the step name, operation, and cause instead of leaking raw `unknown` rejections.
45
+ - `AiGateway` HTTP requests abort in-flight fetches when the running fiber is interrupted, and merge a caller-supplied `AbortSignal`.
46
+
47
+ Additions:
48
+
49
+ - Named tracing spans across the public client surface (`Kv.put`, `R2.get`, `DurableObject.call`, `QueueBinding.send`, `Email.send`, ...) with binding/operation attributes, so operations show up in the OTLP traces the package exports.
50
+ - Error classes render actionable messages by default: `Cause.pretty` and logs now show the binding, operation, error code when present, and the underlying cause instead of an empty message with a stack trace.
51
+ - `WorkerConfig.providerFromEnv` accepts `{ preserveEmptyStrings: true }` for environments where an empty-string var must decode as `""` rather than as absent.
52
+ - `Email` error `code` extraction is documented as best-effort (dev-time remote-proxy bindings can strip the property).
53
+ - `package.json` declares `sideEffects: []` for better tree-shaking of Workers bundles, and `@cloudflare/workers-types` is an optional peer for consumers type-checking against the public declarations.
54
+
3
55
  ## 0.20.1
4
56
 
5
57
  ### Patch Changes
package/README.md CHANGED
@@ -87,6 +87,12 @@ export const readCounter = Effect.gen(function* () {
87
87
 
88
88
  Define Wrangler bindings and migrations in the consuming application. Durable Object namespace bindings are provided with `YourObject.layer({ binding })`, and consumers use `const namespace = yield* YourObject`.
89
89
 
90
+ `DurableObjectState.waitUntil` accepts either a raw Promise or an Effect. The
91
+ Effect form runs in the background with the caller's Effect context and the
92
+ same failure modes as `WorkerContext.waitUntil`, so Durable Objects can
93
+ schedule background Effects (for example a pump consuming an outbound
94
+ WebSocket) without capturing a Context and calling `Effect.runPromiseWith`.
95
+
90
96
  ## Container Example
91
97
 
92
98
  Container entrypoints remain owned by `@cloudflare/containers`; `effect-cf`
@@ -118,12 +124,30 @@ export default Worker.make(RenderersLive, {
118
124
  ```
119
125
 
120
126
  The instance client exposes `state`, `fetch`, `start`,
121
- `startAndWaitForPorts`, `stop`, `destroy`, and the Effect-valued native
122
- `unsafeRaw` stub.
127
+ `startAndWaitForPorts`, `waitForPort`, `stop` (named or numeric signals),
128
+ `destroy`, the runtime host-policy operations (`setAllowedHosts`,
129
+ `setDeniedHosts`, `allowHost`, `denyHost`, `removeAllowedHost`,
130
+ `removeDeniedHost`), and the Effect-valued native `rawUnsafe` stub.
131
+ Host-policy operations only forward the native remote calls; applications
132
+ continue to own hostname policy and outbound handlers.
123
133
  Responses are returned unchanged, including non-2xx and WebSocket upgrade
124
134
  responses. If the Container uses outbound interception, also export
125
135
  `ContainerProxy` from `@cloudflare/containers`.
126
136
 
137
+ `ContainerNamespace.Tag` accepts an optional second type parameter carrying
138
+ the exact native namespace type. `rawUnsafe` on the namespace and on named
139
+ instances then preserves that exact type, including extra subclass methods,
140
+ instead of the minimal structural shape:
141
+
142
+ ```ts
143
+ class Sandboxes extends ContainerNamespace.Tag<Sandboxes, DurableObjectNamespace<CodexSandbox>>()(
144
+ "Sandboxes",
145
+ ) {}
146
+
147
+ // Effect<DurableObjectStub<CodexSandbox>, ContainerOperationError, Sandboxes>
148
+ const stub = Sandboxes.byName("codex").rawUnsafe;
149
+ ```
150
+
127
151
  See [`examples/containers/README.md`](../../examples/containers/README.md) for
128
152
  the corresponding Wrangler configuration and entrypoint responsibilities.
129
153
 
@@ -366,7 +390,7 @@ export const recordPageView = (request: Request) =>
366
390
 
367
391
  Define the dataset binding in the consuming Worker's `wrangler.jsonc` with `analytics_engine_datasets`, then provide `RequestAnalytics.layer({ binding: "REQUEST_ANALYTICS" })` from the Worker layer. Invalid writes fail with `AnalyticsEngineWriteValidationError` by default. Use `write: { onInvalid: "drop" }` on the layer or `{ onInvalid: "drop" }` per call when dropping invalid points is preferable.
368
392
 
369
- Analytics Engine query tags wrap Cloudflare's HTTP SQL API. Configuration can stay in Effect `Config`, including a redacted API token, the outbound transport is an Effect `HttpClient` dependency, and rows can be decoded with Effect schemas at the query boundary. Use `fetchLayerConfig(...)` as shorthand when the platform fetch-backed client is enough.
393
+ Analytics Engine query tags wrap Cloudflare's HTTP SQL API. Configuration can stay in Effect `Config`, including a redacted API token, the outbound transport is an Effect `HttpClient` dependency, and rows can be decoded with Effect schemas at the query boundary. Use `layerFetchConfig(...)` as shorthand when the platform fetch-backed client is enough.
370
394
 
371
395
  ```ts
372
396
  import { Effect, Layer, Schema as S } from "effect";
@@ -1,5 +1,7 @@
1
1
  import { Config, ConfigProvider, Context, Effect, Layer } from "effect";
2
- //#region src/Environment.d.ts
2
+ declare namespace Environment_d_exports {
3
+ export { WorkerConfig, WorkerEnv, WorkerEnvironment };
4
+ }
3
5
  /** Cloudflare worker environment object (`env`). */
4
6
  type WorkerEnv = Cloudflare.Env;
5
7
  declare const WorkerEnvironment_base: Context.ServiceClass<WorkerEnvironment, "effect-cf/WorkerEnvironment", Cloudflare.Env>;
@@ -51,8 +53,23 @@ declare namespace WorkerConfig {
51
53
  const integer: <const Name extends Key>(name: Name) => Config.Config<number>;
52
54
  /** Read a scalar Cloudflare var or secret as a boolean. */
53
55
  const boolean: <const Name extends Key>(name: Name) => Config.Config<boolean>;
54
- /** Build a `ConfigProvider` from a Cloudflare worker `env` object. */
55
- const providerFromEnv: (env: WorkerEnv) => ConfigProvider.ConfigProvider;
56
+ /** Options for building a `ConfigProvider` from a Cloudflare worker `env` object. */
57
+ interface ProviderOptions {
58
+ /**
59
+ * Keep empty-string env values as explicit `""` config values.
60
+ *
61
+ * By default (absent or `false`), empty strings are treated as missing
62
+ * config, matching `ConfigProvider.fromUnknown`.
63
+ */
64
+ readonly preserveEmptyStrings?: boolean;
65
+ }
66
+ /**
67
+ * Build a `ConfigProvider` from a Cloudflare worker `env` object.
68
+ *
69
+ * Empty-string values are treated as missing config by default; pass
70
+ * `{ preserveEmptyStrings: true }` to keep them as explicit values.
71
+ */
72
+ const providerFromEnv: (env: WorkerEnv, options?: ProviderOptions) => ConfigProvider.ConfigProvider;
56
73
  /**
57
74
  * Build a `ConfigProvider` from the current `WorkerEnvironment` with a custom
58
75
  * conversion function.
@@ -64,17 +81,19 @@ declare namespace WorkerConfig {
64
81
  * Replace the active Effect `ConfigProvider` with one backed by the current
65
82
  * Cloudflare worker `env` object.
66
83
  */
67
- const providerLayer: import("effect/Layer").Layer<never, never, WorkerEnvironment>;
84
+ const providerLayer: Layer.Layer<never, never, WorkerEnvironment>;
68
85
  /** Alias for `providerLayer` for concise use in worker layers. */
69
- const layer: import("effect/Layer").Layer<never, never, WorkerEnvironment>;
86
+ const layer: Layer.Layer<never, never, WorkerEnvironment>;
70
87
  /** Build a `ConfigProvider` layer with a custom `env` conversion function. */
71
- const layerWith: (makeProvider: (env: WorkerEnv) => ConfigProvider.ConfigProvider) => import("effect/Layer").Layer<never, never, WorkerEnvironment>;
88
+ const layerWith: (makeProvider: (env: WorkerEnv) => ConfigProvider.ConfigProvider) => Layer.Layer<never, never, WorkerEnvironment>;
72
89
  }
73
90
  declare namespace Binding_d_exports {
74
91
  export { BindingNotFoundError, BindingService, BindingValidationError, Service, TypeId, ValidationOptions, layer$1 as layer };
75
92
  }
76
93
  /** Internal type id marker used by binding helper services. */
77
- declare const TypeId: "effect-cf/Binding";
94
+ declare const TypeId: "~effect-cf/Binding";
95
+ /** Internal type id marker used by binding helper services. */
96
+ type TypeId = typeof TypeId;
78
97
  declare const BindingNotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
79
98
  readonly _tag: "BindingNotFoundError";
80
99
  } & Readonly<A>;
@@ -98,14 +117,22 @@ interface ValidationOptions {
98
117
  }
99
118
  /**
100
119
  * Creates a Context tag + layer for reading and validating a Cloudflare binding.
120
+ *
121
+ * The Context key is namespaced as `effect-cf/Binding/<id>`; `id` stays the
122
+ * bare user-supplied identifier.
101
123
  */
102
- interface BindingService<Self, Id extends string, Service> extends Context.ServiceClass<Self, Id, Service> {
103
- readonly [TypeId]: typeof TypeId;
124
+ interface BindingService<Self, Id extends string, Service> extends Context.ServiceClass<Self, `effect-cf/Binding/${Id}`, Service> {
125
+ readonly [TypeId]: TypeId;
126
+ readonly id: Id;
104
127
  readonly binding: string;
105
128
  readonly layer: Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
106
129
  }
107
- declare const layer$1: <Self, Resource, Service = Resource>(tag: Context.Service<Self, Service>, binding: string, isResource: (value: unknown) => value is Resource, wrap?: (resource: Resource) => Service, options?: ValidationOptions) => Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
108
- declare const Service: <Self>() => <Id extends string, Resource, Service = Resource>(id: Id, binding: string, isResource: (value: unknown) => value is Resource, wrap?: (resource: Resource) => Service, options?: ValidationOptions) => BindingService<Self, Id, Service>;
130
+ declare function layer$1<Self, Resource>(tag: Context.Service<Self, Resource>, binding: string, isResource: (value: unknown) => value is Resource, wrap?: undefined, options?: ValidationOptions): Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
131
+ declare function layer$1<Self, Resource, Service>(tag: Context.Service<Self, Service>, binding: string, isResource: (value: unknown) => value is Resource, wrap: (resource: Resource) => Service, options?: ValidationOptions): Layer.Layer<Self, BindingNotFoundError | BindingValidationError, WorkerEnvironment>;
132
+ declare const Service: <Self>() => {
133
+ <Id extends string, Resource>(id: Id, binding: string, isResource: (value: unknown) => value is Resource, wrap?: undefined, options?: ValidationOptions): BindingService<Self, Id, Resource>;
134
+ <Id extends string, Resource, Service>(id: Id, binding: string, isResource: (value: unknown) => value is Resource, wrap: (resource: Resource) => Service, options?: ValidationOptions): BindingService<Self, Id, Service>;
135
+ };
109
136
  declare namespace Hyperdrive_d_exports {
110
137
  export { HyperdriveClient, HyperdriveDefinition, HyperdriveService, LayerOptions, Tag, TagClass, isHyperdrive, layer, make, makeClient };
111
138
  }
@@ -116,7 +143,7 @@ interface HyperdriveDefinition {
116
143
  }
117
144
  interface HyperdriveClient {
118
145
  readonly connectionString: string;
119
- readonly unsafeRaw: Effect.Effect<Hyperdrive>;
146
+ readonly rawUnsafe: Effect.Effect<Hyperdrive>;
120
147
  readonly definition: HyperdriveDefinition;
121
148
  }
122
149
  declare const HyperdriveServiceTypeId: unique symbol;
@@ -139,4 +166,4 @@ declare const layer: <Self>(tag: Context.Service<Self, HyperdriveClient>, defini
139
166
  declare const make: <Id extends string>(id: Id) => TagClass<HyperdriveService<Id>, Id>;
140
167
  declare const Tag: <Self>() => <Id extends string>(id: Id) => TagClass<Self, Id>;
141
168
  //#endregion
142
- export { BindingService as a, WorkerConfig as c, BindingNotFoundError as i, WorkerEnv as l, LayerOptions as n, BindingValidationError as o, TagClass as r, Binding_d_exports as s, Hyperdrive_d_exports as t, WorkerEnvironment as u };
169
+ export { BindingService as a, Environment_d_exports as c, WorkerEnvironment as d, BindingNotFoundError as i, WorkerConfig as l, LayerOptions as n, BindingValidationError as o, TagClass as r, Binding_d_exports as s, Hyperdrive_d_exports as t, WorkerEnv as u };
@@ -1,10 +1,18 @@
1
- import { i as BindingNotFoundError, n as LayerOptions, o as BindingValidationError, r as TagClass, u as WorkerEnvironment } from "./Hyperdrive-RTjgirMV.mjs";
1
+ import { d as WorkerEnvironment, i as BindingNotFoundError, n as LayerOptions, o as BindingValidationError, r as TagClass } from "./Hyperdrive-COyg7R26.mjs";
2
2
  import { Layer } from "effect";
3
3
  import { PgClient } from "@effect/sql-pg";
4
+ import { SqlClient, SqlError } from "effect/unstable/sql";
4
5
  //#region src/HyperdrivePg.d.ts
5
- type PgLayerOptions = Omit<PgClient.PgClientConfig & {
6
- readonly acquireForStream?: boolean;
7
- }, "url" | "host" | "port" | "path" | "ssl" | "database" | "username" | "password" | "stream">;
8
- declare const layer: <Self, Id extends string>(tag: TagClass<Self, Id>, binding: LayerOptions, options?: PgLayerOptions) => Layer.Layer<PgClient.PgClient | import("effect/unstable/sql/SqlClient").SqlClient, BindingNotFoundError | BindingValidationError | import("effect/unstable/sql/SqlError").SqlError, WorkerEnvironment | Exclude<Exclude<Self, import("effect/Scope").Scope>, Self>>;
6
+ /** Hyperdrive owns database pooling, so app-side pool and connection options are not exposed. */
7
+ type PgLayerOptions = Omit<Parameters<typeof PgClient.makeClient>[0], "url" | "host" | "port" | "path" | "ssl" | "database" | "username" | "password" | "stream">;
8
+ /**
9
+ * Provides `PgClient` and `SqlClient` backed by a Hyperdrive binding.
10
+ *
11
+ * Note: since Effect `4.0.0-beta.99`, `PgClient.makeClient` connects eagerly,
12
+ * so the TCP connection to Hyperdrive is opened when this layer is built.
13
+ * In per-request Workers runtimes, build the layer within the request
14
+ * lifecycle rather than sharing it across requests.
15
+ */
16
+ 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>;
9
17
  //#endregion
10
18
  export { PgLayerOptions, layer };
@@ -1,12 +1,17 @@
1
1
  import { Effect, Layer, Redacted } from "effect";
2
2
  import { PgClient } from "@effect/sql-pg";
3
3
  //#region src/HyperdrivePg.ts
4
- const layer = (tag, binding, options) => Layer.unwrap(Effect.gen(function* () {
5
- const hyperdrive = yield* tag;
6
- return PgClient.layerFrom(PgClient.makeClient({
7
- ...options,
8
- url: Redacted.make(hyperdrive.connectionString)
9
- }));
10
- })).pipe(Layer.provide(tag.layer(binding)));
4
+ /**
5
+ * Provides `PgClient` and `SqlClient` backed by a Hyperdrive binding.
6
+ *
7
+ * Note: since Effect `4.0.0-beta.99`, `PgClient.makeClient` connects eagerly,
8
+ * so the TCP connection to Hyperdrive is opened when this layer is built.
9
+ * In per-request Workers runtimes, build the layer within the request
10
+ * lifecycle rather than sharing it across requests.
11
+ */
12
+ const layer = (tag, binding, options) => PgClient.layerFrom(Effect.flatMap(tag, (hyperdrive) => PgClient.makeClient({
13
+ ...options,
14
+ url: Redacted.make(hyperdrive.connectionString)
15
+ }))).pipe(Layer.provide(tag.layer(binding)));
11
16
  //#endregion
12
17
  export { layer };