effect-cf 0.41.0 → 0.41.1

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # effect-cf
2
2
 
3
+ ## 0.41.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#161](https://github.com/danieljvdm/effect-cf/pull/161) [`a627f80`](https://github.com/danieljvdm/effect-cf/commit/a627f80449bf40227bddf917640aae9574faa563) Thanks [@danieljvdm](https://github.com/danieljvdm)! - Retain Sandbox and Container RPC channels for each invocation so repeated lookups after callbacks do not exhaust Cloudflare's subrequest depth. Sandbox configuration continues to apply on each lookup, and failed channels are replaced on subsequent acquisition.
8
+
3
9
  ## 0.41.0
4
10
 
5
11
  ### Minor Changes
@@ -1,6 +1,7 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { layer as layer$1 } from "./Binding.mjs";
3
3
  import { causeMessage } from "./internal/ErrorMessage.mjs";
4
+ import { get, invalidate } from "./RpcTargets.mjs";
4
5
  import * as Context from "effect/Context";
5
6
  import * as Data from "effect/Data";
6
7
  import * as Effect from "effect/Effect";
@@ -37,7 +38,7 @@ var ContainerOperationError = class extends Data.TaggedError("ContainerOperation
37
38
  return `Container ${this.operation} failed for binding "${this.binding}" instance "${this.instance}": ${causeMessage(this.cause)}`;
38
39
  }
39
40
  };
40
- const tryContainerPromise = (definition, instance, operation, evaluate) => Effect.tryPromise({
41
+ const tryContainerPromise = (definition, instance, operation, evaluate, target) => Effect.tryPromise({
41
42
  try: evaluate,
42
43
  catch: (cause) => new ContainerOperationError({
43
44
  binding: definition.binding,
@@ -45,43 +46,44 @@ const tryContainerPromise = (definition, instance, operation, evaluate) => Effec
45
46
  operation,
46
47
  cause
47
48
  })
48
- });
49
+ }).pipe(Effect.tapCause(() => invalidate(target)));
49
50
  const makeInstanceClient = (definition, instance, stub) => {
51
+ const attempt = (operation, evaluate) => tryContainerPromise(definition, instance, operation, evaluate, stub);
50
52
  const spanOptions = (operation) => ({ attributes: {
51
53
  binding: definition.binding,
52
54
  instance,
53
55
  operation
54
56
  } });
55
57
  const hostListOperation = (operation) => Effect.fn(`ContainerNamespace.${operation}`, spanOptions(operation))(function* (hosts) {
56
- return yield* tryContainerPromise(definition, instance, operation, () => stub[operation]([...hosts]));
58
+ return yield* attempt(operation, () => stub[operation]([...hosts]));
57
59
  });
58
60
  const hostnameOperation = (operation) => Effect.fn(`ContainerNamespace.${operation}`, spanOptions(operation))(function* (hostname) {
59
- return yield* tryContainerPromise(definition, instance, operation, () => stub[operation](hostname));
61
+ return yield* attempt(operation, () => stub[operation](hostname));
60
62
  });
61
63
  return {
62
64
  rawUnsafe: Effect.succeed(stub),
63
- state: tryContainerPromise(definition, instance, "state", () => stub.getState()).pipe(Effect.flatMap(S.decodeUnknownEffect(ContainerState)), Effect.mapError((cause) => cause instanceof ContainerOperationError ? cause : new ContainerOperationError({
65
+ state: attempt("state", () => stub.getState()).pipe(Effect.flatMap(S.decodeUnknownEffect(ContainerState)), Effect.mapError((cause) => cause instanceof ContainerOperationError ? cause : new ContainerOperationError({
64
66
  binding: definition.binding,
65
67
  instance,
66
68
  operation: "state",
67
69
  cause
68
70
  })), Effect.withSpan("ContainerNamespace.state", spanOptions("state"))),
69
71
  fetch: Effect.fn("ContainerNamespace.fetch", spanOptions("fetch"))(function* (input, init) {
70
- return yield* tryContainerPromise(definition, instance, "fetch", () => stub.fetch(input, init));
72
+ return yield* attempt("fetch", () => stub.fetch(input, init));
71
73
  }),
72
74
  start: Effect.fn("ContainerNamespace.start", spanOptions("start"))(function* (options, waitOptions) {
73
- return yield* tryContainerPromise(definition, instance, "start", () => stub.start(options, waitOptions));
75
+ return yield* attempt("start", () => stub.start(options, waitOptions));
74
76
  }),
75
77
  startAndWaitForPorts: Effect.fn("ContainerNamespace.startAndWaitForPorts", spanOptions("startAndWaitForPorts"))(function* (options) {
76
- return yield* tryContainerPromise(definition, instance, "startAndWaitForPorts", () => stub.startAndWaitForPorts(options));
78
+ return yield* attempt("startAndWaitForPorts", () => stub.startAndWaitForPorts(options));
77
79
  }),
78
80
  waitForPort: Effect.fn("ContainerNamespace.waitForPort", spanOptions("waitForPort"))(function* (options) {
79
- return yield* tryContainerPromise(definition, instance, "waitForPort", () => stub.waitForPort(options));
81
+ return yield* attempt("waitForPort", () => stub.waitForPort(options));
80
82
  }),
81
83
  stop: Effect.fn("ContainerNamespace.stop", spanOptions("stop"))(function* (signal) {
82
- return yield* tryContainerPromise(definition, instance, "stop", () => stub.stop(signal));
84
+ return yield* attempt("stop", () => stub.stop(signal));
83
85
  }),
84
- destroy: tryContainerPromise(definition, instance, "destroy", () => stub.destroy()).pipe(Effect.withSpan("ContainerNamespace.destroy", spanOptions("destroy"))),
86
+ destroy: attempt("destroy", () => stub.destroy()).pipe(Effect.withSpan("ContainerNamespace.destroy", spanOptions("destroy"))),
85
87
  setAllowedHosts: hostListOperation("setAllowedHosts"),
86
88
  setDeniedHosts: hostListOperation("setDeniedHosts"),
87
89
  allowHost: hostnameOperation("allowHost"),
@@ -92,15 +94,16 @@ const makeInstanceClient = (definition, instance, stub) => {
92
94
  };
93
95
  const isContainerNamespaceResource = (value) => Predicate.hasProperty(value, "getByName") && Predicate.isFunction(value.getByName);
94
96
  const makeClient = (definition) => (namespace) => {
95
- const getByName = (name, options) => Effect.try({
96
- try: () => makeInstanceClient(definition, name, namespace.getByName(name, options)),
97
- catch: (cause) => new ContainerOperationError({
98
- binding: definition.binding,
99
- instance: name,
100
- operation: "getByName",
101
- cause
102
- })
103
- });
97
+ const getByName = (name, options) => get(namespace, JSON.stringify([
98
+ "container",
99
+ name,
100
+ options
101
+ ]), () => namespace.getByName(name, options)).pipe(Effect.map((stub) => makeInstanceClient(definition, name, stub)), Effect.mapError((error) => new ContainerOperationError({
102
+ binding: definition.binding,
103
+ instance: name,
104
+ operation: "getByName",
105
+ cause: error.cause
106
+ })));
104
107
  const byName = (name, options) => {
105
108
  const instance = getByName(name, options);
106
109
  return {
@@ -1,8 +1,8 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { layer as layer$1 } from "./Binding.mjs";
3
3
  import { causeMessage } from "./internal/ErrorMessage.mjs";
4
- import { decodeSuccess, encodeArgs } from "./RpcDefinition.mjs";
5
4
  import { get, invalidate } from "./RpcTargets.mjs";
5
+ import { decodeSuccess, encodeArgs } from "./RpcDefinition.mjs";
6
6
  import { withRpcClientSpan, withRpcTraceContext } from "./RpcTracing.mjs";
7
7
  import { invokeRpcMethod } from "./internal/RpcInvocation.mjs";
8
8
  import { resolve, scoped } from "./Rpc.mjs";
@@ -1,5 +1,5 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
- import * as Context from "effect/Context";
2
+ import { CurrentTargets } from "./internal/RpcTargets.mjs";
3
3
  import * as Data from "effect/Data";
4
4
  import * as Effect from "effect/Effect";
5
5
  import * as Option from "effect/Option";
@@ -12,7 +12,6 @@ var RpcTargets_exports = /* @__PURE__ */ __exportAll({
12
12
  });
13
13
  /** A native RPC target could not be constructed. */
14
14
  var RpcTargetError = class extends Data.TaggedError("RpcTargetError") {};
15
- var CurrentTargets = class extends Context.Service()("effect-cf/RpcTargets") {};
16
15
  /**
17
16
  * Reuse a native RPC target within the current invocation. Native Durable Object
18
17
  * stubs capture the calling request's channel when created. Recreating a stub
package/dist/Sandbox.mjs CHANGED
@@ -1,6 +1,8 @@
1
1
  import { WorkerEnvironment } from "./Environment.mjs";
2
2
  import { layer as layer$1 } from "./Binding.mjs";
3
3
  import { causeMessage } from "./internal/ErrorMessage.mjs";
4
+ import { CurrentTargets } from "./internal/RpcTargets.mjs";
5
+ import { get, invalidate } from "./RpcTargets.mjs";
4
6
  import * as Context from "effect/Context";
5
7
  import * as Data from "effect/Data";
6
8
  import * as Effect from "effect/Effect";
@@ -14,7 +16,7 @@ var SandboxOperationError = class extends Data.TaggedError("SandboxOperationErro
14
16
  return `Sandbox ${this.operation} failed for binding "${this.binding}" instance "${this.instance}": ${causeMessage(this.cause)}`;
15
17
  }
16
18
  };
17
- const trySandboxPromise = (definition, instance, operation, evaluate) => Effect.tryPromise({
19
+ const trySandboxPromise = (definition, instance, operation, evaluate, target) => Effect.tryPromise({
18
20
  try: evaluate,
19
21
  catch: (cause) => new SandboxOperationError({
20
22
  binding: definition.binding,
@@ -22,8 +24,8 @@ const trySandboxPromise = (definition, instance, operation, evaluate) => Effect.
22
24
  operation,
23
25
  cause
24
26
  })
25
- });
26
- const sandboxStream = (definition, instance, operation, acquire) => Stream.unwrap(Effect.map(trySandboxPromise(definition, instance, operation, acquire), (readable) => Stream.fromReadableStream({
27
+ }).pipe(Effect.tapCause(() => target === void 0 ? Effect.void : invalidate(target)));
28
+ const sandboxStream = (definition, instance, operation, acquire, target) => Stream.unwrap(Effect.map(trySandboxPromise(definition, instance, operation, acquire, target), (readable) => Stream.fromReadableStream({
27
29
  evaluate: () => readable,
28
30
  onError: (cause) => new SandboxOperationError({
29
31
  binding: definition.binding,
@@ -31,7 +33,7 @@ const sandboxStream = (definition, instance, operation, acquire) => Stream.unwra
31
33
  operation,
32
34
  cause
33
35
  })
34
- })));
36
+ }))).pipe(Stream.tapCause(() => invalidate(target)));
35
37
  const decodeSseData = (payload) => {
36
38
  if (payload === "[DONE]" || payload.trim() === "") return [];
37
39
  try {
@@ -53,7 +55,9 @@ const decodeSseEvents = (bytes) => bytes.pipe(Stream.decodeText(), Stream.splitL
53
55
  }
54
56
  return [pending, []];
55
57
  }, { onHalt: (pending) => pending.length > 0 ? decodeSseData(pending.join("\n")) : [] }));
56
- const makeProcessHandle = (definition, instance, process) => {
58
+ const makeProcessHandle = (definition, instance, process, target) => {
59
+ const attempt = (operation, evaluate) => trySandboxPromise(definition, instance, operation, evaluate, target);
60
+ const stream = (operation, acquire) => sandboxStream(definition, instance, operation, acquire, target);
57
61
  const spanOptions = (operation) => ({ attributes: {
58
62
  binding: definition.binding,
59
63
  instance,
@@ -64,49 +68,51 @@ const makeProcessHandle = (definition, instance, process) => {
64
68
  id: process.id,
65
69
  pid: process.pid,
66
70
  rawUnsafe: Effect.succeed(process),
67
- status: trySandboxPromise(definition, instance, "process.status", () => process.status()).pipe(Effect.withSpan("Sandbox.process.status", spanOptions("process.status"))),
68
- exitCode: trySandboxPromise(definition, instance, "process.exitCode", () => process.exitCode).pipe(Effect.withSpan("Sandbox.process.exitCode", spanOptions("process.exitCode"))),
69
- logs: (options) => sandboxStream(definition, instance, "process.logs", (signal) => process.logs({
71
+ status: attempt("process.status", () => process.status()).pipe(Effect.withSpan("Sandbox.process.status", spanOptions("process.status"))),
72
+ exitCode: attempt("process.exitCode", () => process.exitCode).pipe(Effect.withSpan("Sandbox.process.exitCode", spanOptions("process.exitCode"))),
73
+ logs: (options) => stream("process.logs", (signal) => process.logs({
70
74
  ...options,
71
75
  signal
72
76
  })),
73
77
  waitForLog: Effect.fn("Sandbox.process.waitForLog", spanOptions("process.waitForLog"))(function* (pattern, options) {
74
- return yield* trySandboxPromise(definition, instance, "process.waitForLog", (signal) => process.waitForLog(pattern, {
78
+ return yield* attempt("process.waitForLog", (signal) => process.waitForLog(pattern, {
75
79
  ...options,
76
80
  signal
77
81
  }));
78
82
  }),
79
83
  waitForExit: Effect.fn("Sandbox.process.waitForExit", spanOptions("process.waitForExit"))(function* (options) {
80
- return yield* trySandboxPromise(definition, instance, "process.waitForExit", (signal) => process.waitForExit({
84
+ return yield* attempt("process.waitForExit", (signal) => process.waitForExit({
81
85
  ...options,
82
86
  signal
83
87
  }));
84
88
  }),
85
89
  output: Effect.fn("Sandbox.process.output", spanOptions("process.output"))(function* (options) {
86
- return yield* trySandboxPromise(definition, instance, "process.output", (signal) => process.output({
90
+ return yield* attempt("process.output", (signal) => process.output({
87
91
  ...options,
88
92
  signal
89
93
  }));
90
94
  }),
91
95
  outputText: Effect.fn("Sandbox.process.outputText", spanOptions("process.outputText"))(function* (options) {
92
- return yield* trySandboxPromise(definition, instance, "process.outputText", (signal) => process.output({
96
+ return yield* attempt("process.outputText", (signal) => process.output({
93
97
  ...options,
94
98
  encoding: "utf8",
95
99
  signal
96
100
  }));
97
101
  }),
98
102
  waitForPort: Effect.fn("Sandbox.process.waitForPort", spanOptions("process.waitForPort"))(function* (port, options) {
99
- return yield* trySandboxPromise(definition, instance, "process.waitForPort", (signal) => process.waitForPort(port, {
103
+ return yield* attempt("process.waitForPort", (signal) => process.waitForPort(port, {
100
104
  ...options,
101
105
  signal
102
106
  }));
103
107
  }),
104
108
  kill: Effect.fn("Sandbox.process.kill", spanOptions("process.kill"))(function* (signal) {
105
- return yield* trySandboxPromise(definition, instance, "process.kill", () => process.kill(signal));
109
+ return yield* attempt("process.kill", () => process.kill(signal));
106
110
  })
107
111
  };
108
112
  };
109
- const makeTerminalHandle = (definition, instance, terminal) => {
113
+ const makeTerminalHandle = (definition, instance, terminal, target) => {
114
+ const attempt = (operation, evaluate) => trySandboxPromise(definition, instance, operation, evaluate, target);
115
+ const stream = (operation, acquire) => sandboxStream(definition, instance, operation, acquire, target);
110
116
  const spanOptions = (operation) => ({ attributes: {
111
117
  binding: definition.binding,
112
118
  instance,
@@ -116,31 +122,34 @@ const makeTerminalHandle = (definition, instance, terminal) => {
116
122
  return {
117
123
  id: terminal.id,
118
124
  rawUnsafe: Effect.succeed(terminal),
119
- snapshot: trySandboxPromise(definition, instance, "terminal.snapshot", () => terminal.getSnapshot()).pipe(Effect.withSpan("Sandbox.terminal.snapshot", spanOptions("terminal.snapshot"))),
125
+ snapshot: attempt("terminal.snapshot", () => terminal.getSnapshot()).pipe(Effect.withSpan("Sandbox.terminal.snapshot", spanOptions("terminal.snapshot"))),
120
126
  write: Effect.fn("Sandbox.terminal.write", spanOptions("terminal.write"))(function* (data) {
121
- return yield* trySandboxPromise(definition, instance, "terminal.write", () => terminal.write(data));
127
+ return yield* attempt("terminal.write", () => terminal.write(data));
122
128
  }),
123
129
  resize: Effect.fn("Sandbox.terminal.resize", spanOptions("terminal.resize"))(function* (cols, rows) {
124
- return yield* trySandboxPromise(definition, instance, "terminal.resize", () => terminal.resize(cols, rows));
130
+ return yield* attempt("terminal.resize", () => terminal.resize(cols, rows));
125
131
  }),
126
- output: (options) => sandboxStream(definition, instance, "terminal.output", (signal) => terminal.output({
132
+ output: (options) => stream("terminal.output", (signal) => terminal.output({
127
133
  ...options,
128
134
  signal
129
135
  })),
130
136
  waitForExit: Effect.fn("Sandbox.terminal.waitForExit", spanOptions("terminal.waitForExit"))(function* (options) {
131
- return yield* trySandboxPromise(definition, instance, "terminal.waitForExit", (signal) => terminal.waitForExit({
137
+ return yield* attempt("terminal.waitForExit", (signal) => terminal.waitForExit({
132
138
  ...options,
133
139
  signal
134
140
  }));
135
141
  }),
136
- interrupt: trySandboxPromise(definition, instance, "terminal.interrupt", () => terminal.interrupt()).pipe(Effect.withSpan("Sandbox.terminal.interrupt", spanOptions("terminal.interrupt"))),
137
- terminate: trySandboxPromise(definition, instance, "terminal.terminate", () => terminal.terminate()).pipe(Effect.withSpan("Sandbox.terminal.terminate", spanOptions("terminal.terminate"))),
142
+ interrupt: attempt("terminal.interrupt", () => terminal.interrupt()).pipe(Effect.withSpan("Sandbox.terminal.interrupt", spanOptions("terminal.interrupt"))),
143
+ terminate: attempt("terminal.terminate", () => terminal.terminate()).pipe(Effect.withSpan("Sandbox.terminal.terminate", spanOptions("terminal.terminate"))),
138
144
  connect: Effect.fn("Sandbox.terminal.connect", spanOptions("terminal.connect"))(function* (request, options) {
139
- return yield* trySandboxPromise(definition, instance, "terminal.connect", () => terminal.connect(request, options));
145
+ return yield* attempt("terminal.connect", () => terminal.connect(request, options));
140
146
  })
141
147
  };
142
148
  };
143
- const fromSandboxClient = (client, definition, instance) => {
149
+ const fromSandboxClient = (client, definition, instance) => makeSandboxClient(client, definition, instance, client);
150
+ const makeSandboxClient = (client, definition, instance, target) => {
151
+ const attempt = (operation, evaluate) => trySandboxPromise(definition, instance, operation, evaluate, target);
152
+ const stream = (operation, acquire) => sandboxStream(definition, instance, operation, acquire, target);
144
153
  const spanOptions = (operation) => ({ attributes: {
145
154
  binding: definition.binding,
146
155
  instance,
@@ -149,135 +158,135 @@ const fromSandboxClient = (client, definition, instance) => {
149
158
  return {
150
159
  rawUnsafe: Effect.succeed(client),
151
160
  exec: Effect.fn("Sandbox.exec", spanOptions("exec"))(function* (command, options) {
152
- const process = yield* trySandboxPromise(definition, instance, "exec", () => client.exec(command, options));
153
- return makeProcessHandle(definition, instance, process);
161
+ const process = yield* attempt("exec", () => client.exec(command, options));
162
+ return makeProcessHandle(definition, instance, process, target);
154
163
  }),
155
164
  getProcess: Effect.fn("Sandbox.getProcess", spanOptions("getProcess"))(function* (id) {
156
- const process = yield* trySandboxPromise(definition, instance, "getProcess", () => client.getProcess(id));
157
- return Option.map(Option.fromNullishOr(process), (found) => makeProcessHandle(definition, instance, found));
165
+ const process = yield* attempt("getProcess", () => client.getProcess(id));
166
+ return Option.map(Option.fromNullishOr(process), (found) => makeProcessHandle(definition, instance, found, target));
158
167
  }),
159
- listProcesses: trySandboxPromise(definition, instance, "listProcesses", () => client.listProcesses()).pipe(Effect.withSpan("Sandbox.listProcesses", spanOptions("listProcesses"))),
168
+ listProcesses: attempt("listProcesses", () => client.listProcesses()).pipe(Effect.withSpan("Sandbox.listProcesses", spanOptions("listProcesses"))),
160
169
  writeFile: Effect.fn("Sandbox.writeFile", spanOptions("writeFile"))(function* (path, content, options) {
161
170
  yield* Effect.annotateCurrentSpan("path", path);
162
- return yield* trySandboxPromise(definition, instance, "writeFile", () => client.writeFile(path, content, options));
171
+ return yield* attempt("writeFile", () => client.writeFile(path, content, options));
163
172
  }),
164
173
  readFile: Effect.fn("Sandbox.readFile", spanOptions("readFile"))(function* (path, options) {
165
174
  yield* Effect.annotateCurrentSpan("path", path);
166
- return yield* trySandboxPromise(definition, instance, "readFile", () => client.readFile(path, options));
175
+ return yield* attempt("readFile", () => client.readFile(path, options));
167
176
  }),
168
- readFileStream: (path) => sandboxStream(definition, instance, "readFileStream", () => client.readFileStream(path)),
177
+ readFileStream: (path) => stream("readFileStream", () => client.readFileStream(path)),
169
178
  mkdir: Effect.fn("Sandbox.mkdir", spanOptions("mkdir"))(function* (path, options) {
170
179
  yield* Effect.annotateCurrentSpan("path", path);
171
- return yield* trySandboxPromise(definition, instance, "mkdir", () => client.mkdir(path, options));
180
+ return yield* attempt("mkdir", () => client.mkdir(path, options));
172
181
  }),
173
182
  deleteFile: Effect.fn("Sandbox.deleteFile", spanOptions("deleteFile"))(function* (path) {
174
183
  yield* Effect.annotateCurrentSpan("path", path);
175
- return yield* trySandboxPromise(definition, instance, "deleteFile", () => client.deleteFile(path));
184
+ return yield* attempt("deleteFile", () => client.deleteFile(path));
176
185
  }),
177
186
  renameFile: Effect.fn("Sandbox.renameFile", spanOptions("renameFile"))(function* (oldPath, newPath) {
178
187
  yield* Effect.annotateCurrentSpan({
179
188
  oldPath,
180
189
  newPath
181
190
  });
182
- return yield* trySandboxPromise(definition, instance, "renameFile", () => client.renameFile(oldPath, newPath));
191
+ return yield* attempt("renameFile", () => client.renameFile(oldPath, newPath));
183
192
  }),
184
193
  moveFile: Effect.fn("Sandbox.moveFile", spanOptions("moveFile"))(function* (sourcePath, destinationPath) {
185
194
  yield* Effect.annotateCurrentSpan({
186
195
  sourcePath,
187
196
  destinationPath
188
197
  });
189
- return yield* trySandboxPromise(definition, instance, "moveFile", () => client.moveFile(sourcePath, destinationPath));
198
+ return yield* attempt("moveFile", () => client.moveFile(sourcePath, destinationPath));
190
199
  }),
191
200
  listFiles: Effect.fn("Sandbox.listFiles", spanOptions("listFiles"))(function* (path, options) {
192
201
  yield* Effect.annotateCurrentSpan("path", path);
193
- return yield* trySandboxPromise(definition, instance, "listFiles", () => client.listFiles(path, options));
202
+ return yield* attempt("listFiles", () => client.listFiles(path, options));
194
203
  }),
195
204
  exists: Effect.fn("Sandbox.exists", spanOptions("exists"))(function* (path) {
196
205
  yield* Effect.annotateCurrentSpan("path", path);
197
- return yield* trySandboxPromise(definition, instance, "exists", () => client.exists(path));
206
+ return yield* attempt("exists", () => client.exists(path));
198
207
  }),
199
- watch: (path, options) => decodeSseEvents(sandboxStream(definition, instance, "watch", () => client.watch(path, options))),
208
+ watch: (path, options) => decodeSseEvents(stream("watch", () => client.watch(path, options))),
200
209
  checkChanges: Effect.fn("Sandbox.checkChanges", spanOptions("checkChanges"))(function* (path, options) {
201
210
  yield* Effect.annotateCurrentSpan("path", path);
202
- return yield* trySandboxPromise(definition, instance, "checkChanges", () => client.checkChanges(path, options));
211
+ return yield* attempt("checkChanges", () => client.checkChanges(path, options));
203
212
  }),
204
213
  setEnvVars: Effect.fn("Sandbox.setEnvVars", spanOptions("setEnvVars"))(function* (envVars) {
205
- return yield* trySandboxPromise(definition, instance, "setEnvVars", () => client.setEnvVars(envVars));
214
+ return yield* attempt("setEnvVars", () => client.setEnvVars(envVars));
206
215
  }),
207
216
  exposePort: Effect.fn("Sandbox.exposePort", spanOptions("exposePort"))(function* (port, options) {
208
217
  yield* Effect.annotateCurrentSpan("port", port);
209
- return yield* trySandboxPromise(definition, instance, "exposePort", () => client.exposePort(port, options));
218
+ return yield* attempt("exposePort", () => client.exposePort(port, options));
210
219
  }),
211
220
  unexposePort: Effect.fn("Sandbox.unexposePort", spanOptions("unexposePort"))(function* (port) {
212
221
  yield* Effect.annotateCurrentSpan("port", port);
213
- return yield* trySandboxPromise(definition, instance, "unexposePort", () => client.unexposePort(port));
222
+ return yield* attempt("unexposePort", () => client.unexposePort(port));
214
223
  }),
215
224
  getExposedPorts: Effect.fn("Sandbox.getExposedPorts", spanOptions("getExposedPorts"))(function* (hostname) {
216
- return yield* trySandboxPromise(definition, instance, "getExposedPorts", () => client.getExposedPorts(hostname));
225
+ return yield* attempt("getExposedPorts", () => client.getExposedPorts(hostname));
217
226
  }),
218
227
  isPortExposed: Effect.fn("Sandbox.isPortExposed", spanOptions("isPortExposed"))(function* (port) {
219
228
  yield* Effect.annotateCurrentSpan("port", port);
220
- return yield* trySandboxPromise(definition, instance, "isPortExposed", () => client.isPortExposed(port));
229
+ return yield* attempt("isPortExposed", () => client.isPortExposed(port));
221
230
  }),
222
231
  validatePortToken: Effect.fn("Sandbox.validatePortToken", spanOptions("validatePortToken"))(function* (port, token) {
223
232
  yield* Effect.annotateCurrentSpan("port", port);
224
- return yield* trySandboxPromise(definition, instance, "validatePortToken", () => client.validatePortToken(port, token));
233
+ return yield* attempt("validatePortToken", () => client.validatePortToken(port, token));
225
234
  }),
226
235
  containerFetch: Effect.fn("Sandbox.containerFetch", spanOptions("containerFetch"))(function* (requestOrUrl, port) {
227
- return yield* trySandboxPromise(definition, instance, "containerFetch", () => client.containerFetch(requestOrUrl, port));
236
+ return yield* attempt("containerFetch", () => client.containerFetch(requestOrUrl, port));
228
237
  }),
229
238
  wsConnect: Effect.fn("Sandbox.wsConnect", spanOptions("wsConnect"))(function* (request, port) {
230
239
  yield* Effect.annotateCurrentSpan("port", port);
231
- return yield* trySandboxPromise(definition, instance, "wsConnect", () => client.wsConnect(request, port));
240
+ return yield* attempt("wsConnect", () => client.wsConnect(request, port));
232
241
  }),
233
242
  mountBucket: Effect.fn("Sandbox.mountBucket", spanOptions("mountBucket"))(function* (bucket, mountPath, options) {
234
243
  yield* Effect.annotateCurrentSpan({
235
244
  bucket,
236
245
  mountPath
237
246
  });
238
- return yield* trySandboxPromise(definition, instance, "mountBucket", () => client.mountBucket(bucket, mountPath, options));
247
+ return yield* attempt("mountBucket", () => client.mountBucket(bucket, mountPath, options));
239
248
  }),
240
249
  unmountBucket: Effect.fn("Sandbox.unmountBucket", spanOptions("unmountBucket"))(function* (mountPath) {
241
250
  yield* Effect.annotateCurrentSpan("mountPath", mountPath);
242
- return yield* trySandboxPromise(definition, instance, "unmountBucket", () => client.unmountBucket(mountPath));
251
+ return yield* attempt("unmountBucket", () => client.unmountBucket(mountPath));
243
252
  }),
244
253
  createBackup: Effect.fn("Sandbox.createBackup", spanOptions("createBackup"))(function* (options) {
245
254
  yield* Effect.annotateCurrentSpan("dir", options.dir);
246
- return yield* trySandboxPromise(definition, instance, "createBackup", () => client.createBackup(options));
255
+ return yield* attempt("createBackup", () => client.createBackup(options));
247
256
  }),
248
257
  restoreBackup: Effect.fn("Sandbox.restoreBackup", spanOptions("restoreBackup"))(function* (backup) {
249
258
  yield* Effect.annotateCurrentSpan({
250
259
  backupId: backup.id,
251
260
  dir: backup.dir
252
261
  });
253
- return yield* trySandboxPromise(definition, instance, "restoreBackup", () => client.restoreBackup(backup));
262
+ return yield* attempt("restoreBackup", () => client.restoreBackup(backup));
254
263
  }),
255
264
  createTerminal: Effect.fn("Sandbox.createTerminal", spanOptions("createTerminal"))(function* (options) {
256
- const terminal = yield* trySandboxPromise(definition, instance, "createTerminal", () => client.createTerminal(options));
257
- return makeTerminalHandle(definition, instance, terminal);
265
+ const terminal = yield* attempt("createTerminal", () => client.createTerminal(options));
266
+ return makeTerminalHandle(definition, instance, terminal, target);
258
267
  }),
259
268
  getTerminal: Effect.fn("Sandbox.getTerminal", spanOptions("getTerminal"))(function* (id) {
260
- const terminal = yield* trySandboxPromise(definition, instance, "getTerminal", () => client.getTerminal(id));
261
- return Option.map(Option.fromNullishOr(terminal), (found) => makeTerminalHandle(definition, instance, found));
269
+ const terminal = yield* attempt("getTerminal", () => client.getTerminal(id));
270
+ return Option.map(Option.fromNullishOr(terminal), (found) => makeTerminalHandle(definition, instance, found, target));
262
271
  }),
263
- listTerminals: trySandboxPromise(definition, instance, "listTerminals", () => client.listTerminals()).pipe(Effect.map((terminals) => terminals.map((terminal) => makeTerminalHandle(definition, instance, terminal))), Effect.withSpan("Sandbox.listTerminals", spanOptions("listTerminals"))),
272
+ listTerminals: attempt("listTerminals", () => client.listTerminals()).pipe(Effect.map((terminals) => terminals.map((terminal) => makeTerminalHandle(definition, instance, terminal, target))), Effect.withSpan("Sandbox.listTerminals", spanOptions("listTerminals"))),
264
273
  tunnels: {
265
274
  get: Effect.fn("Sandbox.tunnels.get", spanOptions("tunnels.get"))(function* (port, options) {
266
275
  yield* Effect.annotateCurrentSpan("port", port);
267
- return yield* trySandboxPromise(definition, instance, "tunnels.get", () => client.tunnels.get(port, options));
276
+ return yield* attempt("tunnels.get", () => client.tunnels.get(port, options));
268
277
  }),
269
- list: trySandboxPromise(definition, instance, "tunnels.list", () => client.tunnels.list()).pipe(Effect.withSpan("Sandbox.tunnels.list", spanOptions("tunnels.list"))),
278
+ list: attempt("tunnels.list", () => client.tunnels.list()).pipe(Effect.withSpan("Sandbox.tunnels.list", spanOptions("tunnels.list"))),
270
279
  destroy: Effect.fn("Sandbox.tunnels.destroy", spanOptions("tunnels.destroy"))(function* (portOrInfo) {
271
- return yield* trySandboxPromise(definition, instance, "tunnels.destroy", () => client.tunnels.destroy(portOrInfo));
280
+ return yield* attempt("tunnels.destroy", () => client.tunnels.destroy(portOrInfo));
272
281
  })
273
282
  },
274
283
  start: Effect.fn("Sandbox.start", spanOptions("start"))(function* (options) {
275
- return yield* trySandboxPromise(definition, instance, "start", () => client.start(options));
284
+ return yield* attempt("start", () => client.start(options));
276
285
  }),
277
286
  stop: Effect.fn("Sandbox.stop", spanOptions("stop"))(function* (signal) {
278
- return yield* trySandboxPromise(definition, instance, "stop", () => client.stop(signal));
287
+ return yield* attempt("stop", () => client.stop(signal));
279
288
  }),
280
- destroy: trySandboxPromise(definition, instance, "destroy", () => client.destroy()).pipe(Effect.withSpan("Sandbox.destroy", spanOptions("destroy")))
289
+ destroy: attempt("destroy", () => client.destroy()).pipe(Effect.withSpan("Sandbox.destroy", spanOptions("destroy")))
281
290
  };
282
291
  };
283
292
  /**
@@ -306,7 +315,20 @@ const makeClient = (definition) => (namespace) => {
306
315
  } })(function* (name, options) {
307
316
  yield* Effect.annotateCurrentSpan("instance", name);
308
317
  const sandboxModule = yield* importSandboxModule(definition, name);
309
- const nativeNamespace = namespace;
318
+ const targets = yield* Effect.serviceOption(CurrentTargets);
319
+ const scopedNamespace = yield* get(namespace, "sandbox-namespace", () => {
320
+ const adapter = {
321
+ idFromName: (name) => namespace.idFromName(name),
322
+ get: (id, options) => Option.isSome(targets) ? targets.value.get(adapter, JSON.stringify([id.toString(), options]), () => namespace.get(id, options)) : namespace.get(id, options)
323
+ };
324
+ return adapter;
325
+ }).pipe(Effect.mapError((error) => new SandboxOperationError({
326
+ binding: definition.binding,
327
+ instance: name,
328
+ operation: "get",
329
+ cause: error.cause
330
+ })));
331
+ const nativeNamespace = scopedNamespace;
310
332
  const client = yield* Effect.try({
311
333
  try: () => sandboxModule.getSandbox(nativeNamespace, name, options),
312
334
  catch: (cause) => new SandboxOperationError({
@@ -316,7 +338,7 @@ const makeClient = (definition) => (namespace) => {
316
338
  cause
317
339
  })
318
340
  });
319
- return fromSandboxClient(client, definition, name);
341
+ return makeSandboxClient(client, definition, name, scopedNamespace);
320
342
  }),
321
343
  rawUnsafe: Effect.succeed(namespace)
322
344
  };
package/dist/Worker.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { fromExecutionContext } from "./internal/WorkerContext.mjs";
3
+ import { withScope } from "./RpcTargets.mjs";
3
4
  import { fromMessage, fromMessageBatch } from "./Queue.mjs";
4
5
  import { reservedMethodNames as reservedMethodNames$1 } from "./RpcDefinition.mjs";
5
- import { withScope } from "./RpcTargets.mjs";
6
6
  import { assumeEntrypointClass, defineEntrypointRpcMethods } from "./internal/Entrypoint.mjs";
7
7
  import { makeEntrypointRuntime, runEventPromise } from "./internal/Runtime.mjs";
8
8
  import { scheduleTelemetryFlush as scheduleTelemetryFlush$1 } from "./internal/Telemetry.mjs";
package/dist/index.mjs CHANGED
@@ -11,13 +11,13 @@ import { DurableObjectWebSocket_exports } from "./DurableObjectWebSocket.mjs";
11
11
  import { DurableObjectState_exports } from "./DurableObjectState.mjs";
12
12
  import { CloudflareOtlp_exports } from "./CloudflareOtlp.mjs";
13
13
  import { CloudflareTracer_exports } from "./CloudflareTracer.mjs";
14
+ import { RpcTargets_exports } from "./RpcTargets.mjs";
14
15
  import { ContainerNamespace_exports } from "./ContainerNamespace.mjs";
15
16
  import { D1_exports } from "./D1.mjs";
16
17
  import { QueueBinding_exports } from "./QueueBinding.mjs";
17
18
  import { QueueDefinition_exports } from "./QueueDefinition.mjs";
18
19
  import { Queue_exports } from "./Queue.mjs";
19
20
  import { RpcDefinition_exports } from "./RpcDefinition.mjs";
20
- import { RpcTargets_exports } from "./RpcTargets.mjs";
21
21
  import { RpcTracing_exports } from "./RpcTracing.mjs";
22
22
  import { Rpc_exports } from "./Rpc.mjs";
23
23
  import { ServiceBinding_exports } from "./ServiceBinding.mjs";
@@ -0,0 +1,5 @@
1
+ import * as Context from "effect/Context";
2
+ //#region src/internal/RpcTargets.ts
3
+ var CurrentTargets = class extends Context.Service()("effect-cf/RpcTargets") {};
4
+ //#endregion
5
+ export { CurrentTargets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.41.0",
3
+ "version": "0.41.1",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {