effect-cf 0.6.0 → 0.7.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/CHANGELOG.md +8 -0
- package/README.md +30 -29
- package/dist/index.d.mts +837 -1027
- package/dist/index.mjs +328 -407
- package/package.json +1 -1
- package/src/Binding.ts +17 -10
- package/src/DurableObject.ts +117 -23
- package/src/DurableObjectDefinition.ts +251 -72
- package/src/DurableObjectNamespace.ts +239 -287
- package/src/Kv.ts +173 -199
- package/src/Queue.ts +18 -4
- package/src/QueueBinding.ts +45 -97
- package/src/QueueDefinition.ts +87 -41
- package/src/ServiceBinding.ts +260 -116
- package/src/Worker.ts +114 -20
- package/src/WorkerDefinition.ts +187 -63
- package/src/Workflow.ts +23 -4
- package/src/WorkflowBinding.ts +100 -109
- package/src/WorkflowDefinition.ts +116 -51
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# effect-cf
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#20](https://github.com/danieljvdm/effect-cf/pull/20) [`f57a59c`](https://github.com/danieljvdm/effect-cf/commit/f57a59c14d317438348b36ac0341dc921fe72be2) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Tighten binding APIs around Cloudflare RPC and the single-tag KV model. `rpc` now exposes the raw Cloudflare RPC result, while `call` and `scopedCall` resolve and decode definition-backed success values. Durable Object static direct helpers now keep the namespace layer requirement in their effect environment, and the old concrete `Kv.make` / `Kv.Service` constructors have been removed in favor of `Kv.Tag(...).layer({ binding })`.
|
|
8
|
+
|
|
9
|
+
- [#19](https://github.com/danieljvdm/effect-cf/pull/19) [`37b4883`](https://github.com/danieljvdm/effect-cf/commit/37b4883de9790df151ddbb16f2fd432b2d4348b5) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Replace separate binding classes with a single exported tag class API for Queues, Workflows, KV namespaces, Worker service bindings, and Durable Object namespaces. These tags now expose `layer({ binding })` directly, consumers use `const service = yield* Service`, and the old definition `.Binding(...)` / `.binding(...)` / `.Namespace(...)` / `.namespace(...)` helpers have been removed.
|
|
10
|
+
|
|
3
11
|
## 0.6.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -32,20 +32,19 @@ Runtime creation belongs at Cloudflare entrypoints, not inside binding helpers.
|
|
|
32
32
|
- `DurableObjectWebSocket` - WebSocket upgrade helpers for Durable Objects
|
|
33
33
|
- `Kv` - typed KV namespace helper
|
|
34
34
|
- `D1` - typed D1 database binding helper with an `@effect/sql-d1` backed SQL layer
|
|
35
|
-
- `Queue`
|
|
36
|
-
- `Workflow`
|
|
35
|
+
- `Queue` - typed Queue producer/consumer tags plus client and error types
|
|
36
|
+
- `Workflow` - typed Workflow entrypoints, steps, starter clients, and instance types
|
|
37
37
|
- `Rpc` - Cloudflare RPC type helpers and scoped disposal utilities
|
|
38
38
|
- `WorkerConfig` - Effect `Config` helpers backed by Cloudflare `env`
|
|
39
39
|
|
|
40
40
|
## Worker Example
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
|
-
import {
|
|
43
|
+
import { Effect, Layer } from "effect";
|
|
44
|
+
import { HttpServerResponse } from "effect/unstable/http";
|
|
44
45
|
import { Worker } from "effect-cf";
|
|
45
46
|
|
|
46
|
-
export default Worker.make(
|
|
47
|
-
fetch: () => HttpServerResponse.text("ok"),
|
|
48
|
-
});
|
|
47
|
+
export default Worker.make(Layer.empty, Effect.succeed(HttpServerResponse.text("ok")));
|
|
49
48
|
```
|
|
50
49
|
|
|
51
50
|
## Durable Object Example
|
|
@@ -70,27 +69,30 @@ export const CounterDurableObject = Counter.make(Layer.empty, {
|
|
|
70
69
|
}),
|
|
71
70
|
},
|
|
72
71
|
});
|
|
72
|
+
|
|
73
|
+
export const CounterLayer = Counter.layer({ binding: "COUNTER" });
|
|
74
|
+
|
|
75
|
+
export const readCounter = Effect.gen(function* () {
|
|
76
|
+
const counters = yield* Counter;
|
|
77
|
+
return yield* counters.byName("home").get();
|
|
78
|
+
});
|
|
73
79
|
```
|
|
74
80
|
|
|
75
|
-
Define Wrangler bindings and migrations in the consuming application.
|
|
81
|
+
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`.
|
|
76
82
|
|
|
77
83
|
## Queue Example
|
|
78
84
|
|
|
79
|
-
Queues
|
|
85
|
+
Queues define the message contract once. The same class is the producer service tag and the consumer Worker definition: use `YourQueue.layer({ binding })` to provide a Cloudflare producer binding from `WorkerEnvironment`, and use `.make(...)` for the consumer Worker entrypoint.
|
|
80
86
|
|
|
81
87
|
```ts
|
|
82
88
|
import { Effect, Layer, Schema as S } from "effect";
|
|
83
89
|
import { Queue } from "effect-cf";
|
|
84
90
|
|
|
85
|
-
class
|
|
91
|
+
class AvatarQueue extends Queue.Tag<AvatarQueue>()("AvatarQueue", {
|
|
86
92
|
message: S.Struct({ userId: S.String, imageKey: S.String }),
|
|
87
93
|
}) {}
|
|
88
94
|
|
|
89
|
-
export const
|
|
90
|
-
binding: "AVATAR_QUEUE",
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
export const AvatarQueueConsumer = AvatarJobs.make(Layer.empty, {
|
|
95
|
+
export const AvatarQueueConsumer = AvatarQueue.make(Layer.empty, {
|
|
94
96
|
queue: (batch) =>
|
|
95
97
|
Effect.gen(function* () {
|
|
96
98
|
for (const message of batch.messages) {
|
|
@@ -100,6 +102,8 @@ export const AvatarQueueConsumer = AvatarJobs.make(Layer.empty, {
|
|
|
100
102
|
}),
|
|
101
103
|
});
|
|
102
104
|
|
|
105
|
+
export const AvatarQueueLayer = AvatarQueue.layer({ binding: "AVATAR_QUEUE" });
|
|
106
|
+
|
|
103
107
|
export const enqueueAvatar = (userId: string, imageKey: string) =>
|
|
104
108
|
Effect.gen(function* () {
|
|
105
109
|
const queue = yield* AvatarQueue;
|
|
@@ -107,7 +111,7 @@ export const enqueueAvatar = (userId: string, imageKey: string) =>
|
|
|
107
111
|
});
|
|
108
112
|
```
|
|
109
113
|
|
|
110
|
-
Producers should usually use `const queue = yield* AvatarQueue` and then call `queue.send(...)`, `queue.sendBatch(...)`, or `queue.metrics()`. The static `AvatarQueue.send(...)` helpers remain available for
|
|
114
|
+
Producers should usually use `const queue = yield* AvatarQueue` and then call `queue.send(...)`, `queue.sendBatch(...)`, or `queue.metrics()`. The static `AvatarQueue.send(...)` helpers remain available for concise one-off calls.
|
|
111
115
|
|
|
112
116
|
Queue handlers run inline failures through Cloudflare's normal retry path. If background work scheduled with `WorkerContext.waitUntil(...)` should also make the batch retry, use `WorkerContext.waitUntilPropagating(...)` or `waitUntil(..., { mode: "propagate" })`; the default `waitUntil` mode observes and logs failures without rejecting the native `waitUntil` promise.
|
|
113
117
|
|
|
@@ -136,12 +140,10 @@ export const ExportWorkflowEntrypoint = ExportWorkflow.make(Layer.empty, {
|
|
|
136
140
|
}),
|
|
137
141
|
});
|
|
138
142
|
|
|
139
|
-
export const
|
|
140
|
-
binding: "EXPORT_WORKFLOW",
|
|
141
|
-
});
|
|
143
|
+
export const ExportWorkflowLayer = ExportWorkflow.layer({ binding: "EXPORT_WORKFLOW" });
|
|
142
144
|
```
|
|
143
145
|
|
|
144
|
-
|
|
146
|
+
Provide `ExportWorkflow.layer({ binding: "EXPORT_WORKFLOW" })`, then use `const workflow = yield* ExportWorkflow` or the static `ExportWorkflow.create(...)`, `createBatch(...)`, and `get(...)` helpers to start and inspect instances.
|
|
145
147
|
|
|
146
148
|
In definition-backed workflows, the `payload` argument is the typed decoded payload and is the source of truth. `Workflow.WorkflowEvent.payload` is also re-provided decoded for convenience; `Workflow.WorkflowEvent.raw.payload` remains the native Cloudflare event payload.
|
|
147
149
|
|
|
@@ -193,24 +195,23 @@ export const RoomLive = DurableObject.make(layer, {
|
|
|
193
195
|
|
|
194
196
|
Schema-backed attachments can rehydrate hibernated sockets:
|
|
195
197
|
|
|
196
|
-
```
|
|
197
|
-
const restored =
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
onInvalid: "ignore-and-close",
|
|
202
|
-
});
|
|
198
|
+
```text
|
|
199
|
+
const restored = yield* Attachments.rehydrate({
|
|
200
|
+
tag: "room:general",
|
|
201
|
+
onInvalid: "ignore-and-close",
|
|
202
|
+
});
|
|
203
203
|
|
|
204
204
|
for (const { socket, attachment } of restored) {
|
|
205
|
-
yield
|
|
205
|
+
yield* socket.send(`restored:${attachment.id}`).pipe(Effect.ignore);
|
|
206
206
|
}
|
|
207
207
|
```
|
|
208
208
|
|
|
209
209
|
Worker-to-Durable-Object forwarding should stay native so WebSocket upgrade responses are preserved:
|
|
210
210
|
|
|
211
|
-
```
|
|
211
|
+
```text
|
|
212
212
|
if (Worker.isWebSocketUpgrade(request)) {
|
|
213
|
-
|
|
213
|
+
const rooms = yield* ChatRoom;
|
|
214
|
+
return yield* rooms.byName(roomId).fetch(request);
|
|
214
215
|
}
|
|
215
216
|
```
|
|
216
217
|
|