@alchemy.run/e2b 0.0.0 → 2.0.0-beta.87
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/LICENSE +201 -0
- package/README.md +56 -4
- package/lib/ApiKey.d.ts +53 -0
- package/lib/ApiKey.d.ts.map +1 -0
- package/lib/ApiKey.js +107 -0
- package/lib/ApiKey.js.map +1 -0
- package/lib/AuthProvider.d.ts +60 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +293 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/Bootstrap.d.ts +7 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +25 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +67 -0
- package/lib/ConnectSandbox.d.ts.map +1 -0
- package/lib/ConnectSandbox.js +3 -0
- package/lib/ConnectSandbox.js.map +1 -0
- package/lib/ConnectSandboxHttp.d.ts +22 -0
- package/lib/ConnectSandboxHttp.d.ts.map +1 -0
- package/lib/ConnectSandboxHttp.js +30 -0
- package/lib/ConnectSandboxHttp.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/CreateSandbox.d.ts +139 -0
- package/lib/CreateSandbox.d.ts.map +1 -0
- package/lib/CreateSandbox.js +3 -0
- package/lib/CreateSandbox.js.map +1 -0
- package/lib/CreateSandboxHttp.d.ts +22 -0
- package/lib/CreateSandboxHttp.d.ts.map +1 -0
- package/lib/CreateSandboxHttp.js +99 -0
- package/lib/CreateSandboxHttp.js.map +1 -0
- package/lib/CreateSecret.d.ts +57 -0
- package/lib/CreateSecret.d.ts.map +1 -0
- package/lib/CreateSecret.js +3 -0
- package/lib/CreateSecret.js.map +1 -0
- package/lib/CreateSecretHttp.d.ts +20 -0
- package/lib/CreateSecretHttp.d.ts.map +1 -0
- package/lib/CreateSecretHttp.js +64 -0
- package/lib/CreateSecretHttp.js.map +1 -0
- package/lib/CreateSnapshot.d.ts +53 -0
- package/lib/CreateSnapshot.d.ts.map +1 -0
- package/lib/CreateSnapshot.js +3 -0
- package/lib/CreateSnapshot.js.map +1 -0
- package/lib/CreateSnapshotHttp.d.ts +20 -0
- package/lib/CreateSnapshotHttp.d.ts.map +1 -0
- package/lib/CreateSnapshotHttp.js +41 -0
- package/lib/CreateSnapshotHttp.js.map +1 -0
- package/lib/CreateTemplate.d.ts +96 -0
- package/lib/CreateTemplate.d.ts.map +1 -0
- package/lib/CreateTemplate.js +3 -0
- package/lib/CreateTemplate.js.map +1 -0
- package/lib/CreateTemplateHttp.d.ts +20 -0
- package/lib/CreateTemplateHttp.d.ts.map +1 -0
- package/lib/CreateTemplateHttp.js +99 -0
- package/lib/CreateTemplateHttp.js.map +1 -0
- package/lib/CreateVolume.d.ts +58 -0
- package/lib/CreateVolume.d.ts.map +1 -0
- package/lib/CreateVolume.js +3 -0
- package/lib/CreateVolume.js.map +1 -0
- package/lib/CreateVolumeHttp.d.ts +20 -0
- package/lib/CreateVolumeHttp.d.ts.map +1 -0
- package/lib/CreateVolumeHttp.js +51 -0
- package/lib/CreateVolumeHttp.js.map +1 -0
- package/lib/Credentials.d.ts +18 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +55 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/E2BBindings.d.ts +35 -0
- package/lib/E2BBindings.d.ts.map +1 -0
- package/lib/E2BBindings.js +127 -0
- package/lib/E2BBindings.js.map +1 -0
- package/lib/Errors.d.ts +61 -0
- package/lib/Errors.d.ts.map +1 -0
- package/lib/Errors.js +23 -0
- package/lib/Errors.js.map +1 -0
- package/lib/InferEnv.d.ts +26 -0
- package/lib/InferEnv.d.ts.map +1 -0
- package/lib/InferEnv.js +1 -0
- package/lib/InferEnv.js.map +1 -0
- package/lib/MountVolume.d.ts +86 -0
- package/lib/MountVolume.d.ts.map +1 -0
- package/lib/MountVolume.js +3 -0
- package/lib/MountVolume.js.map +1 -0
- package/lib/MountVolumeLive.d.ts +23 -0
- package/lib/MountVolumeLive.d.ts.map +1 -0
- package/lib/MountVolumeLive.js +41 -0
- package/lib/MountVolumeLive.js.map +1 -0
- package/lib/Providers.d.ts +14 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +23 -0
- package/lib/Providers.js.map +1 -0
- package/lib/ReadTeam.d.ts +41 -0
- package/lib/ReadTeam.d.ts.map +1 -0
- package/lib/ReadTeam.js +3 -0
- package/lib/ReadTeam.js.map +1 -0
- package/lib/ReadTeamHttp.d.ts +20 -0
- package/lib/ReadTeamHttp.d.ts.map +1 -0
- package/lib/ReadTeamHttp.js +40 -0
- package/lib/ReadTeamHttp.js.map +1 -0
- package/lib/ReadVolume.d.ts +25 -0
- package/lib/ReadVolume.d.ts.map +1 -0
- package/lib/ReadVolume.js +3 -0
- package/lib/ReadVolume.js.map +1 -0
- package/lib/ReadVolumeHttp.d.ts +20 -0
- package/lib/ReadVolumeHttp.d.ts.map +1 -0
- package/lib/ReadVolumeHttp.js +27 -0
- package/lib/ReadVolumeHttp.js.map +1 -0
- package/lib/ReadWebhook.d.ts +32 -0
- package/lib/ReadWebhook.d.ts.map +1 -0
- package/lib/ReadWebhook.js +3 -0
- package/lib/ReadWebhook.js.map +1 -0
- package/lib/ReadWebhookHttp.d.ts +20 -0
- package/lib/ReadWebhookHttp.d.ts.map +1 -0
- package/lib/ReadWebhookHttp.js +31 -0
- package/lib/ReadWebhookHttp.js.map +1 -0
- package/lib/ReadWriteVolume.d.ts +26 -0
- package/lib/ReadWriteVolume.d.ts.map +1 -0
- package/lib/ReadWriteVolume.js +3 -0
- package/lib/ReadWriteVolume.js.map +1 -0
- package/lib/ReadWriteVolumeHttp.d.ts +20 -0
- package/lib/ReadWriteVolumeHttp.d.ts.map +1 -0
- package/lib/ReadWriteVolumeHttp.js +27 -0
- package/lib/ReadWriteVolumeHttp.js.map +1 -0
- package/lib/Sandbox.d.ts +295 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +351 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxClient.d.ts +226 -0
- package/lib/SandboxClient.d.ts.map +1 -0
- package/lib/SandboxClient.js +1 -0
- package/lib/SandboxClient.js.map +1 -0
- package/lib/SandboxEvents.d.ts +87 -0
- package/lib/SandboxEvents.d.ts.map +1 -0
- package/lib/SandboxEvents.js +39 -0
- package/lib/SandboxEvents.js.map +1 -0
- package/lib/SandboxEventsLive.d.ts +13 -0
- package/lib/SandboxEventsLive.d.ts.map +1 -0
- package/lib/SandboxEventsLive.js +80 -0
- package/lib/SandboxEventsLive.js.map +1 -0
- package/lib/Secret.d.ts +105 -0
- package/lib/Secret.d.ts.map +1 -0
- package/lib/Secret.js +161 -0
- package/lib/Secret.js.map +1 -0
- package/lib/Snapshot.d.ts +118 -0
- package/lib/Snapshot.d.ts.map +1 -0
- package/lib/Snapshot.js +158 -0
- package/lib/Snapshot.js.map +1 -0
- package/lib/Template.d.ts +313 -0
- package/lib/Template.d.ts.map +1 -0
- package/lib/Template.js +421 -0
- package/lib/Template.js.map +1 -0
- package/lib/Volume.d.ts +88 -0
- package/lib/Volume.d.ts.map +1 -0
- package/lib/Volume.js +136 -0
- package/lib/Volume.js.map +1 -0
- package/lib/VolumeFiles.d.ts +39 -0
- package/lib/VolumeFiles.d.ts.map +1 -0
- package/lib/VolumeFiles.js +1 -0
- package/lib/VolumeFiles.js.map +1 -0
- package/lib/Webhook.d.ts +83 -0
- package/lib/Webhook.d.ts.map +1 -0
- package/lib/Webhook.js +138 -0
- package/lib/Webhook.js.map +1 -0
- package/lib/WriteSecret.d.ts +34 -0
- package/lib/WriteSecret.d.ts.map +1 -0
- package/lib/WriteSecret.js +3 -0
- package/lib/WriteSecret.js.map +1 -0
- package/lib/WriteSecretHttp.d.ts +20 -0
- package/lib/WriteSecretHttp.d.ts.map +1 -0
- package/lib/WriteSecretHttp.js +37 -0
- package/lib/WriteSecretHttp.js.map +1 -0
- package/lib/WriteVolume.d.ts +25 -0
- package/lib/WriteVolume.d.ts.map +1 -0
- package/lib/WriteVolume.js +3 -0
- package/lib/WriteVolume.js.map +1 -0
- package/lib/WriteVolumeHttp.d.ts +20 -0
- package/lib/WriteVolumeHttp.d.ts.map +1 -0
- package/lib/WriteVolumeHttp.js +27 -0
- package/lib/WriteVolumeHttp.js.map +1 -0
- package/lib/index.d.ts +43 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +43 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/Declared.d.ts +29 -0
- package/lib/internal/Declared.d.ts.map +1 -0
- package/lib/internal/Declared.js +31 -0
- package/lib/internal/Declared.js.map +1 -0
- package/lib/internal/Login.d.ts +45 -0
- package/lib/internal/Login.d.ts.map +1 -0
- package/lib/internal/Login.js +157 -0
- package/lib/internal/Login.js.map +1 -0
- package/lib/internal/Ownership.d.ts +29 -0
- package/lib/internal/Ownership.d.ts.map +1 -0
- package/lib/internal/Ownership.js +49 -0
- package/lib/internal/Ownership.js.map +1 -0
- package/lib/internal/Program.d.ts +31 -0
- package/lib/internal/Program.d.ts.map +1 -0
- package/lib/internal/Program.js +60 -0
- package/lib/internal/Program.js.map +1 -0
- package/lib/internal/SandboxHandle.d.ts +25 -0
- package/lib/internal/SandboxHandle.d.ts.map +1 -0
- package/lib/internal/SandboxHandle.js +316 -0
- package/lib/internal/SandboxHandle.js.map +1 -0
- package/lib/internal/SnapshotBuild.d.ts +19 -0
- package/lib/internal/SnapshotBuild.d.ts.map +1 -0
- package/lib/internal/SnapshotBuild.js +49 -0
- package/lib/internal/SnapshotBuild.js.map +1 -0
- package/lib/internal/Tar.d.ts +10 -0
- package/lib/internal/Tar.d.ts.map +1 -0
- package/lib/internal/Tar.js +61 -0
- package/lib/internal/Tar.js.map +1 -0
- package/lib/internal/TemplateBuild.d.ts +142 -0
- package/lib/internal/TemplateBuild.d.ts.map +1 -0
- package/lib/internal/TemplateBuild.js +220 -0
- package/lib/internal/TemplateBuild.js.map +1 -0
- package/lib/internal/TemplatePlan.d.ts +57 -0
- package/lib/internal/TemplatePlan.d.ts.map +1 -0
- package/lib/internal/TemplatePlan.js +185 -0
- package/lib/internal/TemplatePlan.js.map +1 -0
- package/lib/internal/VolumeHttp.d.ts +5 -0
- package/lib/internal/VolumeHttp.d.ts.map +1 -0
- package/lib/internal/VolumeHttp.js +46 -0
- package/lib/internal/VolumeHttp.js.map +1 -0
- package/package.json +62 -3
- package/src/ApiKey.ts +148 -0
- package/src/AuthProvider.ts +437 -0
- package/src/Bootstrap.ts +51 -0
- package/src/ConnectSandbox.ts +71 -0
- package/src/ConnectSandboxHttp.ts +38 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateSandbox.ts +157 -0
- package/src/CreateSandboxHttp.ts +131 -0
- package/src/CreateSecret.ts +65 -0
- package/src/CreateSecretHttp.ts +94 -0
- package/src/CreateSnapshot.ts +64 -0
- package/src/CreateSnapshotHttp.ts +55 -0
- package/src/CreateTemplate.ts +135 -0
- package/src/CreateTemplateHttp.ts +152 -0
- package/src/CreateVolume.ts +65 -0
- package/src/CreateVolumeHttp.ts +80 -0
- package/src/Credentials.ts +81 -0
- package/src/E2BBindings.ts +160 -0
- package/src/Errors.ts +47 -0
- package/src/InferEnv.ts +27 -0
- package/src/MountVolume.ts +92 -0
- package/src/MountVolumeLive.ts +49 -0
- package/src/Providers.ts +48 -0
- package/src/ReadTeam.ts +55 -0
- package/src/ReadTeamHttp.ts +44 -0
- package/src/ReadVolume.ts +29 -0
- package/src/ReadVolumeHttp.ts +32 -0
- package/src/ReadWebhook.ts +41 -0
- package/src/ReadWebhookHttp.ts +42 -0
- package/src/ReadWriteVolume.ts +30 -0
- package/src/ReadWriteVolumeHttp.ts +32 -0
- package/src/Sandbox.ts +581 -0
- package/src/SandboxClient.ts +268 -0
- package/src/SandboxEvents.ts +101 -0
- package/src/SandboxEventsLive.ts +118 -0
- package/src/Secret.ts +229 -0
- package/src/Snapshot.ts +234 -0
- package/src/Template.ts +636 -0
- package/src/Volume.ts +173 -0
- package/src/VolumeFiles.ts +53 -0
- package/src/Webhook.ts +215 -0
- package/src/WriteSecret.ts +39 -0
- package/src/WriteSecretHttp.ts +43 -0
- package/src/WriteVolume.ts +29 -0
- package/src/WriteVolumeHttp.ts +32 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +42 -0
- package/src/internal/Declared.ts +80 -0
- package/src/internal/Login.ts +210 -0
- package/src/internal/Ownership.ts +67 -0
- package/src/internal/Program.ts +75 -0
- package/src/internal/SandboxHandle.ts +534 -0
- package/src/internal/SnapshotBuild.ts +74 -0
- package/src/internal/Tar.ts +74 -0
- package/src/internal/TemplateBuild.ts +383 -0
- package/src/internal/TemplatePlan.ts +230 -0
- package/src/internal/VolumeHttp.ts +88 -0
package/src/Errors.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as Data from "effect/Data";
|
|
2
|
+
|
|
3
|
+
/** E2B answered in a way a lifecycle step cannot continue from (e.g. a resource vanished right after create). */
|
|
4
|
+
export class E2BUnexpectedResponse extends Data.TaggedError("E2B.UnexpectedResponse")<{
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly cause?: unknown;
|
|
7
|
+
}> {}
|
|
8
|
+
|
|
9
|
+
/** A template build finished in a failed state. */
|
|
10
|
+
export class TemplateBuildFailed extends Data.TaggedError("E2B.TemplateBuildFailed")<{
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly templateId: string;
|
|
13
|
+
readonly buildId: string;
|
|
14
|
+
readonly reason?: string;
|
|
15
|
+
readonly logs?: ReadonlyArray<string>;
|
|
16
|
+
}> {}
|
|
17
|
+
|
|
18
|
+
/** A Dockerfile uses something E2B's builder does not support. Raised at plan time. */
|
|
19
|
+
export class UnsupportedDockerfileInstruction extends Data.TaggedError(
|
|
20
|
+
"E2B.UnsupportedDockerfileInstruction",
|
|
21
|
+
)<{
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly line?: number;
|
|
24
|
+
}> {}
|
|
25
|
+
|
|
26
|
+
/** A command run while building a snapshot exited non-zero. */
|
|
27
|
+
export class SnapshotSetupFailed extends Data.TaggedError("E2B.SnapshotSetupFailed")<{
|
|
28
|
+
readonly message: string;
|
|
29
|
+
readonly command: string;
|
|
30
|
+
readonly exitCode: number;
|
|
31
|
+
readonly stderr: string;
|
|
32
|
+
}> {}
|
|
33
|
+
|
|
34
|
+
/** `E2B.CreateSandbox()` was bound without a base and `create()` was called without `templateID`. */
|
|
35
|
+
export class SandboxBaseMissing extends Data.TaggedError("E2B.SandboxBaseMissing")<{
|
|
36
|
+
readonly message: string;
|
|
37
|
+
}> {}
|
|
38
|
+
|
|
39
|
+
/** `exec` killed a command that ran past its `timeout`. */
|
|
40
|
+
export class ExecTimedOut extends Data.TaggedError("E2B.ExecTimedOut")<{
|
|
41
|
+
readonly pid: number;
|
|
42
|
+
readonly timeoutMs: number;
|
|
43
|
+
}> {
|
|
44
|
+
override get message() {
|
|
45
|
+
return `process ${this.pid} ran longer than ${this.timeoutMs}ms and was killed`;
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/InferEnv.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type * as Effect from "effect/Effect";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Typed `env` for an async (non-Effect) {@link Template} program. A
|
|
5
|
+
* template program reads its bindings from environment variables, so every
|
|
6
|
+
* entry is a `string`: cast `process.env` to it.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* export const Worker = E2B.Template("Worker", {
|
|
11
|
+
* image: "node:22-bookworm",
|
|
12
|
+
* main: "./src/worker.mjs",
|
|
13
|
+
* env: { QUEUE_URL: queue.url },
|
|
14
|
+
* });
|
|
15
|
+
* export type WorkerEnv = E2B.InferEnv<typeof Worker>;
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export type InferEnv<F> =
|
|
19
|
+
F extends Effect.Effect<infer A, infer _E, infer _R>
|
|
20
|
+
? InferEnv<A>
|
|
21
|
+
: F extends { readonly Props: { readonly env?: infer E } }
|
|
22
|
+
? InferEnvRecord<Exclude<E, undefined>>
|
|
23
|
+
: InferEnvRecord<F>;
|
|
24
|
+
|
|
25
|
+
type InferEnvRecord<E> = {
|
|
26
|
+
readonly [K in keyof E]: string;
|
|
27
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
3
|
+
import type * as Effect from "effect/Effect";
|
|
4
|
+
import type { Volume } from "./Volume.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A volume to mount: a declared `E2B.Volume`, or a volume `CreateVolume`
|
|
8
|
+
* returned. E2B mounts volumes by name.
|
|
9
|
+
*/
|
|
10
|
+
export interface MountableVolume {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** A volume mounted into a sandbox at `path`. */
|
|
15
|
+
export interface VolumeMount {
|
|
16
|
+
readonly volume: MountableVolume;
|
|
17
|
+
/** Absolute path inside the sandbox. */
|
|
18
|
+
readonly path: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A volume bound to a host with `E2B.MountVolume`. Its name is read at
|
|
23
|
+
* runtime, so pass the whole reference to `mounts`.
|
|
24
|
+
*/
|
|
25
|
+
export interface BoundVolumeMount {
|
|
26
|
+
readonly volume: { readonly name: Effect.Effect<string, never, RuntimeContext> };
|
|
27
|
+
/** Absolute path inside the sandbox. */
|
|
28
|
+
readonly path: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface MountVolumeOptions {
|
|
32
|
+
/** Absolute path inside the sandbox. */
|
|
33
|
+
readonly path: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Mount a declared `E2B.Volume` at a path.
|
|
38
|
+
*
|
|
39
|
+
* In an `E2B.Template` program, the mount becomes part of the template:
|
|
40
|
+
* every sandbox created from it (with `CreateSandbox(template)` or
|
|
41
|
+
* `E2B.Sandbox({ template })`) mounts the volume, and the program finds its
|
|
42
|
+
* files at `path`. E2B attaches volumes when a sandbox is created, so a
|
|
43
|
+
* sandbox already running keeps the mounts it started with.
|
|
44
|
+
*
|
|
45
|
+
* Anywhere else (a Worker, a Function), it returns a reference to pass to
|
|
46
|
+
* `create({ mounts })`.
|
|
47
|
+
*
|
|
48
|
+
* E2B enables volumes per team; on a team without them, deploying the
|
|
49
|
+
* volume fails with `VolumesNotEnabled`.
|
|
50
|
+
*
|
|
51
|
+
* ### In a template program
|
|
52
|
+
* **Example:** A program that serves a volume's files
|
|
53
|
+
* ```typescript
|
|
54
|
+
* export default class Api extends E2B.Template<Api>()(
|
|
55
|
+
* "Api",
|
|
56
|
+
* { main: import.meta.url },
|
|
57
|
+
* Effect.gen(function* () {
|
|
58
|
+
* const data = yield* E2B.MountVolume(Data, { path: "/data" });
|
|
59
|
+
* const fs = yield* FileSystem.FileSystem;
|
|
60
|
+
* return {
|
|
61
|
+
* fetch: Effect.gen(function* () {
|
|
62
|
+
* const files = yield* fs.readDirectory(data.path);
|
|
63
|
+
* return yield* HttpServerResponse.json(files);
|
|
64
|
+
* }).pipe(Effect.orDie),
|
|
65
|
+
* };
|
|
66
|
+
* }).pipe(Effect.provide(E2B.MountVolumeLive)),
|
|
67
|
+
* ) {}
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* ### From a Worker
|
|
71
|
+
* **Example:** Mount a shared volume and a per-user one
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const data = yield* E2B.MountVolume(Data, { path: "/data" });
|
|
74
|
+
* const sandboxes = yield* E2B.CreateSandbox(Agent);
|
|
75
|
+
* const volumes = yield* E2B.CreateVolume();
|
|
76
|
+
* // in fetch:
|
|
77
|
+
* const home = yield* volumes.getOrCreate(`home-${user}`);
|
|
78
|
+
* const sandbox = yield* sandboxes.create({
|
|
79
|
+
* mounts: [data, { volume: home, path: "/home/user/work" }],
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* @binding
|
|
84
|
+
* @product Volume
|
|
85
|
+
*/
|
|
86
|
+
export interface MountVolume extends Binding.Service<
|
|
87
|
+
MountVolume,
|
|
88
|
+
"E2B.MountVolume",
|
|
89
|
+
(volume: Volume, options: MountVolumeOptions) => Effect.Effect<BoundVolumeMount>
|
|
90
|
+
> {}
|
|
91
|
+
|
|
92
|
+
export const MountVolume = Binding.Service<MountVolume>("E2B.MountVolume");
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { MountVolume, type BoundVolumeMount, type MountVolumeOptions } from "./MountVolume.ts";
|
|
6
|
+
import type { Template } from "./Template.ts";
|
|
7
|
+
import type { Volume } from "./Volume.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The implementation of {@link MountVolume}. It makes no API call: E2B
|
|
11
|
+
* mounts a volume by name when a sandbox is created, so the binding binds
|
|
12
|
+
* the name onto the host and, in an `E2B.Template` program, adds the mount
|
|
13
|
+
* to the template.
|
|
14
|
+
*
|
|
15
|
+
* ### Provide the layer
|
|
16
|
+
* **Example:** On a Worker
|
|
17
|
+
* ```typescript
|
|
18
|
+
* Effect.gen(function* () {
|
|
19
|
+
* const data = yield* E2B.MountVolume(Data, { path: "/data" });
|
|
20
|
+
* // ...
|
|
21
|
+
* }).pipe(Effect.provide(E2B.MountVolumeLive))
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @layer
|
|
25
|
+
* @product Volume
|
|
26
|
+
* @provides E2B.MountVolume
|
|
27
|
+
*/
|
|
28
|
+
export const MountVolumeLive = Layer.succeed(
|
|
29
|
+
MountVolume,
|
|
30
|
+
Effect.fn("E2B.MountVolume")(function* (volume: Volume, options: MountVolumeOptions) {
|
|
31
|
+
if (!globalThis.__ALCHEMY_RUNTIME__) {
|
|
32
|
+
const host = yield* Binding.Host;
|
|
33
|
+
// A mount is part of a template program's own sandboxes, so it is
|
|
34
|
+
// attached to the template itself. `Binding.Host` is typed as a bare
|
|
35
|
+
// `ResourceLike` (a host's binding contract is only known per type),
|
|
36
|
+
// hence the cast once the type is checked.
|
|
37
|
+
if (host?.Type === "E2B.Template") {
|
|
38
|
+
yield* (host as unknown as Template).bind`${volume}`({
|
|
39
|
+
volumes: [{ volume: { name: volume.name }, path: options.path }],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const name = yield* Output.named(
|
|
44
|
+
volume.name as Output.Output<string, never>,
|
|
45
|
+
`E2B_VOLUME_${volume.LogicalId}`,
|
|
46
|
+
).asEffect();
|
|
47
|
+
return { volume: { name }, path: options.path } satisfies BoundVolumeMount;
|
|
48
|
+
}),
|
|
49
|
+
);
|
package/src/Providers.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CredentialsStoreLive } from "alchemy/Auth/Credentials";
|
|
2
|
+
import { ProfileStoreLive } from "alchemy/Auth/Profile";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import * as FetchHttpClient from "effect/http/FetchHttpClient";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import { ApiKey, ApiKeyProvider } from "./ApiKey.ts";
|
|
7
|
+
import { E2BAuth } from "./AuthProvider.ts";
|
|
8
|
+
import * as Credentials from "./Credentials.ts";
|
|
9
|
+
import { Sandbox, SandboxProvider } from "./Sandbox.ts";
|
|
10
|
+
import { Secret, SecretProvider } from "./Secret.ts";
|
|
11
|
+
import { Snapshot, SnapshotProvider } from "./Snapshot.ts";
|
|
12
|
+
import { Template, TemplateProvider } from "./Template.ts";
|
|
13
|
+
import { Volume, VolumeProvider } from "./Volume.ts";
|
|
14
|
+
import { Webhook, WebhookProvider } from "./Webhook.ts";
|
|
15
|
+
|
|
16
|
+
export { Credentials } from "@distilled.cloud/e2b/Credentials";
|
|
17
|
+
|
|
18
|
+
export class Providers extends Provider.ProviderCollection<Providers>()("E2B") {}
|
|
19
|
+
|
|
20
|
+
export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* E2B providers and credentials. Wires up every E2B resource and registers
|
|
24
|
+
* the E2B AuthProvider so `alchemy profile edit --add E2B` can configure it.
|
|
25
|
+
*/
|
|
26
|
+
export const providers = () =>
|
|
27
|
+
Layer.effect(
|
|
28
|
+
Providers,
|
|
29
|
+
Provider.collection([ApiKey, Sandbox, Secret, Snapshot, Template, Volume, Webhook]),
|
|
30
|
+
).pipe(
|
|
31
|
+
Layer.provide(
|
|
32
|
+
Layer.mergeAll(
|
|
33
|
+
ApiKeyProvider(),
|
|
34
|
+
SandboxProvider(),
|
|
35
|
+
SecretProvider(),
|
|
36
|
+
SnapshotProvider(),
|
|
37
|
+
TemplateProvider(),
|
|
38
|
+
VolumeProvider(),
|
|
39
|
+
WebhookProvider(),
|
|
40
|
+
),
|
|
41
|
+
),
|
|
42
|
+
Layer.provideMerge(Credentials.fromAuthProvider()),
|
|
43
|
+
Layer.provideMerge(FetchHttpClient.layer),
|
|
44
|
+
Layer.provideMerge(E2BAuth),
|
|
45
|
+
Layer.provideMerge(ProfileStoreLive),
|
|
46
|
+
Layer.provideMerge(CredentialsStoreLive),
|
|
47
|
+
Layer.orDie,
|
|
48
|
+
);
|
package/src/ReadTeam.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type * as auth from "@distilled.cloud/e2b/auth";
|
|
2
|
+
import type * as events from "@distilled.cloud/e2b/events";
|
|
3
|
+
import * as Binding from "alchemy/Binding";
|
|
4
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
5
|
+
import type * as Effect from "effect/Effect";
|
|
6
|
+
import type { E2BError } from "./SandboxClient.ts";
|
|
7
|
+
|
|
8
|
+
/** Team usage and the sandbox lifecycle event log. */
|
|
9
|
+
export interface TeamClient {
|
|
10
|
+
/** The team's id: the deployer's team, which the host's key belongs to. */
|
|
11
|
+
readonly teamId: Effect.Effect<string, never, RuntimeContext>;
|
|
12
|
+
/** Concurrent sandboxes and sandbox start rate over time (unix seconds). */
|
|
13
|
+
metrics(
|
|
14
|
+
options?: Omit<auth.ListTeamMetricsRequest, "teamID">,
|
|
15
|
+
): Effect.Effect<auth.ListTeamMetricsResponse, E2BError, RuntimeContext>;
|
|
16
|
+
/** The peak of one metric over a window. */
|
|
17
|
+
maxMetric(
|
|
18
|
+
options: Omit<auth.GetTeamMetricsMaxRequest, "teamID">,
|
|
19
|
+
): Effect.Effect<auth.MaxTeamMetric, E2BError, RuntimeContext>;
|
|
20
|
+
/** Lifecycle events of every sandbox in the team, newest first by default. */
|
|
21
|
+
events(
|
|
22
|
+
options?: events.ListTeamSandboxEventsRequest,
|
|
23
|
+
): Effect.Effect<events.ListTeamSandboxEventsResponse, E2BError, RuntimeContext>;
|
|
24
|
+
/** Lifecycle events of one sandbox. */
|
|
25
|
+
sandboxEvents(
|
|
26
|
+
sandboxId: string,
|
|
27
|
+
options?: Omit<events.ListSandboxEventsRequest, "sandboxID">,
|
|
28
|
+
): Effect.Effect<events.ListSandboxEventsResponse, E2BError, RuntimeContext>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Read the team's sandbox usage and lifecycle event log: dashboards, quotas,
|
|
33
|
+
* auditing which sandboxes started, paused and were killed.
|
|
34
|
+
*
|
|
35
|
+
* To react to lifecycle events as they happen, use `E2B.SandboxEvents`.
|
|
36
|
+
*
|
|
37
|
+
* ### Reading usage
|
|
38
|
+
* **Example:** Concurrent sandboxes over the last hour
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const team = yield* E2B.ReadTeam();
|
|
41
|
+
* // in fetch:
|
|
42
|
+
* const now = Math.floor(Date.now() / 1000);
|
|
43
|
+
* const metrics = yield* team.metrics({ start: now - 3600, end: now });
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* @binding
|
|
47
|
+
* @product Team
|
|
48
|
+
*/
|
|
49
|
+
export interface ReadTeam extends Binding.Service<
|
|
50
|
+
ReadTeam,
|
|
51
|
+
"E2B.ReadTeam",
|
|
52
|
+
() => Effect.Effect<TeamClient>
|
|
53
|
+
> {}
|
|
54
|
+
|
|
55
|
+
export const ReadTeam = Binding.Service<ReadTeam>("E2B.ReadTeam");
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as auth from "@distilled.cloud/e2b/auth";
|
|
2
|
+
import * as events from "@distilled.cloud/e2b/events";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { bindE2B } from "./E2BBindings.ts";
|
|
6
|
+
import { ReadTeam, type TeamClient } from "./ReadTeam.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* HTTP implementation of {@link ReadTeam}. Works on any host.
|
|
10
|
+
*
|
|
11
|
+
* ### Provide the layer
|
|
12
|
+
* **Example:** On a Worker
|
|
13
|
+
* ```typescript
|
|
14
|
+
* Effect.gen(function* () {
|
|
15
|
+
* const team = yield* E2B.ReadTeam();
|
|
16
|
+
* // ...
|
|
17
|
+
* }).pipe(Effect.provide(E2B.ReadTeamHttp))
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @layer
|
|
21
|
+
* @product Team
|
|
22
|
+
* @provides E2B.ReadTeam
|
|
23
|
+
*/
|
|
24
|
+
export const ReadTeamHttp = Layer.succeed(
|
|
25
|
+
ReadTeam,
|
|
26
|
+
Effect.fn("E2B.ReadTeam")(function* () {
|
|
27
|
+
const e2b = yield* bindE2B;
|
|
28
|
+
const client: TeamClient = {
|
|
29
|
+
teamId: e2b.teamId,
|
|
30
|
+
metrics: Effect.fn("E2B.ReadTeam.metrics")(function* (options) {
|
|
31
|
+
const teamID = yield* e2b.teamId;
|
|
32
|
+
return yield* e2b.authorize(auth.listTeamMetrics({ ...options, teamID }));
|
|
33
|
+
}),
|
|
34
|
+
maxMetric: Effect.fn("E2B.ReadTeam.maxMetric")(function* (options) {
|
|
35
|
+
const teamID = yield* e2b.teamId;
|
|
36
|
+
return yield* e2b.authorize(auth.getTeamMetricsMax({ ...options, teamID }));
|
|
37
|
+
}),
|
|
38
|
+
events: (options) => e2b.authorize(events.listTeamSandboxEvents({ ...options })),
|
|
39
|
+
sandboxEvents: (sandboxId, options) =>
|
|
40
|
+
e2b.authorize(events.listSandboxEvents({ ...options, sandboxID: sandboxId })),
|
|
41
|
+
};
|
|
42
|
+
return client;
|
|
43
|
+
}),
|
|
44
|
+
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type * as Effect from "effect/Effect";
|
|
3
|
+
import type { Volume } from "./Volume.ts";
|
|
4
|
+
import type { ReadVolumeClient } from "./VolumeFiles.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Read a {@link Volume}'s files from outside any sandbox: a report a sandbox wrote, a dataset to inspect.
|
|
8
|
+
*
|
|
9
|
+
* The client talks to E2B's volume content API with the volume's own token,
|
|
10
|
+
* looked up once through the host's API key.
|
|
11
|
+
*
|
|
12
|
+
* ### Using the client
|
|
13
|
+
* **Example:** In a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const reports = yield* E2B.ReadVolume(Reports);
|
|
16
|
+
* // in fetch:
|
|
17
|
+
* const report = yield* reports.readText("/report.json");
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @binding
|
|
21
|
+
* @product Volume
|
|
22
|
+
*/
|
|
23
|
+
export interface ReadVolume extends Binding.Service<
|
|
24
|
+
ReadVolume,
|
|
25
|
+
"E2B.ReadVolume",
|
|
26
|
+
(volume: Volume) => Effect.Effect<ReadVolumeClient>
|
|
27
|
+
> {}
|
|
28
|
+
|
|
29
|
+
export const ReadVolume = Binding.Service<ReadVolume>("E2B.ReadVolume");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type * as Output from "alchemy/Output";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { bindE2B } from "./E2BBindings.ts";
|
|
5
|
+
import { makeVolumeFiles } from "./internal/VolumeHttp.ts";
|
|
6
|
+
import { ReadVolume } from "./ReadVolume.ts";
|
|
7
|
+
import type { Volume } from "./Volume.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link ReadVolume}. Works on any host.
|
|
11
|
+
*
|
|
12
|
+
* ### Provide the layer
|
|
13
|
+
* **Example:** On a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Effect.gen(function* () {
|
|
16
|
+
* const reports = yield* E2B.ReadVolume(Reports);
|
|
17
|
+
* // ...
|
|
18
|
+
* }).pipe(Effect.provide(E2B.ReadVolumeHttp))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @layer
|
|
22
|
+
* @product Volume
|
|
23
|
+
* @provides E2B.ReadVolume
|
|
24
|
+
*/
|
|
25
|
+
export const ReadVolumeHttp = Layer.succeed(
|
|
26
|
+
ReadVolume,
|
|
27
|
+
Effect.fn("E2B.ReadVolume")(function* (volume: Volume) {
|
|
28
|
+
const auth = yield* bindE2B;
|
|
29
|
+
const volumeId = yield* (volume.volumeId as Output.Output<string, never>).asEffect();
|
|
30
|
+
return makeVolumeFiles(auth, volumeId);
|
|
31
|
+
}),
|
|
32
|
+
);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type * as webhooks from "@distilled.cloud/e2b/webhooks";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type { E2BError } from "./SandboxClient.ts";
|
|
6
|
+
import type { Webhook } from "./Webhook.ts";
|
|
7
|
+
|
|
8
|
+
/** A webhook's delivery history and stats. */
|
|
9
|
+
export interface WebhookClient {
|
|
10
|
+
/** Deliveries grouped by event, newest first, with each attempt's request and response. */
|
|
11
|
+
deliveries(
|
|
12
|
+
options?: Omit<webhooks.ListWebhookDeliveriesRequest, "webhookID">,
|
|
13
|
+
): Effect.Effect<webhooks.WebhookDeliveriesListPayload, E2BError, RuntimeContext>;
|
|
14
|
+
/** Delivery counts, failures and latency over time. */
|
|
15
|
+
stats(
|
|
16
|
+
options?: Omit<webhooks.GetWebhookStatsRequest, "webhookID">,
|
|
17
|
+
): Effect.Effect<webhooks.WebhookDeliveryStats, E2BError, RuntimeContext>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Read an E2B {@link Webhook}'s delivery history and stats: debug a failing
|
|
22
|
+
* endpoint, or alert on failed deliveries.
|
|
23
|
+
*
|
|
24
|
+
* ### Reading deliveries
|
|
25
|
+
* **Example:** Failed deliveries in the last hour
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const hook = yield* E2B.ReadWebhook(Lifecycle);
|
|
28
|
+
* // in fetch:
|
|
29
|
+
* const failed = yield* hook.deliveries({ deliveryStatus: ["failed"] });
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @binding
|
|
33
|
+
* @product Webhook
|
|
34
|
+
*/
|
|
35
|
+
export interface ReadWebhook extends Binding.Service<
|
|
36
|
+
ReadWebhook,
|
|
37
|
+
"E2B.ReadWebhook",
|
|
38
|
+
(webhook: Webhook) => Effect.Effect<WebhookClient>
|
|
39
|
+
> {}
|
|
40
|
+
|
|
41
|
+
export const ReadWebhook = Binding.Service<ReadWebhook>("E2B.ReadWebhook");
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as webhooks from "@distilled.cloud/e2b/webhooks";
|
|
2
|
+
import type * as Output from "alchemy/Output";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { bindE2B } from "./E2BBindings.ts";
|
|
6
|
+
import { ReadWebhook, type WebhookClient } from "./ReadWebhook.ts";
|
|
7
|
+
import type { Webhook } from "./Webhook.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link ReadWebhook}. Works on any host.
|
|
11
|
+
*
|
|
12
|
+
* ### Provide the layer
|
|
13
|
+
* **Example:** On a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Effect.gen(function* () {
|
|
16
|
+
* const hook = yield* E2B.ReadWebhook(Lifecycle);
|
|
17
|
+
* // ...
|
|
18
|
+
* }).pipe(Effect.provide(E2B.ReadWebhookHttp))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @layer
|
|
22
|
+
* @product Webhook
|
|
23
|
+
* @provides E2B.ReadWebhook
|
|
24
|
+
*/
|
|
25
|
+
export const ReadWebhookHttp = Layer.succeed(
|
|
26
|
+
ReadWebhook,
|
|
27
|
+
Effect.fn("E2B.ReadWebhook")(function* (webhook: Webhook) {
|
|
28
|
+
const auth = yield* bindE2B;
|
|
29
|
+
const webhookId = yield* (webhook.webhookId as Output.Output<string, never>).asEffect();
|
|
30
|
+
const client: WebhookClient = {
|
|
31
|
+
deliveries: (options) =>
|
|
32
|
+
Effect.flatMap(webhookId, (id) =>
|
|
33
|
+
auth.authorize(webhooks.listWebhookDeliveries({ ...options, webhookID: id })),
|
|
34
|
+
),
|
|
35
|
+
stats: (options) =>
|
|
36
|
+
Effect.flatMap(webhookId, (id) =>
|
|
37
|
+
auth.authorize(webhooks.getWebhookStats({ ...options, webhookID: id })),
|
|
38
|
+
),
|
|
39
|
+
};
|
|
40
|
+
return client;
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type * as Effect from "effect/Effect";
|
|
3
|
+
import type { Volume } from "./Volume.ts";
|
|
4
|
+
import type { ReadWriteVolumeClient } from "./VolumeFiles.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Read and write a {@link Volume}'s files from outside any sandbox.
|
|
8
|
+
*
|
|
9
|
+
* The client talks to E2B's volume content API with the volume's own token,
|
|
10
|
+
* looked up once through the host's API key.
|
|
11
|
+
*
|
|
12
|
+
* ### Using the client
|
|
13
|
+
* **Example:** In a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* const cache = yield* E2B.ReadWriteVolume(Cache);
|
|
16
|
+
* // in fetch:
|
|
17
|
+
* yield* cache.write("/notes.md", "hello");
|
|
18
|
+
* const notes = yield* cache.readText("/notes.md");
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @binding
|
|
22
|
+
* @product Volume
|
|
23
|
+
*/
|
|
24
|
+
export interface ReadWriteVolume extends Binding.Service<
|
|
25
|
+
ReadWriteVolume,
|
|
26
|
+
"E2B.ReadWriteVolume",
|
|
27
|
+
(volume: Volume) => Effect.Effect<ReadWriteVolumeClient>
|
|
28
|
+
> {}
|
|
29
|
+
|
|
30
|
+
export const ReadWriteVolume = Binding.Service<ReadWriteVolume>("E2B.ReadWriteVolume");
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type * as Output from "alchemy/Output";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { bindE2B } from "./E2BBindings.ts";
|
|
5
|
+
import { makeVolumeFiles } from "./internal/VolumeHttp.ts";
|
|
6
|
+
import { ReadWriteVolume } from "./ReadWriteVolume.ts";
|
|
7
|
+
import type { Volume } from "./Volume.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link ReadWriteVolume}. Works on any host.
|
|
11
|
+
*
|
|
12
|
+
* ### Provide the layer
|
|
13
|
+
* **Example:** On a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Effect.gen(function* () {
|
|
16
|
+
* const cache = yield* E2B.ReadWriteVolume(Cache);
|
|
17
|
+
* // ...
|
|
18
|
+
* }).pipe(Effect.provide(E2B.ReadWriteVolumeHttp))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @layer
|
|
22
|
+
* @product Volume
|
|
23
|
+
* @provides E2B.ReadWriteVolume
|
|
24
|
+
*/
|
|
25
|
+
export const ReadWriteVolumeHttp = Layer.succeed(
|
|
26
|
+
ReadWriteVolume,
|
|
27
|
+
Effect.fn("E2B.ReadWriteVolume")(function* (volume: Volume) {
|
|
28
|
+
const auth = yield* bindE2B;
|
|
29
|
+
const volumeId = yield* (volume.volumeId as Output.Output<string, never>).asEffect();
|
|
30
|
+
return makeVolumeFiles(auth, volumeId);
|
|
31
|
+
}),
|
|
32
|
+
);
|