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.
- package/CHANGELOG.md +52 -0
- package/README.md +27 -3
- package/dist/{Hyperdrive-RTjgirMV.d.mts → Hyperdrive-COyg7R26.d.mts} +40 -13
- package/dist/HyperdrivePg.d.mts +13 -5
- package/dist/HyperdrivePg.mjs +12 -7
- package/dist/index.d.mts +1113 -922
- package/dist/index.mjs +980 -604
- package/package.json +10 -5
- package/src/AiGateway.ts +82 -47
- package/src/AnalyticsEngine.ts +74 -58
- package/src/Binding.ts +66 -13
- package/src/BrowserRendering.ts +30 -7
- package/src/Cache.ts +32 -8
- package/src/CloudflareOtlp.ts +32 -9
- package/src/ContainerNamespace.ts +251 -80
- package/src/D1.ts +13 -3
- package/src/DurableObject.ts +27 -164
- package/src/DurableObjectAlarm.ts +30 -9
- package/src/DurableObjectDefinition.ts +58 -54
- package/src/DurableObjectNamespace.ts +99 -96
- package/src/DurableObjectRpcWebSocket.ts +14 -6
- package/src/DurableObjectSqlite.ts +6 -3
- package/src/DurableObjectState.ts +63 -39
- package/src/DurableObjectStorage.ts +7 -1
- package/src/DurableObjectWebSocket.ts +51 -41
- package/src/Email.ts +40 -13
- package/src/Environment.ts +26 -6
- package/src/Hyperdrive.ts +2 -2
- package/src/HyperdrivePg.ts +25 -13
- package/src/Images.ts +77 -82
- package/src/Kv.ts +37 -27
- package/src/Queue.ts +6 -1
- package/src/QueueBinding.ts +18 -21
- package/src/QueueDefinition.ts +15 -14
- package/src/R2.ts +107 -29
- package/src/Rpc.ts +3 -1
- package/src/RpcDefinition.ts +177 -133
- package/src/ServiceBinding.ts +112 -108
- package/src/Vectorize.ts +59 -14
- package/src/Worker.ts +172 -192
- package/src/WorkerDefinition.ts +5 -10
- package/src/WorkersAi.ts +27 -17
- package/src/Workflow.ts +54 -49
- package/src/WorkflowBinding.ts +19 -11
- package/src/WorkflowDefinition.ts +24 -27
- package/src/index.ts +4 -3
- package/src/internal/Entrypoint.ts +3 -1
- package/src/internal/ErrorMessage.ts +24 -0
- package/src/internal/RpcInvocation.ts +11 -8
- package/src/internal/Runtime.ts +52 -0
- package/src/internal/WorkerContext.ts +39 -17
- package/src/Entry.ts +0 -259
- package/src/internal/Clock.ts +0 -37
package/src/BrowserRendering.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Context, Data, Effect, type Layer } from "effect";
|
|
|
2
2
|
|
|
3
3
|
import * as Binding from "./Binding";
|
|
4
4
|
import type { WorkerEnvironment } from "./Environment";
|
|
5
|
+
import * as ErrorMessage from "./internal/ErrorMessage";
|
|
5
6
|
|
|
6
7
|
const expectedBrowserRenderingBinding = "Browser Rendering binding resource";
|
|
7
8
|
|
|
@@ -12,7 +13,11 @@ export class BrowserRenderingOperationError extends Data.TaggedError(
|
|
|
12
13
|
readonly binding: string;
|
|
13
14
|
readonly operation: string;
|
|
14
15
|
readonly cause: unknown;
|
|
15
|
-
}> {
|
|
16
|
+
}> {
|
|
17
|
+
override get message(): string {
|
|
18
|
+
return `Browser Rendering ${this.operation} failed for binding "${this.binding}": ${ErrorMessage.causeMessage(this.cause)}`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
/** Typed Browser Rendering binding definition. */
|
|
18
23
|
export interface BrowserRenderingDefinition {
|
|
@@ -106,7 +111,7 @@ export interface BrowserRenderingClient<
|
|
|
106
111
|
connect: BrowserRenderingConnect<RawBinding, Browser, ConnectOptions>,
|
|
107
112
|
options?: ConnectOptions,
|
|
108
113
|
) => Effect.Effect<BrowserRenderingBrowserClient<Browser, Page>, BrowserRenderingOperationError>;
|
|
109
|
-
readonly
|
|
114
|
+
readonly rawUnsafe: Effect.Effect<RawBinding>;
|
|
110
115
|
readonly definition: BrowserRenderingDefinition;
|
|
111
116
|
}
|
|
112
117
|
|
|
@@ -251,15 +256,33 @@ export const makeClient =
|
|
|
251
256
|
) =>
|
|
252
257
|
(binding: RawBinding): BrowserRenderingClient<RawBinding> => ({
|
|
253
258
|
definition,
|
|
254
|
-
launchWith:
|
|
259
|
+
launchWith: <
|
|
260
|
+
Browser extends BrowserRenderingBrowserLike<Page>,
|
|
261
|
+
Page extends BrowserRenderingPageLike = BrowserRenderingPageLike,
|
|
262
|
+
LaunchOptions = unknown,
|
|
263
|
+
>(
|
|
264
|
+
launch: BrowserRenderingLaunch<RawBinding, Browser, LaunchOptions>,
|
|
265
|
+
options?: LaunchOptions,
|
|
266
|
+
) =>
|
|
255
267
|
tryBrowserRenderingPromise(definition.binding, "launch", () => launch(binding, options)).pipe(
|
|
256
|
-
Effect.map((browser) => wrapBrowser(definition.binding, browser)),
|
|
268
|
+
Effect.map((browser) => wrapBrowser<Browser, Page>(definition.binding, browser)),
|
|
269
|
+
Effect.withSpan("BrowserRendering.launchWith"),
|
|
257
270
|
),
|
|
258
|
-
connectWith:
|
|
271
|
+
connectWith: <
|
|
272
|
+
Browser extends BrowserRenderingBrowserLike<Page>,
|
|
273
|
+
Page extends BrowserRenderingPageLike = BrowserRenderingPageLike,
|
|
274
|
+
ConnectOptions = unknown,
|
|
275
|
+
>(
|
|
276
|
+
connect: BrowserRenderingConnect<RawBinding, Browser, ConnectOptions>,
|
|
277
|
+
options?: ConnectOptions,
|
|
278
|
+
) =>
|
|
259
279
|
tryBrowserRenderingPromise(definition.binding, "connect", () =>
|
|
260
280
|
connect(binding, options),
|
|
261
|
-
).pipe(
|
|
262
|
-
|
|
281
|
+
).pipe(
|
|
282
|
+
Effect.map((browser) => wrapBrowser<Browser, Page>(definition.binding, browser)),
|
|
283
|
+
Effect.withSpan("BrowserRendering.connectWith"),
|
|
284
|
+
),
|
|
285
|
+
rawUnsafe: Effect.succeed(binding),
|
|
263
286
|
});
|
|
264
287
|
|
|
265
288
|
export const layer = <Self>(
|
package/src/Cache.ts
CHANGED
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
} from "@cloudflare/workers-types";
|
|
7
7
|
import { Context, Data, Effect, Layer, Option } from "effect";
|
|
8
8
|
|
|
9
|
+
import * as ErrorMessage from "./internal/ErrorMessage";
|
|
10
|
+
|
|
9
11
|
/** Request key accepted by Cloudflare's Cache API. */
|
|
10
12
|
export type CacheRequest = CloudflareRequestInfo | URL;
|
|
11
13
|
|
|
@@ -20,7 +22,11 @@ export class CacheOperationError extends Data.TaggedError("CacheOperationError")
|
|
|
20
22
|
readonly cache: string;
|
|
21
23
|
readonly operation: CacheOperation;
|
|
22
24
|
readonly cause: unknown;
|
|
23
|
-
}> {
|
|
25
|
+
}> {
|
|
26
|
+
override get message(): string {
|
|
27
|
+
return `Cache ${this.operation} failed for cache "${this.cache}": ${ErrorMessage.causeMessage(this.cause)}`;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
24
30
|
|
|
25
31
|
/** Effect wrapper around one Cloudflare `Cache` instance. */
|
|
26
32
|
export interface CacheClient {
|
|
@@ -42,7 +48,7 @@ export interface CacheClient {
|
|
|
42
48
|
options?: CacheQueryOptions,
|
|
43
49
|
) => Effect.Effect<boolean, CacheOperationError>;
|
|
44
50
|
/** Access to the native Cloudflare `Cache` instance. */
|
|
45
|
-
readonly
|
|
51
|
+
readonly rawUnsafe: Effect.Effect<CloudflareCache>;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
/** Effect wrapper around Cloudflare's global `caches` object. */
|
|
@@ -52,7 +58,7 @@ export interface CacheStorageClient {
|
|
|
52
58
|
/** Opens a named cache. */
|
|
53
59
|
readonly open: (name: string) => Effect.Effect<CacheClient, CacheOperationError>;
|
|
54
60
|
/** Access to the native Cloudflare `CacheStorage` instance. */
|
|
55
|
-
readonly
|
|
61
|
+
readonly rawUnsafe: Effect.Effect<CloudflareCacheStorage>;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
/** Service for Cloudflare's global Cache API. */
|
|
@@ -73,17 +79,34 @@ const tryCachePromise = <A>(
|
|
|
73
79
|
catch: (cause) => cacheError(cache, operation, cause),
|
|
74
80
|
});
|
|
75
81
|
|
|
82
|
+
const spanOptions = (cache: string, operation: CacheOperation) => ({
|
|
83
|
+
attributes: { cache, operation },
|
|
84
|
+
});
|
|
85
|
+
|
|
76
86
|
/** Wraps a native Cloudflare `Cache` instance. */
|
|
77
87
|
export const makeCacheClient = (cache: CloudflareCache, name = "default"): CacheClient => ({
|
|
78
88
|
name,
|
|
79
|
-
match: (
|
|
89
|
+
match: Effect.fn(
|
|
90
|
+
"Cache.match",
|
|
91
|
+
spanOptions(name, "match"),
|
|
92
|
+
)((request: CacheRequest, options?: CacheQueryOptions) =>
|
|
80
93
|
tryCachePromise(name, "match", () => cache.match(request, options)).pipe(
|
|
81
94
|
Effect.map(Option.fromUndefinedOr),
|
|
82
95
|
),
|
|
83
|
-
|
|
84
|
-
|
|
96
|
+
),
|
|
97
|
+
put: Effect.fn(
|
|
98
|
+
"Cache.put",
|
|
99
|
+
spanOptions(name, "put"),
|
|
100
|
+
)((request: CacheRequest, response: Response) =>
|
|
101
|
+
tryCachePromise(name, "put", () => cache.put(request, response)),
|
|
102
|
+
),
|
|
103
|
+
delete: Effect.fn(
|
|
104
|
+
"Cache.delete",
|
|
105
|
+
spanOptions(name, "delete"),
|
|
106
|
+
)((request: CacheRequest, options?: CacheQueryOptions) =>
|
|
85
107
|
tryCachePromise(name, "delete", () => cache.delete(request, options)),
|
|
86
|
-
|
|
108
|
+
),
|
|
109
|
+
rawUnsafe: Effect.succeed(cache),
|
|
87
110
|
});
|
|
88
111
|
|
|
89
112
|
/** Wraps a native Cloudflare `CacheStorage` instance. */
|
|
@@ -92,8 +115,9 @@ export const makeClient = (storage: CloudflareCacheStorage): CacheStorageClient
|
|
|
92
115
|
open: (name) =>
|
|
93
116
|
tryCachePromise(name, "open", () => storage.open(name)).pipe(
|
|
94
117
|
Effect.map((cache) => makeCacheClient(cache, name)),
|
|
118
|
+
Effect.withSpan("Cache.open", spanOptions(name, "open")),
|
|
95
119
|
),
|
|
96
|
-
|
|
120
|
+
rawUnsafe: Effect.succeed(storage),
|
|
97
121
|
});
|
|
98
122
|
|
|
99
123
|
/** Provides Cache API services from an explicit native `CacheStorage` instance. */
|
package/src/CloudflareOtlp.ts
CHANGED
|
@@ -1,7 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTLP telemetry layers for Cloudflare Workers and Durable Objects.
|
|
3
|
+
*
|
|
4
|
+
* Every layer exposes {@link OtlpExporter.Flusher}, which drains buffered
|
|
5
|
+
* telemetry on demand. Cloudflare isolates can freeze before the periodic
|
|
6
|
+
* export interval fires, so flush explicitly before returning a response, or
|
|
7
|
+
* hand the flush to `ctx.waitUntil`:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* const flusher = yield* OtlpExporter.Flusher;
|
|
11
|
+
*
|
|
12
|
+
* yield* flusher.flush;
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
1
15
|
import { ConfigProvider, Effect, Layer, Option } from "effect";
|
|
2
16
|
import type * as Tracer from "effect/Tracer";
|
|
3
17
|
import { FetchHttpClient, type Headers } from "effect/unstable/http";
|
|
4
18
|
import {
|
|
19
|
+
OtlpExporter,
|
|
5
20
|
OtlpLogger,
|
|
6
21
|
OtlpMetrics,
|
|
7
22
|
OtlpSerialization,
|
|
@@ -138,7 +153,7 @@ const mergeSignalLayers = (layers: ReadonlyArray<SignalLayer>): SignalLayer => {
|
|
|
138
153
|
const makeLayer = (
|
|
139
154
|
options: LayerOptions = {},
|
|
140
155
|
runtimeAttributes: Record<string, unknown> = {},
|
|
141
|
-
): Layer.Layer<
|
|
156
|
+
): Layer.Layer<OtlpExporter.Flusher> => {
|
|
142
157
|
const signals = selectedSignals(options.signals);
|
|
143
158
|
const resource = makeResource(options, runtimeAttributes);
|
|
144
159
|
const layers: Array<SignalLayer> = [];
|
|
@@ -174,7 +189,7 @@ const makeLayer = (
|
|
|
174
189
|
}
|
|
175
190
|
|
|
176
191
|
if (layers.length === 0) {
|
|
177
|
-
return
|
|
192
|
+
return OtlpExporter.layerFlusher;
|
|
178
193
|
}
|
|
179
194
|
|
|
180
195
|
return mergeSignalLayers(layers).pipe(
|
|
@@ -191,16 +206,22 @@ const makeLayer = (
|
|
|
191
206
|
* layers. In Cloudflare Workers and Durable Objects, the current `env` object is
|
|
192
207
|
* installed as the primary `ConfigProvider`; outside Cloudflare, the ambient
|
|
193
208
|
* Effect `ConfigProvider` remains the fallback.
|
|
209
|
+
*
|
|
210
|
+
* The layer provides {@link OtlpExporter.Flusher} for draining buffered
|
|
211
|
+
* telemetry before the isolate freezes.
|
|
194
212
|
*/
|
|
195
|
-
export const layer = (options: LayerOptions = {}) =>
|
|
213
|
+
export const layer = (options: LayerOptions = {}): Layer.Layer<OtlpExporter.Flusher> =>
|
|
214
|
+
makeLayer(options);
|
|
196
215
|
|
|
197
216
|
/** Base OTLP telemetry layer forced to JSON serialization. */
|
|
198
|
-
export const layerJson = (
|
|
199
|
-
|
|
217
|
+
export const layerJson = (
|
|
218
|
+
options: Omit<LayerOptions, "serialization"> = {},
|
|
219
|
+
): Layer.Layer<OtlpExporter.Flusher> => layer({ ...options, serialization: "json" });
|
|
200
220
|
|
|
201
221
|
/** Base OTLP telemetry layer forced to protobuf serialization. */
|
|
202
|
-
export const layerProtobuf = (
|
|
203
|
-
|
|
222
|
+
export const layerProtobuf = (
|
|
223
|
+
options: Omit<LayerOptions, "serialization"> = {},
|
|
224
|
+
): Layer.Layer<OtlpExporter.Flusher> => layer({ ...options, serialization: "protobuf" });
|
|
204
225
|
|
|
205
226
|
/**
|
|
206
227
|
* OTLP layer with Cloudflare Worker resource attributes.
|
|
@@ -208,7 +229,7 @@ export const layerProtobuf = (options: Omit<LayerOptions, "serialization"> = {})
|
|
|
208
229
|
* Provide this layer at runtime scope for long-lived metrics aggregation, or at
|
|
209
230
|
* handler scope when traces/logs should flush as the Cloudflare event finishes.
|
|
210
231
|
*/
|
|
211
|
-
export const
|
|
232
|
+
export const layerWorker = (options: WorkerLayerOptions = {}): Layer.Layer<OtlpExporter.Flusher> =>
|
|
212
233
|
makeLayer(options, {
|
|
213
234
|
"cloudflare.resource_type": "worker",
|
|
214
235
|
"cloudflare.worker.name": options.workerName,
|
|
@@ -221,7 +242,9 @@ export const workerLayer = (options: WorkerLayerOptions = {}) =>
|
|
|
221
242
|
* Durable Object id. Prefer leaving `includeObjectId` disabled unless the
|
|
222
243
|
* backend can tolerate high-cardinality resource attributes.
|
|
223
244
|
*/
|
|
224
|
-
export const
|
|
245
|
+
export const layerDurableObject = (
|
|
246
|
+
options: DurableObjectLayerOptions = {},
|
|
247
|
+
): Layer.Layer<OtlpExporter.Flusher, never, DurableObjectState> =>
|
|
225
248
|
Layer.unwrap(
|
|
226
249
|
Effect.map(DurableObjectState, (state) =>
|
|
227
250
|
makeLayer(options, {
|