effect-cf 0.40.3 → 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/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,5 +1,6 @@
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
6
  import { assumeEntrypointClass, defineEntrypointRpcMethods } from "./internal/Entrypoint.mjs";
@@ -61,15 +62,15 @@ const renderFetchSuccess = (effect, eventLayer) => Effect.suspend(() => {
61
62
  context
62
63
  });
63
64
  });
64
- const telemetryMiddleware = HttpMiddleware.make((self) => Effect.gen(function* () {
65
+ const telemetryMiddleware = HttpMiddleware.make((self) => withScope(Effect.gen(function* () {
65
66
  yield* Effect.addFinalizer(() => scheduleTelemetryFlush);
66
67
  return yield* self;
67
- }));
68
- const handled = eventLayer === void 0 ? HttpEffect.toHandled(httpApp, handleResponse, telemetryMiddleware) : Effect.flatMap(References.TracerEnabled, (tracerEnabled) => HttpEffect.toHandled(httpApp, handleResponse, HttpMiddleware.make((self) => Effect.provideService(Effect.gen(function* () {
68
+ })));
69
+ const handled = eventLayer === void 0 ? HttpEffect.toHandled(httpApp, handleResponse, telemetryMiddleware) : Effect.flatMap(References.TracerEnabled, (tracerEnabled) => HttpEffect.toHandled(httpApp, handleResponse, HttpMiddleware.make((self) => withScope(Effect.provideService(Effect.gen(function* () {
69
70
  const context = yield* Layer.build(Layer.fresh(eventLayer));
70
71
  yield* Effect.addFinalizer(() => Effect.provideContext(scheduleTelemetryFlush, context));
71
72
  return yield* HttpMiddleware.tracer(self).pipe(Effect.onExit(() => Effect.yieldNow), Effect.provideContext(context));
72
- }), References.TracerEnabled, tracerEnabled))).pipe(Effect.withTracerEnabled(false)));
73
+ }), References.TracerEnabled, tracerEnabled)))).pipe(Effect.withTracerEnabled(false)));
73
74
  const captured = () => nativeResponse ?? webResponse ?? new Response(null, { status: 500 });
74
75
  return Effect.matchCause(handled, {
75
76
  onFailure: captured,
package/dist/Workflow.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.mjs";
2
2
  import { causeMessage } from "./internal/ErrorMessage.mjs";
3
3
  import { fromExecutionContext } from "./internal/WorkerContext.mjs";
4
+ import { withScope } from "./RpcTargets.mjs";
4
5
  import { assumeEntrypointClass } from "./internal/Entrypoint.mjs";
5
6
  import { makeEntrypointRuntime, runEventPromise } from "./internal/Runtime.mjs";
6
7
  import { ExecutionContext, WorkerContext } from "./Worker.mjs";
@@ -74,7 +75,7 @@ const fromWorkflowStep = (step) => ({
74
75
  return yield* Effect.tryPromise({
75
76
  try: () => {
76
77
  const run = (stepContext) => {
77
- const stepEffect = Effect.scoped(Effect.provideService(effect, WorkflowStepContext$1, stepContext));
78
+ const stepEffect = Effect.scoped(withScope(Effect.provideService(effect, WorkflowStepContext$1, stepContext)));
78
79
  return runPromise(exposeCloudflareNonRetryableError(Effect.provideContext(stepEffect, context)));
79
80
  };
80
81
  const rawStep = step;
package/dist/index.d.mts CHANGED
@@ -34,8 +34,9 @@ import { Email_d_exports } from "./Email.mjs";
34
34
  import { Images_d_exports } from "./Images.mjs";
35
35
  import { Kv_d_exports } from "./Kv.mjs";
36
36
  import { R2_d_exports } from "./R2.mjs";
37
+ import { RpcTargets_d_exports } from "./RpcTargets.mjs";
37
38
  import { Vectorize_d_exports } from "./Vectorize.mjs";
38
39
  import { WebTransport_d_exports } from "./WebTransport.mjs";
39
40
  import { WorkflowDefinition_d_exports } from "./WorkflowDefinition.mjs";
40
41
  import { Workflow_d_exports } from "./Workflow.mjs";
41
- export { AiGateway_d_exports as AiGateway, AnalyticsEngine_d_exports as AnalyticsEngine, Artifacts_d_exports as Artifacts, Binding_d_exports as Binding, BrowserRendering_d_exports as BrowserRendering, Cache_d_exports as Cache, CloudflareOtlp_d_exports as CloudflareOtlp, CloudflareTracer_d_exports as CloudflareTracer, ContainerNamespace_d_exports as ContainerNamespace, D1_d_exports as D1, DurableObject_d_exports as DurableObject, DurableObjectAlarm_d_exports as DurableObjectAlarm, DurableObjectDefinition_d_exports as DurableObjectDefinition, DurableObjectNamespace_d_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_d_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_d_exports as DurableObjectSqlite, DurableObjectState_d_exports as DurableObjectState, DurableObjectStorage_d_exports as DurableObjectStorage, DurableObjectWebSocket_d_exports as DurableObjectWebSocket, Email_d_exports as Email, Environment_d_exports as Environment, Hyperdrive_d_exports as Hyperdrive, Images_d_exports as Images, Kv_d_exports as Kv, Queue_d_exports as Queue, QueueBinding_d_exports as QueueBinding, QueueDefinition_d_exports as QueueDefinition, R2_d_exports as R2, Rpc_d_exports as Rpc, RpcDefinition_d_exports as RpcDefinition, RpcTracing_d_exports as RpcTracing, ServiceBinding_d_exports as ServiceBinding, Vectorize_d_exports as Vectorize, WebTransport_d_exports as WebTransport, Worker_d_exports as Worker, WorkerConfig, WorkerDefinition_d_exports as WorkerDefinition, type WorkerEnv, WorkerEnvironment, WorkersAi_d_exports as WorkersAi, Workflow_d_exports as Workflow, WorkflowBinding_d_exports as WorkflowBinding, WorkflowDefinition_d_exports as WorkflowDefinition };
42
+ export { AiGateway_d_exports as AiGateway, AnalyticsEngine_d_exports as AnalyticsEngine, Artifacts_d_exports as Artifacts, Binding_d_exports as Binding, BrowserRendering_d_exports as BrowserRendering, Cache_d_exports as Cache, CloudflareOtlp_d_exports as CloudflareOtlp, CloudflareTracer_d_exports as CloudflareTracer, ContainerNamespace_d_exports as ContainerNamespace, D1_d_exports as D1, DurableObject_d_exports as DurableObject, DurableObjectAlarm_d_exports as DurableObjectAlarm, DurableObjectDefinition_d_exports as DurableObjectDefinition, DurableObjectNamespace_d_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_d_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_d_exports as DurableObjectSqlite, DurableObjectState_d_exports as DurableObjectState, DurableObjectStorage_d_exports as DurableObjectStorage, DurableObjectWebSocket_d_exports as DurableObjectWebSocket, Email_d_exports as Email, Environment_d_exports as Environment, Hyperdrive_d_exports as Hyperdrive, Images_d_exports as Images, Kv_d_exports as Kv, Queue_d_exports as Queue, QueueBinding_d_exports as QueueBinding, QueueDefinition_d_exports as QueueDefinition, R2_d_exports as R2, Rpc_d_exports as Rpc, RpcDefinition_d_exports as RpcDefinition, RpcTargets_d_exports as RpcTargets, RpcTracing_d_exports as RpcTracing, ServiceBinding_d_exports as ServiceBinding, Vectorize_d_exports as Vectorize, WebTransport_d_exports as WebTransport, Worker_d_exports as Worker, WorkerConfig, WorkerDefinition_d_exports as WorkerDefinition, type WorkerEnv, WorkerEnvironment, WorkersAi_d_exports as WorkersAi, Workflow_d_exports as Workflow, WorkflowBinding_d_exports as WorkflowBinding, WorkflowDefinition_d_exports as WorkflowDefinition };
package/dist/index.mjs CHANGED
@@ -11,6 +11,7 @@ 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";
@@ -38,4 +39,4 @@ import { WebTransport_exports } from "./WebTransport.mjs";
38
39
  import { WorkflowBinding_exports } from "./WorkflowBinding.mjs";
39
40
  import { WorkflowDefinition_exports } from "./WorkflowDefinition.mjs";
40
41
  import { Workflow_exports } from "./Workflow.mjs";
41
- export { AiGateway_exports as AiGateway, AnalyticsEngine_exports as AnalyticsEngine, Artifacts_exports as Artifacts, Binding_exports as Binding, BrowserRendering_exports as BrowserRendering, Cache_exports as Cache, CloudflareOtlp_exports as CloudflareOtlp, CloudflareTracer_exports as CloudflareTracer, ContainerNamespace_exports as ContainerNamespace, D1_exports as D1, DurableObject_exports as DurableObject, DurableObjectAlarm_exports as DurableObjectAlarm, DurableObjectDefinition_exports as DurableObjectDefinition, DurableObjectNamespace_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_exports as DurableObjectSqlite, DurableObjectState_exports as DurableObjectState, DurableObjectStorage_exports as DurableObjectStorage, DurableObjectWebSocket_exports as DurableObjectWebSocket, Email_exports as Email, Environment_exports as Environment, Hyperdrive_exports as Hyperdrive, Images_exports as Images, Kv_exports as Kv, Queue_exports as Queue, QueueBinding_exports as QueueBinding, QueueDefinition_exports as QueueDefinition, R2_exports as R2, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, RpcTracing_exports as RpcTracing, ServiceBinding_exports as ServiceBinding, Vectorize_exports as Vectorize, WebTransport_exports as WebTransport, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment, WorkersAi_exports as WorkersAi, Workflow_exports as Workflow, WorkflowBinding_exports as WorkflowBinding, WorkflowDefinition_exports as WorkflowDefinition };
42
+ export { AiGateway_exports as AiGateway, AnalyticsEngine_exports as AnalyticsEngine, Artifacts_exports as Artifacts, Binding_exports as Binding, BrowserRendering_exports as BrowserRendering, Cache_exports as Cache, CloudflareOtlp_exports as CloudflareOtlp, CloudflareTracer_exports as CloudflareTracer, ContainerNamespace_exports as ContainerNamespace, D1_exports as D1, DurableObject_exports as DurableObject, DurableObjectAlarm_exports as DurableObjectAlarm, DurableObjectDefinition_exports as DurableObjectDefinition, DurableObjectNamespace_exports as DurableObjectNamespace, DurableObjectRpcWebSocket_exports as DurableObjectRpcWebSocket, DurableObjectSqlite_exports as DurableObjectSqlite, DurableObjectState_exports as DurableObjectState, DurableObjectStorage_exports as DurableObjectStorage, DurableObjectWebSocket_exports as DurableObjectWebSocket, Email_exports as Email, Environment_exports as Environment, Hyperdrive_exports as Hyperdrive, Images_exports as Images, Kv_exports as Kv, Queue_exports as Queue, QueueBinding_exports as QueueBinding, QueueDefinition_exports as QueueDefinition, R2_exports as R2, Rpc_exports as Rpc, RpcDefinition_exports as RpcDefinition, RpcTargets_exports as RpcTargets, RpcTracing_exports as RpcTracing, ServiceBinding_exports as ServiceBinding, Vectorize_exports as Vectorize, WebTransport_exports as WebTransport, Worker_exports as Worker, WorkerConfig, WorkerDefinition_exports as WorkerDefinition, WorkerEnvironment, WorkersAi_exports as WorkersAi, Workflow_exports as Workflow, WorkflowBinding_exports as WorkflowBinding, WorkflowDefinition_exports as WorkflowDefinition };
@@ -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 };
@@ -1,4 +1,5 @@
1
1
  import { WorkerConfig, WorkerEnvironment } from "../Environment.mjs";
2
+ import { withScope } from "../RpcTargets.mjs";
2
3
  import { provideEntrypointServices } from "./Entrypoint.mjs";
3
4
  import * as Effect from "effect/Effect";
4
5
  import * as Layer from "effect/Layer";
@@ -21,10 +22,10 @@ const makeEntrypointRuntime = (layer, env, services) => {
21
22
  function runEventPromise(...args) {
22
23
  const [runtime, effect, eventLayer, parent] = args;
23
24
  if (eventLayer === void 0) {
24
- const event = Effect.scoped(effect);
25
+ const event = Effect.scoped(withScope(effect));
25
26
  return runtime.runPromise(parent === void 0 ? event : Effect.withParentSpan(event, parent));
26
27
  }
27
- const event = Effect.scoped(effect.pipe(Effect.provide(eventLayer, { local: true })));
28
+ const event = Effect.scoped(withScope(effect.pipe(Effect.provide(eventLayer, { local: true }))));
28
29
  return runtime.runPromise(parent === void 0 ? event : Effect.withParentSpan(event, parent));
29
30
  }
30
31
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effect-cf",
3
- "version": "0.40.3",
3
+ "version": "0.41.1",
4
4
  "description": "Effect-native primitives for Cloudflare Workers and bindings.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -6,6 +6,7 @@ import * as S from "effect/Schema";
6
6
  import type { Layer } from "effect";
7
7
 
8
8
  import * as Binding from "./Binding";
9
+ import * as RpcTargets from "./RpcTargets";
9
10
  import type { WorkerEnvironment } from "./Environment";
10
11
  import * as ErrorMessage from "./internal/ErrorMessage";
11
12
 
@@ -231,6 +232,7 @@ const tryContainerPromise = <A>(
231
232
  instance: string,
232
233
  operation: string,
233
234
  evaluate: () => Promise<A>,
235
+ target: ContainerStub,
234
236
  ): Effect.Effect<A, ContainerOperationError> =>
235
237
  Effect.tryPromise({
236
238
  try: evaluate,
@@ -241,13 +243,15 @@ const tryContainerPromise = <A>(
241
243
  operation,
242
244
  cause,
243
245
  }),
244
- });
246
+ }).pipe(Effect.tapCause(() => RpcTargets.invalidate(target)));
245
247
 
246
248
  const makeInstanceClient = <Stub extends ContainerStub>(
247
249
  definition: ContainerNamespaceDefinition,
248
250
  instance: string,
249
251
  stub: Stub,
250
252
  ): ContainerInstanceClient<Stub> => {
253
+ const attempt = <A>(operation: string, evaluate: () => Promise<A>) =>
254
+ tryContainerPromise(definition, instance, operation, evaluate, stub);
251
255
  const spanOptions = (operation: string) => ({
252
256
  attributes: { binding: definition.binding, instance, operation },
253
257
  });
@@ -256,9 +260,7 @@ const makeInstanceClient = <Stub extends ContainerStub>(
256
260
  `ContainerNamespace.${operation}`,
257
261
  spanOptions(operation),
258
262
  )(function* (hosts: ReadonlyArray<string>) {
259
- return yield* tryContainerPromise(definition, instance, operation, () =>
260
- stub[operation]([...hosts]),
261
- );
263
+ return yield* attempt(operation, () => stub[operation]([...hosts]));
262
264
  });
263
265
  const hostnameOperation = (
264
266
  operation: "allowHost" | "denyHost" | "removeAllowedHost" | "removeDeniedHost",
@@ -267,14 +269,12 @@ const makeInstanceClient = <Stub extends ContainerStub>(
267
269
  `ContainerNamespace.${operation}`,
268
270
  spanOptions(operation),
269
271
  )(function* (hostname: string) {
270
- return yield* tryContainerPromise(definition, instance, operation, () =>
271
- stub[operation](hostname),
272
- );
272
+ return yield* attempt(operation, () => stub[operation](hostname));
273
273
  });
274
274
 
275
275
  return {
276
276
  rawUnsafe: Effect.succeed(stub),
277
- state: tryContainerPromise(definition, instance, "state", () => stub.getState()).pipe(
277
+ state: attempt("state", () => stub.getState()).pipe(
278
278
  Effect.flatMap(S.decodeUnknownEffect(ContainerState)),
279
279
  Effect.mapError((cause) =>
280
280
  cause instanceof ContainerOperationError
@@ -292,41 +292,33 @@ const makeInstanceClient = <Stub extends ContainerStub>(
292
292
  "ContainerNamespace.fetch",
293
293
  spanOptions("fetch"),
294
294
  )(function* (input: RequestInfo | URL, init?: RequestInit) {
295
- return yield* tryContainerPromise(definition, instance, "fetch", () =>
296
- stub.fetch(input, init),
297
- );
295
+ return yield* attempt("fetch", () => stub.fetch(input, init));
298
296
  }),
299
297
  start: Effect.fn(
300
298
  "ContainerNamespace.start",
301
299
  spanOptions("start"),
302
300
  )(function* (options?: ContainerStartOptions, waitOptions?: ContainerWaitOptions) {
303
- return yield* tryContainerPromise(definition, instance, "start", () =>
304
- stub.start(options, waitOptions),
305
- );
301
+ return yield* attempt("start", () => stub.start(options, waitOptions));
306
302
  }),
307
303
  startAndWaitForPorts: Effect.fn(
308
304
  "ContainerNamespace.startAndWaitForPorts",
309
305
  spanOptions("startAndWaitForPorts"),
310
306
  )(function* (options?: ContainerStartAndWaitForPortsOptions) {
311
- return yield* tryContainerPromise(definition, instance, "startAndWaitForPorts", () =>
312
- stub.startAndWaitForPorts(options),
313
- );
307
+ return yield* attempt("startAndWaitForPorts", () => stub.startAndWaitForPorts(options));
314
308
  }),
315
309
  waitForPort: Effect.fn(
316
310
  "ContainerNamespace.waitForPort",
317
311
  spanOptions("waitForPort"),
318
312
  )(function* (options: ContainerWaitOptions) {
319
- return yield* tryContainerPromise(definition, instance, "waitForPort", () =>
320
- stub.waitForPort(options),
321
- );
313
+ return yield* attempt("waitForPort", () => stub.waitForPort(options));
322
314
  }),
323
315
  stop: Effect.fn(
324
316
  "ContainerNamespace.stop",
325
317
  spanOptions("stop"),
326
318
  )(function* (signal?: ContainerStopSignal) {
327
- return yield* tryContainerPromise(definition, instance, "stop", () => stub.stop(signal));
319
+ return yield* attempt("stop", () => stub.stop(signal));
328
320
  }),
329
- destroy: tryContainerPromise(definition, instance, "destroy", () => stub.destroy()).pipe(
321
+ destroy: attempt("destroy", () => stub.destroy()).pipe(
330
322
  Effect.withSpan("ContainerNamespace.destroy", spanOptions("destroy")),
331
323
  ),
332
324
  setAllowedHosts: hostListOperation("setAllowedHosts"),
@@ -352,23 +344,24 @@ export const makeClient =
352
344
  name: string,
353
345
  options?: globalThis.DurableObjectNamespaceGetDurableObjectOptions,
354
346
  ) =>
355
- Effect.try({
356
- try: () =>
357
- makeInstanceClient(
358
- definition,
359
- name,
360
- // SAFETY: getByName has a single call signature, so its return type is
361
- // exactly the namespace's stub type.
362
- namespace.getByName(name, options) as ContainerStubOf<Namespace>,
363
- ),
364
- catch: (cause) =>
365
- new ContainerOperationError({
366
- binding: definition.binding,
367
- instance: name,
368
- operation: "getByName",
369
- cause,
370
- }),
371
- });
347
+ RpcTargets.get(
348
+ namespace,
349
+ JSON.stringify(["container", name, options]),
350
+ () =>
351
+ // SAFETY: getByName returns the namespace's declared native stub type.
352
+ namespace.getByName(name, options) as ContainerStubOf<Namespace>,
353
+ ).pipe(
354
+ Effect.map((stub) => makeInstanceClient(definition, name, stub)),
355
+ Effect.mapError(
356
+ (error) =>
357
+ new ContainerOperationError({
358
+ binding: definition.binding,
359
+ instance: name,
360
+ operation: "getByName",
361
+ cause: error.cause,
362
+ }),
363
+ ),
364
+ );
372
365
 
373
366
  const byName = (
374
367
  name: string,