effect-cf 0.23.1 → 0.25.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/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { Cause, Clock, Config, ConfigProvider, Context, Data, DateTime, Duration, Effect, Exit, Function as Function$1, Layer, ManagedRuntime, Option, Predicate, Queue, Result, Schema } from "effect";
2
+ import { a as DurableObjectWebSocket_exports, c as causeMessage, d as WorkerConfig, f as WorkerEnvironment, i as fromExecutionContext, l as violationsMessage, n as DurableObjectState_exports, o as fromWebSocket, r as fromDurableObjectState, s as DurableObjectStorage_exports, t as DurableObjectState, u as Environment_exports } from "./DurableObjectState-B5RCFnRy.mjs";
3
+ import { Clock, Config, ConfigProvider, Context, Data, DateTime, Duration, Effect, Exit, Function as Function$1, Layer, ManagedRuntime, Option, Predicate, Queue, Result, Schema } from "effect";
3
4
  import { FetchHttpClient, HttpClient, HttpClientRequest, HttpEffect, HttpServerRequest, HttpServerResponse } from "effect/unstable/http";
4
5
  import { OtlpExporter, OtlpLogger, OtlpMetrics, OtlpSerialization, OtlpTracer } from "effect/unstable/observability";
5
6
  import { D1Client } from "@effect/sql-d1";
@@ -8,29 +9,6 @@ import * as RpcMessage from "effect/unstable/rpc/RpcMessage";
8
9
  import * as RpcSerialization from "effect/unstable/rpc/RpcSerialization";
9
10
  import * as RpcServer from "effect/unstable/rpc/RpcServer";
10
11
  import { SqliteClient } from "@effect/sql-sqlite-do";
11
- //#region src/Environment.ts
12
- var Environment_exports = /* @__PURE__ */ __exportAll({
13
- WorkerConfig: () => WorkerConfig,
14
- WorkerEnvironment: () => WorkerEnvironment
15
- });
16
- /**
17
- * Context service for reading worker bindings from the current `env` object.
18
- */
19
- var WorkerEnvironment = class extends Context.Service()("effect-cf/WorkerEnvironment") {};
20
- let WorkerConfig;
21
- (function(_WorkerConfig) {
22
- _WorkerConfig.string = (name) => Config.string(name);
23
- _WorkerConfig.redacted = (name) => Config.redacted(name);
24
- _WorkerConfig.number = (name) => Config.number(name);
25
- _WorkerConfig.integer = (name) => Config.int(name);
26
- _WorkerConfig.boolean = (name) => Config.boolean(name);
27
- const providerFromEnv = _WorkerConfig.providerFromEnv = (env, options) => ConfigProvider.fromUnknown(env, options);
28
- const providerWith = _WorkerConfig.providerWith = (makeProvider) => Effect.map(WorkerEnvironment, makeProvider);
29
- const provider = _WorkerConfig.provider = providerWith(providerFromEnv);
30
- _WorkerConfig.layer = _WorkerConfig.providerLayer = ConfigProvider.layer(provider);
31
- _WorkerConfig.layerWith = (makeProvider) => ConfigProvider.layer(providerWith(makeProvider));
32
- })(WorkerConfig || (WorkerConfig = {}));
33
- //#endregion
34
12
  //#region src/Binding.ts
35
13
  var Binding_exports = /* @__PURE__ */ __exportAll({
36
14
  BindingNotFoundError: () => BindingNotFoundError,
@@ -149,25 +127,6 @@ const Service$2 = () => {
149
127
  return makeService;
150
128
  };
151
129
  //#endregion
152
- //#region src/internal/ErrorMessage.ts
153
- /**
154
- * Renders the most useful human-readable description of an unknown `cause`
155
- * for use in tagged error `message` getters.
156
- */
157
- const causeMessage = (cause) => {
158
- if (typeof cause === "object" && cause !== null) {
159
- const message = Reflect.get(cause, "message");
160
- if (typeof message === "string" && message.length > 0) return message;
161
- }
162
- try {
163
- return String(cause);
164
- } catch {
165
- return "unknown cause";
166
- }
167
- };
168
- /** Renders a violation list as a single `path: message; ...` line. */
169
- const violationsMessage = (violations) => violations.map((violation) => `${violation.path}: ${violation.message}`).join("; ");
170
- //#endregion
171
130
  //#region src/WorkersAi.ts
172
131
  var WorkersAi_exports = /* @__PURE__ */ __exportAll({
173
132
  Tag: () => Tag$16,
@@ -433,14 +392,7 @@ const tryAnalyticsEngineSync = (binding, operation, evaluate) => Effect.try({
433
392
  try: evaluate,
434
393
  catch: (cause) => analyticsEngineError(binding, operation, cause)
435
394
  });
436
- const normalizeBatchSize = (batchSize) => {
437
- if (batchSize === void 0 || !Number.isFinite(batchSize) || batchSize <= 0) return writeLimits.maxDataPointsPerInvocation;
438
- return Math.min(Math.floor(batchSize), writeLimits.maxDataPointsPerInvocation);
439
- };
440
- const resolveWritePolicy = (defaults, options) => ({
441
- onInvalid: options?.onInvalid ?? defaults?.onInvalid ?? "error",
442
- batchSize: normalizeBatchSize(options?.batchSize ?? defaults?.batchSize)
443
- });
395
+ const resolveWritePolicy = (defaults, options) => ({ onInvalid: options?.onInvalid ?? defaults?.onInvalid ?? "error" });
444
396
  const fieldPath = (prefix, field) => prefix === "" ? field : `${prefix}.${field}`;
445
397
  const indexedPath = (prefix, field, index) => `${fieldPath(prefix, field)}[${index}]`;
446
398
  const byteLength$1 = (value) => {
@@ -498,13 +450,8 @@ const validateDataPoints = (binding, operation, dataPoints, policy) => Effect.ge
498
450
  if (violations.length > 0) return yield* Effect.fail(analyticsEngineWriteValidationError(binding, operation, violations));
499
451
  return validPoints;
500
452
  });
501
- const writeChunks = (binding, operation, dataset, dataPoints, batchSize) => Effect.gen(function* () {
502
- const writeDataPoints = Reflect.get(dataset, "writeDataPoints");
503
- for (let index = 0; index < dataPoints.length; index += batchSize) {
504
- const chunk = dataPoints.slice(index, index + batchSize);
505
- if (typeof writeDataPoints === "function") yield* tryAnalyticsEngineSync(binding, operation, () => writeDataPoints.call(dataset, chunk));
506
- else for (const point of chunk) yield* tryAnalyticsEngineSync(binding, operation, () => dataset.writeDataPoint(point));
507
- }
453
+ const writeChunks = (binding, operation, dataset, dataPoints) => Effect.gen(function* () {
454
+ for (const point of dataPoints) yield* tryAnalyticsEngineSync(binding, operation, () => dataset.writeDataPoint(point));
508
455
  });
509
456
  const queryApiUrl = (definition) => {
510
457
  const baseUrl = new URL(definition.apiBaseUrl ?? defaultQueryApiBaseUrl);
@@ -561,24 +508,20 @@ const isAnalyticsEngineDataset = (value) => {
561
508
  return typeof Reflect.get(value, "writeDataPoint") === "function";
562
509
  };
563
510
  const makeClient$13 = (definition, defaults) => (dataset) => {
564
- const writeDataPoint = Effect.fn("AnalyticsEngine.writeDataPoint")((dataPoint, options) => {
565
- const policy = resolveWritePolicy(defaults, options);
566
- return validateOptionalDataPoint(definition.binding, "writeDataPoint", dataPoint).pipe(Effect.matchEffect({
567
- onFailure: (error) => policy.onInvalid === "drop" ? Effect.succeed(void 0) : Effect.fail(error),
568
- onSuccess: (point) => tryAnalyticsEngineSync(definition.binding, "writeDataPoint", () => dataset.writeDataPoint(point))
569
- }));
570
- });
571
- const writeDataPoints = Effect.fn("AnalyticsEngine.writeDataPoints")(function* (dataPoints, options) {
572
- const policy = resolveWritePolicy(defaults, options);
573
- const validPoints = yield* validateDataPoints(definition.binding, "writeDataPoints", dataPoints, policy);
574
- yield* writeChunks(definition.binding, "writeDataPoints", dataset, validPoints, policy.batchSize);
575
- });
576
511
  return {
577
512
  definition,
578
- writeDataPoint,
579
- write: writeDataPoint,
580
- writeDataPoints,
581
- writeBatch: writeDataPoints,
513
+ writeDataPoint: Effect.fn("AnalyticsEngine.writeDataPoint")((dataPoint, options) => {
514
+ const policy = resolveWritePolicy(defaults, options);
515
+ return validateOptionalDataPoint(definition.binding, "writeDataPoint", dataPoint).pipe(Effect.matchEffect({
516
+ onFailure: (error) => policy.onInvalid === "drop" ? Effect.succeed(void 0) : Effect.fail(error),
517
+ onSuccess: (point) => tryAnalyticsEngineSync(definition.binding, "writeDataPoint", () => dataset.writeDataPoint(point))
518
+ }));
519
+ }),
520
+ writeDataPoints: Effect.fn("AnalyticsEngine.writeDataPoints")(function* (dataPoints, options) {
521
+ const policy = resolveWritePolicy(defaults, options);
522
+ const validPoints = yield* validateDataPoints(definition.binding, "writeDataPoints", dataPoints, policy);
523
+ yield* writeChunks(definition.binding, "writeDataPoints", dataset, validPoints);
524
+ }),
582
525
  rawUnsafe: Effect.succeed(dataset)
583
526
  };
584
527
  };
@@ -734,345 +677,6 @@ const layerFrom = (storage) => Layer.succeed(CacheStorage, makeClient$11(storage
734
677
  /** Provides Cache API services from Cloudflare's global `caches` object. */
735
678
  const layer$14 = Layer.sync(CacheStorage, () => makeClient$11(caches));
736
679
  //#endregion
737
- //#region src/DurableObjectStorage.ts
738
- var DurableObjectStorage_exports = /* @__PURE__ */ __exportAll({
739
- StorageOperationError: () => StorageOperationError,
740
- fromDurableObjectStorage: () => fromDurableObjectStorage
741
- });
742
- /** Error type used when a storage operation throws or rejects. */
743
- var StorageOperationError = class extends Data.TaggedError("StorageOperationError") {
744
- get message() {
745
- return `Durable Object storage ${this.operation} failed: ${causeMessage(this.cause)}`;
746
- }
747
- };
748
- const storageError = (operation, cause) => new StorageOperationError({
749
- operation,
750
- cause
751
- });
752
- const tryStorageSync = (operation, evaluate) => Effect.try({
753
- try: evaluate,
754
- catch: (cause) => storageError(operation, cause)
755
- });
756
- const tryStoragePromise = (operation, evaluate) => Effect.tryPromise({
757
- try: evaluate,
758
- catch: (cause) => storageError(operation, cause)
759
- });
760
- const fromSqlCursor = (cursor) => ({
761
- next: () => tryStorageSync("sql.next", () => cursor.next()),
762
- toArray: () => tryStorageSync("sql.toArray", () => cursor.toArray()),
763
- one: () => tryStorageSync("sql.one", () => cursor.one()),
764
- raw: () => tryStorageSync("sql.raw", () => cursor.raw()),
765
- get columnNames() {
766
- return cursor.columnNames;
767
- },
768
- rowsRead: tryStorageSync("sql.rowsRead", () => cursor.rowsRead),
769
- rowsWritten: tryStorageSync("sql.rowsWritten", () => cursor.rowsWritten)
770
- });
771
- const fromSqlStorage = (sql) => ({
772
- exec: (query, ...bindings) => tryStorageSync("sql.exec", () => fromSqlCursor(sql.exec(query, ...bindings))),
773
- get databaseSize() {
774
- return sql.databaseSize;
775
- }
776
- });
777
- const schemaBackedSyncKvStorage = (kv, definition) => {
778
- const encodeKey = Schema.encodeEffect(definition.key);
779
- const decodeKey = Schema.decodeUnknownEffect(definition.key);
780
- const encodeValue = Schema.encodeEffect(definition.value);
781
- const decodeValue = Schema.decodeUnknownEffect(definition.value);
782
- return {
783
- get: (key) => Effect.gen(function* () {
784
- const encodedKey = yield* encodeKey(key);
785
- const encodedValue = yield* tryStorageSync("kv.get", () => kv.get(encodedKey));
786
- if (encodedValue === void 0) return Option.none();
787
- return yield* decodeValue(encodedValue).pipe(Effect.map(Option.some));
788
- }),
789
- put: (key, value) => Effect.gen(function* () {
790
- const encodedKey = yield* encodeKey(key);
791
- const encodedValue = yield* encodeValue(value);
792
- yield* tryStorageSync("kv.put", () => kv.put(encodedKey, encodedValue));
793
- }),
794
- delete: (key) => Effect.gen(function* () {
795
- const encodedKey = yield* encodeKey(key);
796
- return yield* tryStorageSync("kv.delete", () => kv.delete(encodedKey));
797
- }),
798
- list: (options) => Effect.gen(function* () {
799
- const entries = Array.from(yield* tryStorageSync("kv.list", () => kv.list(options)));
800
- const decoded = [];
801
- for (const [key, value] of entries) decoded.push([yield* decodeKey(key), yield* decodeValue(value)]);
802
- return decoded;
803
- })
804
- };
805
- };
806
- const fromSyncKvStorage = (kv) => ({
807
- get: (key) => tryStorageSync("kv.get", () => kv.get(key)),
808
- put: (key, value) => tryStorageSync("kv.put", () => kv.put(key, value)),
809
- delete: (key) => tryStorageSync("kv.delete", () => kv.delete(key)),
810
- list: (options) => tryStorageSync("kv.list", () => Array.from(kv.list(options))),
811
- schema: (definition) => schemaBackedSyncKvStorage(kv, definition)
812
- });
813
- const fromDurableObjectTransaction = (txn) => ({
814
- get: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)) : tryStoragePromise("transaction.get", () => txn.get(keyOrKeys, options)),
815
- list: (options) => tryStoragePromise("transaction.list", () => txn.list(options)),
816
- put: (keyOrEntries, valueOrOptions, maybeOptions) => tryStoragePromise("transaction.put", () => typeof keyOrEntries === "string" ? txn.put(keyOrEntries, valueOrOptions, maybeOptions) : txn.put(keyOrEntries, valueOrOptions)),
817
- delete: (keyOrKeys, options) => Array.isArray(keyOrKeys) ? tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)) : tryStoragePromise("transaction.delete", () => txn.delete(keyOrKeys, options)),
818
- rollback: () => tryStorageSync("transaction.rollback", () => txn.rollback()),
819
- getAlarm: (options) => tryStoragePromise("transaction.getAlarm", () => txn.getAlarm(options)),
820
- setAlarm: (scheduledTime, options) => tryStoragePromise("transaction.setAlarm", () => txn.setAlarm(scheduledTime, options)),
821
- deleteAlarm: (options) => tryStoragePromise("transaction.deleteAlarm", () => txn.deleteAlarm(options))
822
- });
823
- /**
824
- * Wraps native Cloudflare storage APIs as Effect-returning helpers.
825
- */
826
- const fromDurableObjectStorage = (storage) => ({
827
- get: (key, options) => tryStoragePromise("get", () => storage.get(key, options)),
828
- put: (key, value, options) => tryStoragePromise("put", () => storage.put(key, value, options)),
829
- delete: (key, options) => tryStoragePromise("delete", () => storage.delete(key, options)),
830
- deleteAll: (options) => tryStoragePromise("deleteAll", () => storage.deleteAll(options)),
831
- getAlarm: (options) => tryStoragePromise("getAlarm", () => storage.getAlarm(options)),
832
- setAlarm: (scheduledTime, options) => tryStoragePromise("setAlarm", () => storage.setAlarm(scheduledTime, options)),
833
- deleteAlarm: (options) => tryStoragePromise("deleteAlarm", () => storage.deleteAlarm(options)),
834
- transactionSync: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.suspend(() => {
835
- try {
836
- return Effect.succeed(storage.transactionSync(() => {
837
- const exit = Effect.runSyncExitWith(context)(closure());
838
- if (Exit.isSuccess(exit)) return exit.value;
839
- throw exit;
840
- }));
841
- } catch (cause) {
842
- if (Exit.isExit(cause) && Exit.isFailure(cause)) return Effect.failCause(cause.cause);
843
- return Effect.fail(storageError("transactionSync", cause));
844
- }
845
- }))),
846
- transaction: (closure) => Effect.context().pipe(Effect.flatMap((context) => Effect.callback((resume) => {
847
- storage.transaction(async (txn) => {
848
- const exit = await Effect.runPromiseExitWith(context)(closure(fromDurableObjectTransaction(txn)));
849
- if (Exit.isSuccess(exit)) return exit.value;
850
- throw exit;
851
- }).then((value) => resume(Effect.succeed(value)), (cause) => {
852
- if (Exit.isExit(cause) && Exit.isFailure(cause)) resume(Effect.failCause(cause.cause));
853
- else resume(Effect.fail(storageError("transaction", cause)));
854
- });
855
- }))),
856
- sync: () => tryStoragePromise("sync", () => storage.sync()),
857
- getCurrentBookmark: () => tryStoragePromise("getCurrentBookmark", () => storage.getCurrentBookmark()),
858
- onNextSessionRestoreBookmark: (bookmark) => tryStoragePromise("onNextSessionRestoreBookmark", () => storage.onNextSessionRestoreBookmark(bookmark)),
859
- sql: fromSqlStorage(storage.sql),
860
- kv: fromSyncKvStorage(storage.kv)
861
- });
862
- //#endregion
863
- //#region src/DurableObjectWebSocket.ts
864
- var DurableObjectWebSocket_exports = /* @__PURE__ */ __exportAll({
865
- DurableWebSocketAttachmentError: () => DurableWebSocketAttachmentError,
866
- DurableWebSocketCloseError: () => DurableWebSocketCloseError,
867
- DurableWebSocketSendError: () => DurableWebSocketSendError,
868
- acceptUpgrade: () => acceptUpgrade,
869
- attachment: () => attachment,
870
- fromWebSocket: () => fromWebSocket,
871
- handlers: () => handlers
872
- });
873
- /** Error raised when sending on a Durable Object websocket fails. */
874
- var DurableWebSocketSendError = class extends Data.TaggedError("DurableWebSocketSendError") {
875
- get message() {
876
- return `Durable Object websocket send failed: ${causeMessage(this.cause)}`;
877
- }
878
- };
879
- /** Error raised when closing a Durable Object websocket fails. */
880
- var DurableWebSocketCloseError = class extends Data.TaggedError("DurableWebSocketCloseError") {
881
- get message() {
882
- return `Durable Object websocket close failed: ${causeMessage(this.cause)}`;
883
- }
884
- };
885
- /** Error raised when serializing or deserializing a websocket attachment fails. */
886
- var DurableWebSocketAttachmentError = class extends Data.TaggedError("DurableWebSocketAttachmentError") {
887
- get message() {
888
- return `Durable Object websocket attachment ${this.operation} failed: ${causeMessage(this.cause)}`;
889
- }
890
- };
891
- const wrappers = /* @__PURE__ */ new WeakMap();
892
- /** Wraps a native Cloudflare websocket in the Effect-native Durable Object API. */
893
- const fromWebSocket = (raw) => {
894
- const existing = wrappers.get(raw);
895
- if (existing !== void 0) return existing;
896
- const socket = {
897
- raw,
898
- send: (data) => Effect.try({
899
- try: () => raw.send(data),
900
- catch: (cause) => new DurableWebSocketSendError({ cause })
901
- }),
902
- close: (code, reason) => Effect.try({
903
- try: () => raw.close(code, reason),
904
- catch: (cause) => new DurableWebSocketCloseError({ cause })
905
- }),
906
- serializeAttachment: (value) => Effect.try({
907
- try: () => raw.serializeAttachment(value),
908
- catch: (cause) => new DurableWebSocketAttachmentError({
909
- operation: "serialize",
910
- cause
911
- })
912
- }),
913
- deserializeAttachment: Effect.try({
914
- try: () => raw.deserializeAttachment(),
915
- catch: (cause) => new DurableWebSocketAttachmentError({
916
- operation: "deserialize",
917
- cause
918
- })
919
- })
920
- };
921
- wrappers.set(raw, socket);
922
- return socket;
923
- };
924
- /**
925
- * Accepts a websocket upgrade and registers the server socket on `DurableObjectState`.
926
- *
927
- * @example
928
- * ```ts
929
- * const response = yield* DurableObjectWebSocket.acceptUpgrade({
930
- * tags: ["room:general"],
931
- * });
932
- *
933
- * return response.response;
934
- * ```
935
- */
936
- const acceptUpgrade = Effect.fn("DurableObjectWebSocket.acceptUpgrade")(function* (options = {}) {
937
- const state = yield* DurableObjectState;
938
- const pair = new WebSocketPair();
939
- const client = pair[0];
940
- const server = fromWebSocket(pair[1]);
941
- if (options.attachment !== void 0) yield* server.serializeAttachment(options.attachment);
942
- yield* state.acceptWebSocket(server, options.tags === void 0 ? void 0 : [...options.tags]);
943
- return {
944
- client,
945
- server,
946
- response: new Response(null, {
947
- status: 101,
948
- webSocket: client
949
- })
950
- };
951
- });
952
- /** Creates typed attachment helpers for accepted and rehydrated sockets. */
953
- const attachment = (schema) => {
954
- const serialize = (socket, value) => Schema.encodeEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
955
- operation: "serialize",
956
- cause
957
- })), Effect.flatMap((encoded) => socket.serializeAttachment(encoded)));
958
- const deserialize = (socket) => Effect.gen(function* () {
959
- const value = yield* socket.deserializeAttachment;
960
- if (value === null || value === void 0) return Option.none();
961
- return Option.some(yield* Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((cause) => new DurableWebSocketAttachmentError({
962
- operation: "deserialize",
963
- cause
964
- }))));
965
- });
966
- const rehydrate = (options = {}) => Effect.gen(function* () {
967
- const sockets = yield* (yield* DurableObjectState).getWebSockets(options.tag);
968
- const restored = [];
969
- const onInvalid = options.onInvalid ?? "ignore";
970
- for (const socket of sockets) {
971
- const decoded = yield* Effect.result(deserialize(socket));
972
- if (Result.isSuccess(decoded) && Option.isSome(decoded.success)) {
973
- restored.push({
974
- socket,
975
- attachment: decoded.success.value
976
- });
977
- continue;
978
- }
979
- if (Result.isFailure(decoded) && onInvalid === "fail") return yield* Effect.fail(decoded.failure);
980
- if (Result.isFailure(decoded) && onInvalid === "ignore-and-close") yield* socket.close(1008, "invalid websocket attachment").pipe(Effect.ignore);
981
- }
982
- return restored;
983
- });
984
- return {
985
- serialize,
986
- deserialize,
987
- rehydrate,
988
- schema
989
- };
990
- };
991
- /** Maps compact websocket lifecycle handler names to `DurableObject.make` options. */
992
- const handlers = (options) => ({
993
- webSocketMessage: options.message,
994
- webSocketClose: options.close,
995
- webSocketError: options.error
996
- });
997
- //#endregion
998
- //#region src/internal/WorkerContext.ts
999
- const causeError = (cause) => {
1000
- const squashed = Cause.squash(cause);
1001
- return squashed instanceof Error ? squashed : new Error(Cause.pretty(cause), { cause: squashed });
1002
- };
1003
- const failureHandler = (label, cause, options) => (options?.onFailure?.(cause) ?? Effect.logError(`${label} failed`, Cause.pretty(cause))).pipe(Effect.catchCause((handlerCause) => Effect.logError(`${label} failure handler failed`, Cause.pretty(cause), Cause.pretty(handlerCause))));
1004
- /**
1005
- * Builds a `waitUntil` scheduler for any Cloudflare lifecycle that accepts
1006
- * background promises (`ExecutionContext`, `DurableObjectState`).
1007
- *
1008
- * Background effects capture the calling fiber's context via `Effect.context`
1009
- * before being registered, so the default module-level `Effect.runPromiseExit`
1010
- * runner is sufficient; entrypoints may still pass a runtime-bound runner.
1011
- */
1012
- const makeWaitUntilScheduler = (label, register, runPromiseExit = (effect) => Effect.runPromiseExit(effect)) => {
1013
- return (effect, options, mode) => Effect.context().pipe(Effect.flatMap((context) => Effect.sync(() => {
1014
- const runHandler = (cause) => runPromiseExit(Effect.scoped(Effect.provideContext(failureHandler(label, cause, options), context))).then((exit) => {
1015
- if (Exit.isFailure(exit)) console.error(`${label} failure handler failed`, Cause.pretty(exit.cause));
1016
- });
1017
- register(runPromiseExit(Effect.scoped(Effect.provideContext(effect, context))).then(async (exit) => {
1018
- if (Exit.isSuccess(exit)) return;
1019
- await runHandler(exit.cause);
1020
- if (mode === "propagate") throw causeError(exit.cause);
1021
- }));
1022
- })));
1023
- };
1024
- /**
1025
- * Builds the `WorkerContext` service from a native `ExecutionContext`.
1026
- */
1027
- const fromExecutionContext = (ctx, runPromiseExit = (effect) => Effect.runPromiseExit(effect)) => {
1028
- const schedule = makeWaitUntilScheduler("WorkerContext.waitUntil", (promise) => ctx.waitUntil(promise), runPromiseExit);
1029
- return {
1030
- raw: ctx,
1031
- waitUntil: (effect, options) => schedule(effect, options, options?.mode ?? "observe"),
1032
- waitUntilPropagating: (effect, options) => schedule(effect, options, "propagate"),
1033
- passThroughOnException: Effect.sync(() => ctx.passThroughOnException())
1034
- };
1035
- };
1036
- //#endregion
1037
- //#region src/DurableObjectState.ts
1038
- var DurableObjectState_exports = /* @__PURE__ */ __exportAll({
1039
- DurableObjectState: () => DurableObjectState,
1040
- fromDurableObjectState: () => fromDurableObjectState
1041
- });
1042
- /**
1043
- * Context tag for accessing the current Durable Object state service.
1044
- */
1045
- var DurableObjectState = class extends Context.Service()("effect-cf/DurableObjectState") {};
1046
- /**
1047
- * Wraps a native Cloudflare `DurableObjectState` as a {@link DurableObjectStateService}.
1048
- */
1049
- const fromDurableObjectState = (state) => {
1050
- const scheduleWaitUntil = makeWaitUntilScheduler("DurableObjectState.waitUntil", (promise) => state.waitUntil(promise));
1051
- const waitUntil = ((input, options) => Effect.isEffect(input) ? scheduleWaitUntil(input, options, options?.mode ?? "observe") : Effect.sync(() => state.waitUntil(input)));
1052
- return {
1053
- raw: state,
1054
- id: state.id,
1055
- storage: fromDurableObjectStorage(state.storage),
1056
- waitUntil,
1057
- blockConcurrencyWhile: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => runPromiseExitPreservingTypedFailures(context, effect)))), Effect.flatten),
1058
- blockConcurrencyWhileOrReset: (effect) => Effect.context().pipe(Effect.flatMap((context) => Effect.promise(() => state.blockConcurrencyWhile(() => Effect.runPromiseWith(context)(effect))))),
1059
- acceptWebSocket: (ws, tags) => Effect.sync(() => state.acceptWebSocket(ws.raw, tags)),
1060
- getWebSockets: (tag) => Effect.sync(() => state.getWebSockets(tag).map((socket) => fromWebSocket(socket))),
1061
- setWebSocketAutoResponse: (pair) => Effect.sync(() => state.setWebSocketAutoResponse(pair)),
1062
- getWebSocketAutoResponse: Effect.sync(() => state.getWebSocketAutoResponse()),
1063
- getWebSocketAutoResponseTimestamp: (ws) => Effect.sync(() => state.getWebSocketAutoResponseTimestamp(ws.raw)),
1064
- setHibernatableWebSocketEventTimeout: (timeoutMs) => Effect.sync(() => state.setHibernatableWebSocketEventTimeout(timeoutMs)),
1065
- getHibernatableWebSocketEventTimeout: Effect.sync(() => state.getHibernatableWebSocketEventTimeout()),
1066
- getTags: (ws) => Effect.sync(() => state.getTags(ws.raw)),
1067
- abort: (reason) => Effect.sync(() => state.abort(reason))
1068
- };
1069
- };
1070
- const runPromiseExitPreservingTypedFailures = async (context, effect) => {
1071
- const exit = await Effect.runPromiseExitWith(context)(effect);
1072
- if (Exit.isFailure(exit) && (Cause.hasDies(exit.cause) || Cause.hasInterrupts(exit.cause))) throw Cause.squash(exit.cause);
1073
- return exit;
1074
- };
1075
- //#endregion
1076
680
  //#region src/CloudflareOtlp.ts
1077
681
  /**
1078
682
  * OTLP telemetry layers for Cloudflare Workers and Durable Objects.
@@ -2530,7 +2134,6 @@ var DurableObjectAlarm_exports = /* @__PURE__ */ __exportAll({
2530
2134
  InvalidRepeatEveryError: () => InvalidRepeatEveryError,
2531
2135
  StoredAlarmDecodeError: () => StoredAlarmDecodeError,
2532
2136
  define: () => define,
2533
- process: () => process,
2534
2137
  processDue: () => processDue
2535
2138
  });
2536
2139
  const INIT_TABLE_SQL = `
@@ -2655,7 +2258,6 @@ const getFailureActionRetryDelay = (action) => typeof action === "string" || act
2655
2258
  const processDue = (handle, options = {}) => Effect.gen(function* () {
2656
2259
  return yield* (yield* DurableObjectAlarm).processDueAlarms(handle, options);
2657
2260
  });
2658
- const process = processDue;
2659
2261
  const isAlarmDefinitionConfig = (definition) => typeof definition === "object" && definition !== null && "payload" in definition;
2660
2262
  const getAlarmDefinitionSchema = (definition) => isAlarmDefinitionConfig(definition) ? definition.payload : definition;
2661
2263
  const getAlarmDefinitionFailureAction = (definition) => {
@@ -3018,7 +2620,6 @@ var Email_exports = /* @__PURE__ */ __exportAll({
3018
2620
  Tag: () => Tag$7,
3019
2621
  emailErrorCodes: () => emailErrorCodes,
3020
2622
  isEmailBinding: () => isEmailBinding,
3021
- isEmailMessageBuilder: () => isEmailMessageBuilder,
3022
2623
  layer: () => layer$6,
3023
2624
  make: () => make$6,
3024
2625
  makeClient: () => makeClient$6,
@@ -3109,24 +2710,6 @@ const tryEmailPromise = (binding, operation, evaluate) => Effect.tryPromise({
3109
2710
  try: evaluate,
3110
2711
  catch: (cause) => emailError(binding, operation, cause)
3111
2712
  });
3112
- const builderFields = [
3113
- "subject",
3114
- "html",
3115
- "text",
3116
- "cc",
3117
- "bcc",
3118
- "replyTo",
3119
- "attachments",
3120
- "headers"
3121
- ];
3122
- /**
3123
- * Distinguishes structured Email Sending messages from raw MIME `EmailMessage`
3124
- * values, which only carry envelope `from` and `to` addresses.
3125
- */
3126
- const isEmailMessageBuilder = (message) => {
3127
- if (typeof message !== "object" || message === null) return false;
3128
- return builderFields.some((field) => Reflect.get(message, field) !== void 0);
3129
- };
3130
2713
  const byteLength = (value) => textEncoder.encode(value).byteLength;
3131
2714
  const limitViolation = (path, label, actual, limit) => ({
3132
2715
  path,
@@ -3261,7 +2844,7 @@ const makeClient$6 = (definition, options) => (email) => {
3261
2844
  return {
3262
2845
  definition,
3263
2846
  send: Effect.fn("Email.send")(function* (message) {
3264
- if (validate && isEmailMessageBuilder(message)) yield* validateSendInput(definition.binding, "send", message);
2847
+ if (validate) yield* validateSendInput(definition.binding, "send", message);
3265
2848
  return yield* tryEmailPromise(definition.binding, "send", () => runtime.send(message));
3266
2849
  }),
3267
2850
  rawUnsafe: Effect.succeed(email)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.23.1",
3
+ "version": "0.25.0",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,6 +27,11 @@
27
27
  "import": "./dist/HyperdrivePg.mjs",
28
28
  "default": "./dist/HyperdrivePg.mjs"
29
29
  },
30
+ "./vitest": {
31
+ "types": "./dist/Vitest.d.mts",
32
+ "import": "./dist/Vitest.mjs",
33
+ "default": "./dist/Vitest.mjs"
34
+ },
30
35
  "./package.json": "./package.json"
31
36
  },
32
37
  "publishConfig": {
@@ -43,7 +48,7 @@
43
48
  "@cloudflare/containers": "catalog:",
44
49
  "@cloudflare/vitest-pool-workers": "catalog:",
45
50
  "@cloudflare/workers-types": "catalog:",
46
- "@effect/platform-node": "4.0.0-beta.105",
51
+ "@effect/platform-node": "^4.0.0-beta.105",
47
52
  "@effect/sql-d1": "catalog:",
48
53
  "@effect/sql-pg": "catalog:",
49
54
  "@effect/sql-sqlite-do": "catalog:",
@@ -53,13 +58,17 @@
53
58
  "vitest": "catalog:"
54
59
  },
55
60
  "peerDependencies": {
61
+ "@cloudflare/vitest-pool-workers": "^0.21.3",
56
62
  "@cloudflare/workers-types": "^4.20260611.1",
57
- "@effect/sql-d1": "4.0.0-beta.105",
58
- "@effect/sql-pg": "4.0.0-beta.105",
59
- "@effect/sql-sqlite-do": "4.0.0-beta.105",
60
- "effect": "4.0.0-beta.105"
63
+ "@effect/sql-d1": "^4.0.0-beta.105",
64
+ "@effect/sql-pg": "^4.0.0-beta.105",
65
+ "@effect/sql-sqlite-do": "^4.0.0-beta.105",
66
+ "effect": "^4.0.0-beta.105"
61
67
  },
62
68
  "peerDependenciesMeta": {
69
+ "@cloudflare/vitest-pool-workers": {
70
+ "optional": true
71
+ },
63
72
  "@cloudflare/workers-types": {
64
73
  "optional": true
65
74
  },