@alchemy.run/e2b 0.0.0 → 2.0.0-beta.86
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/Volume.ts
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as volumes from "@distilled.cloud/e2b/volumes";
|
|
2
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
3
|
+
import { isResolved } from "alchemy/Diff";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { Resource } from "alchemy/Resource";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import { E2BUnexpectedResponse } from "./Errors.ts";
|
|
8
|
+
import { e2bName, isGeneratedName } from "./internal/Ownership.ts";
|
|
9
|
+
import type { Providers } from "./Providers.ts";
|
|
10
|
+
|
|
11
|
+
export interface VolumeProps {
|
|
12
|
+
/**
|
|
13
|
+
* Volume name, unique within the team. Letters, digits, `-` and `_`. If
|
|
14
|
+
* omitted, a unique name is generated from the stack, stage and logical ID.
|
|
15
|
+
* Changing it replaces the volume, and its files are lost.
|
|
16
|
+
*/
|
|
17
|
+
name?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface VolumeAttributes {
|
|
21
|
+
/** E2B's volume id. */
|
|
22
|
+
volumeId: string;
|
|
23
|
+
/** The volume's name. Sandboxes mount a volume by name. */
|
|
24
|
+
name: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface Volume extends Resource<
|
|
28
|
+
"E2B.Volume",
|
|
29
|
+
VolumeProps,
|
|
30
|
+
VolumeAttributes,
|
|
31
|
+
never,
|
|
32
|
+
Providers,
|
|
33
|
+
{ name: string }
|
|
34
|
+
> {}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A persistent E2B volume: a team-wide filesystem that sandboxes mount at a
|
|
38
|
+
* path and that outlives every sandbox using it.
|
|
39
|
+
*
|
|
40
|
+
* Declare a volume when every sandbox shares it (a package cache, a
|
|
41
|
+
* dataset). Per-user and per-session volumes are created at runtime by name
|
|
42
|
+
* with `E2B.CreateVolume()`, and both kinds mount the same way.
|
|
43
|
+
*
|
|
44
|
+
* E2B volumes carry no labels, so Alchemy recognises its volumes by their
|
|
45
|
+
* generated name. A volume found under an explicit name without prior state
|
|
46
|
+
* is reported as unowned and is only adopted with `--adopt`.
|
|
47
|
+
*
|
|
48
|
+
* E2B enables volumes per team; on a team without them, a deploy fails
|
|
49
|
+
* with `VolumesNotEnabled`.
|
|
50
|
+
*
|
|
51
|
+
* ### Creating a Volume
|
|
52
|
+
* **Example:** A shared cache volume
|
|
53
|
+
* ```typescript
|
|
54
|
+
* export const Cache = E2B.Volume("Cache", {});
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* **Example:** A volume with a fixed name
|
|
58
|
+
* ```typescript
|
|
59
|
+
* export const Datasets = E2B.Volume("Datasets", { name: "datasets" });
|
|
60
|
+
* ```
|
|
61
|
+
*
|
|
62
|
+
* ### Mounting a Volume
|
|
63
|
+
* **Example:** Mount it into a declared sandbox
|
|
64
|
+
* ```typescript
|
|
65
|
+
* export const Builder = E2B.Sandbox("Builder", {
|
|
66
|
+
* template: Agent,
|
|
67
|
+
* mounts: [{ volume: Cache, path: "/cache" }],
|
|
68
|
+
* });
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* **Example:** Mount it into the sandboxes a Worker creates
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const cache = yield* E2B.MountVolume(Cache, { path: "/cache" });
|
|
74
|
+
* const sandboxes = yield* E2B.CreateSandbox(Agent);
|
|
75
|
+
* // in fetch:
|
|
76
|
+
* const sandbox = yield* sandboxes.create({ mounts: [cache] });
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* ### Reading files from outside a sandbox
|
|
80
|
+
* **Example:** Read a report the sandbox wrote
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const reports = yield* E2B.ReadVolume(Reports);
|
|
83
|
+
* const report = yield* reports.readFile("/report.json");
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* ### Referencing a volume the stack doesn't manage
|
|
87
|
+
* `E2B.Volume.lookup` finds an existing volume by name. Nothing is created,
|
|
88
|
+
* adopted or deleted.
|
|
89
|
+
*
|
|
90
|
+
* **Example:** Look one up by name
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const datasets = E2B.Volume.lookup({ name: "datasets" });
|
|
93
|
+
* const files = yield* E2B.ReadVolume(datasets);
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @resource
|
|
97
|
+
* @product Volume
|
|
98
|
+
*/
|
|
99
|
+
export const Volume = Resource<Volume>("E2B.Volume");
|
|
100
|
+
|
|
101
|
+
const toAttrs = (volume: { volumeID: string; name: string }): VolumeAttributes => ({
|
|
102
|
+
volumeId: volume.volumeID,
|
|
103
|
+
name: volume.name,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/** The volume with this name, if any. E2B lists a team's volumes in one page. */
|
|
107
|
+
const findByName = (name: string) =>
|
|
108
|
+
volumes.listVolumes({}).pipe(Effect.map((all) => all.find((volume) => volume.name === name)));
|
|
109
|
+
|
|
110
|
+
const observe = (volumeId: string | undefined, name: string) =>
|
|
111
|
+
volumeId !== undefined
|
|
112
|
+
? volumes.getVolume({ volumeID: volumeId }).pipe(
|
|
113
|
+
Effect.map((volume): volumes.Volume | undefined => volume),
|
|
114
|
+
Effect.catchTag("NotFound", () => findByName(name)),
|
|
115
|
+
)
|
|
116
|
+
: findByName(name);
|
|
117
|
+
|
|
118
|
+
export const VolumeProvider = () =>
|
|
119
|
+
Provider.effect(
|
|
120
|
+
Volume,
|
|
121
|
+
Effect.gen(function* () {
|
|
122
|
+
return {
|
|
123
|
+
stables: ["volumeId", "name"],
|
|
124
|
+
diff: Effect.fn(function* ({ id, olds, news, output }) {
|
|
125
|
+
if (!isResolved(news)) return undefined;
|
|
126
|
+
// Only an explicit name can force a rename; a generated name is
|
|
127
|
+
// engine-owned and never compared against a fresh computation.
|
|
128
|
+
if (news.name === undefined && olds?.name === undefined) return undefined;
|
|
129
|
+
const name = output?.name ?? (yield* e2bName(id, olds?.name));
|
|
130
|
+
if (news.name !== name) return { action: "replace" } as const;
|
|
131
|
+
return undefined;
|
|
132
|
+
}),
|
|
133
|
+
lookup: Effect.fn(function* ({ name }) {
|
|
134
|
+
const volume = yield* observe(undefined, name);
|
|
135
|
+
return volume === undefined ? undefined : toAttrs(volume);
|
|
136
|
+
}),
|
|
137
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
138
|
+
const name = output?.name ?? (yield* e2bName(id, olds?.name));
|
|
139
|
+
const volume = yield* observe(output?.volumeId, name);
|
|
140
|
+
if (volume === undefined) return undefined;
|
|
141
|
+
const attrs = toAttrs(volume);
|
|
142
|
+
return output !== undefined || olds?.name === undefined ? attrs : Unowned(attrs);
|
|
143
|
+
}),
|
|
144
|
+
reconcile: Effect.fn(function* ({ id, news, output, session }) {
|
|
145
|
+
const name = output?.name ?? (yield* e2bName(id, news.name));
|
|
146
|
+
// Observe
|
|
147
|
+
const observed = yield* observe(output?.volumeId, name);
|
|
148
|
+
if (observed !== undefined) return toAttrs(observed);
|
|
149
|
+
// Ensure — a Conflict is a peer creating the same name: read it back.
|
|
150
|
+
yield* session.note(`Creating volume ${name}...`);
|
|
151
|
+
const created = yield* volumes.createVolume({ name }).pipe(
|
|
152
|
+
Effect.map((volume): volumes.Volume | undefined => volume),
|
|
153
|
+
Effect.catchTag("Conflict", () => findByName(name)),
|
|
154
|
+
);
|
|
155
|
+
if (created === undefined) {
|
|
156
|
+
return yield* new E2BUnexpectedResponse({
|
|
157
|
+
message: `E2B volume ${name} vanished after create`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return toAttrs(created);
|
|
161
|
+
}),
|
|
162
|
+
delete: Effect.fn(function* ({ output }) {
|
|
163
|
+
yield* volumes
|
|
164
|
+
.deleteVolume({ volumeID: output.volumeId })
|
|
165
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
166
|
+
}),
|
|
167
|
+
list: Effect.fn(function* () {
|
|
168
|
+
const all = yield* volumes.listVolumes({});
|
|
169
|
+
return all.filter((volume) => isGeneratedName(volume.name)).map(toAttrs);
|
|
170
|
+
}),
|
|
171
|
+
};
|
|
172
|
+
}),
|
|
173
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type * as volumeContent from "@distilled.cloud/e2b/volume_content";
|
|
2
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
3
|
+
import type * as Effect from "effect/Effect";
|
|
4
|
+
import type { E2BError } from "./SandboxClient.ts";
|
|
5
|
+
|
|
6
|
+
/** A file, directory or symlink in a volume. */
|
|
7
|
+
export type VolumeEntry = volumeContent.VolumeEntryStat;
|
|
8
|
+
|
|
9
|
+
/** Ownership and permissions for a written file or directory. */
|
|
10
|
+
export interface VolumeEntryOptions {
|
|
11
|
+
readonly uid?: number;
|
|
12
|
+
readonly gid?: number;
|
|
13
|
+
/** POSIX mode, e.g. `0o644`. */
|
|
14
|
+
readonly mode?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Read a volume's files without a sandbox. Paths are absolute inside the volume. */
|
|
18
|
+
export interface ReadVolumeClient {
|
|
19
|
+
read(path: string): Effect.Effect<Uint8Array, E2BError, RuntimeContext>;
|
|
20
|
+
readText(path: string): Effect.Effect<string, E2BError, RuntimeContext>;
|
|
21
|
+
/** Directory entries, `depth` levels deep. */
|
|
22
|
+
list(
|
|
23
|
+
path: string,
|
|
24
|
+
options?: { readonly depth?: number },
|
|
25
|
+
): Effect.Effect<ReadonlyArray<VolumeEntry>, E2BError, RuntimeContext>;
|
|
26
|
+
stat(path: string): Effect.Effect<VolumeEntry, E2BError, RuntimeContext>;
|
|
27
|
+
exists(path: string): Effect.Effect<boolean, E2BError, RuntimeContext>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Write a volume's files without a sandbox. Paths are absolute inside the volume. */
|
|
31
|
+
export interface WriteVolumeClient {
|
|
32
|
+
/** Writes a file, creating parent directories. */
|
|
33
|
+
write(
|
|
34
|
+
path: string,
|
|
35
|
+
data: string | Uint8Array,
|
|
36
|
+
options?: VolumeEntryOptions,
|
|
37
|
+
): Effect.Effect<VolumeEntry, E2BError, RuntimeContext>;
|
|
38
|
+
/** Creates a directory and its parents. */
|
|
39
|
+
makeDir(
|
|
40
|
+
path: string,
|
|
41
|
+
options?: VolumeEntryOptions,
|
|
42
|
+
): Effect.Effect<VolumeEntry, E2BError, RuntimeContext>;
|
|
43
|
+
/** Changes ownership or mode. */
|
|
44
|
+
chmod(
|
|
45
|
+
path: string,
|
|
46
|
+
options: VolumeEntryOptions,
|
|
47
|
+
): Effect.Effect<VolumeEntry, E2BError, RuntimeContext>;
|
|
48
|
+
/** Removes a file or a directory tree. Removing a missing path succeeds. */
|
|
49
|
+
remove(path: string): Effect.Effect<void, E2BError, RuntimeContext>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Read and write a volume's files without a sandbox. */
|
|
53
|
+
export interface ReadWriteVolumeClient extends ReadVolumeClient, WriteVolumeClient {}
|
package/src/Webhook.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import * as webhooks from "@distilled.cloud/e2b/webhooks";
|
|
2
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
3
|
+
import * as Provider from "alchemy/Provider";
|
|
4
|
+
import { Resource } from "alchemy/Resource";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Redacted from "effect/Redacted";
|
|
7
|
+
import { E2BUnexpectedResponse } from "./Errors.ts";
|
|
8
|
+
import { e2bName, isGeneratedName } from "./internal/Ownership.ts";
|
|
9
|
+
import type { Providers } from "./Providers.ts";
|
|
10
|
+
|
|
11
|
+
/** Sandbox lifecycle events E2B delivers to webhooks. */
|
|
12
|
+
export type SandboxEventType =
|
|
13
|
+
| "sandbox.lifecycle.created"
|
|
14
|
+
| "sandbox.lifecycle.killed"
|
|
15
|
+
| "sandbox.lifecycle.updated"
|
|
16
|
+
| "sandbox.lifecycle.paused"
|
|
17
|
+
| "sandbox.lifecycle.resumed"
|
|
18
|
+
| "sandbox.lifecycle.checkpointed";
|
|
19
|
+
|
|
20
|
+
export const ALL_SANDBOX_EVENTS: ReadonlyArray<SandboxEventType> = [
|
|
21
|
+
"sandbox.lifecycle.created",
|
|
22
|
+
"sandbox.lifecycle.killed",
|
|
23
|
+
"sandbox.lifecycle.updated",
|
|
24
|
+
"sandbox.lifecycle.paused",
|
|
25
|
+
"sandbox.lifecycle.resumed",
|
|
26
|
+
"sandbox.lifecycle.checkpointed",
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export interface WebhookProps {
|
|
30
|
+
/**
|
|
31
|
+
* Webhook name. If omitted, a unique name is generated from the stack,
|
|
32
|
+
* stage and logical ID. Updated in place.
|
|
33
|
+
*/
|
|
34
|
+
name?: string;
|
|
35
|
+
/** The URL E2B POSTs each event to. */
|
|
36
|
+
url: string;
|
|
37
|
+
/**
|
|
38
|
+
* The events to deliver.
|
|
39
|
+
* @default every sandbox lifecycle event
|
|
40
|
+
*/
|
|
41
|
+
events?: SandboxEventType[];
|
|
42
|
+
/**
|
|
43
|
+
* Whether E2B delivers events.
|
|
44
|
+
* @default true
|
|
45
|
+
*/
|
|
46
|
+
enabled?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The secret E2B signs each delivery with. The `e2b-signature` header is
|
|
49
|
+
* the unpadded base64 SHA-256 of this secret followed by the raw body.
|
|
50
|
+
* At least 32 characters.
|
|
51
|
+
*/
|
|
52
|
+
signatureSecret: Redacted.Redacted<string>;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface WebhookAttributes {
|
|
56
|
+
/** E2B's webhook id. */
|
|
57
|
+
webhookId: string;
|
|
58
|
+
name: string;
|
|
59
|
+
url: string;
|
|
60
|
+
events: string[];
|
|
61
|
+
enabled: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface Webhook extends Resource<
|
|
65
|
+
"E2B.Webhook",
|
|
66
|
+
WebhookProps,
|
|
67
|
+
WebhookAttributes,
|
|
68
|
+
never,
|
|
69
|
+
Providers,
|
|
70
|
+
{ name: string }
|
|
71
|
+
> {}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* An E2B webhook: E2B POSTs every sandbox lifecycle event (created, paused,
|
|
75
|
+
* resumed, checkpointed, updated, killed) in your team to a URL.
|
|
76
|
+
*
|
|
77
|
+
* Use `E2B.SandboxEvents` to point a webhook at a Worker or Function and
|
|
78
|
+
* handle the events there; it declares this resource for you and verifies
|
|
79
|
+
* each delivery's signature. Declare a `Webhook` directly for an endpoint
|
|
80
|
+
* Alchemy does not deploy.
|
|
81
|
+
*
|
|
82
|
+
* E2B webhooks carry no labels, so Alchemy recognises its webhooks by their
|
|
83
|
+
* generated name.
|
|
84
|
+
*
|
|
85
|
+
* ### Creating a Webhook
|
|
86
|
+
* **Example:** Deliver pause and kill events to an existing endpoint
|
|
87
|
+
* ```typescript
|
|
88
|
+
* export const Lifecycle = E2B.Webhook("Lifecycle", {
|
|
89
|
+
* url: "https://hooks.example.com/e2b",
|
|
90
|
+
* events: ["sandbox.lifecycle.paused", "sandbox.lifecycle.killed"],
|
|
91
|
+
* signatureSecret: Config.Redacted("E2B_WEBHOOK_SECRET"),
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* ### Referencing a webhook the stack doesn't manage
|
|
96
|
+
* `E2B.Webhook.lookup` finds an existing webhook by name. Nothing is created,
|
|
97
|
+
* adopted or deleted.
|
|
98
|
+
*
|
|
99
|
+
* **Example:** Look one up by name
|
|
100
|
+
* ```typescript
|
|
101
|
+
* const audit = E2B.Webhook.lookup({ name: "audit" });
|
|
102
|
+
* const deliveries = yield* E2B.ReadWebhook(audit);
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @resource
|
|
106
|
+
* @product Webhook
|
|
107
|
+
*/
|
|
108
|
+
export const Webhook = Resource<Webhook>("E2B.Webhook");
|
|
109
|
+
|
|
110
|
+
const toAttrs = (
|
|
111
|
+
webhook: webhooks.WebhookDetail | webhooks.WebhookCreation,
|
|
112
|
+
): WebhookAttributes => ({
|
|
113
|
+
webhookId: webhook.id,
|
|
114
|
+
name: webhook.name,
|
|
115
|
+
url: webhook.url,
|
|
116
|
+
events: [...webhook.events],
|
|
117
|
+
enabled: webhook.enabled,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const findByName = (name: string) =>
|
|
121
|
+
webhooks.listWebhooks({}).pipe(Effect.map((all) => all.find((hook) => hook.name === name)));
|
|
122
|
+
|
|
123
|
+
const observe = (webhookId: string | undefined, name: string) =>
|
|
124
|
+
webhookId !== undefined
|
|
125
|
+
? webhooks.getWebhook({ webhookID: webhookId }).pipe(
|
|
126
|
+
Effect.map((hook): webhooks.WebhookDetail | undefined => hook),
|
|
127
|
+
Effect.catchTag("NotFound", () => findByName(name)),
|
|
128
|
+
)
|
|
129
|
+
: findByName(name);
|
|
130
|
+
|
|
131
|
+
const sameEvents = (a: ReadonlyArray<string>, b: ReadonlyArray<string>) =>
|
|
132
|
+
a.length === b.length && [...a].sort().join() === [...b].sort().join();
|
|
133
|
+
|
|
134
|
+
export const WebhookProvider = () =>
|
|
135
|
+
Provider.effect(
|
|
136
|
+
Webhook,
|
|
137
|
+
Effect.gen(function* () {
|
|
138
|
+
return {
|
|
139
|
+
stables: ["webhookId"],
|
|
140
|
+
lookup: Effect.fn(function* ({ name }) {
|
|
141
|
+
const hook = yield* observe(undefined, name);
|
|
142
|
+
return hook === undefined ? undefined : toAttrs(hook);
|
|
143
|
+
}),
|
|
144
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
145
|
+
const name = output?.name ?? (yield* e2bName(id, olds?.name));
|
|
146
|
+
const hook = yield* observe(output?.webhookId, name);
|
|
147
|
+
if (hook === undefined) return undefined;
|
|
148
|
+
const attrs = toAttrs(hook);
|
|
149
|
+
return output !== undefined || olds?.name === undefined ? attrs : Unowned(attrs);
|
|
150
|
+
}),
|
|
151
|
+
reconcile: Effect.fn(function* ({ id, news, olds, output, session }) {
|
|
152
|
+
// Webhooks are renamed in place, so the desired name wins over the
|
|
153
|
+
// stored one; the stored id finds the webhook either way.
|
|
154
|
+
const name = news.name ?? output?.name ?? (yield* e2bName(id, undefined));
|
|
155
|
+
const events = [...(news.events ?? ALL_SANDBOX_EVENTS)];
|
|
156
|
+
const enabled = news.enabled ?? true;
|
|
157
|
+
|
|
158
|
+
// Observe
|
|
159
|
+
const observed = yield* observe(output?.webhookId, output?.name ?? name);
|
|
160
|
+
|
|
161
|
+
// Ensure
|
|
162
|
+
if (observed === undefined) {
|
|
163
|
+
yield* session.note(`Creating webhook ${name}...`);
|
|
164
|
+
const created = yield* webhooks.createWebhook({
|
|
165
|
+
name,
|
|
166
|
+
url: news.url,
|
|
167
|
+
events,
|
|
168
|
+
enabled,
|
|
169
|
+
signatureSecret: news.signatureSecret,
|
|
170
|
+
});
|
|
171
|
+
return toAttrs(created);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Sync — the signing secret is write-only, so `olds` is the only
|
|
175
|
+
// signal that the stored one already matches.
|
|
176
|
+
const secretChanged =
|
|
177
|
+
olds === undefined ||
|
|
178
|
+
Redacted.value(olds.signatureSecret) !== Redacted.value(news.signatureSecret);
|
|
179
|
+
if (
|
|
180
|
+
observed.name !== name ||
|
|
181
|
+
observed.url !== news.url ||
|
|
182
|
+
observed.enabled !== enabled ||
|
|
183
|
+
!sameEvents(observed.events, events) ||
|
|
184
|
+
secretChanged
|
|
185
|
+
) {
|
|
186
|
+
yield* webhooks.updateWebhook({
|
|
187
|
+
webhookID: observed.id,
|
|
188
|
+
name,
|
|
189
|
+
url: news.url,
|
|
190
|
+
events,
|
|
191
|
+
enabled,
|
|
192
|
+
...(secretChanged ? { signatureSecret: news.signatureSecret } : {}),
|
|
193
|
+
});
|
|
194
|
+
const updated = yield* observe(observed.id, name);
|
|
195
|
+
if (updated === undefined) {
|
|
196
|
+
return yield* new E2BUnexpectedResponse({
|
|
197
|
+
message: `E2B webhook ${name} vanished after update`,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return toAttrs(updated);
|
|
201
|
+
}
|
|
202
|
+
return toAttrs(observed);
|
|
203
|
+
}),
|
|
204
|
+
delete: Effect.fn(function* ({ output }) {
|
|
205
|
+
yield* webhooks
|
|
206
|
+
.deleteWebhook({ webhookID: output.webhookId })
|
|
207
|
+
.pipe(Effect.catchTag("NotFound", () => Effect.void));
|
|
208
|
+
}),
|
|
209
|
+
list: Effect.fn(function* () {
|
|
210
|
+
const all = yield* webhooks.listWebhooks({});
|
|
211
|
+
return all.filter((hook) => isGeneratedName(hook.name)).map(toAttrs);
|
|
212
|
+
}),
|
|
213
|
+
};
|
|
214
|
+
}),
|
|
215
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
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 * as Redacted from "effect/Redacted";
|
|
5
|
+
import type { E2BError } from "./SandboxClient.ts";
|
|
6
|
+
import type { Secret, SecretAttributes } from "./Secret.ts";
|
|
7
|
+
|
|
8
|
+
/** Rotate one declared secret. */
|
|
9
|
+
export interface WriteSecretClient {
|
|
10
|
+
/** Stores a new version of the secret. Sandboxes resolve it on their next request. */
|
|
11
|
+
put(value: Redacted.Redacted<string>): Effect.Effect<SecretAttributes, E2BError, RuntimeContext>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Rotate a declared {@link Secret} at runtime: a scheduled job refreshing a
|
|
16
|
+
* short-lived token, or a webhook storing a reissued credential. Sandboxes
|
|
17
|
+
* resolve the new version on their next request.
|
|
18
|
+
*
|
|
19
|
+
* A later deploy stores the declared `value` again only when that value
|
|
20
|
+
* changes.
|
|
21
|
+
*
|
|
22
|
+
* ### Rotating a secret
|
|
23
|
+
* **Example:** Store a refreshed token
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const token = yield* E2B.WriteSecret(GitHubToken);
|
|
26
|
+
* // in a scheduled handler:
|
|
27
|
+
* yield* token.put(Redacted.make(fresh));
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @binding
|
|
31
|
+
* @product Secret
|
|
32
|
+
*/
|
|
33
|
+
export interface WriteSecret extends Binding.Service<
|
|
34
|
+
WriteSecret,
|
|
35
|
+
"E2B.WriteSecret",
|
|
36
|
+
(secret: Secret) => Effect.Effect<WriteSecretClient>
|
|
37
|
+
> {}
|
|
38
|
+
|
|
39
|
+
export const WriteSecret = Binding.Service<WriteSecret>("E2B.WriteSecret");
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as secrets from "@distilled.cloud/e2b/secrets";
|
|
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 { type Secret, toSecretAttributes } from "./Secret.ts";
|
|
7
|
+
import { WriteSecret, type WriteSecretClient } from "./WriteSecret.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link WriteSecret}. Works on any host.
|
|
11
|
+
*
|
|
12
|
+
* ### Provide the layer
|
|
13
|
+
* **Example:** On a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Effect.gen(function* () {
|
|
16
|
+
* const token = yield* E2B.WriteSecret(GitHubToken);
|
|
17
|
+
* // ...
|
|
18
|
+
* }).pipe(Effect.provide(E2B.WriteSecretHttp))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @layer
|
|
22
|
+
* @product Secret
|
|
23
|
+
* @provides E2B.WriteSecret
|
|
24
|
+
*/
|
|
25
|
+
export const WriteSecretHttp = Layer.succeed(
|
|
26
|
+
WriteSecret,
|
|
27
|
+
Effect.fn("E2B.WriteSecret")(function* (secret: Secret) {
|
|
28
|
+
const auth = yield* bindE2B;
|
|
29
|
+
const secretId = yield* (secret.secretId as Output.Output<string, never>).asEffect();
|
|
30
|
+
const client: WriteSecretClient = {
|
|
31
|
+
put: Effect.fn("E2B.WriteSecret.put")(function* (value) {
|
|
32
|
+
const id = yield* secretId;
|
|
33
|
+
// Keep the secret's metadata (ownership stamp included) as it is.
|
|
34
|
+
const current = yield* auth.authorize(secrets.getSecret({ secretID: id }));
|
|
35
|
+
const stored = yield* auth.authorize(
|
|
36
|
+
secrets.updateSecret({ secretID: id, value, metadata: current.metadata }),
|
|
37
|
+
);
|
|
38
|
+
return toSecretAttributes(stored);
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
return client;
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
@@ -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 { WriteVolumeClient } from "./VolumeFiles.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Write a {@link Volume}'s files from outside any sandbox: seed inputs before sandboxes start, or clean up after them.
|
|
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 inputs = yield* E2B.WriteVolume(Inputs);
|
|
16
|
+
* // in fetch:
|
|
17
|
+
* yield* inputs.write("/task.json", JSON.stringify(task));
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* @binding
|
|
21
|
+
* @product Volume
|
|
22
|
+
*/
|
|
23
|
+
export interface WriteVolume extends Binding.Service<
|
|
24
|
+
WriteVolume,
|
|
25
|
+
"E2B.WriteVolume",
|
|
26
|
+
(volume: Volume) => Effect.Effect<WriteVolumeClient>
|
|
27
|
+
> {}
|
|
28
|
+
|
|
29
|
+
export const WriteVolume = Binding.Service<WriteVolume>("E2B.WriteVolume");
|
|
@@ -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 type { Volume } from "./Volume.ts";
|
|
7
|
+
import { WriteVolume } from "./WriteVolume.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP implementation of {@link WriteVolume}. Works on any host.
|
|
11
|
+
*
|
|
12
|
+
* ### Provide the layer
|
|
13
|
+
* **Example:** On a Worker
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Effect.gen(function* () {
|
|
16
|
+
* const inputs = yield* E2B.WriteVolume(Inputs);
|
|
17
|
+
* // ...
|
|
18
|
+
* }).pipe(Effect.provide(E2B.WriteVolumeHttp))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @layer
|
|
22
|
+
* @product Volume
|
|
23
|
+
* @provides E2B.WriteVolume
|
|
24
|
+
*/
|
|
25
|
+
export const WriteVolumeHttp = Layer.succeed(
|
|
26
|
+
WriteVolume,
|
|
27
|
+
Effect.fn("E2B.WriteVolume")(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
|
+
);
|
package/src/globals.d.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export * from "./ApiKey.ts";
|
|
2
|
+
export * from "./AuthProvider.ts";
|
|
3
|
+
export * from "./ConnectSandbox.ts";
|
|
4
|
+
export * from "./ConnectSandboxHttp.ts";
|
|
5
|
+
export * from "./CreateSandbox.ts";
|
|
6
|
+
export * from "./CreateSandboxHttp.ts";
|
|
7
|
+
export * from "./CreateSecret.ts";
|
|
8
|
+
export * from "./CreateSecretHttp.ts";
|
|
9
|
+
export * from "./CreateSnapshot.ts";
|
|
10
|
+
export * from "./CreateSnapshotHttp.ts";
|
|
11
|
+
export * from "./CreateTemplate.ts";
|
|
12
|
+
export * from "./CreateTemplateHttp.ts";
|
|
13
|
+
export * from "./CreateVolume.ts";
|
|
14
|
+
export * from "./CreateVolumeHttp.ts";
|
|
15
|
+
export * from "./Credentials.ts";
|
|
16
|
+
export * from "./Errors.ts";
|
|
17
|
+
export * from "./InferEnv.ts";
|
|
18
|
+
export * from "./MountVolume.ts";
|
|
19
|
+
export * from "./MountVolumeLive.ts";
|
|
20
|
+
export * from "./Providers.ts";
|
|
21
|
+
export * from "./ReadTeam.ts";
|
|
22
|
+
export * from "./ReadTeamHttp.ts";
|
|
23
|
+
export * from "./ReadVolume.ts";
|
|
24
|
+
export * from "./ReadWebhook.ts";
|
|
25
|
+
export * from "./ReadWebhookHttp.ts";
|
|
26
|
+
export * from "./ReadVolumeHttp.ts";
|
|
27
|
+
export * from "./ReadWriteVolume.ts";
|
|
28
|
+
export * from "./ReadWriteVolumeHttp.ts";
|
|
29
|
+
export * from "./Sandbox.ts";
|
|
30
|
+
export * from "./SandboxClient.ts";
|
|
31
|
+
export * from "./SandboxEvents.ts";
|
|
32
|
+
export * from "./SandboxEventsLive.ts";
|
|
33
|
+
export * from "./Secret.ts";
|
|
34
|
+
export * from "./Snapshot.ts";
|
|
35
|
+
export * from "./Template.ts";
|
|
36
|
+
export * from "./Volume.ts";
|
|
37
|
+
export * from "./VolumeFiles.ts";
|
|
38
|
+
export * from "./Webhook.ts";
|
|
39
|
+
export * from "./WriteSecret.ts";
|
|
40
|
+
export * from "./WriteSecretHttp.ts";
|
|
41
|
+
export * from "./WriteVolume.ts";
|
|
42
|
+
export * from "./WriteVolumeHttp.ts";
|