@alchemy.run/archil 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 +57 -4
- package/lib/AWS/S3Disk.d.ts +68 -0
- package/lib/AWS/S3Disk.d.ts.map +1 -0
- package/lib/AWS/S3Disk.js +100 -0
- package/lib/AWS/S3Disk.js.map +1 -0
- package/lib/AWS/index.d.ts +2 -0
- package/lib/AWS/index.d.ts.map +1 -0
- package/lib/AWS/index.js +2 -0
- package/lib/AWS/index.js.map +1 -0
- package/lib/ApiToken.d.ts +63 -0
- package/lib/ApiToken.d.ts.map +1 -0
- package/lib/ApiToken.js +121 -0
- package/lib/ApiToken.js.map +1 -0
- package/lib/ArchilBindings.d.ts +65 -0
- package/lib/ArchilBindings.d.ts.map +1 -0
- package/lib/ArchilBindings.js +128 -0
- package/lib/ArchilBindings.js.map +1 -0
- package/lib/AuthProvider.d.ts +40 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +87 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/Bootstrap.d.ts +8 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +27 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/Branch.d.ts +101 -0
- package/lib/Branch.d.ts.map +1 -0
- package/lib/Branch.js +117 -0
- package/lib/Branch.js.map +1 -0
- package/lib/BranchDisk.d.ts +42 -0
- package/lib/BranchDisk.d.ts.map +1 -0
- package/lib/BranchDisk.js +14 -0
- package/lib/BranchDisk.js.map +1 -0
- package/lib/Checkpoint.d.ts +78 -0
- package/lib/Checkpoint.d.ts.map +1 -0
- package/lib/Checkpoint.js +95 -0
- package/lib/Checkpoint.js.map +1 -0
- package/lib/Clients.d.ts +369 -0
- package/lib/Clients.d.ts.map +1 -0
- package/lib/Clients.js +334 -0
- package/lib/Clients.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +69 -0
- package/lib/ConnectSandbox.d.ts.map +1 -0
- package/lib/ConnectSandbox.js +21 -0
- package/lib/ConnectSandbox.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/CreateDisk.d.ts +90 -0
- package/lib/CreateDisk.d.ts.map +1 -0
- package/lib/CreateDisk.js +47 -0
- package/lib/CreateDisk.js.map +1 -0
- package/lib/CreateImage.d.ts +42 -0
- package/lib/CreateImage.d.ts.map +1 -0
- package/lib/CreateImage.js +19 -0
- package/lib/CreateImage.js.map +1 -0
- package/lib/CreateSandbox.d.ts +104 -0
- package/lib/CreateSandbox.d.ts.map +1 -0
- package/lib/CreateSandbox.js +98 -0
- package/lib/CreateSandbox.js.map +1 -0
- package/lib/Credentials.d.ts +44 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +57 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Disk.d.ts +283 -0
- package/lib/Disk.d.ts.map +1 -0
- package/lib/Disk.js +294 -0
- package/lib/Disk.js.map +1 -0
- package/lib/DiskObjectsHttp.d.ts +20 -0
- package/lib/DiskObjectsHttp.d.ts.map +1 -0
- package/lib/DiskObjectsHttp.js +51 -0
- package/lib/DiskObjectsHttp.js.map +1 -0
- package/lib/DiskUser.d.ts +189 -0
- package/lib/DiskUser.d.ts.map +1 -0
- package/lib/DiskUser.js +243 -0
- package/lib/DiskUser.js.map +1 -0
- package/lib/ExecDisk.d.ts +57 -0
- package/lib/ExecDisk.d.ts.map +1 -0
- package/lib/ExecDisk.js +3 -0
- package/lib/ExecDisk.js.map +1 -0
- package/lib/ExecDiskHttp.d.ts +5 -0
- package/lib/ExecDiskHttp.d.ts.map +1 -0
- package/lib/ExecDiskHttp.js +18 -0
- package/lib/ExecDiskHttp.js.map +1 -0
- package/lib/ExecDisks.d.ts +54 -0
- package/lib/ExecDisks.d.ts.map +1 -0
- package/lib/ExecDisks.js +37 -0
- package/lib/ExecDisks.js.map +1 -0
- package/lib/Image.d.ts +188 -0
- package/lib/Image.d.ts.map +1 -0
- package/lib/Image.js +191 -0
- package/lib/Image.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/MountDisk.d.ts +190 -0
- package/lib/MountDisk.d.ts.map +1 -0
- package/lib/MountDisk.js +227 -0
- package/lib/MountDisk.js.map +1 -0
- package/lib/Providers.d.ts +25 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +48 -0
- package/lib/Providers.js.map +1 -0
- package/lib/ReadDisk.d.ts +55 -0
- package/lib/ReadDisk.d.ts.map +1 -0
- package/lib/ReadDisk.js +3 -0
- package/lib/ReadDisk.js.map +1 -0
- package/lib/ReadWriteDisk.d.ts +26 -0
- package/lib/ReadWriteDisk.d.ts.map +1 -0
- package/lib/ReadWriteDisk.js +3 -0
- package/lib/ReadWriteDisk.js.map +1 -0
- package/lib/Sandbox.d.ts +507 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +729 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxOptions.d.ts +185 -0
- package/lib/SandboxOptions.d.ts.map +1 -0
- package/lib/SandboxOptions.js +102 -0
- package/lib/SandboxOptions.js.map +1 -0
- package/lib/SandboxPortToken.d.ts +64 -0
- package/lib/SandboxPortToken.d.ts.map +1 -0
- package/lib/SandboxPortToken.js +77 -0
- package/lib/SandboxPortToken.js.map +1 -0
- package/lib/WriteDisk.d.ts +37 -0
- package/lib/WriteDisk.d.ts.map +1 -0
- package/lib/WriteDisk.js +3 -0
- package/lib/WriteDisk.js.map +1 -0
- package/lib/index.d.ts +29 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +28 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/DeployerKey.d.ts +21 -0
- package/lib/internal/DeployerKey.d.ts.map +1 -0
- package/lib/internal/DeployerKey.js +34 -0
- package/lib/internal/DeployerKey.js.map +1 -0
- package/lib/internal/archil.d.ts +87 -0
- package/lib/internal/archil.d.ts.map +1 -0
- package/lib/internal/archil.js +154 -0
- package/lib/internal/archil.js.map +1 -0
- package/lib/internal/hosted.d.ts +90 -0
- package/lib/internal/hosted.d.ts.map +1 -0
- package/lib/internal/hosted.js +291 -0
- package/lib/internal/hosted.js.map +1 -0
- package/package.json +79 -3
- package/src/AWS/S3Disk.ts +125 -0
- package/src/AWS/index.ts +1 -0
- package/src/ApiToken.ts +168 -0
- package/src/ArchilBindings.ts +179 -0
- package/src/AuthProvider.ts +122 -0
- package/src/Bootstrap.ts +54 -0
- package/src/Branch.ts +199 -0
- package/src/BranchDisk.ts +57 -0
- package/src/Checkpoint.ts +145 -0
- package/src/Clients.ts +954 -0
- package/src/ConnectSandbox.ts +91 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateDisk.ts +165 -0
- package/src/CreateImage.ts +73 -0
- package/src/CreateSandbox.ts +258 -0
- package/src/Credentials.ts +101 -0
- package/src/Disk.ts +468 -0
- package/src/DiskObjectsHttp.ts +64 -0
- package/src/DiskUser.ts +369 -0
- package/src/ExecDisk.ts +62 -0
- package/src/ExecDiskHttp.ts +25 -0
- package/src/ExecDisks.ts +100 -0
- package/src/Image.ts +316 -0
- package/src/InferEnv.ts +27 -0
- package/src/MountDisk.ts +466 -0
- package/src/Providers.ts +75 -0
- package/src/ReadDisk.ts +61 -0
- package/src/ReadWriteDisk.ts +31 -0
- package/src/Sandbox.ts +1064 -0
- package/src/SandboxOptions.ts +230 -0
- package/src/SandboxPortToken.ts +125 -0
- package/src/WriteDisk.ts +42 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +59 -0
- package/src/internal/DeployerKey.ts +63 -0
- package/src/internal/archil.ts +273 -0
- package/src/internal/hosted.ts +402 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Stream from "effect/Stream";
|
|
6
|
+
import { ApiAccess, runtimeName, runtimePrefix } from "./ArchilBindings.js";
|
|
7
|
+
import { makeDiskHandle } from "./Clients.js";
|
|
8
|
+
import { deleteDisk, ensureDisk } from "./Disk.js";
|
|
9
|
+
import { findDiskByName, listAllDisks } from "./internal/archil.js";
|
|
10
|
+
export const CreateDisk = Binding.Service("Archil.CreateDisk");
|
|
11
|
+
/** {@link CreateDisk} over Archil's HTTP API, usable from any host. */
|
|
12
|
+
export const CreateDiskHttp = Layer.effect(CreateDisk, Effect.gen(function* () {
|
|
13
|
+
const access = yield* ApiAccess;
|
|
14
|
+
return Effect.fn(function* (options) {
|
|
15
|
+
const authorize = yield* access();
|
|
16
|
+
const { prefix: owner } = yield* runtimePrefix("Disks");
|
|
17
|
+
const prefix = Effect.succeed(owner);
|
|
18
|
+
const fullName = (name) => Effect.succeed(runtimeName(owner, name));
|
|
19
|
+
const handle = (disk) => makeDiskHandle({ diskId: disk.id, name: disk.name }, authorize);
|
|
20
|
+
return {
|
|
21
|
+
prefix: owner,
|
|
22
|
+
create: (name, createOptions) => authorize(Effect.gen(function* () {
|
|
23
|
+
const disk = yield* ensureDisk(yield* fullName(name), createOptions?.storage ?? options?.storage);
|
|
24
|
+
return handle(disk);
|
|
25
|
+
})),
|
|
26
|
+
get: (name) => authorize(Effect.gen(function* () {
|
|
27
|
+
const diskName = yield* fullName(name);
|
|
28
|
+
const disk = yield* findDiskByName(diskName);
|
|
29
|
+
return disk && disk.status !== "deleted" ? handle(disk) : undefined;
|
|
30
|
+
})),
|
|
31
|
+
list: () => authorize(Effect.gen(function* () {
|
|
32
|
+
const p = yield* prefix;
|
|
33
|
+
const disks = yield* Stream.runCollect(listAllDisks());
|
|
34
|
+
return disks
|
|
35
|
+
.filter((d) => d.name.startsWith(`${p}-`) && d.status !== "deleted")
|
|
36
|
+
.map(handle);
|
|
37
|
+
})),
|
|
38
|
+
delete: (name) => authorize(Effect.gen(function* () {
|
|
39
|
+
const diskName = yield* fullName(name);
|
|
40
|
+
const disk = yield* findDiskByName(diskName);
|
|
41
|
+
if (disk)
|
|
42
|
+
yield* deleteDisk(disk.id);
|
|
43
|
+
})),
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}));
|
|
47
|
+
//# sourceMappingURL=CreateDisk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateDisk.js","sources":["../src/CreateDisk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAmB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAoB,MAAM,WAAW,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAmGpE,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAa,mBAAmB,CAAC,CAAC;AAE3E,uEAAuE;AACvE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CACxC,UAAU,EACV,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,OAA2B;QACrD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,CAAC,IAAkC,EAAE,EAAE,CACpD,cAAc,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,CAAC,CAAC;QAClE,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,EAAE,EAAE,CAC9B,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,UAAU,CAC5B,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EACrB,aAAa,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,CAC3C,CAAC;gBACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC,CAAC,CACH;YACH,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CACZ,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAC7C,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACtE,CAAC,CAAC,CACH;YACH,IAAI,EAAE,GAAG,EAAE,CACT,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC;gBACxB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;gBACvD,OAAO,KAAK;qBACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;qBACnE,GAAG,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,CAAC,CACH;YACH,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBAC7C,IAAI,IAAI;oBAAE,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC,CAAC,CACH;SACuB,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ImageRegistry } from "@alchemy.run/docker/Registry";
|
|
2
|
+
import * as archil from "@distilled.cloud/archil";
|
|
3
|
+
import * as Binding from "alchemy/Binding";
|
|
4
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import { type ImageAttributes } from "./Image.ts";
|
|
8
|
+
import type { ArchilFailed, ArchilNotReady } from "./internal/archil.ts";
|
|
9
|
+
export interface CreateImageClient {
|
|
10
|
+
/**
|
|
11
|
+
* Pull an OCI reference into an Archil image and wait until it is ready.
|
|
12
|
+
* Takes the same `image` and `registry` props as {@link Image}.
|
|
13
|
+
*/
|
|
14
|
+
build(props: {
|
|
15
|
+
readonly image: string;
|
|
16
|
+
readonly registry?: ImageRegistry;
|
|
17
|
+
}): Effect.Effect<ImageAttributes, archil.CreateImageError | archil.GetImageError | ArchilFailed | ArchilNotReady, RuntimeContext>;
|
|
18
|
+
/** An image by id, or `undefined` when it doesn't exist. */
|
|
19
|
+
get(imageId: string): Effect.Effect<ImageAttributes | undefined, archil.GetImageError, RuntimeContext>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Build sandbox images at run time, e.g. one per customer repository, with
|
|
23
|
+
* the same props as the deploy-time {@link Image}. Pass the result's
|
|
24
|
+
* `imageId` to `CreateSandbox`.
|
|
25
|
+
*
|
|
26
|
+
* ### Building Images
|
|
27
|
+
* **Example:** An image per tenant
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const images = yield* Archil.CreateImage();
|
|
30
|
+
* const image = yield* images.build({ image: `ghcr.io/acme/${tenant}:latest` });
|
|
31
|
+
* const sandbox = yield* sandboxes.create({ name: tenant, image: image.imageId });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @binding
|
|
35
|
+
* @product Image
|
|
36
|
+
*/
|
|
37
|
+
export interface CreateImage extends Binding.Service<CreateImage, "Archil.CreateImage", () => Effect.Effect<CreateImageClient>> {
|
|
38
|
+
}
|
|
39
|
+
export declare const CreateImage: CreateImage;
|
|
40
|
+
/** {@link CreateImage} over Archil's HTTP API, usable from any host. */
|
|
41
|
+
export declare const CreateImageHttp: Layer.Layer<CreateImage, never, never>;
|
|
42
|
+
//# sourceMappingURL=CreateImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateImage.d.ts","sources":["../src/CreateImage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAgC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEzE,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE;QACX,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;KACnC,GAAG,MAAM,CAAC,MAAM,CACf,eAAe,EACf,MAAM,CAAC,gBAAgB,GAAG,MAAM,CAAC,aAAa,GAAG,YAAY,GAAG,cAAc,EAC9E,cAAc,CACf,CAAC;IACF,4DAA4D;IAC5D,GAAG,CACD,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,CAAC,eAAe,GAAG,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;CACrF;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAY,SAAQ,OAAO,CAAC,OAAO,CAClD,WAAW,EACX,oBAAoB,EACpB,MAAM,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CACvC;CAAG;AAEJ,eAAO,MAAM,WAAW,aAAqD,CAAC;AAE9E,wEAAwE;AACxE,eAAO,MAAM,eAAe,wCAkB3B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { ApiAccess } from "./ArchilBindings.js";
|
|
6
|
+
import { pullImage, toImageAttributes } from "./Image.js";
|
|
7
|
+
export const CreateImage = Binding.Service("Archil.CreateImage");
|
|
8
|
+
/** {@link CreateImage} over Archil's HTTP API, usable from any host. */
|
|
9
|
+
export const CreateImageHttp = Layer.effect(CreateImage, Effect.gen(function* () {
|
|
10
|
+
const access = yield* ApiAccess;
|
|
11
|
+
return Effect.fn(function* () {
|
|
12
|
+
const authorize = yield* access();
|
|
13
|
+
return {
|
|
14
|
+
build: (props) => authorize(pullImage(props.image, props.registry, props.image)),
|
|
15
|
+
get: (imageId) => authorize(archil.getImage({ image_id: imageId }).pipe(Effect.map(({ data }) => toImageAttributes(data, data.source)), Effect.catchTag("NotFound", () => Effect.undefined))),
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
}));
|
|
19
|
+
//# sourceMappingURL=CreateImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateImage.js","sources":["../src/CreateImage.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAwB,MAAM,YAAY,CAAC;AA4ChF,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAc,oBAAoB,CAAC,CAAC;AAE9E,wEAAwE;AACxE,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CACzC,WAAW,EACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC;QACxB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO;YACL,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAChF,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,CACf,SAAS,CACP,MAAM,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CACzC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,EAC9D,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CACpD,CACF;SACwB,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import * as Layer from "effect/Layer";
|
|
6
|
+
import { type SandboxHandle } from "./Clients.ts";
|
|
7
|
+
import type { Image } from "./Image.ts";
|
|
8
|
+
import type { ArchilFailed, ArchilNotReady } from "./internal/archil.ts";
|
|
9
|
+
import { deleteSandbox, type Sandbox, type SandboxProps } from "./Sandbox.ts";
|
|
10
|
+
import { MountDiskUnresolved, type MountOptionUnsupported } from "./SandboxOptions.ts";
|
|
11
|
+
/**
|
|
12
|
+
* A run-time create: a box {@link Sandbox}'s props (no program), with a
|
|
13
|
+
* required name. A mount's disk is a `DiskHandle` (e.g. from
|
|
14
|
+
* `CreateDisk`), or a `MountDisk` reference this host bound at deploy.
|
|
15
|
+
*/
|
|
16
|
+
export interface CreateSandboxRequest extends Omit<SandboxProps, "name" | "main" | "handler" | "port" | "build" | "extraFiles" | "isExternal"> {
|
|
17
|
+
/** Name, stamped with this binding's prefix. Lowercase letters, digits and `-`. */
|
|
18
|
+
readonly name: string;
|
|
19
|
+
}
|
|
20
|
+
export type CreateSandboxError = archil.CreateSandboxError | archil.ForkSandboxError | archil.GetSandboxError | archil.ListSandboxesError | ArchilFailed | ArchilNotReady | MountOptionUnsupported | MountDiskUnresolved;
|
|
21
|
+
export interface CreateSandboxClient {
|
|
22
|
+
/**
|
|
23
|
+
* The name prefix this client puts on everything it creates,
|
|
24
|
+
* `alc-<id>-<hash of stack/stage/id>`.
|
|
25
|
+
*/
|
|
26
|
+
readonly prefix: string;
|
|
27
|
+
/**
|
|
28
|
+
* Create a sandbox (or return the one that already has this name) and
|
|
29
|
+
* wait until it is running. Takes a {@link Sandbox}'s props; the bound
|
|
30
|
+
* image is the default.
|
|
31
|
+
*/
|
|
32
|
+
create(request: CreateSandboxRequest): Effect.Effect<SandboxHandle, CreateSandboxError, RuntimeContext>;
|
|
33
|
+
/** A sandbox this client created, or `undefined`. */
|
|
34
|
+
get(name: string): Effect.Effect<SandboxHandle | undefined, archil.ListSandboxesError, RuntimeContext>;
|
|
35
|
+
/** Every sandbox this client created. */
|
|
36
|
+
list(): Effect.Effect<SandboxHandle[], archil.ListSandboxesError, RuntimeContext>;
|
|
37
|
+
/** Delete a sandbox this client created. Deleting a missing sandbox succeeds. */
|
|
38
|
+
delete(name: string): Effect.Effect<void, archil.ListSandboxesError | Effect.Error<ReturnType<typeof deleteSandbox>>, RuntimeContext>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create sandboxes at run time, one per user, session, or task: Firecracker
|
|
42
|
+
* microVMs with disks mounted, public ports, and an outbound network policy
|
|
43
|
+
* that can inject credentials at the boundary. Bind an {@link Image} to make
|
|
44
|
+
* it the default image; a run-time `create` takes the same props as a
|
|
45
|
+
* deploy-time {@link Sandbox}. Bind a {@link Sandbox} instead and `create`
|
|
46
|
+
* forks it: each sandbox starts from its memory and disk, with whatever its
|
|
47
|
+
* `run` commands set up, and changes only its own copy.
|
|
48
|
+
*
|
|
49
|
+
* Objects created at run time are tagged with the stack, stage and binding
|
|
50
|
+
* (`alchemy::stack`, `alchemy::stage`, `alchemy::id`) and are not deleted
|
|
51
|
+
* when the stack is destroyed. List them by those tags to clean them up.
|
|
52
|
+
* Archil has no tags, labels or descriptions, so the tags are a name
|
|
53
|
+
* prefix, `alc-<id>-<hash of stack/stage/id>`: every sandbox (and fork)
|
|
54
|
+
* this client creates is `<prefix>-<name>`, and `prefix` on the client is the value.
|
|
55
|
+
*
|
|
56
|
+
* ### Sandboxes per Task
|
|
57
|
+
* **Example:** Run a task in a sandbox with the user's disk mounted
|
|
58
|
+
* ```typescript
|
|
59
|
+
* export default class Api extends Cloudflare.Worker<Api>()(
|
|
60
|
+
* "Api",
|
|
61
|
+
* { main: import.meta.url },
|
|
62
|
+
* Effect.gen(function* () {
|
|
63
|
+
* const disks = yield* Archil.CreateDisk();
|
|
64
|
+
* const sandboxes = yield* Archil.CreateSandbox(Agent);
|
|
65
|
+
* return {
|
|
66
|
+
* fetch: Effect.gen(function* () {
|
|
67
|
+
* const home = yield* disks.create("user-1");
|
|
68
|
+
* const sandbox = yield* sandboxes.create({
|
|
69
|
+
* name: "task-1",
|
|
70
|
+
* mounts: [{ disk: home, path: "/home/user" }],
|
|
71
|
+
* network: { egress: { default: "deny", allow: ["registry.npmjs.org"] } },
|
|
72
|
+
* idleTtlSeconds: 300,
|
|
73
|
+
* });
|
|
74
|
+
* const result = yield* sandbox.exec("npm test", { cwd: "/home/user/app" });
|
|
75
|
+
* yield* sandbox.pause();
|
|
76
|
+
* return HttpServerResponse.text(result.stdout);
|
|
77
|
+
* }),
|
|
78
|
+
* };
|
|
79
|
+
* }).pipe(Effect.provide(Layer.mergeAll(Archil.CreateDiskHttp, Archil.CreateSandboxHttp))),
|
|
80
|
+
* ) {}
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* ### Forking a Sandbox Built at Deploy
|
|
84
|
+
* **Example:** A fork per user from a sandbox set up at deploy
|
|
85
|
+
* ```typescript
|
|
86
|
+
* export const Golden = Archil.Sandbox("Golden", {
|
|
87
|
+
* run: ["git clone --depth 1 https://github.com/sindresorhus/is ~/is"],
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* // in a Worker or program:
|
|
91
|
+
* const sandboxes = yield* Archil.CreateSandbox(Golden);
|
|
92
|
+
* const sandbox = (yield* sandboxes.get(`user-${user}`)) ?? (yield* sandboxes.create({ name: `user-${user}` }));
|
|
93
|
+
* const result = yield* sandbox.exec("git log -1", { cwd: "~/is" });
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @binding
|
|
97
|
+
* @product Sandbox
|
|
98
|
+
*/
|
|
99
|
+
export interface CreateSandbox extends Binding.Service<CreateSandbox, "Archil.CreateSandbox", (base?: Image | Sandbox) => Effect.Effect<CreateSandboxClient>> {
|
|
100
|
+
}
|
|
101
|
+
export declare const CreateSandbox: CreateSandbox;
|
|
102
|
+
/** {@link CreateSandbox} over Archil's HTTP API, usable from any host. */
|
|
103
|
+
export declare const CreateSandboxHttp: Layer.Layer<CreateSandbox, never, never>;
|
|
104
|
+
//# sourceMappingURL=CreateSandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSandbox.d.ts","sources":["../src/CreateSandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EAAqB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EACL,aAAa,EAEb,KAAK,OAAO,EACZ,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EAKnB,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAC;AAE7B;;;;GAIG;AACH,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,YAAY,EACZ,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,CAC7E;IACC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,kBAAkB,GAC1B,MAAM,CAAC,kBAAkB,GACzB,MAAM,CAAC,gBAAgB,GACvB,MAAM,CAAC,eAAe,GACtB,MAAM,CAAC,kBAAkB,GACzB,YAAY,GACZ,cAAc,GACd,sBAAsB,GACtB,mBAAmB,CAAC;AAoBxB,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,MAAM,CACJ,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC;IACpE,qDAAqD;IACrD,GAAG,CACD,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CAAC,aAAa,GAAG,SAAS,EAAE,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;IACvF,yCAAyC;IACzC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;IAClF,iFAAiF;IACjF,MAAM,CACJ,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,MAAM,CAAC,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,EAC1E,cAAc,CACf,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,MAAM,WAAW,aAAc,SAAQ,OAAO,CAAC,OAAO,CACpD,aAAa,EACb,sBAAsB,EACtB,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAC/D;CAAG;AAEJ,eAAO,MAAM,aAAa,eAAyD,CAAC;AAEpF,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,0CA4F7B,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as archil from "@distilled.cloud/archil";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Random from "effect/Random";
|
|
6
|
+
import { ApiAccess, runtimeName, runtimePrefix } from "./ArchilBindings.js";
|
|
7
|
+
import { makeSandboxHandle } from "./Clients.js";
|
|
8
|
+
import { findSandboxByName, listSandboxes, waitForSandbox } from "./internal/archil.js";
|
|
9
|
+
import { deleteSandbox, toCreateSandboxRequest, } from "./Sandbox.js";
|
|
10
|
+
import { MountDiskUnresolved, mountDiskId, toSandboxMount, } from "./SandboxOptions.js";
|
|
11
|
+
/**
|
|
12
|
+
* A mount's disk id at run time: a handle carries it; a declared disk
|
|
13
|
+
* reads the id `MountDisk` bound into this host at deploy.
|
|
14
|
+
*/
|
|
15
|
+
const runtimeDiskId = Effect.fn(function* (disk, path) {
|
|
16
|
+
if (isDiskRef(disk))
|
|
17
|
+
return disk.diskId;
|
|
18
|
+
if (Effect.isEffect(disk)) {
|
|
19
|
+
return yield* new MountDiskUnresolved({
|
|
20
|
+
path,
|
|
21
|
+
message: `The disk mounted at ${path} is a declaration: bind it with Archil.MountDisk(disk) and pass that reference, or pass a DiskHandle.`,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
const diskId = yield* disk.diskId;
|
|
25
|
+
return yield* diskId;
|
|
26
|
+
});
|
|
27
|
+
const isDiskRef = (disk) => mountDiskId(disk) !== undefined;
|
|
28
|
+
export const CreateSandbox = Binding.Service("Archil.CreateSandbox");
|
|
29
|
+
/** {@link CreateSandbox} over Archil's HTTP API, usable from any host. */
|
|
30
|
+
export const CreateSandboxHttp = Layer.effect(CreateSandbox, Effect.gen(function* () {
|
|
31
|
+
const access = yield* ApiAccess;
|
|
32
|
+
return Effect.fn(function* (base) {
|
|
33
|
+
const authorize = yield* access();
|
|
34
|
+
const { prefix: owner } = yield* runtimePrefix("Sandboxes");
|
|
35
|
+
const prefix = Effect.succeed(owner);
|
|
36
|
+
// Resources are proxies (every property reads as an Output), so tell a
|
|
37
|
+
// bound sandbox from a bound image by its type, not by `in`.
|
|
38
|
+
const isSandbox = (b) => b.Type === "Archil.Sandbox";
|
|
39
|
+
const source = base !== undefined && isSandbox(base) ? yield* base.sandboxId : undefined;
|
|
40
|
+
const imageId = base !== undefined && !isSandbox(base) ? yield* base.imageId : undefined;
|
|
41
|
+
const fullName = (name) => Effect.succeed(runtimeName(owner, name));
|
|
42
|
+
// Forks carry the same prefix as the sandboxes they come from; an
|
|
43
|
+
// unnamed fork gets a random name.
|
|
44
|
+
const forkName = Effect.fn(function* (name) {
|
|
45
|
+
const id = (yield* Random.nextIntBetween(0, 2 ** 31)).toString(36);
|
|
46
|
+
return yield* fullName(name ?? `fork-${id}`);
|
|
47
|
+
});
|
|
48
|
+
const handle = (s) => makeSandboxHandle({ sandboxId: s.sandbox_id, name: s.name }, authorize, forkName);
|
|
49
|
+
return {
|
|
50
|
+
prefix: owner,
|
|
51
|
+
create: (request) => authorize(Effect.gen(function* () {
|
|
52
|
+
const name = yield* fullName(request.name);
|
|
53
|
+
const existing = yield* findSandboxByName(name);
|
|
54
|
+
if (existing)
|
|
55
|
+
return handle(existing);
|
|
56
|
+
if (source !== undefined) {
|
|
57
|
+
// A bound sandbox is the base: fork its memory and disk.
|
|
58
|
+
const { data } = yield* archil.forkSandbox({
|
|
59
|
+
sid: yield* source,
|
|
60
|
+
wait: true,
|
|
61
|
+
name,
|
|
62
|
+
});
|
|
63
|
+
return handle(yield* waitForSandbox(data.sandbox_id));
|
|
64
|
+
}
|
|
65
|
+
const defaultImage = request.image === undefined && request.baseImage === undefined && imageId
|
|
66
|
+
? yield* imageId
|
|
67
|
+
: request.image;
|
|
68
|
+
const mounts = [];
|
|
69
|
+
for (const mount of request.mounts ?? []) {
|
|
70
|
+
const diskId = yield* runtimeDiskId(mount.disk, mount.path);
|
|
71
|
+
mounts.push(yield* toSandboxMount(diskId, mount));
|
|
72
|
+
}
|
|
73
|
+
const { data } = yield* archil
|
|
74
|
+
.createSandbox(toCreateSandboxRequest(name, { ...request, image: defaultImage }, mounts))
|
|
75
|
+
.pipe(Effect.catchTag("SandboxNameConflict", (conflict) => findSandboxByName(name).pipe(Effect.flatMap((found) => found ? Effect.succeed({ data: found }) : Effect.fail(conflict)))));
|
|
76
|
+
return handle(yield* waitForSandbox(data.sandbox_id));
|
|
77
|
+
})),
|
|
78
|
+
get: (name) => authorize(Effect.gen(function* () {
|
|
79
|
+
const sandboxName = yield* fullName(name);
|
|
80
|
+
const found = yield* findSandboxByName(sandboxName);
|
|
81
|
+
return found ? handle(found) : undefined;
|
|
82
|
+
})),
|
|
83
|
+
list: () => authorize(Effect.gen(function* () {
|
|
84
|
+
const p = yield* prefix;
|
|
85
|
+
return (yield* listSandboxes())
|
|
86
|
+
.filter((s) => s.name.startsWith(`${p}-`) && s.status !== "deleted")
|
|
87
|
+
.map(handle);
|
|
88
|
+
})),
|
|
89
|
+
delete: (name) => authorize(Effect.gen(function* () {
|
|
90
|
+
const sandboxName = yield* fullName(name);
|
|
91
|
+
const found = yield* findSandboxByName(sandboxName);
|
|
92
|
+
if (found)
|
|
93
|
+
yield* deleteSandbox(found.sandbox_id);
|
|
94
|
+
})),
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}));
|
|
98
|
+
//# sourceMappingURL=CreateSandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSandbox.js","sources":["../src/CreateSandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,yBAAyB,CAAC;AAClD,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAsB,MAAM,cAAc,CAAC;AAGrE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACxF,OAAO,EACL,aAAa,EACb,sBAAsB,GAGvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,cAAc,GAIf,MAAM,qBAAqB,CAAC;AAyB7B;;;GAGG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAmB,EAAE,IAAY;IAC1E,IAAI,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IACxC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC,CAAC,IAAI,mBAAmB,CAAC;YACpC,IAAI;YACJ,OAAO,EAAE,uBAAuB,IAAI,uGAAuG;SAC5I,CAAC,CAAC;IACL,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAClC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,MAAM,SAAS,GAAG,CAAC,IAAmB,EAAmB,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;AAiG5F,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAgB,sBAAsB,CAAC,CAAC;AAEpF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAC3C,aAAa,EACb,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;IAChC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAsB;QAChD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrC,uEAAuE;QACvE,6DAA6D;QAC7D,MAAM,SAAS,GAAG,CAAC,CAAkB,EAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC;QACpF,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;QACzF,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5E,kEAAkE;QAClE,mCAAmC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAwB;YAC5D,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACnE,OAAO,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,CAAC,CAAuC,EAAE,EAAE,CACzD,iBAAiB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpF,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAClB,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,QAAQ;oBAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBACzB,yDAAyD;oBACzD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;wBACzC,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM;wBAClB,IAAI,EAAE,IAAI;wBACV,IAAI;qBACL,CAAC,CAAC;oBACH,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;gBACxD,CAAC;gBACD,MAAM,YAAY,GAChB,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO;oBACvE,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO;oBAChB,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC;gBACpB,MAAM,MAAM,GAA0B,EAAE,CAAC;gBACzC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;oBACzC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC5D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;gBACpD,CAAC;gBACD,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM;qBAC3B,aAAa,CACZ,sBAAsB,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,MAAM,CAAC,CAC1E;qBACA,IAAI,CACH,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,EAAE,CAClD,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAC1B,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAChE,CACF,CACF,CACF,CAAC;gBACJ,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YACxD,CAAC,CAAC,CACH;YACH,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CACZ,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBACpD,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC3C,CAAC,CAAC,CACH;YACH,IAAI,EAAE,GAAG,EAAE,CACT,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;qBAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC;qBACnE,GAAG,CAAC,MAAM,CAAC,CAAC;YACjB,CAAC,CAAC,CACH;YACH,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CACf,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,KAAK;oBAAE,KAAK,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpD,CAAC,CAAC,CACH;SAC0B,CAAC;IAClC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Credentials } from "@distilled.cloud/archil/Credentials";
|
|
2
|
+
import * as Context from "effect/Context";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import * as Redacted from "effect/Redacted";
|
|
6
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_REGION, REGIONS, } from "@distilled.cloud/archil/Credentials";
|
|
7
|
+
/** Where the current Archil credentials act. */
|
|
8
|
+
export interface ArchilAccount {
|
|
9
|
+
/** Archil region id, e.g. `aws-us-east-1`. */
|
|
10
|
+
readonly region: string;
|
|
11
|
+
/** Archil organization id, when configured. */
|
|
12
|
+
readonly organization: string | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const Account_base: Context.ServiceClass<Account, "Archil.Account", Effect.Effect<ArchilAccount, never, never>>;
|
|
15
|
+
/**
|
|
16
|
+
* The region (and organization) the current Archil credentials act in.
|
|
17
|
+
* Holds an effect so it resolves on first use, never at layer build.
|
|
18
|
+
*/
|
|
19
|
+
export declare class Account extends Account_base {
|
|
20
|
+
}
|
|
21
|
+
/** The region and organization of the current Archil credentials. */
|
|
22
|
+
export declare const account: Effect.Effect<ArchilAccount, never, Account>;
|
|
23
|
+
/**
|
|
24
|
+
* Build Archil `Credentials` + `Account` from an explicit API key. Useful
|
|
25
|
+
* for tests, or for a runtime that reads its key from a binding.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* Effect.provide(Archil.fromApiKey({ apiKey: "key-...", region: "aws-us-east-1" }))
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const fromApiKey: (input: {
|
|
33
|
+
apiKey: string | Redacted.Redacted<string>;
|
|
34
|
+
region?: string;
|
|
35
|
+
organization?: string;
|
|
36
|
+
}) => Layer.Layer<Account | Credentials, never, never>;
|
|
37
|
+
/**
|
|
38
|
+
* Build Archil `Credentials` + `Account` that resolve through the Alchemy
|
|
39
|
+
* AuthProvider: environment credentials (`ARCHIL_API_KEY`) when present,
|
|
40
|
+
* otherwise the selected profile. Resolution is deferred until the first
|
|
41
|
+
* API call, so building the provider layers never needs a profile.
|
|
42
|
+
*/
|
|
43
|
+
export declare const fromAuthProvider: () => Layer.Layer<Account | Credentials, never, import("alchemy").AuthProviders | import("alchemy/Auth/Profile").ProfileStore>;
|
|
44
|
+
//# sourceMappingURL=Credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.d.ts","sources":["../src/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EAGZ,MAAM,qCAAqC,CAAC;AAG7C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAG5C,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,OAAO,GACR,MAAM,qCAAqC,CAAC;AAE7C,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;;AAED;;;GAGG;AACH,qBAAa,OAAQ,SAAQ,YAE5B;CAAG;AAEJ,qEAAqE;AACrE,eAAO,MAAM,OAAO,8CAElB,CAAC;AA0BH;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,UAAW;IAChC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,qDAOmC,CAAC;AAErC;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,gIAM1B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { controlPlaneUrl, Credentials, DEFAULT_REGION, REGIONS, } from "@distilled.cloud/archil/Credentials";
|
|
2
|
+
import { ConfigError } from "@distilled.cloud/core/errors";
|
|
3
|
+
import { lazyCredentials } from "alchemy/Auth/Resolve";
|
|
4
|
+
import * as Context from "effect/Context";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import * as Redacted from "effect/Redacted";
|
|
8
|
+
import { ARCHIL_AUTH_PROVIDER_NAME } from "./AuthProvider.js";
|
|
9
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_REGION, REGIONS, } from "@distilled.cloud/archil/Credentials";
|
|
10
|
+
/**
|
|
11
|
+
* The region (and organization) the current Archil credentials act in.
|
|
12
|
+
* Holds an effect so it resolves on first use, never at layer build.
|
|
13
|
+
*/
|
|
14
|
+
export class Account extends Context.Service()("Archil.Account") {
|
|
15
|
+
}
|
|
16
|
+
/** The region and organization of the current Archil credentials. */
|
|
17
|
+
export const account = Effect.gen(function* () {
|
|
18
|
+
return yield* yield* Account;
|
|
19
|
+
});
|
|
20
|
+
const make = (resolve) => Effect.gen(function* () {
|
|
21
|
+
const credentials = Effect.flatMap(resolve, (creds) => {
|
|
22
|
+
const apiBaseUrl = controlPlaneUrl(creds.region);
|
|
23
|
+
return apiBaseUrl
|
|
24
|
+
? Effect.succeed({ apiKey: creds.apiKey, apiBaseUrl, region: creds.region })
|
|
25
|
+
: Effect.fail(new ConfigError({
|
|
26
|
+
message: `Unknown Archil region "${creds.region}". Valid regions: ${Object.keys(REGIONS).join(", ")}`,
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
29
|
+
// `Account` is typed as never failing, so a credentials failure dies
|
|
30
|
+
// here; the engine still reports it as `CredentialsRequired`.
|
|
31
|
+
const accountInfo = yield* resolve.pipe(Effect.map((creds) => ({ region: creds.region, organization: creds.organization })), Effect.orDie, Effect.cached);
|
|
32
|
+
return Context.make(Credentials, credentials).pipe(Context.add(Account, accountInfo));
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Build Archil `Credentials` + `Account` from an explicit API key. Useful
|
|
36
|
+
* for tests, or for a runtime that reads its key from a binding.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* Effect.provide(Archil.fromApiKey({ apiKey: "key-...", region: "aws-us-east-1" }))
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export const fromApiKey = (input) => Effect.succeed({
|
|
44
|
+
type: "apiKey",
|
|
45
|
+
apiKey: typeof input.apiKey === "string" ? Redacted.make(input.apiKey) : input.apiKey,
|
|
46
|
+
region: input.region ?? DEFAULT_REGION,
|
|
47
|
+
organization: input.organization,
|
|
48
|
+
source: { type: "stored" },
|
|
49
|
+
}).pipe(make, Layer.effectContext);
|
|
50
|
+
/**
|
|
51
|
+
* Build Archil `Credentials` + `Account` that resolve through the Alchemy
|
|
52
|
+
* AuthProvider: environment credentials (`ARCHIL_API_KEY`) when present,
|
|
53
|
+
* otherwise the selected profile. Resolution is deferred until the first
|
|
54
|
+
* API call, so building the provider layers never needs a profile.
|
|
55
|
+
*/
|
|
56
|
+
export const fromAuthProvider = () => Layer.effectContext(lazyCredentials()(ARCHIL_AUTH_PROVIDER_NAME, (creds) => creds).pipe(Effect.flatMap(make)));
|
|
57
|
+
//# sourceMappingURL=Credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.js","sources":["../src/Credentials.ts"],"names":[],"mappings":"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"}
|