effect-cf 0.5.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 +14 -0
- package/README.md +36 -29
- package/dist/index.d.mts +854 -1216
- package/dist/index.mjs +469 -441
- package/package.json +1 -1
- package/src/Binding.ts +36 -13
- package/src/DurableObject.ts +117 -23
- package/src/DurableObjectDefinition.ts +251 -72
- package/src/DurableObjectNamespace.ts +305 -158
- package/src/Kv.ts +181 -154
- package/src/Queue.ts +18 -4
- package/src/QueueBinding.ts +43 -62
- package/src/QueueDefinition.ts +87 -41
- package/src/ServiceBinding.ts +288 -81
- 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,19 @@
|
|
|
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
|
+
|
|
11
|
+
## 0.6.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- [#16](https://github.com/danieljvdm/effect-cf/pull/16) [`8195f35`](https://github.com/danieljvdm/effect-cf/commit/8195f356537bd8a063ddebe30f61d0028ddccba1) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Provide Effect-native clients when yielding Queue, KV, Worker service, and Durable Object namespace binding tags, while keeping existing static helpers compatible.
|
|
16
|
+
|
|
3
17
|
## 0.5.0
|
|
4
18
|
|
|
5
19
|
### 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) {
|
|
@@ -99,9 +101,17 @@ export const AvatarQueueConsumer = AvatarJobs.make(Layer.empty, {
|
|
|
99
101
|
}
|
|
100
102
|
}),
|
|
101
103
|
});
|
|
104
|
+
|
|
105
|
+
export const AvatarQueueLayer = AvatarQueue.layer({ binding: "AVATAR_QUEUE" });
|
|
106
|
+
|
|
107
|
+
export const enqueueAvatar = (userId: string, imageKey: string) =>
|
|
108
|
+
Effect.gen(function* () {
|
|
109
|
+
const queue = yield* AvatarQueue;
|
|
110
|
+
yield* queue.send({ userId, imageKey });
|
|
111
|
+
});
|
|
102
112
|
```
|
|
103
113
|
|
|
104
|
-
Producers
|
|
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.
|
|
105
115
|
|
|
106
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.
|
|
107
117
|
|
|
@@ -130,12 +140,10 @@ export const ExportWorkflowEntrypoint = ExportWorkflow.make(Layer.empty, {
|
|
|
130
140
|
}),
|
|
131
141
|
});
|
|
132
142
|
|
|
133
|
-
export const
|
|
134
|
-
binding: "EXPORT_WORKFLOW",
|
|
135
|
-
});
|
|
143
|
+
export const ExportWorkflowLayer = ExportWorkflow.layer({ binding: "EXPORT_WORKFLOW" });
|
|
136
144
|
```
|
|
137
145
|
|
|
138
|
-
|
|
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.
|
|
139
147
|
|
|
140
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.
|
|
141
149
|
|
|
@@ -187,24 +195,23 @@ export const RoomLive = DurableObject.make(layer, {
|
|
|
187
195
|
|
|
188
196
|
Schema-backed attachments can rehydrate hibernated sockets:
|
|
189
197
|
|
|
190
|
-
```
|
|
191
|
-
const restored =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
onInvalid: "ignore-and-close",
|
|
196
|
-
});
|
|
198
|
+
```text
|
|
199
|
+
const restored = yield* Attachments.rehydrate({
|
|
200
|
+
tag: "room:general",
|
|
201
|
+
onInvalid: "ignore-and-close",
|
|
202
|
+
});
|
|
197
203
|
|
|
198
204
|
for (const { socket, attachment } of restored) {
|
|
199
|
-
yield
|
|
205
|
+
yield* socket.send(`restored:${attachment.id}`).pipe(Effect.ignore);
|
|
200
206
|
}
|
|
201
207
|
```
|
|
202
208
|
|
|
203
209
|
Worker-to-Durable-Object forwarding should stay native so WebSocket upgrade responses are preserved:
|
|
204
210
|
|
|
205
|
-
```
|
|
211
|
+
```text
|
|
206
212
|
if (Worker.isWebSocketUpgrade(request)) {
|
|
207
|
-
|
|
213
|
+
const rooms = yield* ChatRoom;
|
|
214
|
+
return yield* rooms.byName(roomId).fetch(request);
|
|
208
215
|
}
|
|
209
216
|
```
|
|
210
217
|
|