@alchemy.run/daytona 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 +76 -4
- package/lib/ApiKey.d.ts +99 -0
- package/lib/ApiKey.d.ts.map +1 -0
- package/lib/ApiKey.js +152 -0
- package/lib/ApiKey.js.map +1 -0
- package/lib/AuthProvider.d.ts +55 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +280 -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 +28 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +72 -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 +5 -0
- package/lib/ConnectSandboxHttp.d.ts.map +1 -0
- package/lib/ConnectSandboxHttp.js +22 -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 +86 -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 +5 -0
- package/lib/CreateSandboxHttp.d.ts.map +1 -0
- package/lib/CreateSandboxHttp.js +65 -0
- package/lib/CreateSandboxHttp.js.map +1 -0
- package/lib/CreateSecret.d.ts +56 -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 +5 -0
- package/lib/CreateSecretHttp.d.ts.map +1 -0
- package/lib/CreateSecretHttp.js +39 -0
- package/lib/CreateSecretHttp.js.map +1 -0
- package/lib/CreateSnapshot.d.ts +80 -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 +5 -0
- package/lib/CreateSnapshotHttp.d.ts.map +1 -0
- package/lib/CreateSnapshotHttp.js +47 -0
- package/lib/CreateSnapshotHttp.js.map +1 -0
- package/lib/CreateVolume.d.ts +81 -0
- package/lib/CreateVolume.d.ts.map +1 -0
- package/lib/CreateVolume.js +10 -0
- package/lib/CreateVolume.js.map +1 -0
- package/lib/CreateVolumeHttp.d.ts +5 -0
- package/lib/CreateVolumeHttp.d.ts.map +1 -0
- package/lib/CreateVolumeHttp.js +31 -0
- package/lib/CreateVolumeHttp.js.map +1 -0
- package/lib/Credentials.d.ts +9 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +18 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/DaytonaBindings.d.ts +51 -0
- package/lib/DaytonaBindings.d.ts.map +1 -0
- package/lib/DaytonaBindings.js +61 -0
- package/lib/DaytonaBindings.js.map +1 -0
- package/lib/IdentityProvider.d.ts +80 -0
- package/lib/IdentityProvider.d.ts.map +1 -0
- package/lib/IdentityProvider.js +111 -0
- package/lib/IdentityProvider.js.map +1 -0
- package/lib/MountVolume.d.ts +86 -0
- package/lib/MountVolume.d.ts.map +1 -0
- package/lib/MountVolume.js +27 -0
- package/lib/MountVolume.js.map +1 -0
- package/lib/OAuthClient.d.ts +14 -0
- package/lib/OAuthClient.d.ts.map +1 -0
- package/lib/OAuthClient.js +23 -0
- package/lib/OAuthClient.js.map +1 -0
- package/lib/Organization.d.ts +40 -0
- package/lib/Organization.d.ts.map +1 -0
- package/lib/Organization.js +80 -0
- package/lib/Organization.js.map +1 -0
- package/lib/OrganizationInvitation.d.ts +70 -0
- package/lib/OrganizationInvitation.d.ts.map +1 -0
- package/lib/OrganizationInvitation.js +109 -0
- package/lib/OrganizationInvitation.js.map +1 -0
- package/lib/OrganizationMember.d.ts +86 -0
- package/lib/OrganizationMember.d.ts.map +1 -0
- package/lib/OrganizationMember.js +109 -0
- package/lib/OrganizationMember.js.map +1 -0
- package/lib/OrganizationOtelConfig.d.ts +59 -0
- package/lib/OrganizationOtelConfig.d.ts.map +1 -0
- package/lib/OrganizationOtelConfig.js +87 -0
- package/lib/OrganizationOtelConfig.js.map +1 -0
- package/lib/OrganizationRole.d.ts +66 -0
- package/lib/OrganizationRole.d.ts.map +1 -0
- package/lib/OrganizationRole.js +106 -0
- package/lib/OrganizationRole.js.map +1 -0
- package/lib/OrganizationSettings.d.ts +76 -0
- package/lib/OrganizationSettings.d.ts.map +1 -0
- package/lib/OrganizationSettings.js +107 -0
- package/lib/OrganizationSettings.js.map +1 -0
- package/lib/Providers.d.ts +14 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +53 -0
- package/lib/Providers.js.map +1 -0
- package/lib/ReadAuditLogs.d.ts +30 -0
- package/lib/ReadAuditLogs.d.ts.map +1 -0
- package/lib/ReadAuditLogs.js +17 -0
- package/lib/ReadAuditLogs.js.map +1 -0
- package/lib/ReadOrganization.d.ts +39 -0
- package/lib/ReadOrganization.d.ts.map +1 -0
- package/lib/ReadOrganization.js +39 -0
- package/lib/ReadOrganization.js.map +1 -0
- package/lib/ReadUsage.d.ts +31 -0
- package/lib/ReadUsage.d.ts.map +1 -0
- package/lib/ReadUsage.js +17 -0
- package/lib/ReadUsage.js.map +1 -0
- package/lib/Region.d.ts +78 -0
- package/lib/Region.d.ts.map +1 -0
- package/lib/Region.js +169 -0
- package/lib/Region.js.map +1 -0
- package/lib/Registry.d.ts +84 -0
- package/lib/Registry.d.ts.map +1 -0
- package/lib/Registry.js +97 -0
- package/lib/Registry.js.map +1 -0
- package/lib/Runner.d.ts +66 -0
- package/lib/Runner.d.ts.map +1 -0
- package/lib/Runner.js +116 -0
- package/lib/Runner.js.map +1 -0
- package/lib/Sandbox.d.ts +376 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +565 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxClient.d.ts +258 -0
- package/lib/SandboxClient.d.ts.map +1 -0
- package/lib/SandboxClient.js +233 -0
- package/lib/SandboxClient.js.map +1 -0
- package/lib/Secret.d.ts +93 -0
- package/lib/Secret.d.ts.map +1 -0
- package/lib/Secret.js +130 -0
- package/lib/Secret.js.map +1 -0
- package/lib/Snapshot.d.ts +327 -0
- package/lib/Snapshot.d.ts.map +1 -0
- package/lib/Snapshot.js +447 -0
- package/lib/Snapshot.js.map +1 -0
- package/lib/Volume.d.ts +99 -0
- package/lib/Volume.d.ts.map +1 -0
- package/lib/Volume.js +152 -0
- package/lib/Volume.js.map +1 -0
- package/lib/WarmPool.d.ts +61 -0
- package/lib/WarmPool.d.ts.map +1 -0
- package/lib/WarmPool.js +81 -0
- package/lib/WarmPool.js.map +1 -0
- package/lib/Webhooks.d.ts +58 -0
- package/lib/Webhooks.d.ts.map +1 -0
- package/lib/Webhooks.js +75 -0
- package/lib/Webhooks.js.map +1 -0
- package/lib/index.d.ts +37 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +36 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/BuildContext.d.ts +16 -0
- package/lib/internal/BuildContext.d.ts.map +1 -0
- package/lib/internal/BuildContext.js +50 -0
- package/lib/internal/BuildContext.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/Derived.d.ts +40 -0
- package/lib/internal/Derived.d.ts.map +1 -0
- package/lib/internal/Derived.js +64 -0
- package/lib/internal/Derived.js.map +1 -0
- package/lib/internal/Errors.d.ts +4 -0
- package/lib/internal/Errors.d.ts.map +1 -0
- package/lib/internal/Errors.js +1 -0
- package/lib/internal/Errors.js.map +1 -0
- package/lib/internal/Labels.d.ts +20 -0
- package/lib/internal/Labels.d.ts.map +1 -0
- package/lib/internal/Labels.js +22 -0
- package/lib/internal/Labels.js.map +1 -0
- package/lib/internal/Names.d.ts +18 -0
- package/lib/internal/Names.d.ts.map +1 -0
- package/lib/internal/Names.js +25 -0
- package/lib/internal/Names.js.map +1 -0
- package/lib/internal/Organization.d.ts +27 -0
- package/lib/internal/Organization.d.ts.map +1 -0
- package/lib/internal/Organization.js +32 -0
- package/lib/internal/Organization.js.map +1 -0
- package/lib/internal/Process.d.ts +14 -0
- package/lib/internal/Process.d.ts.map +1 -0
- package/lib/internal/Process.js +15 -0
- package/lib/internal/Process.js.map +1 -0
- package/lib/internal/Program.d.ts +83 -0
- package/lib/internal/Program.d.ts.map +1 -0
- package/lib/internal/Program.js +169 -0
- package/lib/internal/Program.js.map +1 -0
- package/lib/internal/Ref.d.ts +14 -0
- package/lib/internal/Ref.d.ts.map +1 -0
- package/lib/internal/Ref.js +7 -0
- package/lib/internal/Ref.js.map +1 -0
- package/lib/internal/Scoped.d.ts +31 -0
- package/lib/internal/Scoped.d.ts.map +1 -0
- package/lib/internal/Scoped.js +48 -0
- package/lib/internal/Scoped.js.map +1 -0
- package/lib/internal/Tar.d.ts +13 -0
- package/lib/internal/Tar.d.ts.map +1 -0
- package/lib/internal/Tar.js +62 -0
- package/lib/internal/Tar.js.map +1 -0
- package/lib/internal/Toolbox.d.ts +11 -0
- package/lib/internal/Toolbox.d.ts.map +1 -0
- package/lib/internal/Toolbox.js +20 -0
- package/lib/internal/Toolbox.js.map +1 -0
- package/lib/internal/Wait.d.ts +49 -0
- package/lib/internal/Wait.d.ts.map +1 -0
- package/lib/internal/Wait.js +57 -0
- package/lib/internal/Wait.js.map +1 -0
- package/package.json +64 -3
- package/src/ApiKey.ts +221 -0
- package/src/AuthProvider.ts +406 -0
- package/src/Bootstrap.ts +55 -0
- package/src/ConnectSandbox.ts +76 -0
- package/src/ConnectSandboxHttp.ts +26 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateSandbox.ts +107 -0
- package/src/CreateSandboxHttp.ts +97 -0
- package/src/CreateSecret.ts +73 -0
- package/src/CreateSecretHttp.ts +58 -0
- package/src/CreateSnapshot.ts +133 -0
- package/src/CreateSnapshotHttp.ts +77 -0
- package/src/CreateVolume.ts +104 -0
- package/src/CreateVolumeHttp.ts +50 -0
- package/src/Credentials.ts +37 -0
- package/src/DaytonaBindings.ts +111 -0
- package/src/IdentityProvider.ts +181 -0
- package/src/MountVolume.ts +122 -0
- package/src/OAuthClient.ts +27 -0
- package/src/Organization.ts +121 -0
- package/src/OrganizationInvitation.ts +174 -0
- package/src/OrganizationMember.ts +174 -0
- package/src/OrganizationOtelConfig.ts +138 -0
- package/src/OrganizationRole.ts +167 -0
- package/src/OrganizationSettings.ts +187 -0
- package/src/Providers.ts +93 -0
- package/src/ReadAuditLogs.ts +50 -0
- package/src/ReadOrganization.ts +83 -0
- package/src/ReadUsage.ts +51 -0
- package/src/Region.ts +226 -0
- package/src/Registry.ts +164 -0
- package/src/Runner.ts +166 -0
- package/src/Sandbox.ts +927 -0
- package/src/SandboxClient.ts +625 -0
- package/src/Secret.ts +203 -0
- package/src/Snapshot.ts +685 -0
- package/src/Volume.ts +229 -0
- package/src/WarmPool.ts +128 -0
- package/src/Webhooks.ts +121 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +46 -0
- package/src/internal/BuildContext.ts +62 -0
- package/src/internal/Declared.ts +80 -0
- package/src/internal/Derived.ts +97 -0
- package/src/internal/Errors.ts +4 -0
- package/src/internal/Labels.ts +39 -0
- package/src/internal/Names.ts +37 -0
- package/src/internal/Organization.ts +40 -0
- package/src/internal/Process.ts +25 -0
- package/src/internal/Program.ts +239 -0
- package/src/internal/Ref.ts +15 -0
- package/src/internal/Scoped.ts +102 -0
- package/src/internal/Tar.ts +72 -0
- package/src/internal/Toolbox.ts +27 -0
- package/src/internal/Wait.ts +105 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as sandboxes from "@distilled.cloud/daytona/sandbox";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { CreateSandbox } from "./CreateSandbox.js";
|
|
5
|
+
import { makeAccess, makeOwnerLabels, withOwnerLabels } from "./DaytonaBindings.js";
|
|
6
|
+
import { definedLabels } from "./internal/Labels.js";
|
|
7
|
+
import { waitForState } from "./internal/Wait.js";
|
|
8
|
+
import { volumeIdOf } from "./MountVolume.js";
|
|
9
|
+
import { makeSandboxClient } from "./SandboxClient.js";
|
|
10
|
+
/** {@link CreateSandbox} over Daytona's HTTP API; works on any host. */
|
|
11
|
+
export const CreateSandboxHttp = Layer.effect(CreateSandbox, Effect.gen(function* () {
|
|
12
|
+
const access = yield* makeAccess;
|
|
13
|
+
return Effect.fn(function* (base) {
|
|
14
|
+
const purpose = `${base?.LogicalId ?? ""}Sandboxes`;
|
|
15
|
+
const { authorize, organizationId } = yield* access(purpose, [
|
|
16
|
+
"write:sandboxes",
|
|
17
|
+
"delete:sandboxes",
|
|
18
|
+
]);
|
|
19
|
+
const ownerLabels = yield* makeOwnerLabels;
|
|
20
|
+
const baseName = base ? yield* base.name : undefined;
|
|
21
|
+
const handle = (s) => Effect.succeed(makeSandboxClient(s, organizationId, authorize));
|
|
22
|
+
const client = {
|
|
23
|
+
create: (input) => authorize(Effect.gen(function* () {
|
|
24
|
+
const labels = withOwnerLabels(input?.labels ? definedLabels(input.labels) : undefined, yield* ownerLabels);
|
|
25
|
+
const snapshot = input?.snapshot ?? (baseName ? yield* baseName : undefined);
|
|
26
|
+
const { mounts, ...request } = input ?? {};
|
|
27
|
+
const volumes = mounts
|
|
28
|
+
? yield* Effect.forEach(mounts, (m) => Effect.map(volumeIdOf(m.volume), (volumeId) => ({
|
|
29
|
+
volumeId,
|
|
30
|
+
mountPath: m.path,
|
|
31
|
+
subpath: m.subpath,
|
|
32
|
+
})))
|
|
33
|
+
: undefined;
|
|
34
|
+
const created = yield* sandboxes.createSandbox({
|
|
35
|
+
...request,
|
|
36
|
+
snapshot,
|
|
37
|
+
labels,
|
|
38
|
+
volumes,
|
|
39
|
+
});
|
|
40
|
+
return yield* waitForState({
|
|
41
|
+
kind: "sandbox",
|
|
42
|
+
id: created.id,
|
|
43
|
+
observe: sandboxes.getSandbox({ sandboxIdOrName: created.id }),
|
|
44
|
+
want: ["started"],
|
|
45
|
+
fail: ["error", "build_failed", "destroyed"],
|
|
46
|
+
reason: (s) => s.errorReason,
|
|
47
|
+
budget: "5 minutes",
|
|
48
|
+
});
|
|
49
|
+
})).pipe(Effect.flatMap(handle)),
|
|
50
|
+
get: (idOrName) => authorize(sandboxes.getSandbox({ sandboxIdOrName: idOrName }).pipe(Effect.map((s) => s.state === "destroyed" || s.state === "destroying" ? undefined : s), Effect.catchTag("SandboxNotFound", () => Effect.undefined))).pipe(Effect.flatMap((s) => (s ? handle(s) : Effect.undefined))),
|
|
51
|
+
list: (input) => authorize(Effect.gen(function* () {
|
|
52
|
+
const snapshots = input?.snapshots ?? (baseName ? [yield* baseName] : undefined);
|
|
53
|
+
const page = yield* sandboxes.listSandboxes({
|
|
54
|
+
...input,
|
|
55
|
+
snapshots,
|
|
56
|
+
labels: input?.labels ? JSON.stringify(input.labels) : undefined,
|
|
57
|
+
});
|
|
58
|
+
return page.items;
|
|
59
|
+
})),
|
|
60
|
+
delete: (idOrName) => authorize(sandboxes.deleteSandbox({ sandboxIdOrName: idOrName }).pipe(Effect.asVoid, Effect.catchTag("SandboxNotFound", () => Effect.void))),
|
|
61
|
+
};
|
|
62
|
+
return client;
|
|
63
|
+
});
|
|
64
|
+
}));
|
|
65
|
+
//# sourceMappingURL=CreateSandboxHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSandboxHttp.js","sources":["../src/CreateSandboxHttp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,kCAAkC,CAAC;AAC9D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,aAAa,EAA4B,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD,wEAAwE;AACxE,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAC3C,aAAa,EACb,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC;IACjC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAe;QACzC,MAAM,OAAO,GAAG,GAAG,IAAI,EAAE,SAAS,IAAI,EAAE,WAAW,CAAC;QACpD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;YAC3D,iBAAiB;YACjB,kBAAkB;SACnB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,eAAe,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAErD,MAAM,MAAM,GAAG,CAAC,CAAqB,EAAE,EAAE,CACvC,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EAAE,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;QAElE,MAAM,MAAM,GAAwB;YAClC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAChB,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,MAAM,GAAG,eAAe,CAC5B,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,EACvD,KAAK,CAAC,CAAC,WAAW,CACnB,CAAC;gBACF,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAQ,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC7E,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC3C,MAAM,OAAO,GAAG,MAAM;oBACpB,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAClC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;wBAC9C,QAAQ;wBACR,SAAS,EAAE,CAAC,CAAC,IAAI;wBACjB,OAAO,EAAE,CAAC,CAAC,OAAO;qBACnB,CAAC,CAAC,CACJ;oBACH,CAAC,CAAC,SAAS,CAAC;gBACd,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC;oBAC7C,GAAG,OAAO;oBACV,QAAQ;oBACR,MAAM;oBACN,OAAO;iBACR,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC;oBACzB,IAAI,EAAE,SAAS;oBACf,EAAE,EAAE,OAAO,CAAC,EAAE;oBACd,OAAO,EAAE,SAAS,CAAC,UAAU,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;oBAC9D,IAAI,EAAE,CAAC,SAAS,CAAC;oBACjB,IAAI,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,CAAC;oBAC5C,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW;oBAC5B,MAAM,EAAE,WAAW;iBACpB,CAAC,CAAC;YACL,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAChC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,CAChB,SAAS,CACP,SAAS,CAAC,UAAU,CAAC,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CACtD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACf,CAAC,CAAC,KAAK,KAAK,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CACpE,EACD,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAC3D,CACF,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YACnE,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CACd,SAAS,CACP,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAClB,MAAM,SAAS,GAAG,KAAK,EAAE,SAAS,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBACjF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC;oBAC1C,GAAG,KAAK;oBACR,SAAS;oBACT,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;iBACjE,CAAC,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC,CAAC,CACH;YACH,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CACnB,SAAS,CACP,SAAS,CAAC,aAAa,CAAC,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CACzD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CACtD,CACF;SACJ,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type * as secrets from "@distilled.cloud/daytona/secret";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type * as Redacted from "effect/Redacted";
|
|
6
|
+
import type { SecretAttributes } from "./Secret.ts";
|
|
7
|
+
export interface CreateSecretClient {
|
|
8
|
+
/**
|
|
9
|
+
* Create the secret, or write a new value (and description and hosts)
|
|
10
|
+
* to the one with this name. Returns the same attributes as
|
|
11
|
+
* `Daytona.Secret`; pass `placeholder` into a sandbox's env or the
|
|
12
|
+
* secret's `name` in `secrets`.
|
|
13
|
+
*/
|
|
14
|
+
put(input: {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly value: string | Redacted.Redacted<string>;
|
|
17
|
+
readonly description?: string;
|
|
18
|
+
readonly hosts?: string[];
|
|
19
|
+
}): Effect.Effect<SecretAttributes, secrets.CreateSecretError | secrets.UpdateSecretError | secrets.ListSecretsPaginatedError, RuntimeContext>;
|
|
20
|
+
/** The secret with this name, or `undefined`. Values are never returned. */
|
|
21
|
+
get(name: string): Effect.Effect<SecretAttributes | undefined, secrets.ListSecretsPaginatedError, RuntimeContext>;
|
|
22
|
+
/** Every secret in the organization. */
|
|
23
|
+
list(): Effect.Effect<SecretAttributes[], secrets.ListSecretsPaginatedError, RuntimeContext>;
|
|
24
|
+
/** Delete the secret with this name. Deleting a missing one succeeds. */
|
|
25
|
+
delete(name: string): Effect.Effect<void, secrets.DeleteSecretError | secrets.ListSecretsPaginatedError, RuntimeContext>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Store secrets in Daytona at runtime: a credential per user, injected
|
|
29
|
+
* into that user's sandboxes without the sandbox (or an agent in it)
|
|
30
|
+
* ever seeing the value. Daytona swaps the placeholder for the value only
|
|
31
|
+
* on requests to the secret's `hosts`.
|
|
32
|
+
*
|
|
33
|
+
* The host gets its own Daytona API key with `manage:secrets`. Secrets
|
|
34
|
+
* have no labels, so each one it creates carries `stack/stage/id` in its
|
|
35
|
+
* description. They are not deleted when the stack is destroyed: list them
|
|
36
|
+
* (`list()`) and match the description to clean them up.
|
|
37
|
+
*
|
|
38
|
+
* ### A Credential per User
|
|
39
|
+
* **Example:** The user's GitHub token, only sent to GitHub's API
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const secrets = yield* Daytona.CreateSecret();
|
|
42
|
+
* const github = yield* secrets.put({
|
|
43
|
+
* name: `github-${user}`,
|
|
44
|
+
* value: token,
|
|
45
|
+
* hosts: ["api.github.com"],
|
|
46
|
+
* });
|
|
47
|
+
* const sandbox = yield* sandboxes.create({ secrets: [{ GITHUB_TOKEN: github.name }] });
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @binding
|
|
51
|
+
* @product Secret
|
|
52
|
+
*/
|
|
53
|
+
export interface CreateSecret extends Binding.Service<CreateSecret, "Daytona.CreateSecret", () => Effect.Effect<CreateSecretClient>> {
|
|
54
|
+
}
|
|
55
|
+
export declare const CreateSecret: CreateSecret;
|
|
56
|
+
//# sourceMappingURL=CreateSecret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSecret.d.ts","sources":["../src/CreateSecret.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,iCAAiC,CAAC;AAChE,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE;QACT,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnD,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,GAAG,MAAM,CAAC,MAAM,CACf,gBAAgB,EAChB,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,EACzF,cAAc,CACf,CAAC;IACF,4EAA4E;IAC5E,GAAG,CACD,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,EAAE,OAAO,CAAC,yBAAyB,EAAE,cAAc,CAAC,CAAC;IAClG,wCAAwC;IACxC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,OAAO,CAAC,yBAAyB,EAAE,cAAc,CAAC,CAAC;IAC7F,yEAAyE;IACzE,MAAM,CACJ,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,yBAAyB,EAC7D,cAAc,CACf,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,OAAO,CACnD,YAAY,EACZ,sBAAsB,EACtB,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CACxC;CAAG;AAEJ,eAAO,MAAM,YAAY,cAAwD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSecret.js","sources":["../src/CreateSecret.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAuE3C,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAe,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
import { CreateSecret } from "./CreateSecret.ts";
|
|
3
|
+
/** {@link CreateSecret} over Daytona's HTTP API; works on any host. */
|
|
4
|
+
export declare const CreateSecretHttp: Layer.Layer<CreateSecret, never, never>;
|
|
5
|
+
//# sourceMappingURL=CreateSecretHttp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSecretHttp.d.ts","sources":["../src/CreateSecretHttp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,YAAY,EAA2B,MAAM,mBAAmB,CAAC;AAI1E,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,yCAgD5B,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as secrets from "@distilled.cloud/daytona/secret";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as Stream from "effect/Stream";
|
|
5
|
+
import { CreateSecret } from "./CreateSecret.js";
|
|
6
|
+
import { makeAccess, makeOwnerLabels, ownerDescription } from "./DaytonaBindings.js";
|
|
7
|
+
import { ensureSecret, findSecretByName, toSecretAttributes } from "./Secret.js";
|
|
8
|
+
/** {@link CreateSecret} over Daytona's HTTP API; works on any host. */
|
|
9
|
+
export const CreateSecretHttp = Layer.effect(CreateSecret, Effect.gen(function* () {
|
|
10
|
+
const access = yield* makeAccess;
|
|
11
|
+
return Effect.fn(function* () {
|
|
12
|
+
const { authorize } = yield* access("Secrets", ["manage:secrets"]);
|
|
13
|
+
// Secrets have no labels, so the owner goes in the description.
|
|
14
|
+
const marker = Effect.map(yield* makeOwnerLabels, ownerDescription);
|
|
15
|
+
const client = {
|
|
16
|
+
put: (input) => authorize(Effect.gen(function* () {
|
|
17
|
+
const mark = yield* marker;
|
|
18
|
+
return yield* ensureSecret({
|
|
19
|
+
name: input.name,
|
|
20
|
+
value: input.value,
|
|
21
|
+
description: input.description ? `${input.description} (${mark})` : mark,
|
|
22
|
+
hosts: input.hosts,
|
|
23
|
+
});
|
|
24
|
+
})),
|
|
25
|
+
get: (name) => authorize(findSecretByName(name).pipe(Effect.map((s) => (s ? toSecretAttributes(s, "") : undefined)))),
|
|
26
|
+
list: () => authorize(secrets.listSecretsPaginated.items({}).pipe(Stream.runCollect, Effect.map((all) => Array.from(all, (s) => toSecretAttributes(s, ""))))),
|
|
27
|
+
delete: (name) => authorize(Effect.gen(function* () {
|
|
28
|
+
const found = yield* findSecretByName(name);
|
|
29
|
+
if (found === undefined)
|
|
30
|
+
return;
|
|
31
|
+
yield* secrets
|
|
32
|
+
.deleteSecret({ secretId: found.id })
|
|
33
|
+
.pipe(Effect.catchTag("SecretNotFound", () => Effect.void));
|
|
34
|
+
})),
|
|
35
|
+
};
|
|
36
|
+
return client;
|
|
37
|
+
});
|
|
38
|
+
}));
|
|
39
|
+
//# sourceMappingURL=CreateSecretHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSecretHttp.js","sources":["../src/CreateSecretHttp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { UnsupportedDockerfile } from "@alchemy.run/docker/BuildPlan";
|
|
2
|
+
import type { DockerfileSyntaxError } from "@alchemy.run/docker/DockerfileParser";
|
|
3
|
+
import type * as sandboxes from "@distilled.cloud/daytona/sandbox";
|
|
4
|
+
import type * as snapshots from "@distilled.cloud/daytona/snapshots";
|
|
5
|
+
import * as Binding from "alchemy/Binding";
|
|
6
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
7
|
+
import type * as Effect from "effect/Effect";
|
|
8
|
+
import type { NameOutsidePrefix } from "./CreateVolume.ts";
|
|
9
|
+
import type { ProcessError } from "./internal/Errors.ts";
|
|
10
|
+
import type { StateFailed, StateTimeout } from "./internal/Wait.ts";
|
|
11
|
+
import type { ResolvedSnapshotSource, SnapshotAttributes, SnapshotContextUnsupported, SnapshotImageTagInvalid, SnapshotRunFailed } from "./Snapshot.ts";
|
|
12
|
+
/** `create` input: a name and one source, as `Daytona.Snapshot` takes them (Dockerfile as content). */
|
|
13
|
+
export interface CreateSnapshotInput extends Omit<ResolvedSnapshotSource, "contextHashes"> {
|
|
14
|
+
readonly name: string;
|
|
15
|
+
}
|
|
16
|
+
export interface CreateSnapshotClient {
|
|
17
|
+
/**
|
|
18
|
+
* Build a snapshot and wait until it is active: pull `image`, build
|
|
19
|
+
* `dockerfile` on Daytona, or start a sandbox from `from`, `run` the
|
|
20
|
+
* commands and capture it. Returns the same attributes as
|
|
21
|
+
* `Daytona.Snapshot`.
|
|
22
|
+
*/
|
|
23
|
+
create(input: CreateSnapshotInput): Effect.Effect<SnapshotAttributes, snapshots.CreateSnapshotError | snapshots.GetSnapshotError | snapshots.ActivateSnapshotError | sandboxes.CreateSandboxError | sandboxes.GetSandboxError | sandboxes.CreateSandboxSnapshotError | ProcessError | SnapshotRunFailed | SnapshotImageTagInvalid | SnapshotContextUnsupported | UnsupportedDockerfile | DockerfileSyntaxError | StateTimeout | StateFailed | NameOutsidePrefix, RuntimeContext>;
|
|
24
|
+
/** The snapshot with this id or name, or `undefined`. */
|
|
25
|
+
get(idOrName: string): Effect.Effect<SnapshotAttributes | undefined, snapshots.GetSnapshotError, RuntimeContext>;
|
|
26
|
+
/** Snapshots matching Daytona's list filters. */
|
|
27
|
+
list(input?: Omit<snapshots.GetAllSnapshotsRequest, "xDaytonaOrganizationID" | "page">): Effect.Effect<SnapshotAttributes[], snapshots.GetAllSnapshotsError, RuntimeContext>;
|
|
28
|
+
/** Make a deactivated snapshot usable again and wait until it is active. */
|
|
29
|
+
activate(idOrName: string): Effect.Effect<SnapshotAttributes, snapshots.GetSnapshotError | snapshots.ActivateSnapshotError | StateTimeout | StateFailed, RuntimeContext>;
|
|
30
|
+
/** Deactivate a snapshot; sandboxes can't be created from it until it is activated. */
|
|
31
|
+
deactivate(idOrName: string): Effect.Effect<void, snapshots.DeactivateSnapshotError, RuntimeContext>;
|
|
32
|
+
/** A URL streaming the snapshot's build logs. */
|
|
33
|
+
buildLogsUrl(idOrName: string): Effect.Effect<snapshots.Url, snapshots.GetSnapshotBuildLogsUrlError, RuntimeContext>;
|
|
34
|
+
/** Delete a snapshot and wait until it is gone. Deleting a missing one succeeds. */
|
|
35
|
+
delete(idOrName: string): Effect.Effect<void, snapshots.RemoveSnapshotError | snapshots.GetSnapshotError | StateTimeout, RuntimeContext>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Options for {@link CreateSnapshot}. Snapshots have only a name, no labels
|
|
39
|
+
* or description, so a `prefix` is how you find the ones a binding
|
|
40
|
+
* created: the binding refuses names that don't start with it.
|
|
41
|
+
*/
|
|
42
|
+
export interface CreateSnapshotOptions {
|
|
43
|
+
/** Every name the binding creates must start with this. */
|
|
44
|
+
readonly prefix?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build Daytona snapshots at runtime: a warm base per repository, built
|
|
48
|
+
* when it's first needed, that later sandboxes start from. To capture a
|
|
49
|
+
* sandbox you already have, use `sandbox.createSandboxSnapshot` on its
|
|
50
|
+
* handle.
|
|
51
|
+
*
|
|
52
|
+
* The host gets its own Daytona API key with `write:snapshots`,
|
|
53
|
+
* `delete:snapshots` and, for `from` builds, `write:sandboxes` and
|
|
54
|
+
* `delete:sandboxes`. Snapshots have only a name, so the `prefix` you give
|
|
55
|
+
* is how you find the ones it created. They are not deleted when the stack
|
|
56
|
+
* is destroyed: `list()` and delete the names with your prefix to clean
|
|
57
|
+
* them up.
|
|
58
|
+
*
|
|
59
|
+
* ### A Warm Base per Repository
|
|
60
|
+
* **Example:** Build it on first use, then start sandboxes from it
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const images = yield* Daytona.CreateSnapshot({ prefix: "repo-" });
|
|
63
|
+
* const name = `repo-${owner}-${repo}`;
|
|
64
|
+
* const base =
|
|
65
|
+
* (yield* images.get(name)) ??
|
|
66
|
+
* (yield* images.create({
|
|
67
|
+
* name,
|
|
68
|
+
* from: "daytonaio/sandbox:0.4.3",
|
|
69
|
+
* run: [`git clone https://github.com/${owner}/${repo} /home/daytona/repo`, "cd /home/daytona/repo && npm ci"],
|
|
70
|
+
* }));
|
|
71
|
+
* const sandbox = yield* sandboxes.create({ snapshot: base.name });
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @binding
|
|
75
|
+
* @product Snapshot
|
|
76
|
+
*/
|
|
77
|
+
export interface CreateSnapshot extends Binding.Service<CreateSnapshot, "Daytona.CreateSnapshot", (options?: CreateSnapshotOptions) => Effect.Effect<CreateSnapshotClient>> {
|
|
78
|
+
}
|
|
79
|
+
export declare const CreateSnapshot: CreateSnapshot;
|
|
80
|
+
//# sourceMappingURL=CreateSnapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSnapshot.d.ts","sources":["../src/CreateSnapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSnapshot.js","sources":["../src/CreateSnapshot.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAgI3C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAAiB,wBAAwB,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
import { CreateSnapshot } from "./CreateSnapshot.ts";
|
|
3
|
+
/** {@link CreateSnapshot} over Daytona's HTTP API; works on any host. */
|
|
4
|
+
export declare const CreateSnapshotHttp: Layer.Layer<CreateSnapshot, never, never>;
|
|
5
|
+
//# sourceMappingURL=CreateSnapshotHttp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSnapshotHttp.d.ts","sources":["../src/CreateSnapshotHttp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,EACL,cAAc,EAGf,MAAM,qBAAqB,CAAC;AAY7B,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,2CAuD9B,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as snapshots from "@distilled.cloud/daytona/snapshots";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import * as Stream from "effect/Stream";
|
|
5
|
+
import { CreateSnapshot, } from "./CreateSnapshot.js";
|
|
6
|
+
import { NameOutsidePrefix } from "./CreateVolume.js";
|
|
7
|
+
import { makeAccess, makeOwnerLabels } from "./DaytonaBindings.js";
|
|
8
|
+
import { buildSnapshot, checkRuntimeDockerfile, deleteSnapshot, getSnapshot, toSnapshotAttributes, waitForSnapshot, } from "./Snapshot.js";
|
|
9
|
+
/** {@link CreateSnapshot} over Daytona's HTTP API; works on any host. */
|
|
10
|
+
export const CreateSnapshotHttp = Layer.effect(CreateSnapshot, Effect.gen(function* () {
|
|
11
|
+
const access = yield* makeAccess;
|
|
12
|
+
return Effect.fn(function* (options) {
|
|
13
|
+
const { authorize } = yield* access("Snapshots", [
|
|
14
|
+
"write:snapshots",
|
|
15
|
+
"delete:snapshots",
|
|
16
|
+
"write:sandboxes",
|
|
17
|
+
"delete:sandboxes",
|
|
18
|
+
]);
|
|
19
|
+
// A snapshot has only a name: `prefix` scopes it. The owner labels go
|
|
20
|
+
// on the sandbox a warm base is captured from.
|
|
21
|
+
const labels = yield* makeOwnerLabels;
|
|
22
|
+
const prefix = options?.prefix;
|
|
23
|
+
const client = {
|
|
24
|
+
create: ({ name, ...source }) => prefix !== undefined && !name.startsWith(prefix)
|
|
25
|
+
? Effect.fail(new NameOutsidePrefix({ objectName: name, prefix }))
|
|
26
|
+
: authorize(Effect.gen(function* () {
|
|
27
|
+
if (source.dockerfile !== undefined)
|
|
28
|
+
yield* checkRuntimeDockerfile(source.dockerfile);
|
|
29
|
+
const built = yield* buildSnapshot({
|
|
30
|
+
name,
|
|
31
|
+
source,
|
|
32
|
+
labels: yield* labels,
|
|
33
|
+
note: () => Effect.void,
|
|
34
|
+
});
|
|
35
|
+
return toSnapshotAttributes(built, "");
|
|
36
|
+
})),
|
|
37
|
+
get: (idOrName) => authorize(getSnapshot(idOrName).pipe(Effect.map((s) => (s ? toSnapshotAttributes(s, "") : undefined)))),
|
|
38
|
+
list: (input) => authorize(snapshots.getAllSnapshots.items({ ...input }).pipe(Stream.runCollect, Effect.map((all) => Array.from(all, (s) => toSnapshotAttributes(s, ""))))),
|
|
39
|
+
activate: (idOrName) => authorize(waitForSnapshot(idOrName).pipe(Effect.map((s) => toSnapshotAttributes(s, "")))),
|
|
40
|
+
deactivate: (idOrName) => authorize(snapshots.deactivateSnapshot({ id: idOrName }).pipe(Effect.asVoid)),
|
|
41
|
+
buildLogsUrl: (idOrName) => authorize(snapshots.getSnapshotBuildLogsUrl({ id: idOrName })),
|
|
42
|
+
delete: (idOrName) => authorize(deleteSnapshot(idOrName)),
|
|
43
|
+
};
|
|
44
|
+
return client;
|
|
45
|
+
});
|
|
46
|
+
}));
|
|
47
|
+
//# sourceMappingURL=CreateSnapshotHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateSnapshotHttp.js","sources":["../src/CreateSnapshotHttp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type * as volumes from "@distilled.cloud/daytona/volumes";
|
|
2
|
+
import * as Binding from "alchemy/Binding";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import type * as Effect from "effect/Effect";
|
|
5
|
+
import type { StateFailed, StateTimeout } from "./internal/Wait.ts";
|
|
6
|
+
import type { VolumeAttributes } from "./Volume.ts";
|
|
7
|
+
declare const NameOutsidePrefix_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
8
|
+
readonly _tag: "Daytona.NameOutsidePrefix";
|
|
9
|
+
} & Readonly<A>;
|
|
10
|
+
/** A name outside the binding's `prefix`. */
|
|
11
|
+
export declare class NameOutsidePrefix extends NameOutsidePrefix_base<{
|
|
12
|
+
readonly objectName: string;
|
|
13
|
+
readonly prefix: string;
|
|
14
|
+
}> {
|
|
15
|
+
get message(): string;
|
|
16
|
+
}
|
|
17
|
+
export interface CreateVolumeClient {
|
|
18
|
+
/**
|
|
19
|
+
* The volume named `name`, created (and waited on until ready) if it
|
|
20
|
+
* doesn't exist. Returns the same attributes as `Daytona.Volume`.
|
|
21
|
+
*/
|
|
22
|
+
getOrCreate(input: {
|
|
23
|
+
readonly name: string;
|
|
24
|
+
}): Effect.Effect<VolumeAttributes, volumes.CreateVolumeError | volumes.GetVolumeByNameError | volumes.GetVolumeError | StateTimeout | StateFailed | NameOutsidePrefix, RuntimeContext>;
|
|
25
|
+
/** The volume with this name, or `undefined`. */
|
|
26
|
+
get(name: string): Effect.Effect<VolumeAttributes | undefined, volumes.GetVolumeByNameError, RuntimeContext>;
|
|
27
|
+
/** Every volume in the organization. */
|
|
28
|
+
list(): Effect.Effect<VolumeAttributes[], volumes.ListVolumesError, RuntimeContext>;
|
|
29
|
+
/**
|
|
30
|
+
* Delete a volume. Returns once Daytona has accepted the delete; it
|
|
31
|
+
* removes the volume in the background. Fails with `VolumeInUse` while a
|
|
32
|
+
* sandbox mounts it: Daytona releases a volume about a minute after the
|
|
33
|
+
* sandbox that wrote to it is deleted, so retry later. Deleting a missing
|
|
34
|
+
* one succeeds.
|
|
35
|
+
*/
|
|
36
|
+
delete(volumeId: string): Effect.Effect<void, volumes.DeleteVolumeError | volumes.GetVolumeError | StateTimeout, RuntimeContext>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Options for {@link CreateVolume}. Volumes have only a name, no labels or
|
|
40
|
+
* description, so a `prefix` is how you find the ones a binding created:
|
|
41
|
+
* the binding refuses names that don't start with it.
|
|
42
|
+
*/
|
|
43
|
+
export interface CreateVolumeOptions {
|
|
44
|
+
/** Every name the binding creates or gets must start with this. */
|
|
45
|
+
readonly prefix?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create, find and delete Daytona volumes at runtime: a volume per user,
|
|
49
|
+
* per project or per session, mounted into the sandboxes you create.
|
|
50
|
+
*
|
|
51
|
+
* The host gets its own Daytona API key with `read:volumes`,
|
|
52
|
+
* `write:volumes` and `delete:volumes`. Volumes have only a name, so the
|
|
53
|
+
* `prefix` you give is how you find the ones it created. They are not
|
|
54
|
+
* deleted when the stack is destroyed: `list()` and delete the names with
|
|
55
|
+
* your prefix to clean them up.
|
|
56
|
+
*
|
|
57
|
+
* ### Volume per User
|
|
58
|
+
* **Example:** Mount the user's volume as their home directory
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const volumes = yield* Daytona.CreateVolume({ prefix: "user-" });
|
|
61
|
+
* const sandboxes = yield* Daytona.CreateSandbox(Base);
|
|
62
|
+
* return {
|
|
63
|
+
* fetch: Effect.gen(function* () {
|
|
64
|
+
* const home = yield* volumes.getOrCreate({ name: `user-${user}` });
|
|
65
|
+
* const sandbox = yield* sandboxes.create({
|
|
66
|
+
* mounts: [{ volume: home, path: "/home/daytona/work" }],
|
|
67
|
+
* });
|
|
68
|
+
* const ls = yield* sandbox.exec("ls /home/daytona/work");
|
|
69
|
+
* return yield* HttpServerResponse.json(ls);
|
|
70
|
+
* }),
|
|
71
|
+
* };
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @binding
|
|
75
|
+
* @product Volume
|
|
76
|
+
*/
|
|
77
|
+
export interface CreateVolume extends Binding.Service<CreateVolume, "Daytona.CreateVolume", (options?: CreateVolumeOptions) => Effect.Effect<CreateVolumeClient>> {
|
|
78
|
+
}
|
|
79
|
+
export declare const CreateVolume: CreateVolume;
|
|
80
|
+
export {};
|
|
81
|
+
//# sourceMappingURL=CreateVolume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateVolume.d.ts","sources":["../src/CreateVolume.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kCAAkC,CAAC;AACjE,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;;;;AAEpD,6CAA6C;AAC7C,qBAAa,iBAAkB,SAAQ,uBAA8C;IACnF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;IACA,IAAa,OAAO,WAEnB;CACF;AAED,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,WAAW,CAAC,KAAK,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,GAAG,MAAM,CAAC,MAAM,CACf,gBAAgB,EACd,OAAO,CAAC,iBAAiB,GACzB,OAAO,CAAC,oBAAoB,GAC5B,OAAO,CAAC,cAAc,GACtB,YAAY,GACZ,WAAW,GACX,iBAAiB,EACnB,cAAc,CACf,CAAC;IACF,iDAAiD;IACjD,GAAG,CACD,IAAI,EAAE,MAAM,GACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,EAAE,OAAO,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC;IAC7F,wCAAwC;IACxC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,OAAO,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACpF;;;;;;OAMG;IACH,MAAM,CACJ,QAAQ,EAAE,MAAM,GACf,MAAM,CAAC,MAAM,CACd,IAAI,EACJ,OAAO,CAAC,iBAAiB,GAAG,OAAO,CAAC,cAAc,GAAG,YAAY,EACjE,cAAc,CACf,CAAC;CACH;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,YAAa,SAAQ,OAAO,CAAC,OAAO,CACnD,YAAY,EACZ,sBAAsB,EACtB,CAAC,OAAO,CAAC,EAAE,mBAAmB,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CACrE;CAAG;AAEJ,eAAO,MAAM,YAAY,cAAwD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import * as Data from "effect/Data";
|
|
3
|
+
/** A name outside the binding's `prefix`. */
|
|
4
|
+
export class NameOutsidePrefix extends Data.TaggedError("Daytona.NameOutsidePrefix") {
|
|
5
|
+
get message() {
|
|
6
|
+
return `${this.objectName} must start with ${this.prefix}: the binding only manages names with that prefix`;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export const CreateVolume = Binding.Service("Daytona.CreateVolume");
|
|
10
|
+
//# sourceMappingURL=CreateVolume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateVolume.js","sources":["../src/CreateVolume.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAC;AAE3C,OAAO,KAAK,IAAI,MAAM,aAAa,CAAC;AAKpC,6CAA6C;AAC7C,MAAM,OAAO,iBAAkB,SAAQ,IAAI,CAAC,WAAW,CAAC,2BAA2B,CAGjF;IACA,IAAa,OAAO;QAClB,OAAO,GAAG,IAAI,CAAC,UAAU,oBAAoB,IAAI,CAAC,MAAM,mDAAmD,CAAC;IAC9G,CAAC;CACF;AAuFD,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAe,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as Layer from "effect/Layer";
|
|
2
|
+
import { CreateVolume } from "./CreateVolume.ts";
|
|
3
|
+
/** {@link CreateVolume} over Daytona's HTTP API; works on any host. */
|
|
4
|
+
export declare const CreateVolumeHttp: Layer.Layer<CreateVolume, never, never>;
|
|
5
|
+
//# sourceMappingURL=CreateVolumeHttp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateVolumeHttp.d.ts","sources":["../src/CreateVolumeHttp.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,YAAY,EAIb,MAAM,mBAAmB,CAAC;AAI3B,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,yCAoC5B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as volumes from "@distilled.cloud/daytona/volumes";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { CreateVolume, NameOutsidePrefix, } from "./CreateVolume.js";
|
|
5
|
+
import { makeAccess } from "./DaytonaBindings.js";
|
|
6
|
+
import { deleteVolumeById, ensureVolume, getVolumeByName, toVolumeAttributes } from "./Volume.js";
|
|
7
|
+
/** {@link CreateVolume} over Daytona's HTTP API; works on any host. */
|
|
8
|
+
export const CreateVolumeHttp = Layer.effect(CreateVolume, Effect.gen(function* () {
|
|
9
|
+
const access = yield* makeAccess;
|
|
10
|
+
return Effect.fn(function* (options) {
|
|
11
|
+
const { authorize } = yield* access("Volumes", [
|
|
12
|
+
"read:volumes",
|
|
13
|
+
"write:volumes",
|
|
14
|
+
"delete:volumes",
|
|
15
|
+
]);
|
|
16
|
+
// A volume has only a name: `prefix` scopes it.
|
|
17
|
+
const prefix = options?.prefix;
|
|
18
|
+
const client = {
|
|
19
|
+
getOrCreate: ({ name }) => prefix !== undefined && !name.startsWith(prefix)
|
|
20
|
+
? Effect.fail(new NameOutsidePrefix({ objectName: name, prefix }))
|
|
21
|
+
: authorize(ensureVolume(name).pipe(Effect.map(toVolumeAttributes))),
|
|
22
|
+
get: (name) => authorize(getVolumeByName(name).pipe(Effect.map((v) => (v ? toVolumeAttributes(v) : undefined)))),
|
|
23
|
+
list: () => authorize(volumes
|
|
24
|
+
.listVolumes({})
|
|
25
|
+
.pipe(Effect.map((all) => all.filter((v) => v.state !== "deleted").map(toVolumeAttributes)))),
|
|
26
|
+
delete: (volumeId) => authorize(deleteVolumeById(volumeId, { wait: false })),
|
|
27
|
+
};
|
|
28
|
+
return client;
|
|
29
|
+
});
|
|
30
|
+
}));
|
|
31
|
+
//# sourceMappingURL=CreateVolumeHttp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CreateVolumeHttp.js","sources":["../src/CreateVolumeHttp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,kCAAkC,CAAC;AAC5D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EACL,YAAY,EACZ,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAElG,uEAAuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAC1C,YAAY,EACZ,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC;IACjC,OAAO,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,OAA6B;QACvD,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;YAC7C,cAAc;YACd,eAAe;YACf,gBAAgB;SACjB,CAAC,CAAC;QACH,gDAAgD;QAChD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;QAC/B,MAAM,MAAM,GAAuB;YACjC,WAAW,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CACxB,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;gBAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBAClE,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACxE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CACZ,SAAS,CACP,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CACvF;YACH,IAAI,EAAE,GAAG,EAAE,CACT,SAAS,CACP,OAAO;iBACJ,WAAW,CAAC,EAAE,CAAC;iBACf,IAAI,CACH,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CACjE,CACF,CACJ;YACH,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;SAC7E,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Credentials } from "@distilled.cloud/daytona/Credentials";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_ANALYTICS_BASE_URL, DEFAULT_API_BASE_URL, DEFAULT_TOOLBOX_BASE_URL, } from "@distilled.cloud/daytona/Credentials";
|
|
4
|
+
/**
|
|
5
|
+
* A `Credentials` layer that resolves Daytona credentials through the
|
|
6
|
+
* Alchemy AuthProvider for the current profile.
|
|
7
|
+
*/
|
|
8
|
+
export declare const fromAuthProvider: () => Layer.Layer<Credentials, never, import("alchemy/Auth/Registry").AuthProviders | import("alchemy/Auth/Profile").ProfileStore>;
|
|
9
|
+
//# sourceMappingURL=Credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.d.ts","sources":["../src/Credentials.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EAGZ,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAGtC,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAE9C;;;GAGG;AACH,eAAO,MAAM,gBAAgB,oIAc1B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/core/errors";
|
|
2
|
+
import { Credentials, DEFAULT_ANALYTICS_BASE_URL, DEFAULT_TOOLBOX_BASE_URL, } from "@distilled.cloud/daytona/Credentials";
|
|
3
|
+
import { lazyCredentials } from "alchemy/Auth/Resolve";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { DAYTONA_AUTH_PROVIDER_NAME } from "./AuthProvider.js";
|
|
6
|
+
export { Credentials, CredentialsFromEnv, DEFAULT_ANALYTICS_BASE_URL, DEFAULT_API_BASE_URL, DEFAULT_TOOLBOX_BASE_URL, } from "@distilled.cloud/daytona/Credentials";
|
|
7
|
+
/**
|
|
8
|
+
* A `Credentials` layer that resolves Daytona credentials through the
|
|
9
|
+
* Alchemy AuthProvider for the current profile.
|
|
10
|
+
*/
|
|
11
|
+
export const fromAuthProvider = () => Layer.effect(Credentials, lazyCredentials()(DAYTONA_AUTH_PROVIDER_NAME, (creds) => ({
|
|
12
|
+
apiKey: creds.token,
|
|
13
|
+
apiBaseUrl: creds.apiBaseUrl,
|
|
14
|
+
analyticsBaseUrl: DEFAULT_ANALYTICS_BASE_URL,
|
|
15
|
+
toolboxBaseUrl: DEFAULT_TOOLBOX_BASE_URL,
|
|
16
|
+
organizationId: creds.organizationId,
|
|
17
|
+
}), { expiresAt: (creds) => creds.expires }));
|
|
18
|
+
//# sourceMappingURL=Credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Credentials.js","sources":["../src/Credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EACL,WAAW,EACX,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,0BAA0B,EAAmC,MAAM,mBAAmB,CAAC;AAEhG,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,sCAAsC,CAAC;AAE9C;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,EAAE,CACnC,KAAK,CAAC,MAAM,CACV,WAAW,EACX,eAAe,EAA2C,CACxD,0BAA0B,EAC1B,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACV,MAAM,EAAE,KAAK,CAAC,KAAK;IACnB,UAAU,EAAE,KAAK,CAAC,UAAU;IAC5B,gBAAgB,EAAE,0BAA0B;IAC5C,cAAc,EAAE,wBAAwB;IACxC,cAAc,EAAE,KAAK,CAAC,cAAc;CACrC,CAAC,EACF,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CACxC,CACF,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Credentials } from "@distilled.cloud/daytona/Credentials";
|
|
2
|
+
import * as Output from "alchemy/Output";
|
|
3
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import * as Effect from "effect/Effect";
|
|
5
|
+
import type * as HttpClient from "effect/http/HttpClient";
|
|
6
|
+
/**
|
|
7
|
+
* How a Daytona binding reaches the API from any host.
|
|
8
|
+
*
|
|
9
|
+
* Daytona authorizes with API keys whose permissions are checked per kind
|
|
10
|
+
* of object, so each binding mints its own {@link ApiKey} for its host at
|
|
11
|
+
* deploy, with only the permissions it needs, and the host reads the key
|
|
12
|
+
* back at runtime through `RuntimeContext`. The deployer's key never
|
|
13
|
+
* leaves the deploying machine, and the host works on any runtime
|
|
14
|
+
* (Cloudflare Workers, Lambda, containers) because the key travels as a
|
|
15
|
+
* plain secret, not a cloud identity.
|
|
16
|
+
*/
|
|
17
|
+
export interface DaytonaAccess {
|
|
18
|
+
/**
|
|
19
|
+
* Run Daytona operations with the host's minted key. Provides
|
|
20
|
+
* `Credentials` and an `HttpClient`; the result requires only
|
|
21
|
+
* `RuntimeContext`.
|
|
22
|
+
*/
|
|
23
|
+
readonly authorize: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Credentials | HttpClient.HttpClient> | RuntimeContext>;
|
|
24
|
+
/** The organization the key acts on. */
|
|
25
|
+
readonly organizationId: Effect.Effect<string, never, RuntimeContext>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve once, when a binding's layer is built: returns a function that
|
|
29
|
+
* mints (at deploy) and reads back (at runtime) an API key for the current
|
|
30
|
+
* host, named after the host and `purpose`, with `permissions`.
|
|
31
|
+
*/
|
|
32
|
+
export declare const makeAccess: Effect.Effect<(purpose: string, permissions: import("@distilled.cloud/daytona/api_keys").CreateApiKeyRequestPermissionsItem[]) => Effect.Effect<{
|
|
33
|
+
authorize: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Credentials | HttpClient.HttpClient>>;
|
|
34
|
+
organizationId: Output.Accessor<string>;
|
|
35
|
+
}, never, never>, never, never>;
|
|
36
|
+
/**
|
|
37
|
+
* The labels a runtime binding puts on what it creates: the host's
|
|
38
|
+
* `alchemy::stack`, `alchemy::stage` and `alchemy::id`, as Daytona label
|
|
39
|
+
* keys (`alchemy.stack`, `alchemy.stage`, `alchemy.id`; Daytona doesn't
|
|
40
|
+
* accept `::` in a key). Computed at deploy from the host's identity and
|
|
41
|
+
* bound into the host, so the runtime reads them back rather than
|
|
42
|
+
* computing them.
|
|
43
|
+
*/
|
|
44
|
+
export declare const makeOwnerLabels: Effect.Effect<Effect.Effect<Record<string, string>, never, RuntimeContext>, never, never>;
|
|
45
|
+
/** The owner labels as a description, for objects that only have one. */
|
|
46
|
+
export declare const ownerDescription: (labels: Record<string, string>) => string;
|
|
47
|
+
/** User labels with the owner labels on top: a user label never overwrites `alchemy.*`. */
|
|
48
|
+
export declare const withOwnerLabels: (user: Record<string, string> | undefined, owner: Record<string, string>) => {
|
|
49
|
+
[x: string]: string;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=DaytonaBindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DaytonaBindings.d.ts","sources":["../src/DaytonaBindings.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAGZ,MAAM,sCAAsC,CAAC;AAE9C,OAAO,KAAK,MAAM,MAAM,gBAAgB,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,KAAK,KAAK,UAAU,MAAM,wBAAwB,CAAC;AAK1D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC3B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,cAAc,CAAC,CAAC;IAC3F,wCAAwC;IACxC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;CACvE;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU;gBAQA,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;;+BAuB5D,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,2FAW1B,CAAC;AAEH,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,WAAY,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,WACkB,CAAC;AAElF,2FAA2F;AAC3F,eAAO,MAAM,eAAe,SACpB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,SACjC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;CAI7B,CAAC"}
|