effect-cf 0.18.0 → 0.20.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 +18 -0
- package/README.md +16 -2
- package/dist/{Hyperdrive-C0vfrPeG.d.mts → Hyperdrive-RTjgirMV.d.mts} +7 -12
- package/dist/HyperdrivePg.d.mts +2 -6
- package/dist/HyperdrivePg.mjs +0 -1
- package/dist/index.d.mts +160 -106
- package/dist/index.mjs +550 -168
- package/package.json +8 -9
- package/src/AiGateway.ts +3 -0
- package/src/AnalyticsEngine.ts +6 -1
- package/src/Binding.ts +4 -2
- package/src/CloudflareOtlp.ts +20 -7
- package/src/ContainerNamespace.ts +3 -0
- package/src/D1.ts +1 -0
- package/src/DurableObject.ts +10 -2
- package/src/DurableObjectAlarm.ts +19 -0
- package/src/DurableObjectDefinition.ts +34 -6
- package/src/DurableObjectNamespace.ts +4 -1
- package/src/DurableObjectRpcWebSocket.ts +14 -0
- package/src/DurableObjectSqlite.ts +1 -0
- package/src/DurableObjectStorage.ts +2 -0
- package/src/DurableObjectWebSocket.ts +4 -1
- package/src/Email.ts +354 -10
- package/src/HyperdrivePg.ts +1 -1
- package/src/Kv.ts +3 -1
- package/src/QueueBinding.ts +2 -1
- package/src/QueueDefinition.ts +6 -1
- package/src/R2.ts +1 -0
- package/src/RpcDefinition.ts +2 -0
- package/src/ServiceBinding.ts +6 -1
- package/src/Worker.ts +10 -2
- package/src/WorkerDefinition.ts +28 -6
- package/src/WorkflowBinding.ts +5 -2
- package/src/WorkflowDefinition.ts +6 -1
- package/src/internal/Clock.ts +9 -0
- package/src/internal/RpcInvocation.ts +1 -0
- package/dist/Hyperdrive-89hg_Fck.mjs +0 -156
- /package/dist/{chunk-CfYAbeIz.mjs → rolldown-runtime-D7D4PA-g.mjs} +0 -0
package/src/WorkerDefinition.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Context, Effect, type Layer } from "effect";
|
|
2
|
-
import type { Schema as S } from "effect";
|
|
1
|
+
import { Context, Effect, type Layer, type Schema as S } from "effect";
|
|
3
2
|
|
|
4
|
-
import * as Binding from "./Binding";
|
|
3
|
+
import type * as Binding from "./Binding";
|
|
5
4
|
import type { WorkerEnvironment } from "./Environment";
|
|
6
5
|
import * as WorkerEntrypoint from "./Worker";
|
|
7
6
|
import type { WorkerRpcHandler } from "./Worker";
|
|
@@ -9,6 +8,13 @@ import type * as Rpc from "./Rpc";
|
|
|
9
8
|
import * as RpcDefinition from "./RpcDefinition";
|
|
10
9
|
import * as ServiceBinding from "./ServiceBinding";
|
|
11
10
|
|
|
11
|
+
/**
|
|
12
|
+
* The client tuple types are re-established by the final `TagClass` cast, so
|
|
13
|
+
* these internal invocations erase the binding client's generic argument
|
|
14
|
+
* tuples instead of instantiating them at `never`.
|
|
15
|
+
*/
|
|
16
|
+
type UnsafeInvoke<E> = (...args: ReadonlyArray<unknown>) => Effect.Effect<unknown, E>;
|
|
17
|
+
|
|
12
18
|
export type ServiceFreeSchema = S.Codec<any, any, never, never>;
|
|
13
19
|
|
|
14
20
|
export interface Method<
|
|
@@ -238,6 +244,7 @@ export const Tag =
|
|
|
238
244
|
methods: MethodsShape & NoReservedMethods<MethodsShape>,
|
|
239
245
|
) => {
|
|
240
246
|
const definition = makeDefinition<Id, MethodsShape>(id, methods);
|
|
247
|
+
|
|
241
248
|
type SelfDefinition = Definition<Id, MethodsShape>;
|
|
242
249
|
type ClientApi = Api<SelfDefinition>;
|
|
243
250
|
const tag = Context.Service<
|
|
@@ -256,6 +263,7 @@ export const Tag =
|
|
|
256
263
|
const fetch = (input: RequestInfo | URL, init?: RequestInit) =>
|
|
257
264
|
Effect.gen(function* () {
|
|
258
265
|
const service = yield* tag;
|
|
266
|
+
|
|
259
267
|
return yield* service.fetch(input, init);
|
|
260
268
|
});
|
|
261
269
|
|
|
@@ -265,7 +273,11 @@ export const Tag =
|
|
|
265
273
|
) =>
|
|
266
274
|
Effect.gen(function* () {
|
|
267
275
|
const service = yield* tag;
|
|
268
|
-
|
|
276
|
+
|
|
277
|
+
return yield* (service.rpc as UnsafeInvoke<ServiceBinding.ServiceBindingRpcError>)(
|
|
278
|
+
method,
|
|
279
|
+
...args,
|
|
280
|
+
);
|
|
269
281
|
});
|
|
270
282
|
|
|
271
283
|
const call = <Method extends keyof ClientApi>(
|
|
@@ -274,7 +286,11 @@ export const Tag =
|
|
|
274
286
|
) =>
|
|
275
287
|
Effect.gen(function* () {
|
|
276
288
|
const service = yield* tag;
|
|
277
|
-
|
|
289
|
+
|
|
290
|
+
return yield* (service.call as UnsafeInvoke<ServiceBinding.ServiceBindingRpcError>)(
|
|
291
|
+
method,
|
|
292
|
+
...args,
|
|
293
|
+
);
|
|
278
294
|
});
|
|
279
295
|
|
|
280
296
|
const scopedCall = <Method extends keyof ClientApi>(
|
|
@@ -283,7 +299,11 @@ export const Tag =
|
|
|
283
299
|
) =>
|
|
284
300
|
Effect.gen(function* () {
|
|
285
301
|
const service = yield* tag;
|
|
286
|
-
|
|
302
|
+
|
|
303
|
+
return yield* (service.scopedCall as UnsafeInvoke<ServiceBinding.ServiceBindingRpcError>)(
|
|
304
|
+
method,
|
|
305
|
+
...args,
|
|
306
|
+
);
|
|
287
307
|
});
|
|
288
308
|
|
|
289
309
|
const directMethods = ServiceBinding.makeDirectMethods<Self, ClientApi, SelfDefinition>(
|
|
@@ -315,10 +335,12 @@ const wrapHandlers = <ROut, const Self extends Definition.Any>(
|
|
|
315
335
|
RpcDefinition.Definition.MethodNames<Self>
|
|
316
336
|
>) {
|
|
317
337
|
const handler = handlers[key];
|
|
338
|
+
|
|
318
339
|
wrapped[key] = (...args: Array<unknown>) =>
|
|
319
340
|
Effect.gen(function* () {
|
|
320
341
|
const decodedArgs = yield* RpcDefinition.decodeArgs(definition, key, args);
|
|
321
342
|
const value = yield* handler(...decodedArgs);
|
|
343
|
+
|
|
322
344
|
return yield* RpcDefinition.encodeSuccess(definition, key, value);
|
|
323
345
|
});
|
|
324
346
|
}
|
package/src/WorkflowBinding.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
WorkflowInstance as CloudflareWorkflowInstance,
|
|
5
5
|
WorkflowInstanceCreateOptions as CloudflareWorkflowInstanceCreateOptions,
|
|
6
6
|
} from "@cloudflare/workers-types";
|
|
7
|
-
import { Context, Data, Effect, Option, Schema as S } from "effect";
|
|
7
|
+
import { type Context, Data, Effect, Option, Schema as S } from "effect";
|
|
8
8
|
|
|
9
9
|
import * as Binding from "./Binding";
|
|
10
10
|
import type * as RpcDefinition from "./RpcDefinition";
|
|
@@ -187,7 +187,10 @@ export const makeClient = <
|
|
|
187
187
|
return {
|
|
188
188
|
status: status.status,
|
|
189
189
|
output,
|
|
190
|
-
error:
|
|
190
|
+
error:
|
|
191
|
+
status.error === null || status.error === undefined
|
|
192
|
+
? Option.none()
|
|
193
|
+
: Option.some(status.error),
|
|
191
194
|
};
|
|
192
195
|
}),
|
|
193
196
|
),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Context, Effect, Schema as S, type Layer } from "effect";
|
|
2
2
|
|
|
3
|
-
import * as Binding from "./Binding";
|
|
3
|
+
import type * as Binding from "./Binding";
|
|
4
4
|
import type { WorkerEnvironment } from "./Environment";
|
|
5
5
|
import type { ExecutionContext, WorkerContext } from "./Worker";
|
|
6
6
|
import type * as RpcDefinition from "./RpcDefinition";
|
|
@@ -162,6 +162,7 @@ export const Tag =
|
|
|
162
162
|
options?: WorkflowBinding.WorkflowInstanceCreateOptions<S.Codec.Encoded<Payload>>,
|
|
163
163
|
) {
|
|
164
164
|
const workflow = yield* tag;
|
|
165
|
+
|
|
165
166
|
return yield* workflow.create(payload, options);
|
|
166
167
|
});
|
|
167
168
|
|
|
@@ -172,16 +173,19 @@ export const Tag =
|
|
|
172
173
|
>,
|
|
173
174
|
) {
|
|
174
175
|
const workflow = yield* tag;
|
|
176
|
+
|
|
175
177
|
return yield* workflow.createBatch(batch);
|
|
176
178
|
});
|
|
177
179
|
|
|
178
180
|
const get = Effect.fnUntraced(function* (instanceId: string) {
|
|
179
181
|
const workflow = yield* tag;
|
|
182
|
+
|
|
180
183
|
return yield* workflow.get(instanceId);
|
|
181
184
|
});
|
|
182
185
|
|
|
183
186
|
const unsafeRaw = Effect.fnUntraced(function* () {
|
|
184
187
|
const workflow = yield* tag;
|
|
188
|
+
|
|
185
189
|
return yield* workflow.unsafeRaw;
|
|
186
190
|
});
|
|
187
191
|
|
|
@@ -222,6 +226,7 @@ const wrapHandler = <ROut, const Self extends Definition.Any>(
|
|
|
222
226
|
const result = yield* handler(decodedPayload as S.Schema.Type<Self["payload"]>).pipe(
|
|
223
227
|
Effect.provideService(WorkflowEntrypoint.WorkflowEvent, decodedEvent),
|
|
224
228
|
);
|
|
229
|
+
|
|
225
230
|
return yield* encodeResult(result as S.Schema.Type<Self["result"]>);
|
|
226
231
|
});
|
|
227
232
|
};
|
package/src/internal/Clock.ts
CHANGED
|
@@ -8,8 +8,16 @@ export const clock: Clock.Clock = {
|
|
|
8
8
|
currentTimeMillis: Effect.sync(() => clock.currentTimeMillisUnsafe()),
|
|
9
9
|
currentTimeNanosUnsafe: () => BigInt(Date.now()) * nanosPerMilli,
|
|
10
10
|
currentTimeNanos: Effect.sync(() => clock.currentTimeNanosUnsafe()),
|
|
11
|
+
// Workers expose `performance.now()` as time since worker start. It advances
|
|
12
|
+
// only across I/O, like `Date.now()`, but it never moves backward.
|
|
13
|
+
monotonicTimeNanosUnsafe: () =>
|
|
14
|
+
typeof performance === "undefined"
|
|
15
|
+
? BigInt(Date.now()) * nanosPerMilli
|
|
16
|
+
: BigInt(Math.round(performance.now() * 1_000_000)),
|
|
17
|
+
monotonicTimeNanos: Effect.sync(() => clock.monotonicTimeNanosUnsafe()),
|
|
11
18
|
sleep: (duration) => {
|
|
12
19
|
const millis = Duration.toMillis(duration);
|
|
20
|
+
|
|
13
21
|
if (millis <= 0) {
|
|
14
22
|
return Effect.yieldNow;
|
|
15
23
|
}
|
|
@@ -20,6 +28,7 @@ export const clock: Clock.Clock = {
|
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
const handle = setTimeout(() => resume(Effect.void), millis);
|
|
31
|
+
|
|
23
32
|
return Effect.sync(() => clearTimeout(handle));
|
|
24
33
|
});
|
|
25
34
|
},
|
|
@@ -66,6 +66,7 @@ export const invokeRpcMethod = <Api, Method extends AsyncMethodKey<Api>, Error>(
|
|
|
66
66
|
): Effect.Effect<AsyncMethodCloudflareReturn<Api, Method>, Error> =>
|
|
67
67
|
Effect.gen(function* () {
|
|
68
68
|
const fn = yield* lookupRpcMethod<Api, Method, Error>(target, method, makeError);
|
|
69
|
+
|
|
69
70
|
return yield* Effect.try({
|
|
70
71
|
try: () => fn(...args),
|
|
71
72
|
catch: makeError,
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
-
import { Config, ConfigProvider, Context, Data, Effect, Layer } from "effect";
|
|
3
|
-
//#region src/Environment.ts
|
|
4
|
-
/**
|
|
5
|
-
* Context service for reading worker bindings from the current `env` object.
|
|
6
|
-
*/
|
|
7
|
-
var WorkerEnvironment = class extends Context.Service()("effect-cf/WorkerEnvironment") {};
|
|
8
|
-
let WorkerConfig;
|
|
9
|
-
(function(_WorkerConfig) {
|
|
10
|
-
_WorkerConfig.string = (name) => Config.string(name);
|
|
11
|
-
_WorkerConfig.redacted = (name) => Config.redacted(name);
|
|
12
|
-
_WorkerConfig.number = (name) => Config.number(name);
|
|
13
|
-
_WorkerConfig.integer = (name) => Config.int(name);
|
|
14
|
-
_WorkerConfig.boolean = (name) => Config.boolean(name);
|
|
15
|
-
const providerFromEnv = _WorkerConfig.providerFromEnv = (env) => ConfigProvider.fromUnknown(env);
|
|
16
|
-
const providerWith = _WorkerConfig.providerWith = (makeProvider) => Effect.map(WorkerEnvironment, makeProvider);
|
|
17
|
-
const provider = _WorkerConfig.provider = providerWith(providerFromEnv);
|
|
18
|
-
_WorkerConfig.layer = _WorkerConfig.providerLayer = ConfigProvider.layer(provider);
|
|
19
|
-
_WorkerConfig.layerWith = (makeProvider) => ConfigProvider.layer(providerWith(makeProvider));
|
|
20
|
-
})(WorkerConfig || (WorkerConfig = {}));
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/Binding.ts
|
|
23
|
-
var Binding_exports = /* @__PURE__ */ __exportAll({
|
|
24
|
-
BindingNotFoundError: () => BindingNotFoundError,
|
|
25
|
-
BindingValidationError: () => BindingValidationError,
|
|
26
|
-
Service: () => Service,
|
|
27
|
-
TypeId: () => TypeId,
|
|
28
|
-
layer: () => layer$1
|
|
29
|
-
});
|
|
30
|
-
/** Internal type id marker used by binding helper services. */
|
|
31
|
-
const TypeId = "effect-cf/Binding";
|
|
32
|
-
/** Error raised when a configured binding does not exist on `env`. */
|
|
33
|
-
var BindingNotFoundError = class extends Data.TaggedError("BindingNotFoundError") {};
|
|
34
|
-
/** Error raised when a binding exists but does not match the expected shape. */
|
|
35
|
-
var BindingValidationError = class extends Data.TaggedError("BindingValidationError") {};
|
|
36
|
-
const defaultExpected = "Cloudflare binding resource";
|
|
37
|
-
const isPropertyTarget = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
38
|
-
const getObjectName = (value) => {
|
|
39
|
-
const tag = (() => {
|
|
40
|
-
try {
|
|
41
|
-
return Object.prototype.toString.call(value).slice(8, -1);
|
|
42
|
-
} catch {
|
|
43
|
-
return typeof value;
|
|
44
|
-
}
|
|
45
|
-
})();
|
|
46
|
-
const constructorName = (() => {
|
|
47
|
-
try {
|
|
48
|
-
return "constructor" in value && typeof value.constructor === "function" && typeof value.constructor.name === "string" ? value.constructor.name : void 0;
|
|
49
|
-
} catch {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
})();
|
|
53
|
-
if (tag !== "Object") return tag;
|
|
54
|
-
if (constructorName !== void 0 && constructorName !== "" && constructorName !== "Object") return constructorName;
|
|
55
|
-
return tag;
|
|
56
|
-
};
|
|
57
|
-
const propertyNames = (value) => {
|
|
58
|
-
const names = /* @__PURE__ */ new Set();
|
|
59
|
-
for (const target of [value, Object.getPrototypeOf(value)]) {
|
|
60
|
-
if (target === null || target === Object.prototype || target === Function.prototype) continue;
|
|
61
|
-
try {
|
|
62
|
-
for (const name of Object.getOwnPropertyNames(target)) names.add(name);
|
|
63
|
-
} catch {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return [...names].filter((name) => name !== "constructor").sort();
|
|
68
|
-
};
|
|
69
|
-
const isMethod = (value, name) => {
|
|
70
|
-
try {
|
|
71
|
-
return typeof Reflect.get(value, name) === "function";
|
|
72
|
-
} catch {
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
const describeActual = (value) => {
|
|
77
|
-
if (value === null) return "null";
|
|
78
|
-
if (typeof value !== "object" && typeof value !== "function") return typeof value;
|
|
79
|
-
const names = propertyNames(value);
|
|
80
|
-
const methods = names.filter((name) => isMethod(value, name));
|
|
81
|
-
const properties = names.filter((name) => !methods.includes(name));
|
|
82
|
-
const details = [methods.length > 0 ? `methods ${methods.join(", ")}` : void 0, properties.length > 0 ? `properties ${properties.join(", ")}` : void 0].filter((detail) => detail !== void 0);
|
|
83
|
-
if (details.length === 0) return getObjectName(value);
|
|
84
|
-
return `${getObjectName(value)} with ${details.join("; ")}`;
|
|
85
|
-
};
|
|
86
|
-
const getBinding = (env, binding, isResource, options) => Effect.gen(function* () {
|
|
87
|
-
if (!isPropertyTarget(env)) {
|
|
88
|
-
const actual = describeActual(env);
|
|
89
|
-
return yield* Effect.fail(new BindingValidationError({
|
|
90
|
-
binding,
|
|
91
|
-
expected: "WorkerEnvironment object",
|
|
92
|
-
actual,
|
|
93
|
-
message: `Cloudflare binding "${binding}" failed validation. Expected WorkerEnvironment object; got ${actual}`
|
|
94
|
-
}));
|
|
95
|
-
}
|
|
96
|
-
const resource = Reflect.get(env, binding);
|
|
97
|
-
if (resource === void 0) return yield* Effect.fail(new BindingNotFoundError({
|
|
98
|
-
binding,
|
|
99
|
-
message: `Cloudflare binding "${binding}" was not found in WorkerEnvironment`
|
|
100
|
-
}));
|
|
101
|
-
if (!isResource(resource)) {
|
|
102
|
-
const expected = options?.expected ?? defaultExpected;
|
|
103
|
-
const actual = describeActual(resource);
|
|
104
|
-
return yield* Effect.fail(new BindingValidationError({
|
|
105
|
-
binding,
|
|
106
|
-
expected,
|
|
107
|
-
actual,
|
|
108
|
-
message: `Cloudflare binding "${binding}" failed validation. Expected ${expected}; got ${actual}`
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
return resource;
|
|
112
|
-
});
|
|
113
|
-
const layer$1 = (tag, binding, isResource, wrap, options) => Layer.effect(tag, Effect.gen(function* () {
|
|
114
|
-
const resource = yield* getBinding(yield* WorkerEnvironment, binding, isResource, options);
|
|
115
|
-
return wrap === void 0 ? resource : wrap(resource);
|
|
116
|
-
}));
|
|
117
|
-
const Service = () => (id, binding, isResource, wrap, options) => {
|
|
118
|
-
const tag = Context.Service()(id);
|
|
119
|
-
const serviceLayer = layer$1(tag, binding, isResource, wrap, options);
|
|
120
|
-
return Object.assign(tag, {
|
|
121
|
-
[TypeId]: TypeId,
|
|
122
|
-
binding,
|
|
123
|
-
layer: serviceLayer
|
|
124
|
-
});
|
|
125
|
-
};
|
|
126
|
-
//#endregion
|
|
127
|
-
//#region src/Hyperdrive.ts
|
|
128
|
-
var Hyperdrive_exports = /* @__PURE__ */ __exportAll({
|
|
129
|
-
Tag: () => Tag,
|
|
130
|
-
isHyperdrive: () => isHyperdrive,
|
|
131
|
-
layer: () => layer,
|
|
132
|
-
make: () => make,
|
|
133
|
-
makeClient: () => makeClient
|
|
134
|
-
});
|
|
135
|
-
const expectedHyperdrive = "Hyperdrive binding with connectionString";
|
|
136
|
-
const isHyperdrive = (value) => {
|
|
137
|
-
if (typeof value !== "object" || value === null) return false;
|
|
138
|
-
return typeof value.connectionString === "string";
|
|
139
|
-
};
|
|
140
|
-
const makeClient = (definition) => (hyperdrive) => ({
|
|
141
|
-
definition,
|
|
142
|
-
connectionString: hyperdrive.connectionString,
|
|
143
|
-
unsafeRaw: Effect.succeed(hyperdrive)
|
|
144
|
-
});
|
|
145
|
-
const layer = (tag, definition) => layer$1(tag, definition.binding, isHyperdrive, makeClient(definition), { expected: expectedHyperdrive });
|
|
146
|
-
const make = (id) => Tag()(id);
|
|
147
|
-
const Tag = () => (id) => {
|
|
148
|
-
const tag = Context.Service()(id);
|
|
149
|
-
const makeLayer = (definition) => layer(tag, definition);
|
|
150
|
-
return Object.assign(tag, {
|
|
151
|
-
id,
|
|
152
|
-
layer: makeLayer
|
|
153
|
-
});
|
|
154
|
-
};
|
|
155
|
-
//#endregion
|
|
156
|
-
export { WorkerConfig as a, layer$1 as i, Binding_exports as n, WorkerEnvironment as o, Service as r, Hyperdrive_exports as t };
|
|
File without changes
|