@alchemy.run/daytona 0.0.0-stage → 2.0.0-beta.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +80 -2
- 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 +79 -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
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alchemy.run/daytona",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "2.0.0-beta.86",
|
|
4
|
+
"description": "Daytona sandboxes, snapshots, volumes, secrets and the in-sandbox toolbox for Alchemy.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ai-agents",
|
|
7
|
+
"alchemy",
|
|
8
|
+
"daytona",
|
|
9
|
+
"effect",
|
|
10
|
+
"infrastructure-as-code",
|
|
11
|
+
"sandbox"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://alchemy.run",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/alchemy-run/alchemy/issues"
|
|
16
|
+
},
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"author": "Sam Goodwin <sam@alchemy.run>",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/alchemy-run/alchemy.git",
|
|
22
|
+
"directory": "packages/daytona"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"lib",
|
|
26
|
+
"src"
|
|
27
|
+
],
|
|
28
|
+
"type": "module",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./lib/index.d.ts",
|
|
33
|
+
"bun": "./src/index.ts",
|
|
34
|
+
"worker": "./src/index.ts",
|
|
35
|
+
"default": "./lib/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./internal/*": null,
|
|
38
|
+
"./*": {
|
|
39
|
+
"types": "./lib/*.d.ts",
|
|
40
|
+
"bun": "./src/*.ts",
|
|
41
|
+
"worker": "./src/*.ts",
|
|
42
|
+
"default": "./lib/*.js"
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@alchemy.run/docker": "2.0.0-beta.86",
|
|
51
|
+
"@distilled.cloud/aws": "1.0.0-rc.19",
|
|
52
|
+
"@distilled.cloud/core": "1.0.0-rc.19",
|
|
53
|
+
"@distilled.cloud/daytona": "1.0.0-rc.19",
|
|
54
|
+
"rolldown": "1.2.16"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@effect/platform-node": "^4.1.4",
|
|
58
|
+
"@types/bun": "1.4.3",
|
|
59
|
+
"alchemy": "2.0.0-beta.86",
|
|
60
|
+
"effect": "^4.1.4",
|
|
61
|
+
"typescript": "^7.1.0-dev.20261105.1"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@effect/platform-node": "^4.1.4",
|
|
65
|
+
"alchemy": "2.0.0-beta.86",
|
|
66
|
+
"effect": "^4.1.4"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"@effect/platform-node": {
|
|
70
|
+
"optional": true
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
"alchemy": {
|
|
74
|
+
"contributes": [
|
|
75
|
+
"@alchemy.run/daytona/Contributions"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"build": "pnpm -r --filter \"{.}...\" run build:package",
|
|
80
|
+
"build:package": "node scripts/build.ts"
|
|
81
|
+
}
|
|
6
82
|
}
|
package/src/ApiKey.ts
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as apiKeys from "@distilled.cloud/daytona/api_keys";
|
|
2
|
+
import { Credentials } from "@distilled.cloud/daytona/Credentials";
|
|
3
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
4
|
+
import { deepEqual, isResolved } from "alchemy/Diff";
|
|
5
|
+
import * as Provider from "alchemy/Provider";
|
|
6
|
+
import { Resource } from "alchemy/Resource";
|
|
7
|
+
import * as Data from "effect/Data";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Redacted from "effect/Redacted";
|
|
10
|
+
import { isOwnedName, resolveName } from "./internal/Names.ts";
|
|
11
|
+
import { currentOrganizationId } from "./internal/Organization.ts";
|
|
12
|
+
import type { Providers } from "./Providers.ts";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A permission an API key or organization role grants. Daytona checks
|
|
16
|
+
* them per kind of object: `write:sandboxes` allows creating any sandbox in
|
|
17
|
+
* the organization, not one in particular.
|
|
18
|
+
*/
|
|
19
|
+
export type Permission = apiKeys.CreateApiKeyRequestPermissionsItem;
|
|
20
|
+
|
|
21
|
+
export interface ApiKeyProps {
|
|
22
|
+
/**
|
|
23
|
+
* Key name, unique in the organization. If omitted, a unique name is
|
|
24
|
+
* generated from the stack, stage and logical ID. Changing it replaces
|
|
25
|
+
* the key.
|
|
26
|
+
*/
|
|
27
|
+
name?: string;
|
|
28
|
+
/**
|
|
29
|
+
* What the key may do. Changing them replaces the key, since Daytona
|
|
30
|
+
* keys can't be edited.
|
|
31
|
+
*/
|
|
32
|
+
permissions: Permission[];
|
|
33
|
+
/**
|
|
34
|
+
* When the key stops working, as an ISO 8601 timestamp. Changing it
|
|
35
|
+
* replaces the key.
|
|
36
|
+
*/
|
|
37
|
+
expiresAt?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface ApiKeyAttributes {
|
|
41
|
+
/** Key name. */
|
|
42
|
+
name: string;
|
|
43
|
+
/** Permissions the key grants. */
|
|
44
|
+
permissions: Permission[];
|
|
45
|
+
/** When the key expires, if it does. */
|
|
46
|
+
expiresAt: string | undefined;
|
|
47
|
+
/** When the key was created. */
|
|
48
|
+
createdAt: string;
|
|
49
|
+
/** The Daytona API root the key belongs to. */
|
|
50
|
+
apiBaseUrl: string;
|
|
51
|
+
/** The organization the key acts on. */
|
|
52
|
+
organizationId: string;
|
|
53
|
+
/**
|
|
54
|
+
* The key itself, sent as `Authorization: Bearer <value>`. Daytona shows
|
|
55
|
+
* it only when the key is created, so alchemy keeps it in state.
|
|
56
|
+
*/
|
|
57
|
+
value: Redacted.Redacted<string>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type ApiKey = Resource<"Daytona.ApiKey", ApiKeyProps, ApiKeyAttributes, never, Providers>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A Daytona API key with a fixed set of permissions. Give each app the
|
|
64
|
+
* narrowest key it needs; Daytona checks every request against it.
|
|
65
|
+
*
|
|
66
|
+
* The runtime bindings (`Daytona.CreateSandbox`, `Daytona.CreateVolume`, …)
|
|
67
|
+
* mint one of these per host for you, with only the permissions the
|
|
68
|
+
* binding needs. Declare one yourself for CI or for a program outside
|
|
69
|
+
* alchemy.
|
|
70
|
+
*
|
|
71
|
+
* Daytona shows a key's value only once, so alchemy stores it in state as
|
|
72
|
+
* a `Redacted` value. Keys can't be edited: changing any prop mints a new
|
|
73
|
+
* key and deletes the old one.
|
|
74
|
+
*
|
|
75
|
+
* Creating keys needs a signed-in profile, or an API key with
|
|
76
|
+
* `manage:api_keys` (Daytona's managed API keys, enabled on request);
|
|
77
|
+
* otherwise Daytona refuses with `ManagedApiKeysNotEnabled`.
|
|
78
|
+
* @see https://www.daytona.io/docs/en/api-keys/
|
|
79
|
+
*
|
|
80
|
+
* ### Creating a Key
|
|
81
|
+
* **Example:** A key that can only create and delete sandboxes
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const key = yield* Daytona.ApiKey("Ci", {
|
|
84
|
+
* permissions: ["write:sandboxes", "delete:sandboxes"],
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* **Example:** A key that expires
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const key = yield* Daytona.ApiKey("Preview", {
|
|
91
|
+
* permissions: ["write:sandboxes"],
|
|
92
|
+
* expiresAt: "2027-01-01T00:00:00Z",
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @resource
|
|
97
|
+
* @product API Key
|
|
98
|
+
*/
|
|
99
|
+
export const ApiKey = Resource<ApiKey>("Daytona.ApiKey");
|
|
100
|
+
|
|
101
|
+
/** Daytona created a key but returned no value for it. */
|
|
102
|
+
export class ApiKeyValueMissing extends Data.TaggedError("Daytona.ApiKeyValueMissing")<{
|
|
103
|
+
readonly keyName: string;
|
|
104
|
+
}> {
|
|
105
|
+
override get message() {
|
|
106
|
+
return `Daytona returned no value for the new API key ${this.keyName}`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const sorted = (permissions: readonly string[]) => [...permissions].sort();
|
|
111
|
+
|
|
112
|
+
const apiRoot = Effect.gen(function* () {
|
|
113
|
+
const credentials = yield* Credentials;
|
|
114
|
+
return (yield* credentials).apiBaseUrl;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
export const ApiKeyProvider = () =>
|
|
118
|
+
Provider.effect(
|
|
119
|
+
ApiKey,
|
|
120
|
+
Effect.gen(function* () {
|
|
121
|
+
const getKey = (name: string) =>
|
|
122
|
+
apiKeys.getApiKey({ name }).pipe(Effect.catchTag("ApiKeyNotFound", () => Effect.undefined));
|
|
123
|
+
const deleteKey = (name: string) =>
|
|
124
|
+
apiKeys.deleteApiKey({ name }).pipe(Effect.catchTag("ApiKeyNotFound", () => Effect.void));
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
stables: ["name", "createdAt", "value"],
|
|
128
|
+
list: Effect.fn(function* () {
|
|
129
|
+
const keys = yield* apiKeys.listApiKeys({});
|
|
130
|
+
const apiBaseUrl = yield* apiRoot;
|
|
131
|
+
return keys.map((key) => ({
|
|
132
|
+
name: key.name,
|
|
133
|
+
permissions: key.permissions,
|
|
134
|
+
expiresAt: key.expiresAt ?? undefined,
|
|
135
|
+
createdAt: key.createdAt,
|
|
136
|
+
apiBaseUrl,
|
|
137
|
+
organizationId: key.organizationId ?? "",
|
|
138
|
+
value: Redacted.make(""),
|
|
139
|
+
}));
|
|
140
|
+
}),
|
|
141
|
+
diff: Effect.fn(function* ({ id, olds, news, output }) {
|
|
142
|
+
if (!isResolved(news) || output === undefined) return undefined;
|
|
143
|
+
const name = yield* resolveName(
|
|
144
|
+
id,
|
|
145
|
+
news.name,
|
|
146
|
+
olds?.name === news.name ? output.name : undefined,
|
|
147
|
+
);
|
|
148
|
+
if (
|
|
149
|
+
name !== output.name ||
|
|
150
|
+
!deepEqual(sorted(news.permissions), sorted(output.permissions)) ||
|
|
151
|
+
(news.expiresAt ?? undefined) !== (olds?.expiresAt ?? undefined)
|
|
152
|
+
) {
|
|
153
|
+
// A pinned name can't be held by two keys at once.
|
|
154
|
+
return { action: "replace", deleteFirst: name === output.name } as const;
|
|
155
|
+
}
|
|
156
|
+
}),
|
|
157
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
158
|
+
const name = yield* resolveName(id, olds?.name, output?.name);
|
|
159
|
+
const observed = yield* getKey(name);
|
|
160
|
+
if (observed === undefined) return undefined;
|
|
161
|
+
const attrs = {
|
|
162
|
+
name: observed.name,
|
|
163
|
+
permissions: observed.permissions,
|
|
164
|
+
expiresAt: observed.expiresAt ?? undefined,
|
|
165
|
+
createdAt: observed.createdAt,
|
|
166
|
+
apiBaseUrl: output?.apiBaseUrl ?? (yield* apiRoot),
|
|
167
|
+
organizationId: output?.organizationId ?? (yield* currentOrganizationId),
|
|
168
|
+
value: output?.value ?? Redacted.make(""),
|
|
169
|
+
};
|
|
170
|
+
// The value is only shown at creation, so a key with no state
|
|
171
|
+
// can't be adopted with it; reconcile re-mints it.
|
|
172
|
+
return (yield* isOwnedName(id, name, output !== undefined)) ? attrs : Unowned(attrs);
|
|
173
|
+
}),
|
|
174
|
+
reconcile: Effect.fn(function* ({ id, news, output, session }) {
|
|
175
|
+
const name = yield* resolveName(id, news.name, output?.name);
|
|
176
|
+
|
|
177
|
+
// Observe
|
|
178
|
+
const observed = yield* getKey(name);
|
|
179
|
+
if (
|
|
180
|
+
observed !== undefined &&
|
|
181
|
+
output !== undefined &&
|
|
182
|
+
Redacted.value(output.value) !== ""
|
|
183
|
+
) {
|
|
184
|
+
return {
|
|
185
|
+
...output,
|
|
186
|
+
permissions: observed.permissions,
|
|
187
|
+
expiresAt: observed.expiresAt ?? undefined,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Ensure: a key whose value we don't hold (lost create, adoption)
|
|
192
|
+
// is deleted and minted again.
|
|
193
|
+
if (observed !== undefined) {
|
|
194
|
+
yield* session.note(`Re-minting Daytona API key ${name}...`);
|
|
195
|
+
yield* deleteKey(name);
|
|
196
|
+
}
|
|
197
|
+
const created = yield* apiKeys.createApiKey({
|
|
198
|
+
name,
|
|
199
|
+
permissions: news.permissions,
|
|
200
|
+
expiresAt: news.expiresAt,
|
|
201
|
+
});
|
|
202
|
+
const value = Redacted.isRedacted(created.value)
|
|
203
|
+
? created.value
|
|
204
|
+
: Redacted.make(created.value);
|
|
205
|
+
if (Redacted.value(value) === "") return yield* new ApiKeyValueMissing({ keyName: name });
|
|
206
|
+
return {
|
|
207
|
+
name: created.name,
|
|
208
|
+
permissions: created.permissions,
|
|
209
|
+
expiresAt: created.expiresAt ?? undefined,
|
|
210
|
+
createdAt: created.createdAt,
|
|
211
|
+
apiBaseUrl: yield* apiRoot,
|
|
212
|
+
organizationId: yield* currentOrganizationId,
|
|
213
|
+
value,
|
|
214
|
+
};
|
|
215
|
+
}),
|
|
216
|
+
delete: Effect.fn(function* ({ output }) {
|
|
217
|
+
yield* deleteKey(output.name);
|
|
218
|
+
}),
|
|
219
|
+
};
|
|
220
|
+
}),
|
|
221
|
+
);
|