@alchemy.run/e2b 0.0.0-stage → 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.
Files changed (284) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +60 -2
  3. package/lib/ApiKey.d.ts +53 -0
  4. package/lib/ApiKey.d.ts.map +1 -0
  5. package/lib/ApiKey.js +107 -0
  6. package/lib/ApiKey.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +60 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +293 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/Bootstrap.d.ts +7 -0
  12. package/lib/Bootstrap.d.ts.map +1 -0
  13. package/lib/Bootstrap.js +25 -0
  14. package/lib/Bootstrap.js.map +1 -0
  15. package/lib/ConnectSandbox.d.ts +67 -0
  16. package/lib/ConnectSandbox.d.ts.map +1 -0
  17. package/lib/ConnectSandbox.js +3 -0
  18. package/lib/ConnectSandbox.js.map +1 -0
  19. package/lib/ConnectSandboxHttp.d.ts +22 -0
  20. package/lib/ConnectSandboxHttp.d.ts.map +1 -0
  21. package/lib/ConnectSandboxHttp.js +30 -0
  22. package/lib/ConnectSandboxHttp.js.map +1 -0
  23. package/lib/Contributions.d.ts +7 -0
  24. package/lib/Contributions.d.ts.map +1 -0
  25. package/lib/Contributions.js +6 -0
  26. package/lib/Contributions.js.map +1 -0
  27. package/lib/CreateSandbox.d.ts +139 -0
  28. package/lib/CreateSandbox.d.ts.map +1 -0
  29. package/lib/CreateSandbox.js +3 -0
  30. package/lib/CreateSandbox.js.map +1 -0
  31. package/lib/CreateSandboxHttp.d.ts +22 -0
  32. package/lib/CreateSandboxHttp.d.ts.map +1 -0
  33. package/lib/CreateSandboxHttp.js +99 -0
  34. package/lib/CreateSandboxHttp.js.map +1 -0
  35. package/lib/CreateSecret.d.ts +57 -0
  36. package/lib/CreateSecret.d.ts.map +1 -0
  37. package/lib/CreateSecret.js +3 -0
  38. package/lib/CreateSecret.js.map +1 -0
  39. package/lib/CreateSecretHttp.d.ts +20 -0
  40. package/lib/CreateSecretHttp.d.ts.map +1 -0
  41. package/lib/CreateSecretHttp.js +64 -0
  42. package/lib/CreateSecretHttp.js.map +1 -0
  43. package/lib/CreateSnapshot.d.ts +53 -0
  44. package/lib/CreateSnapshot.d.ts.map +1 -0
  45. package/lib/CreateSnapshot.js +3 -0
  46. package/lib/CreateSnapshot.js.map +1 -0
  47. package/lib/CreateSnapshotHttp.d.ts +20 -0
  48. package/lib/CreateSnapshotHttp.d.ts.map +1 -0
  49. package/lib/CreateSnapshotHttp.js +41 -0
  50. package/lib/CreateSnapshotHttp.js.map +1 -0
  51. package/lib/CreateTemplate.d.ts +96 -0
  52. package/lib/CreateTemplate.d.ts.map +1 -0
  53. package/lib/CreateTemplate.js +3 -0
  54. package/lib/CreateTemplate.js.map +1 -0
  55. package/lib/CreateTemplateHttp.d.ts +20 -0
  56. package/lib/CreateTemplateHttp.d.ts.map +1 -0
  57. package/lib/CreateTemplateHttp.js +99 -0
  58. package/lib/CreateTemplateHttp.js.map +1 -0
  59. package/lib/CreateVolume.d.ts +58 -0
  60. package/lib/CreateVolume.d.ts.map +1 -0
  61. package/lib/CreateVolume.js +3 -0
  62. package/lib/CreateVolume.js.map +1 -0
  63. package/lib/CreateVolumeHttp.d.ts +20 -0
  64. package/lib/CreateVolumeHttp.d.ts.map +1 -0
  65. package/lib/CreateVolumeHttp.js +51 -0
  66. package/lib/CreateVolumeHttp.js.map +1 -0
  67. package/lib/Credentials.d.ts +18 -0
  68. package/lib/Credentials.d.ts.map +1 -0
  69. package/lib/Credentials.js +55 -0
  70. package/lib/Credentials.js.map +1 -0
  71. package/lib/E2BBindings.d.ts +35 -0
  72. package/lib/E2BBindings.d.ts.map +1 -0
  73. package/lib/E2BBindings.js +127 -0
  74. package/lib/E2BBindings.js.map +1 -0
  75. package/lib/Errors.d.ts +61 -0
  76. package/lib/Errors.d.ts.map +1 -0
  77. package/lib/Errors.js +23 -0
  78. package/lib/Errors.js.map +1 -0
  79. package/lib/InferEnv.d.ts +26 -0
  80. package/lib/InferEnv.d.ts.map +1 -0
  81. package/lib/InferEnv.js +1 -0
  82. package/lib/InferEnv.js.map +1 -0
  83. package/lib/MountVolume.d.ts +86 -0
  84. package/lib/MountVolume.d.ts.map +1 -0
  85. package/lib/MountVolume.js +3 -0
  86. package/lib/MountVolume.js.map +1 -0
  87. package/lib/MountVolumeLive.d.ts +23 -0
  88. package/lib/MountVolumeLive.d.ts.map +1 -0
  89. package/lib/MountVolumeLive.js +41 -0
  90. package/lib/MountVolumeLive.js.map +1 -0
  91. package/lib/Providers.d.ts +14 -0
  92. package/lib/Providers.d.ts.map +1 -0
  93. package/lib/Providers.js +23 -0
  94. package/lib/Providers.js.map +1 -0
  95. package/lib/ReadTeam.d.ts +41 -0
  96. package/lib/ReadTeam.d.ts.map +1 -0
  97. package/lib/ReadTeam.js +3 -0
  98. package/lib/ReadTeam.js.map +1 -0
  99. package/lib/ReadTeamHttp.d.ts +20 -0
  100. package/lib/ReadTeamHttp.d.ts.map +1 -0
  101. package/lib/ReadTeamHttp.js +40 -0
  102. package/lib/ReadTeamHttp.js.map +1 -0
  103. package/lib/ReadVolume.d.ts +25 -0
  104. package/lib/ReadVolume.d.ts.map +1 -0
  105. package/lib/ReadVolume.js +3 -0
  106. package/lib/ReadVolume.js.map +1 -0
  107. package/lib/ReadVolumeHttp.d.ts +20 -0
  108. package/lib/ReadVolumeHttp.d.ts.map +1 -0
  109. package/lib/ReadVolumeHttp.js +27 -0
  110. package/lib/ReadVolumeHttp.js.map +1 -0
  111. package/lib/ReadWebhook.d.ts +32 -0
  112. package/lib/ReadWebhook.d.ts.map +1 -0
  113. package/lib/ReadWebhook.js +3 -0
  114. package/lib/ReadWebhook.js.map +1 -0
  115. package/lib/ReadWebhookHttp.d.ts +20 -0
  116. package/lib/ReadWebhookHttp.d.ts.map +1 -0
  117. package/lib/ReadWebhookHttp.js +31 -0
  118. package/lib/ReadWebhookHttp.js.map +1 -0
  119. package/lib/ReadWriteVolume.d.ts +26 -0
  120. package/lib/ReadWriteVolume.d.ts.map +1 -0
  121. package/lib/ReadWriteVolume.js +3 -0
  122. package/lib/ReadWriteVolume.js.map +1 -0
  123. package/lib/ReadWriteVolumeHttp.d.ts +20 -0
  124. package/lib/ReadWriteVolumeHttp.d.ts.map +1 -0
  125. package/lib/ReadWriteVolumeHttp.js +27 -0
  126. package/lib/ReadWriteVolumeHttp.js.map +1 -0
  127. package/lib/Sandbox.d.ts +295 -0
  128. package/lib/Sandbox.d.ts.map +1 -0
  129. package/lib/Sandbox.js +351 -0
  130. package/lib/Sandbox.js.map +1 -0
  131. package/lib/SandboxClient.d.ts +226 -0
  132. package/lib/SandboxClient.d.ts.map +1 -0
  133. package/lib/SandboxClient.js +1 -0
  134. package/lib/SandboxClient.js.map +1 -0
  135. package/lib/SandboxEvents.d.ts +87 -0
  136. package/lib/SandboxEvents.d.ts.map +1 -0
  137. package/lib/SandboxEvents.js +39 -0
  138. package/lib/SandboxEvents.js.map +1 -0
  139. package/lib/SandboxEventsLive.d.ts +13 -0
  140. package/lib/SandboxEventsLive.d.ts.map +1 -0
  141. package/lib/SandboxEventsLive.js +80 -0
  142. package/lib/SandboxEventsLive.js.map +1 -0
  143. package/lib/Secret.d.ts +105 -0
  144. package/lib/Secret.d.ts.map +1 -0
  145. package/lib/Secret.js +161 -0
  146. package/lib/Secret.js.map +1 -0
  147. package/lib/Snapshot.d.ts +118 -0
  148. package/lib/Snapshot.d.ts.map +1 -0
  149. package/lib/Snapshot.js +158 -0
  150. package/lib/Snapshot.js.map +1 -0
  151. package/lib/Template.d.ts +313 -0
  152. package/lib/Template.d.ts.map +1 -0
  153. package/lib/Template.js +421 -0
  154. package/lib/Template.js.map +1 -0
  155. package/lib/Volume.d.ts +88 -0
  156. package/lib/Volume.d.ts.map +1 -0
  157. package/lib/Volume.js +136 -0
  158. package/lib/Volume.js.map +1 -0
  159. package/lib/VolumeFiles.d.ts +39 -0
  160. package/lib/VolumeFiles.d.ts.map +1 -0
  161. package/lib/VolumeFiles.js +1 -0
  162. package/lib/VolumeFiles.js.map +1 -0
  163. package/lib/Webhook.d.ts +83 -0
  164. package/lib/Webhook.d.ts.map +1 -0
  165. package/lib/Webhook.js +138 -0
  166. package/lib/Webhook.js.map +1 -0
  167. package/lib/WriteSecret.d.ts +34 -0
  168. package/lib/WriteSecret.d.ts.map +1 -0
  169. package/lib/WriteSecret.js +3 -0
  170. package/lib/WriteSecret.js.map +1 -0
  171. package/lib/WriteSecretHttp.d.ts +20 -0
  172. package/lib/WriteSecretHttp.d.ts.map +1 -0
  173. package/lib/WriteSecretHttp.js +37 -0
  174. package/lib/WriteSecretHttp.js.map +1 -0
  175. package/lib/WriteVolume.d.ts +25 -0
  176. package/lib/WriteVolume.d.ts.map +1 -0
  177. package/lib/WriteVolume.js +3 -0
  178. package/lib/WriteVolume.js.map +1 -0
  179. package/lib/WriteVolumeHttp.d.ts +20 -0
  180. package/lib/WriteVolumeHttp.d.ts.map +1 -0
  181. package/lib/WriteVolumeHttp.js +27 -0
  182. package/lib/WriteVolumeHttp.js.map +1 -0
  183. package/lib/index.d.ts +43 -0
  184. package/lib/index.d.ts.map +1 -0
  185. package/lib/index.js +43 -0
  186. package/lib/index.js.map +1 -0
  187. package/lib/internal/Declared.d.ts +29 -0
  188. package/lib/internal/Declared.d.ts.map +1 -0
  189. package/lib/internal/Declared.js +31 -0
  190. package/lib/internal/Declared.js.map +1 -0
  191. package/lib/internal/Login.d.ts +45 -0
  192. package/lib/internal/Login.d.ts.map +1 -0
  193. package/lib/internal/Login.js +157 -0
  194. package/lib/internal/Login.js.map +1 -0
  195. package/lib/internal/Ownership.d.ts +29 -0
  196. package/lib/internal/Ownership.d.ts.map +1 -0
  197. package/lib/internal/Ownership.js +49 -0
  198. package/lib/internal/Ownership.js.map +1 -0
  199. package/lib/internal/Program.d.ts +31 -0
  200. package/lib/internal/Program.d.ts.map +1 -0
  201. package/lib/internal/Program.js +60 -0
  202. package/lib/internal/Program.js.map +1 -0
  203. package/lib/internal/SandboxHandle.d.ts +25 -0
  204. package/lib/internal/SandboxHandle.d.ts.map +1 -0
  205. package/lib/internal/SandboxHandle.js +316 -0
  206. package/lib/internal/SandboxHandle.js.map +1 -0
  207. package/lib/internal/SnapshotBuild.d.ts +19 -0
  208. package/lib/internal/SnapshotBuild.d.ts.map +1 -0
  209. package/lib/internal/SnapshotBuild.js +49 -0
  210. package/lib/internal/SnapshotBuild.js.map +1 -0
  211. package/lib/internal/Tar.d.ts +10 -0
  212. package/lib/internal/Tar.d.ts.map +1 -0
  213. package/lib/internal/Tar.js +61 -0
  214. package/lib/internal/Tar.js.map +1 -0
  215. package/lib/internal/TemplateBuild.d.ts +142 -0
  216. package/lib/internal/TemplateBuild.d.ts.map +1 -0
  217. package/lib/internal/TemplateBuild.js +220 -0
  218. package/lib/internal/TemplateBuild.js.map +1 -0
  219. package/lib/internal/TemplatePlan.d.ts +57 -0
  220. package/lib/internal/TemplatePlan.d.ts.map +1 -0
  221. package/lib/internal/TemplatePlan.js +185 -0
  222. package/lib/internal/TemplatePlan.js.map +1 -0
  223. package/lib/internal/VolumeHttp.d.ts +5 -0
  224. package/lib/internal/VolumeHttp.d.ts.map +1 -0
  225. package/lib/internal/VolumeHttp.js +46 -0
  226. package/lib/internal/VolumeHttp.js.map +1 -0
  227. package/package.json +78 -3
  228. package/src/ApiKey.ts +148 -0
  229. package/src/AuthProvider.ts +437 -0
  230. package/src/Bootstrap.ts +51 -0
  231. package/src/ConnectSandbox.ts +71 -0
  232. package/src/ConnectSandboxHttp.ts +38 -0
  233. package/src/Contributions.ts +9 -0
  234. package/src/CreateSandbox.ts +157 -0
  235. package/src/CreateSandboxHttp.ts +131 -0
  236. package/src/CreateSecret.ts +65 -0
  237. package/src/CreateSecretHttp.ts +94 -0
  238. package/src/CreateSnapshot.ts +64 -0
  239. package/src/CreateSnapshotHttp.ts +55 -0
  240. package/src/CreateTemplate.ts +135 -0
  241. package/src/CreateTemplateHttp.ts +152 -0
  242. package/src/CreateVolume.ts +65 -0
  243. package/src/CreateVolumeHttp.ts +80 -0
  244. package/src/Credentials.ts +81 -0
  245. package/src/E2BBindings.ts +160 -0
  246. package/src/Errors.ts +47 -0
  247. package/src/InferEnv.ts +27 -0
  248. package/src/MountVolume.ts +92 -0
  249. package/src/MountVolumeLive.ts +49 -0
  250. package/src/Providers.ts +48 -0
  251. package/src/ReadTeam.ts +55 -0
  252. package/src/ReadTeamHttp.ts +44 -0
  253. package/src/ReadVolume.ts +29 -0
  254. package/src/ReadVolumeHttp.ts +32 -0
  255. package/src/ReadWebhook.ts +41 -0
  256. package/src/ReadWebhookHttp.ts +42 -0
  257. package/src/ReadWriteVolume.ts +30 -0
  258. package/src/ReadWriteVolumeHttp.ts +32 -0
  259. package/src/Sandbox.ts +581 -0
  260. package/src/SandboxClient.ts +268 -0
  261. package/src/SandboxEvents.ts +101 -0
  262. package/src/SandboxEventsLive.ts +118 -0
  263. package/src/Secret.ts +229 -0
  264. package/src/Snapshot.ts +234 -0
  265. package/src/Template.ts +636 -0
  266. package/src/Volume.ts +173 -0
  267. package/src/VolumeFiles.ts +53 -0
  268. package/src/Webhook.ts +215 -0
  269. package/src/WriteSecret.ts +39 -0
  270. package/src/WriteSecretHttp.ts +43 -0
  271. package/src/WriteVolume.ts +29 -0
  272. package/src/WriteVolumeHttp.ts +32 -0
  273. package/src/globals.d.ts +2 -0
  274. package/src/index.ts +42 -0
  275. package/src/internal/Declared.ts +80 -0
  276. package/src/internal/Login.ts +210 -0
  277. package/src/internal/Ownership.ts +67 -0
  278. package/src/internal/Program.ts +75 -0
  279. package/src/internal/SandboxHandle.ts +534 -0
  280. package/src/internal/SnapshotBuild.ts +74 -0
  281. package/src/internal/Tar.ts +74 -0
  282. package/src/internal/TemplateBuild.ts +383 -0
  283. package/src/internal/TemplatePlan.ts +230 -0
  284. package/src/internal/VolumeHttp.ts +88 -0
@@ -0,0 +1,87 @@
1
+ import * as Context from "effect/Context";
2
+ import type * as Effect from "effect/Effect";
3
+ import type * as Redacted from "effect/Redacted";
4
+ import type { SandboxEventType } from "./Webhook.ts";
5
+ /** A sandbox lifecycle event, as E2B delivers it to a webhook. */
6
+ export interface SandboxEvent {
7
+ /** The event's id. A redelivered event keeps it: deduplicate on it. */
8
+ readonly id: string;
9
+ readonly version: string;
10
+ readonly type: SandboxEventType;
11
+ readonly timestamp: string;
12
+ readonly sandbox_id: string;
13
+ readonly sandbox_execution_id: string;
14
+ readonly sandbox_template_id: string;
15
+ readonly sandbox_build_id: string;
16
+ readonly sandbox_team_id: string;
17
+ readonly event_data?: {
18
+ /** The sandbox's metadata, including the ownership stamp of the host that created it. */
19
+ readonly sandbox_metadata?: Readonly<Record<string, string>>;
20
+ /** On `killed` and `paused`: what the run used. */
21
+ readonly execution?: Readonly<Record<string, unknown>>;
22
+ /** On `killed`. */
23
+ readonly kill_reason?: string;
24
+ /** On `paused`: `full` (memory and disk) or `filesystem`. */
25
+ readonly pause_mode?: "full" | "filesystem";
26
+ /** On `resumed`: `restore` (memory) or `reboot`. */
27
+ readonly resume_mode?: "restore" | "reboot";
28
+ };
29
+ }
30
+ export interface SandboxEventsProps {
31
+ /**
32
+ * The events to receive.
33
+ * @default every sandbox lifecycle event
34
+ */
35
+ readonly events?: ReadonlyArray<SandboxEventType>;
36
+ /**
37
+ * The secret E2B signs deliveries with. A random one is generated and
38
+ * bound onto the host when omitted.
39
+ */
40
+ readonly secret?: Redacted.Redacted<string>;
41
+ /**
42
+ * The path on the host E2B delivers to.
43
+ * @default "/__alchemy/e2b/events"
44
+ */
45
+ readonly path?: string;
46
+ }
47
+ /** Receives sandbox lifecycle events on a host. */
48
+ export type SandboxEventsService = <Req = never>(props: SandboxEventsProps, process: (event: SandboxEvent) => Effect.Effect<void, never, Req>) => Effect.Effect<void, never, never>;
49
+ declare const SandboxEvents_base: Context.ServiceClass<SandboxEvents, "E2B.SandboxEvents", SandboxEventsService>;
50
+ /**
51
+ * Receive E2B sandbox lifecycle events (created, paused, resumed,
52
+ * checkpointed, updated, killed) in a Worker or any other webhook host.
53
+ *
54
+ * At deploy, an {@link Webhook} is created pointing at the host. At runtime,
55
+ * each delivery's `e2b-signature` is verified before the handler runs; an
56
+ * unsigned or wrongly signed request is rejected with 401. E2B retries a
57
+ * failed delivery up to three times, so handlers should be idempotent on
58
+ * `event.id`.
59
+ *
60
+ * ### Handling lifecycle events
61
+ * **Example:** Record every killed sandbox
62
+ * ```typescript
63
+ * export default class Api extends Cloudflare.Worker<Api>()(
64
+ * "Api",
65
+ * { main: import.meta.url },
66
+ * Effect.gen(function* () {
67
+ * yield* E2B.consumeSandboxEvents({ events: ["sandbox.lifecycle.killed"] }, (event) =>
68
+ * Effect.log(`sandbox ${event.sandbox_id} killed: ${event.event_data?.kill_reason}`),
69
+ * );
70
+ * return { fetch: Effect.succeed(HttpServerResponse.text("ok")) };
71
+ * }).pipe(Effect.provide(E2B.SandboxEventsLive)),
72
+ * ) {}
73
+ * ```
74
+ *
75
+ * @binding
76
+ * @product Webhook
77
+ */
78
+ export declare class SandboxEvents extends SandboxEvents_base {
79
+ }
80
+ /** Subscribes the current host to sandbox lifecycle events. */
81
+ export declare const consumeSandboxEvents: <Req = never>(props: SandboxEventsProps, process: (event: SandboxEvent) => Effect.Effect<void, never, Req>) => Effect.Effect<void, never, SandboxEvents>;
82
+ /** Where E2B delivers on the host. */
83
+ export declare const sandboxEventsPath: (props: SandboxEventsProps) => string;
84
+ /** The env var the signing secret is bound under. */
85
+ export declare const sandboxEventsSecretEnvName: (path: string) => string;
86
+ export {};
87
+ //# sourceMappingURL=SandboxEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEvents.d.ts","sources":["../src/SandboxEvents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,kEAAkE;AAClE,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE;QACpB,yFAAyF;QACzF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7D,mDAAmD;QACnD,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACvD,mBAAmB;QACnB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,6DAA6D;QAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;QAC5C,oDAAoD;QACpD,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;KAC7C,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,mDAAmD;AACnD,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,GAAG,KAAK,EAC7C,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,KAC9D,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,aAAc,SAAQ,kBAElC;CAAG;AAEJ,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG,KAAK,SACvC,kBAAkB,WAChB,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,8CACT,CAAC;AAE3D,sCAAsC;AACtC,eAAO,MAAM,iBAAiB,UAAW,kBAAkB,KAAG,MACvB,CAAC;AAExC,qDAAqD;AACrD,eAAO,MAAM,0BAA0B,SAAU,MAAM,KAAG,MACP,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { sanitizeKey } from "alchemy/RuntimeContext";
2
+ import * as Context from "effect/Context";
3
+ /**
4
+ * Receive E2B sandbox lifecycle events (created, paused, resumed,
5
+ * checkpointed, updated, killed) in a Worker or any other webhook host.
6
+ *
7
+ * At deploy, an {@link Webhook} is created pointing at the host. At runtime,
8
+ * each delivery's `e2b-signature` is verified before the handler runs; an
9
+ * unsigned or wrongly signed request is rejected with 401. E2B retries a
10
+ * failed delivery up to three times, so handlers should be idempotent on
11
+ * `event.id`.
12
+ *
13
+ * ### Handling lifecycle events
14
+ * **Example:** Record every killed sandbox
15
+ * ```typescript
16
+ * export default class Api extends Cloudflare.Worker<Api>()(
17
+ * "Api",
18
+ * { main: import.meta.url },
19
+ * Effect.gen(function* () {
20
+ * yield* E2B.consumeSandboxEvents({ events: ["sandbox.lifecycle.killed"] }, (event) =>
21
+ * Effect.log(`sandbox ${event.sandbox_id} killed: ${event.event_data?.kill_reason}`),
22
+ * );
23
+ * return { fetch: Effect.succeed(HttpServerResponse.text("ok")) };
24
+ * }).pipe(Effect.provide(E2B.SandboxEventsLive)),
25
+ * ) {}
26
+ * ```
27
+ *
28
+ * @binding
29
+ * @product Webhook
30
+ */
31
+ export class SandboxEvents extends Context.Service()("E2B.SandboxEvents") {
32
+ }
33
+ /** Subscribes the current host to sandbox lifecycle events. */
34
+ export const consumeSandboxEvents = (props, process) => SandboxEvents.use((source) => source(props, process));
35
+ /** Where E2B delivers on the host. */
36
+ export const sandboxEventsPath = (props) => props.path ?? "/__alchemy/e2b/events";
37
+ /** The env var the signing secret is bound under. */
38
+ export const sandboxEventsSecretEnvName = (path) => `ALCHEMY_E2B_WEBHOOK_SECRET_${sanitizeKey(path)}`;
39
+ //# sourceMappingURL=SandboxEvents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEvents.js","sources":["../src/SandboxEvents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAuD1C;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,aAAc,SAAQ,OAAO,CAAC,OAAO,EAAuC,CACvF,mBAAmB,CACpB;CAAG;AAEJ,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,KAAyB,EACzB,OAAiE,EACjE,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAE3D,sCAAsC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAyB,EAAU,EAAE,CACrE,KAAK,CAAC,IAAI,IAAI,uBAAuB,CAAC;AAExC,qDAAqD;AACrD,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,IAAY,EAAU,EAAE,CACjE,8BAA8B,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { WebhookHost } from "alchemy/WebhookHost";
2
+ import * as Layer from "effect/Layer";
3
+ import { SandboxEvents } from "./SandboxEvents.ts";
4
+ /**
5
+ * {@link SandboxEvents} on any {@link WebhookHost}: every Cloudflare Worker
6
+ * is one.
7
+ *
8
+ * @layer
9
+ * @product Webhook
10
+ * @provides E2B.SandboxEvents
11
+ */
12
+ export declare const SandboxEventsLive: Layer.Layer<SandboxEvents, never, WebhookHost>;
13
+ //# sourceMappingURL=SandboxEventsLive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEventsLive.d.ts","sources":["../src/SandboxEventsLive.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAEL,aAAa,EAKd,MAAM,oBAAoB,CAAC;AAG5B;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,gDAuC7B,CAAC"}
@@ -0,0 +1,80 @@
1
+ import * as Namespace from "alchemy/Namespace";
2
+ import * as Output from "alchemy/Output";
3
+ import { Random } from "alchemy/Random";
4
+ import { WebhookHost } from "alchemy/WebhookHost";
5
+ import * as Effect from "effect/Effect";
6
+ import * as Layer from "effect/Layer";
7
+ import * as Redacted from "effect/Redacted";
8
+ import { SandboxEvents, sandboxEventsPath, sandboxEventsSecretEnvName, } from "./SandboxEvents.js";
9
+ import { ALL_SANDBOX_EVENTS, Webhook } from "./Webhook.js";
10
+ /**
11
+ * {@link SandboxEvents} on any {@link WebhookHost}: every Cloudflare Worker
12
+ * is one.
13
+ *
14
+ * @layer
15
+ * @product Webhook
16
+ * @provides E2B.SandboxEvents
17
+ */
18
+ export const SandboxEventsLive = Layer.effect(SandboxEvents, Effect.gen(function* () {
19
+ const host = yield* WebhookHost;
20
+ // Yielding the resource class erases its `Providers` requirement; the
21
+ // stack satisfies it at plan time.
22
+ const createWebhook = yield* Webhook;
23
+ return Effect.fn(function* (props, process) {
24
+ const path = sandboxEventsPath(props);
25
+ const secret = props.secret ??
26
+ (yield* Namespace.push(host.LogicalId, Random(`E2BEventsSecret${path}`))).text;
27
+ if (!globalThis.__ALCHEMY_RUNTIME__) {
28
+ yield* Namespace.push(host.LogicalId, Effect.asVoid(createWebhook(`E2BEvents${path}`, {
29
+ url: Output.interpolate `${host.url}${path}`,
30
+ events: [...(props.events ?? ALL_SANDBOX_EVENTS)],
31
+ signatureSecret: secret,
32
+ })));
33
+ }
34
+ // Registers the secret on the host at deploy, reads it back at runtime.
35
+ const boundSecret = yield* Output.named(Output.asOutput(secret), sandboxEventsSecretEnvName(path)).asEffect();
36
+ yield* host.route(path, (request) => handleDelivery(request, boundSecret, process));
37
+ });
38
+ }));
39
+ const handleDelivery = (request, secret, process) => Effect.gen(function* () {
40
+ if (request.method !== "POST")
41
+ return new Response("method not allowed", { status: 405 });
42
+ const body = yield* Effect.tryPromise(() => request.text()).pipe(Effect.option);
43
+ if (body._tag === "None")
44
+ return new Response("unreadable body", { status: 400 });
45
+ const resolved = yield* secret;
46
+ const valid = yield* verifySignature(resolved === undefined ? undefined : Redacted.value(resolved), body.value, request.headers.get("e2b-signature") ?? undefined);
47
+ if (!valid)
48
+ return new Response("invalid signature", { status: 401 });
49
+ const event = yield* Effect.try(() => JSON.parse(body.value)).pipe(Effect.orElseSucceed(() => undefined));
50
+ if (event === undefined)
51
+ return new Response("invalid payload", { status: 400 });
52
+ yield* process(event);
53
+ return new Response(null, { status: 202 });
54
+ });
55
+ /**
56
+ * E2B's signature: the unpadded base64 SHA-256 of the secret followed by the
57
+ * raw body (a plain hash, not an HMAC).
58
+ */
59
+ const verifySignature = (secret, body, signature) => Effect.gen(function* () {
60
+ if (!secret || !signature)
61
+ return false;
62
+ const digest = yield* Effect.tryPromise(() => crypto.subtle.digest("SHA-256", new TextEncoder().encode(secret + body))).pipe(Effect.option);
63
+ if (digest._tag === "None")
64
+ return false;
65
+ let binary = "";
66
+ for (const byte of new Uint8Array(digest.value))
67
+ binary += String.fromCharCode(byte);
68
+ const expected = btoa(binary).replace(/=+$/, "");
69
+ return timingSafeEqual(expected, signature);
70
+ });
71
+ /** Constant-time comparison; `crypto.timingSafeEqual` needs `nodejs_compat` on Workers. */
72
+ const timingSafeEqual = (a, b) => {
73
+ if (a.length !== b.length)
74
+ return false;
75
+ let mismatch = 0;
76
+ for (let i = 0; i < a.length; i++)
77
+ mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
78
+ return mismatch === 0;
79
+ };
80
+ //# sourceMappingURL=SandboxEventsLive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SandboxEventsLive.js","sources":["../src/SandboxEventsLive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,105 @@
1
+ import * as secrets from "@distilled.cloud/e2b/secrets";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ import * as Redacted from "effect/Redacted";
6
+ import type { Providers } from "./Providers.ts";
7
+ export interface SecretProps {
8
+ /**
9
+ * Secret name, unique within the team. E2B lowercases it. If omitted, a
10
+ * unique name is generated from the stack, stage and logical ID. Changing
11
+ * it replaces the secret.
12
+ */
13
+ name?: string;
14
+ /**
15
+ * The secret value. Write-only: E2B never returns it. Changing it stores a
16
+ * new version, which every sandbox resolves on its next request.
17
+ */
18
+ value: Redacted.Redacted<string>;
19
+ /** Your own metadata (at most 32 entries). */
20
+ metadata?: Record<string, string>;
21
+ }
22
+ export interface SecretAttributes {
23
+ /** E2B's secret id (`sec_…`). */
24
+ secretId: string;
25
+ /** The secret's canonical (lowercased) name. */
26
+ name: string;
27
+ /** The version sandboxes resolve. */
28
+ version: number;
29
+ /** Your metadata, without Alchemy's ownership stamp. */
30
+ metadata: Record<string, string>;
31
+ /**
32
+ * The placeholder E2B resolves to the secret's value at sandbox egress:
33
+ * `${e2b.secrets.<name>}`. Put it in a sandbox's network header rules; the
34
+ * value itself never enters the sandbox.
35
+ */
36
+ ref: string;
37
+ }
38
+ export interface Secret extends Resource<"E2B.Secret", SecretProps, SecretAttributes, never, Providers, {
39
+ name: string;
40
+ }> {
41
+ }
42
+ /**
43
+ * An E2B secret: a write-only value that E2B injects into a sandbox's
44
+ * outbound requests, so code inside the sandbox never sees it.
45
+ *
46
+ * Reference a secret in a sandbox's network rules with its `ref`
47
+ * placeholder (`${e2b.secrets.<name>}`). E2B resolves the placeholder at
48
+ * egress, on the host, for requests to the domains you list.
49
+ *
50
+ * Alchemy stamps its stack, stage and logical ID into the secret's
51
+ * metadata to recognise the secrets it owns.
52
+ *
53
+ * ### Creating a Secret
54
+ * **Example:** A GitHub token from the stage's config
55
+ * ```typescript
56
+ * export const GitHubToken = E2B.Secret("GitHubToken", {
57
+ * value: Config.Redacted("GITHUB_TOKEN"),
58
+ * });
59
+ * ```
60
+ *
61
+ * ### Injecting a Secret at egress
62
+ * **Example:** Authenticate GitHub API calls from inside a sandbox
63
+ * ```typescript
64
+ * const github = yield* GitHubToken;
65
+ * const sandbox = yield* sandboxes.create({
66
+ * network: {
67
+ * allowOut: ["api.github.com"],
68
+ * rules: {
69
+ * "api.github.com": [{ transform: { headers: { Authorization: `Bearer ${github.ref}` } } }],
70
+ * },
71
+ * },
72
+ * });
73
+ * ```
74
+ *
75
+ * ### Rotating a Secret
76
+ * Changing `value` stores a new version in place. Sandboxes resolve the new
77
+ * version on their next request.
78
+ *
79
+ * **Example:** Rotate at runtime with `WriteSecret`
80
+ * ```typescript
81
+ * const token = yield* E2B.WriteSecret(GitHubToken);
82
+ * yield* token.put(Redacted.make(freshToken));
83
+ * ```
84
+ *
85
+ * ### Referencing a secret the stack doesn't manage
86
+ * `E2B.Secret.lookup` finds an existing secret by name. Nothing is created,
87
+ * adopted or deleted.
88
+ *
89
+ * **Example:** Look one up by name
90
+ * ```typescript
91
+ * const github = E2B.Secret.lookup({ name: "github-token" });
92
+ * const token = yield* E2B.WriteSecret(github);
93
+ * ```
94
+ *
95
+ * @resource
96
+ * @product Secret
97
+ */
98
+ export declare const Secret: import("alchemy/Resource").ResourceClass<Secret>;
99
+ /** E2B's egress placeholder for a secret name. */
100
+ export declare const secretRef: (name: string) => string;
101
+ export declare const toSecretAttributes: (secret: secrets.Secret) => SecretAttributes;
102
+ /** A secret by id or canonical name (E2B accepts either). */
103
+ export declare const observeSecret: (idOrName: string) => Effect.Effect<secrets.Secret | undefined, import("@distilled.cloud/e2b").BadRequest | import("@distilled.cloud/e2b").ConfigError | import("@distilled.cloud/e2b").Conflict | import("@distilled.cloud/e2b").Forbidden | import("effect/http/HttpClientError").HttpClientError | import("@distilled.cloud/core/protocol-http").InvalidInput | import("@distilled.cloud/e2b").Locked | import("@distilled.cloud/core/sdk-error").SdkError | import("@distilled.cloud/e2b").UnprocessableEntity | import("@distilled.cloud/e2b").ClientErrors | import("@distilled.cloud/core/errors").DefaultErrors, secrets.E2BOpContext>;
104
+ export declare const SecretProvider: () => import("effect/Layer").Layer<Provider.Provider<Secret>, never, import("alchemy/Stack").Stack | import("alchemy/Stage").Stage | secrets.E2BOpContext>;
105
+ //# sourceMappingURL=Secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secret.d.ts","sources":["../src/Secret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAGxD,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAU5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,MAAO,SAAQ,QAAQ,CACtC,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,SAAS,EACT;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CACjB;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,eAAO,MAAM,MAAM,kDAAiC,CAAC;AAErD,kDAAkD;AAClD,eAAO,MAAM,SAAS,SAAU,MAAM,KAAG,MAAmC,CAAC;AAE7E,eAAO,MAAM,kBAAkB,WAAY,OAAO,CAAC,MAAM,KAAG,gBAM1D,CAAC;AAEH,6DAA6D;AAC7D,eAAO,MAAM,aAAa,aAAc,MAAM,6lBAI3C,CAAC;AAQJ,eAAO,MAAM,cAAc,4JAsFxB,CAAC"}
package/lib/Secret.js ADDED
@@ -0,0 +1,161 @@
1
+ import * as secrets from "@distilled.cloud/e2b/secrets";
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 * as Redacted from "effect/Redacted";
8
+ import * as Stream from "effect/Stream";
9
+ import { E2BUnexpectedResponse } from "./Errors.js";
10
+ import { e2bName, hasAnyAlchemyMetadata, hasOwnershipMetadata, ownershipMetadata, userMetadata, } from "./internal/Ownership.js";
11
+ /**
12
+ * An E2B secret: a write-only value that E2B injects into a sandbox's
13
+ * outbound requests, so code inside the sandbox never sees it.
14
+ *
15
+ * Reference a secret in a sandbox's network rules with its `ref`
16
+ * placeholder (`${e2b.secrets.<name>}`). E2B resolves the placeholder at
17
+ * egress, on the host, for requests to the domains you list.
18
+ *
19
+ * Alchemy stamps its stack, stage and logical ID into the secret's
20
+ * metadata to recognise the secrets it owns.
21
+ *
22
+ * ### Creating a Secret
23
+ * **Example:** A GitHub token from the stage's config
24
+ * ```typescript
25
+ * export const GitHubToken = E2B.Secret("GitHubToken", {
26
+ * value: Config.Redacted("GITHUB_TOKEN"),
27
+ * });
28
+ * ```
29
+ *
30
+ * ### Injecting a Secret at egress
31
+ * **Example:** Authenticate GitHub API calls from inside a sandbox
32
+ * ```typescript
33
+ * const github = yield* GitHubToken;
34
+ * const sandbox = yield* sandboxes.create({
35
+ * network: {
36
+ * allowOut: ["api.github.com"],
37
+ * rules: {
38
+ * "api.github.com": [{ transform: { headers: { Authorization: `Bearer ${github.ref}` } } }],
39
+ * },
40
+ * },
41
+ * });
42
+ * ```
43
+ *
44
+ * ### Rotating a Secret
45
+ * Changing `value` stores a new version in place. Sandboxes resolve the new
46
+ * version on their next request.
47
+ *
48
+ * **Example:** Rotate at runtime with `WriteSecret`
49
+ * ```typescript
50
+ * const token = yield* E2B.WriteSecret(GitHubToken);
51
+ * yield* token.put(Redacted.make(freshToken));
52
+ * ```
53
+ *
54
+ * ### Referencing a secret the stack doesn't manage
55
+ * `E2B.Secret.lookup` finds an existing secret by name. Nothing is created,
56
+ * adopted or deleted.
57
+ *
58
+ * **Example:** Look one up by name
59
+ * ```typescript
60
+ * const github = E2B.Secret.lookup({ name: "github-token" });
61
+ * const token = yield* E2B.WriteSecret(github);
62
+ * ```
63
+ *
64
+ * @resource
65
+ * @product Secret
66
+ */
67
+ export const Secret = Resource("E2B.Secret");
68
+ /** E2B's egress placeholder for a secret name. */
69
+ export const secretRef = (name) => `\${e2b.secrets.${name}}`;
70
+ export const toSecretAttributes = (secret) => ({
71
+ secretId: secret.secretID,
72
+ name: secret.name,
73
+ version: secret.currentVersion,
74
+ metadata: userMetadata(secret.metadata),
75
+ ref: secretRef(secret.name),
76
+ });
77
+ /** A secret by id or canonical name (E2B accepts either). */
78
+ export const observeSecret = (idOrName) => secrets.getSecret({ secretID: idOrName }).pipe(Effect.map((secret) => secret), Effect.catchTag("NotFound", () => Effect.undefined));
79
+ const sameMetadata = (a, b) => {
80
+ const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
81
+ for (const key of keys)
82
+ if (a[key] !== b[key])
83
+ return false;
84
+ return true;
85
+ };
86
+ export const SecretProvider = () => Provider.effect(Secret, Effect.gen(function* () {
87
+ return {
88
+ stables: ["secretId", "name", "ref"],
89
+ diff: Effect.fn(function* ({ id, olds, news, output }) {
90
+ if (!isResolved(news))
91
+ return undefined;
92
+ if (news.name === undefined && olds?.name === undefined)
93
+ return undefined;
94
+ const name = output?.name ?? (yield* e2bName(id, olds?.name));
95
+ if (news.name?.toLowerCase() !== name)
96
+ return { action: "replace" };
97
+ return undefined;
98
+ }),
99
+ lookup: Effect.fn(function* ({ name }) {
100
+ const secret = yield* observeSecret(name.toLowerCase());
101
+ return secret === undefined ? undefined : toSecretAttributes(secret);
102
+ }),
103
+ read: Effect.fn(function* ({ id, olds, output }) {
104
+ const name = output?.name ?? (yield* e2bName(id, olds?.name));
105
+ const secret = yield* observeSecret(output?.secretId ?? name);
106
+ if (secret === undefined)
107
+ return undefined;
108
+ const attrs = toSecretAttributes(secret);
109
+ const ours = output !== undefined ||
110
+ (yield* hasOwnershipMetadata(id, secret.metadata));
111
+ return ours ? attrs : Unowned(attrs);
112
+ }),
113
+ reconcile: Effect.fn(function* ({ id, news, olds, output, session }) {
114
+ const name = output?.name ?? (yield* e2bName(id, news.name)).toLowerCase();
115
+ const metadata = { ...news.metadata, ...(yield* ownershipMetadata(id)) };
116
+ // Observe
117
+ let secret = yield* observeSecret(output?.secretId ?? name);
118
+ // Ensure — a Conflict is a peer creating the same name: read it back
119
+ // and fall through to the sync, which writes our value.
120
+ if (secret === undefined) {
121
+ yield* session.note(`Creating secret ${name}...`);
122
+ const created = yield* secrets.createSecret({ name, value: news.value, metadata }).pipe(Effect.map((s) => s), Effect.catchTag("Conflict", () => Effect.undefined));
123
+ if (created !== undefined)
124
+ return toSecretAttributes(created);
125
+ secret = yield* observeSecret(name);
126
+ if (secret === undefined) {
127
+ return yield* new E2BUnexpectedResponse({
128
+ message: `E2B secret ${name} vanished after create`,
129
+ });
130
+ }
131
+ // A secret someone else created under this name: write our value.
132
+ olds = undefined;
133
+ }
134
+ // Sync — values are write-only, so `olds` is the only signal that the
135
+ // stored value already matches. Without it (adoption, a lost write),
136
+ // store ours. Metadata is observed.
137
+ const valueChanged = olds === undefined || Redacted.value(olds.value) !== Redacted.value(news.value);
138
+ const metadataChanged = !sameMetadata(metadata, secret.metadata);
139
+ if (valueChanged || metadataChanged) {
140
+ secret = yield* secrets.updateSecret({
141
+ secretID: secret.secretID,
142
+ value: news.value,
143
+ metadata,
144
+ });
145
+ }
146
+ return toSecretAttributes(secret);
147
+ }),
148
+ delete: Effect.fn(function* ({ output }) {
149
+ yield* secrets
150
+ .deleteSecret({ secretID: output.secretId })
151
+ .pipe(Effect.catchTag("NotFound", () => Effect.void));
152
+ }),
153
+ list: Effect.fn(function* () {
154
+ const all = Array.from(yield* Stream.runCollect(secrets.listSecrets.items({ limit: 100 })));
155
+ return all
156
+ .filter((secret) => hasAnyAlchemyMetadata(secret.metadata))
157
+ .map(toSecretAttributes);
158
+ }),
159
+ };
160
+ }));
161
+ //# sourceMappingURL=Secret.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Secret.js","sources":["../src/Secret.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ import * as templates from "@distilled.cloud/e2b/templates";
2
+ import * as Provider from "alchemy/Provider";
3
+ import { Resource } from "alchemy/Resource";
4
+ import * as Effect from "effect/Effect";
5
+ import type { Providers } from "./Providers.ts";
6
+ import type { SandboxTemplate } from "./Sandbox.ts";
7
+ export interface SnapshotProps {
8
+ /**
9
+ * The `E2B.Template` (or `E2B.Snapshot`) the snapshot starts from.
10
+ * Rebuilding it takes the snapshot again.
11
+ */
12
+ template: SandboxTemplate;
13
+ /**
14
+ * Shell commands run in order (`bash -l -c`) before the snapshot is taken:
15
+ * clone a repository, install dependencies, warm a cache. A non-zero exit
16
+ * fails the deploy with `SnapshotSetupFailed`.
17
+ */
18
+ run: string[];
19
+ /** Environment variables for the setup commands. */
20
+ envs?: Record<string, string>;
21
+ /** Working directory for the setup commands. @default the sandbox user's home */
22
+ cwd?: string;
23
+ /**
24
+ * Capture memory as well as the filesystem, so sandboxes resume with the
25
+ * setup's processes still running. `false` captures the filesystem only
26
+ * and sandboxes cold-boot from it.
27
+ * @default true
28
+ */
29
+ memory?: boolean;
30
+ /**
31
+ * Snapshot name. If omitted, a unique name is generated from the stack,
32
+ * stage and logical ID. Changing it replaces the snapshot.
33
+ */
34
+ name?: string;
35
+ /**
36
+ * How long the setup sandbox may run, in seconds.
37
+ * @default 900
38
+ */
39
+ timeout?: number;
40
+ }
41
+ export interface SnapshotAttributes {
42
+ /** The id sandboxes are created from, e.g. `my-team/my-snapshot:default`. */
43
+ snapshotId: string;
44
+ /** The snapshot's name. */
45
+ name: string;
46
+ /** E2B's template id for the snapshot (a snapshot is stored as a template). */
47
+ templateId: string;
48
+ /** Every name the snapshot answers to. */
49
+ names: string[];
50
+ /** Content hash of the base and setup. A deploy re-snapshots only when it changes. */
51
+ setupHash: string;
52
+ }
53
+ export interface Snapshot extends Resource<"E2B.Snapshot", SnapshotProps, SnapshotAttributes, never, Providers, {
54
+ name: string;
55
+ }> {
56
+ }
57
+ /**
58
+ * A warm base to fork sandboxes from: a template booted, set up with your
59
+ * commands, and snapshotted — memory included, so sandboxes created from it
60
+ * start exactly where the setup left off.
61
+ *
62
+ * Use a snapshot for work that is too slow to repeat per sandbox and does
63
+ * not belong in an image: cloning a repository, installing its
64
+ * dependencies, starting a language server. A deploy re-runs the setup only
65
+ * when the template or the commands change. E2B stores a snapshot as a
66
+ * template, so it is created from with `E2B.CreateSandbox(snapshot)` and
67
+ * deleted with its template.
68
+ *
69
+ * ### Creating a Snapshot
70
+ * **Example:** A repository with its dependencies installed
71
+ * ```typescript
72
+ * export const Agent = E2B.Template("Agent", { image: "node:22-bookworm" });
73
+ *
74
+ * export const Warm = E2B.Snapshot("Warm", {
75
+ * template: Agent,
76
+ * run: [
77
+ * "git clone https://github.com/alchemy-run/alchemy /home/user/alchemy",
78
+ * "cd /home/user/alchemy && pnpm install",
79
+ * ],
80
+ * });
81
+ * ```
82
+ *
83
+ * ### Forking sandboxes from a Snapshot
84
+ * **Example:** Every sandbox starts from the warm base
85
+ * ```typescript
86
+ * const sandboxes = yield* E2B.CreateSandbox(Warm);
87
+ * const sandbox = yield* sandboxes.create({ timeout: 600 });
88
+ * yield* sandbox.exec("cd alchemy && pnpm test");
89
+ * ```
90
+ *
91
+ * ### Referencing a snapshot the stack doesn't manage
92
+ * `E2B.Snapshot.lookup` finds an existing snapshot by name. Nothing is created,
93
+ * adopted or deleted.
94
+ *
95
+ * **Example:** Look one up by name
96
+ * ```typescript
97
+ * const warm = E2B.Snapshot.lookup({ name: "warm-repo" });
98
+ * const sandboxes = yield* E2B.CreateSandbox(warm);
99
+ * ```
100
+ *
101
+ * @resource
102
+ * @product Snapshot
103
+ */
104
+ export declare const Snapshot: import("alchemy/Resource").ResourceConstructor<Snapshot, Providers> & Effect.Effect<import("alchemy/Resource").ResourceConstructor<Snapshot, never>, never, never> & {
105
+ Self: import("alchemy/Self").Self<Snapshot>;
106
+ Provider: Provider.Provider<Snapshot>;
107
+ Aliases: readonly string[] | undefined;
108
+ ref(id: string, options?: {
109
+ stage?: string;
110
+ stack?: string;
111
+ }): Effect.Effect<Snapshot, never, never>;
112
+ } & {
113
+ lookup(props: {
114
+ name: import("alchemy/Input").Input<string>;
115
+ }): Snapshot;
116
+ } & ((id: string, props: import("./internal/Declared.ts").DeclaredProps<SnapshotProps>) => Effect.Effect<Snapshot, never, Providers>);
117
+ export declare const SnapshotProvider: () => import("effect/Layer").Layer<Provider.Provider<Snapshot>, never, import("alchemy/Stack").Stack | import("alchemy/Stage").Stage | templates.E2BOpContext>;
118
+ //# sourceMappingURL=Snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Snapshot.d.ts","sources":["../src/Snapshot.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,SAAS,MAAM,gCAAgC,CAAC;AAG5D,OAAO,KAAK,QAAQ,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAKxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,EAAE,eAAe,CAAC;IAC1B;;;;OAIG;IACH,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,QAAS,SAAQ,QAAQ,CACxC,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,KAAK,EACL,SAAS,EACT;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CACjB;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;qIAA6D,CAAC;AAyBnF,eAAO,MAAM,gBAAgB,gKA0F1B,CAAC"}