@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.
Files changed (274) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +80 -2
  3. package/lib/ApiKey.d.ts +99 -0
  4. package/lib/ApiKey.d.ts.map +1 -0
  5. package/lib/ApiKey.js +152 -0
  6. package/lib/ApiKey.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +55 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +280 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/Bootstrap.d.ts +8 -0
  12. package/lib/Bootstrap.d.ts.map +1 -0
  13. package/lib/Bootstrap.js +28 -0
  14. package/lib/Bootstrap.js.map +1 -0
  15. package/lib/ConnectSandbox.d.ts +72 -0
  16. package/lib/ConnectSandbox.d.ts.map +1 -0
  17. package/lib/ConnectSandbox.js +3 -0
  18. package/lib/ConnectSandbox.js.map +1 -0
  19. package/lib/ConnectSandboxHttp.d.ts +5 -0
  20. package/lib/ConnectSandboxHttp.d.ts.map +1 -0
  21. package/lib/ConnectSandboxHttp.js +22 -0
  22. package/lib/ConnectSandboxHttp.js.map +1 -0
  23. package/lib/Contributions.d.ts +7 -0
  24. package/lib/Contributions.d.ts.map +1 -0
  25. package/lib/Contributions.js +6 -0
  26. package/lib/Contributions.js.map +1 -0
  27. package/lib/CreateSandbox.d.ts +86 -0
  28. package/lib/CreateSandbox.d.ts.map +1 -0
  29. package/lib/CreateSandbox.js +3 -0
  30. package/lib/CreateSandbox.js.map +1 -0
  31. package/lib/CreateSandboxHttp.d.ts +5 -0
  32. package/lib/CreateSandboxHttp.d.ts.map +1 -0
  33. package/lib/CreateSandboxHttp.js +65 -0
  34. package/lib/CreateSandboxHttp.js.map +1 -0
  35. package/lib/CreateSecret.d.ts +56 -0
  36. package/lib/CreateSecret.d.ts.map +1 -0
  37. package/lib/CreateSecret.js +3 -0
  38. package/lib/CreateSecret.js.map +1 -0
  39. package/lib/CreateSecretHttp.d.ts +5 -0
  40. package/lib/CreateSecretHttp.d.ts.map +1 -0
  41. package/lib/CreateSecretHttp.js +39 -0
  42. package/lib/CreateSecretHttp.js.map +1 -0
  43. package/lib/CreateSnapshot.d.ts +80 -0
  44. package/lib/CreateSnapshot.d.ts.map +1 -0
  45. package/lib/CreateSnapshot.js +3 -0
  46. package/lib/CreateSnapshot.js.map +1 -0
  47. package/lib/CreateSnapshotHttp.d.ts +5 -0
  48. package/lib/CreateSnapshotHttp.d.ts.map +1 -0
  49. package/lib/CreateSnapshotHttp.js +47 -0
  50. package/lib/CreateSnapshotHttp.js.map +1 -0
  51. package/lib/CreateVolume.d.ts +81 -0
  52. package/lib/CreateVolume.d.ts.map +1 -0
  53. package/lib/CreateVolume.js +10 -0
  54. package/lib/CreateVolume.js.map +1 -0
  55. package/lib/CreateVolumeHttp.d.ts +5 -0
  56. package/lib/CreateVolumeHttp.d.ts.map +1 -0
  57. package/lib/CreateVolumeHttp.js +31 -0
  58. package/lib/CreateVolumeHttp.js.map +1 -0
  59. package/lib/Credentials.d.ts +9 -0
  60. package/lib/Credentials.d.ts.map +1 -0
  61. package/lib/Credentials.js +18 -0
  62. package/lib/Credentials.js.map +1 -0
  63. package/lib/DaytonaBindings.d.ts +51 -0
  64. package/lib/DaytonaBindings.d.ts.map +1 -0
  65. package/lib/DaytonaBindings.js +61 -0
  66. package/lib/DaytonaBindings.js.map +1 -0
  67. package/lib/IdentityProvider.d.ts +80 -0
  68. package/lib/IdentityProvider.d.ts.map +1 -0
  69. package/lib/IdentityProvider.js +111 -0
  70. package/lib/IdentityProvider.js.map +1 -0
  71. package/lib/MountVolume.d.ts +86 -0
  72. package/lib/MountVolume.d.ts.map +1 -0
  73. package/lib/MountVolume.js +27 -0
  74. package/lib/MountVolume.js.map +1 -0
  75. package/lib/OAuthClient.d.ts +14 -0
  76. package/lib/OAuthClient.d.ts.map +1 -0
  77. package/lib/OAuthClient.js +23 -0
  78. package/lib/OAuthClient.js.map +1 -0
  79. package/lib/Organization.d.ts +40 -0
  80. package/lib/Organization.d.ts.map +1 -0
  81. package/lib/Organization.js +80 -0
  82. package/lib/Organization.js.map +1 -0
  83. package/lib/OrganizationInvitation.d.ts +70 -0
  84. package/lib/OrganizationInvitation.d.ts.map +1 -0
  85. package/lib/OrganizationInvitation.js +109 -0
  86. package/lib/OrganizationInvitation.js.map +1 -0
  87. package/lib/OrganizationMember.d.ts +86 -0
  88. package/lib/OrganizationMember.d.ts.map +1 -0
  89. package/lib/OrganizationMember.js +109 -0
  90. package/lib/OrganizationMember.js.map +1 -0
  91. package/lib/OrganizationOtelConfig.d.ts +59 -0
  92. package/lib/OrganizationOtelConfig.d.ts.map +1 -0
  93. package/lib/OrganizationOtelConfig.js +87 -0
  94. package/lib/OrganizationOtelConfig.js.map +1 -0
  95. package/lib/OrganizationRole.d.ts +66 -0
  96. package/lib/OrganizationRole.d.ts.map +1 -0
  97. package/lib/OrganizationRole.js +106 -0
  98. package/lib/OrganizationRole.js.map +1 -0
  99. package/lib/OrganizationSettings.d.ts +76 -0
  100. package/lib/OrganizationSettings.d.ts.map +1 -0
  101. package/lib/OrganizationSettings.js +107 -0
  102. package/lib/OrganizationSettings.js.map +1 -0
  103. package/lib/Providers.d.ts +14 -0
  104. package/lib/Providers.d.ts.map +1 -0
  105. package/lib/Providers.js +53 -0
  106. package/lib/Providers.js.map +1 -0
  107. package/lib/ReadAuditLogs.d.ts +30 -0
  108. package/lib/ReadAuditLogs.d.ts.map +1 -0
  109. package/lib/ReadAuditLogs.js +17 -0
  110. package/lib/ReadAuditLogs.js.map +1 -0
  111. package/lib/ReadOrganization.d.ts +39 -0
  112. package/lib/ReadOrganization.d.ts.map +1 -0
  113. package/lib/ReadOrganization.js +39 -0
  114. package/lib/ReadOrganization.js.map +1 -0
  115. package/lib/ReadUsage.d.ts +31 -0
  116. package/lib/ReadUsage.d.ts.map +1 -0
  117. package/lib/ReadUsage.js +17 -0
  118. package/lib/ReadUsage.js.map +1 -0
  119. package/lib/Region.d.ts +78 -0
  120. package/lib/Region.d.ts.map +1 -0
  121. package/lib/Region.js +169 -0
  122. package/lib/Region.js.map +1 -0
  123. package/lib/Registry.d.ts +84 -0
  124. package/lib/Registry.d.ts.map +1 -0
  125. package/lib/Registry.js +97 -0
  126. package/lib/Registry.js.map +1 -0
  127. package/lib/Runner.d.ts +66 -0
  128. package/lib/Runner.d.ts.map +1 -0
  129. package/lib/Runner.js +116 -0
  130. package/lib/Runner.js.map +1 -0
  131. package/lib/Sandbox.d.ts +376 -0
  132. package/lib/Sandbox.d.ts.map +1 -0
  133. package/lib/Sandbox.js +565 -0
  134. package/lib/Sandbox.js.map +1 -0
  135. package/lib/SandboxClient.d.ts +258 -0
  136. package/lib/SandboxClient.d.ts.map +1 -0
  137. package/lib/SandboxClient.js +233 -0
  138. package/lib/SandboxClient.js.map +1 -0
  139. package/lib/Secret.d.ts +93 -0
  140. package/lib/Secret.d.ts.map +1 -0
  141. package/lib/Secret.js +130 -0
  142. package/lib/Secret.js.map +1 -0
  143. package/lib/Snapshot.d.ts +327 -0
  144. package/lib/Snapshot.d.ts.map +1 -0
  145. package/lib/Snapshot.js +447 -0
  146. package/lib/Snapshot.js.map +1 -0
  147. package/lib/Volume.d.ts +99 -0
  148. package/lib/Volume.d.ts.map +1 -0
  149. package/lib/Volume.js +152 -0
  150. package/lib/Volume.js.map +1 -0
  151. package/lib/WarmPool.d.ts +61 -0
  152. package/lib/WarmPool.d.ts.map +1 -0
  153. package/lib/WarmPool.js +81 -0
  154. package/lib/WarmPool.js.map +1 -0
  155. package/lib/Webhooks.d.ts +58 -0
  156. package/lib/Webhooks.d.ts.map +1 -0
  157. package/lib/Webhooks.js +75 -0
  158. package/lib/Webhooks.js.map +1 -0
  159. package/lib/index.d.ts +37 -0
  160. package/lib/index.d.ts.map +1 -0
  161. package/lib/index.js +36 -0
  162. package/lib/index.js.map +1 -0
  163. package/lib/internal/BuildContext.d.ts +16 -0
  164. package/lib/internal/BuildContext.d.ts.map +1 -0
  165. package/lib/internal/BuildContext.js +50 -0
  166. package/lib/internal/BuildContext.js.map +1 -0
  167. package/lib/internal/Declared.d.ts +29 -0
  168. package/lib/internal/Declared.d.ts.map +1 -0
  169. package/lib/internal/Declared.js +31 -0
  170. package/lib/internal/Declared.js.map +1 -0
  171. package/lib/internal/Derived.d.ts +40 -0
  172. package/lib/internal/Derived.d.ts.map +1 -0
  173. package/lib/internal/Derived.js +64 -0
  174. package/lib/internal/Derived.js.map +1 -0
  175. package/lib/internal/Errors.d.ts +4 -0
  176. package/lib/internal/Errors.d.ts.map +1 -0
  177. package/lib/internal/Errors.js +1 -0
  178. package/lib/internal/Errors.js.map +1 -0
  179. package/lib/internal/Labels.d.ts +20 -0
  180. package/lib/internal/Labels.d.ts.map +1 -0
  181. package/lib/internal/Labels.js +22 -0
  182. package/lib/internal/Labels.js.map +1 -0
  183. package/lib/internal/Names.d.ts +18 -0
  184. package/lib/internal/Names.d.ts.map +1 -0
  185. package/lib/internal/Names.js +25 -0
  186. package/lib/internal/Names.js.map +1 -0
  187. package/lib/internal/Organization.d.ts +27 -0
  188. package/lib/internal/Organization.d.ts.map +1 -0
  189. package/lib/internal/Organization.js +32 -0
  190. package/lib/internal/Organization.js.map +1 -0
  191. package/lib/internal/Process.d.ts +14 -0
  192. package/lib/internal/Process.d.ts.map +1 -0
  193. package/lib/internal/Process.js +15 -0
  194. package/lib/internal/Process.js.map +1 -0
  195. package/lib/internal/Program.d.ts +83 -0
  196. package/lib/internal/Program.d.ts.map +1 -0
  197. package/lib/internal/Program.js +169 -0
  198. package/lib/internal/Program.js.map +1 -0
  199. package/lib/internal/Ref.d.ts +14 -0
  200. package/lib/internal/Ref.d.ts.map +1 -0
  201. package/lib/internal/Ref.js +7 -0
  202. package/lib/internal/Ref.js.map +1 -0
  203. package/lib/internal/Scoped.d.ts +31 -0
  204. package/lib/internal/Scoped.d.ts.map +1 -0
  205. package/lib/internal/Scoped.js +48 -0
  206. package/lib/internal/Scoped.js.map +1 -0
  207. package/lib/internal/Tar.d.ts +13 -0
  208. package/lib/internal/Tar.d.ts.map +1 -0
  209. package/lib/internal/Tar.js +62 -0
  210. package/lib/internal/Tar.js.map +1 -0
  211. package/lib/internal/Toolbox.d.ts +11 -0
  212. package/lib/internal/Toolbox.d.ts.map +1 -0
  213. package/lib/internal/Toolbox.js +20 -0
  214. package/lib/internal/Toolbox.js.map +1 -0
  215. package/lib/internal/Wait.d.ts +49 -0
  216. package/lib/internal/Wait.d.ts.map +1 -0
  217. package/lib/internal/Wait.js +57 -0
  218. package/lib/internal/Wait.js.map +1 -0
  219. package/package.json +79 -3
  220. package/src/ApiKey.ts +221 -0
  221. package/src/AuthProvider.ts +406 -0
  222. package/src/Bootstrap.ts +55 -0
  223. package/src/ConnectSandbox.ts +76 -0
  224. package/src/ConnectSandboxHttp.ts +26 -0
  225. package/src/Contributions.ts +9 -0
  226. package/src/CreateSandbox.ts +107 -0
  227. package/src/CreateSandboxHttp.ts +97 -0
  228. package/src/CreateSecret.ts +73 -0
  229. package/src/CreateSecretHttp.ts +58 -0
  230. package/src/CreateSnapshot.ts +133 -0
  231. package/src/CreateSnapshotHttp.ts +77 -0
  232. package/src/CreateVolume.ts +104 -0
  233. package/src/CreateVolumeHttp.ts +50 -0
  234. package/src/Credentials.ts +37 -0
  235. package/src/DaytonaBindings.ts +111 -0
  236. package/src/IdentityProvider.ts +181 -0
  237. package/src/MountVolume.ts +122 -0
  238. package/src/OAuthClient.ts +27 -0
  239. package/src/Organization.ts +121 -0
  240. package/src/OrganizationInvitation.ts +174 -0
  241. package/src/OrganizationMember.ts +174 -0
  242. package/src/OrganizationOtelConfig.ts +138 -0
  243. package/src/OrganizationRole.ts +167 -0
  244. package/src/OrganizationSettings.ts +187 -0
  245. package/src/Providers.ts +93 -0
  246. package/src/ReadAuditLogs.ts +50 -0
  247. package/src/ReadOrganization.ts +83 -0
  248. package/src/ReadUsage.ts +51 -0
  249. package/src/Region.ts +226 -0
  250. package/src/Registry.ts +164 -0
  251. package/src/Runner.ts +166 -0
  252. package/src/Sandbox.ts +927 -0
  253. package/src/SandboxClient.ts +625 -0
  254. package/src/Secret.ts +203 -0
  255. package/src/Snapshot.ts +685 -0
  256. package/src/Volume.ts +229 -0
  257. package/src/WarmPool.ts +128 -0
  258. package/src/Webhooks.ts +121 -0
  259. package/src/globals.d.ts +2 -0
  260. package/src/index.ts +46 -0
  261. package/src/internal/BuildContext.ts +62 -0
  262. package/src/internal/Declared.ts +80 -0
  263. package/src/internal/Derived.ts +97 -0
  264. package/src/internal/Errors.ts +4 -0
  265. package/src/internal/Labels.ts +39 -0
  266. package/src/internal/Names.ts +37 -0
  267. package/src/internal/Organization.ts +40 -0
  268. package/src/internal/Process.ts +25 -0
  269. package/src/internal/Program.ts +239 -0
  270. package/src/internal/Ref.ts +15 -0
  271. package/src/internal/Scoped.ts +102 -0
  272. package/src/internal/Tar.ts +72 -0
  273. package/src/internal/Toolbox.ts +27 -0
  274. package/src/internal/Wait.ts +105 -0
@@ -0,0 +1,164 @@
1
+ import * as registries from "@distilled.cloud/daytona/docker_registry";
2
+ import { Unowned } from "alchemy/AdoptPolicy";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Resource } from "alchemy/Resource";
5
+ import * as Effect from "effect/Effect";
6
+ import type * as Redacted from "effect/Redacted";
7
+ import { isOwnedName, resolveName } from "./internal/Names.ts";
8
+ import type { Providers } from "./Providers.ts";
9
+
10
+ export interface RegistryProps {
11
+ /**
12
+ * Registry name in Daytona. If omitted, a unique name is generated from
13
+ * the stack, stage and logical ID.
14
+ */
15
+ name?: string;
16
+ /** Registry host, e.g. `ghcr.io`, `docker.io` or an ECR host. */
17
+ url: string;
18
+ /** User name for the registry. */
19
+ username: string;
20
+ /** Password or access token for the registry. Updated in place. */
21
+ password: string | Redacted.Redacted<string>;
22
+ /** Project or namespace within the registry, if it has them. */
23
+ project?: string;
24
+ /** IAM role Daytona assumes for mTLS to the registry (ECR). */
25
+ mtlsRoleArn?: string;
26
+ /** Secrets Manager ARN holding the mTLS client certificate. */
27
+ mtlsSecretArn?: string;
28
+ }
29
+
30
+ export interface RegistryAttributes {
31
+ /** Registry ID. */
32
+ registryId: string;
33
+ /** Registry name. */
34
+ name: string;
35
+ /** Registry host. */
36
+ url: string;
37
+ /** User name. */
38
+ username: string;
39
+ /** Project or namespace. */
40
+ project: string;
41
+ /** `organization`, `internal`, … */
42
+ registryType: string;
43
+ }
44
+
45
+ export type Registry = Resource<
46
+ "Daytona.Registry",
47
+ RegistryProps,
48
+ RegistryAttributes,
49
+ never,
50
+ Providers,
51
+ RegistryLookup
52
+ >;
53
+
54
+ /**
55
+ * Props for {@link Registry.lookup}: find a container registry this
56
+ * stack doesn't manage by its name.
57
+ */
58
+ export interface RegistryLookup {
59
+ /** Registry name. */
60
+ name: string;
61
+ }
62
+
63
+ /**
64
+ * Credentials for a private container registry, so Daytona can pull
65
+ * private images into a {@link Snapshot}. Daytona picks the registry whose
66
+ * `url` matches the image's host.
67
+ * @see https://www.daytona.io/docs/en/snapshots/#images-from-private-registries
68
+ *
69
+ * ### Pulling a Private Image
70
+ * **Example:** GitHub Container Registry
71
+ * ```typescript
72
+ * export const Ghcr = Daytona.Registry("Ghcr", {
73
+ * url: "ghcr.io",
74
+ * username: "alchemy-run",
75
+ * password: Config.Redacted("GHCR_TOKEN"),
76
+ * });
77
+ *
78
+ * export const Base = Daytona.Snapshot("Base", {
79
+ * image: "ghcr.io/alchemy-run/base:1.0.0",
80
+ * registry: Ghcr,
81
+ * });
82
+ * ```
83
+ *
84
+ * ### Looking up an existing registry
85
+ * `Registry.lookup` references a registry Alchemy doesn't manage (created in
86
+ * the Daytona dashboard or by another stack). It is read during plan/deploy,
87
+ * never created, updated or deleted.
88
+ *
89
+ * **Example:** Reference an existing registry
90
+ * ```typescript
91
+ * const ghcr = Daytona.Registry.lookup({ name: "ghcr" });
92
+ * ```
93
+ *
94
+ * @resource
95
+ * @product Registry
96
+ */
97
+ export const Registry = Resource<Registry>("Daytona.Registry");
98
+
99
+ const toAttributes = (r: registries.DockerRegistry2): RegistryAttributes => ({
100
+ registryId: r.id,
101
+ name: r.name,
102
+ url: r.url,
103
+ username: r.username,
104
+ project: r.project,
105
+ registryType: r.registryType,
106
+ });
107
+
108
+ const getById = (id: string) =>
109
+ registries.getRegistry({ id }).pipe(Effect.catchTag("RegistryNotFound", () => Effect.undefined));
110
+
111
+ const findByName = (name: string) =>
112
+ registries.listRegistries({}).pipe(Effect.map((all) => all.find((r) => r.name === name)));
113
+
114
+ export const RegistryProvider = () =>
115
+ Provider.effect(
116
+ Registry,
117
+ Effect.succeed({
118
+ stables: ["registryId"],
119
+ list: Effect.fn(function* () {
120
+ const all = yield* registries.listRegistries({});
121
+ return all.filter((r) => r.registryType === "organization").map(toAttributes);
122
+ }),
123
+ lookup: Effect.fn(function* ({ name }) {
124
+ const found = yield* findByName(name);
125
+ return found === undefined ? undefined : toAttributes(found);
126
+ }),
127
+
128
+ read: Effect.fn(function* ({ id, olds, output }) {
129
+ const name = yield* resolveName(id, olds?.name, output?.name);
130
+ const found =
131
+ (output ? yield* getById(output.registryId) : undefined) ?? (yield* findByName(name));
132
+ if (found === undefined) return undefined;
133
+ const attrs = toAttributes(found);
134
+ return (yield* isOwnedName(id, found.name, output !== undefined)) ? attrs : Unowned(attrs);
135
+ }),
136
+ reconcile: Effect.fn(function* ({ id, news, output }) {
137
+ const name = yield* resolveName(id, news.name, output?.name);
138
+ // Observe
139
+ const current =
140
+ (output ? yield* getById(output.registryId) : undefined) ?? (yield* findByName(name));
141
+ const desired = {
142
+ name,
143
+ url: news.url,
144
+ username: news.username,
145
+ password: news.password,
146
+ project: news.project,
147
+ mtlsRoleArn: news.mtlsRoleArn ?? null,
148
+ mtlsSecretArn: news.mtlsSecretArn ?? null,
149
+ };
150
+ // Ensure
151
+ if (current === undefined) {
152
+ return toAttributes(yield* registries.createRegistry(desired));
153
+ }
154
+ // Sync — the password can't be read back, so every reconcile
155
+ // writes the full registry (updateRegistry is a PATCH of all fields).
156
+ return toAttributes(yield* registries.updateRegistry({ id: current.id, ...desired }));
157
+ }),
158
+ delete: Effect.fn(function* ({ output }) {
159
+ yield* registries
160
+ .deleteRegistry({ id: output.registryId })
161
+ .pipe(Effect.catchTag("RegistryNotFound", () => Effect.void));
162
+ }),
163
+ }),
164
+ );
package/src/Runner.ts ADDED
@@ -0,0 +1,166 @@
1
+ import * as runners from "@distilled.cloud/daytona/runners";
2
+ import { Unowned } from "alchemy/AdoptPolicy";
3
+ import { deepEqual, isResolved } from "alchemy/Diff";
4
+ import * as Provider from "alchemy/Provider";
5
+ import { Resource } from "alchemy/Resource";
6
+ import * as Effect from "effect/Effect";
7
+ import * as Redacted from "effect/Redacted";
8
+ import { declarable } from "./internal/Declared.ts";
9
+ import { isOwnedName, resolveName } from "./internal/Names.ts";
10
+ import { resolved, type Ref } from "./internal/Ref.ts";
11
+ import type { Providers } from "./Providers.ts";
12
+
13
+ /** A region, by id. Accepts a `Daytona.Region` or `{ regionId }`. */
14
+ export type RunnerRegion = { readonly regionId: string };
15
+
16
+ export interface RunnerProps {
17
+ /** Runner name. If omitted, generated from the stack, stage and logical ID. Changing it replaces the runner. */
18
+ name?: string;
19
+ /** Region the runner serves. Changing it replaces the runner. */
20
+ region: Ref<RunnerRegion>;
21
+ /** Tags the scheduler matches sandboxes against. Changing them replaces the runner. */
22
+ tags?: string[];
23
+ /** Sandbox class the runner hosts. Changing it replaces the runner. */
24
+ sandboxClass?: runners.CreateRunnerSandboxClass;
25
+ /** Stop scheduling new sandboxes on it. Updated in place. @default false */
26
+ unschedulable?: boolean;
27
+ /** Drain it: no new sandboxes, and existing ones move off. Updated in place. @default false */
28
+ draining?: boolean;
29
+ }
30
+
31
+ export interface RunnerAttributes {
32
+ /** Runner ID. */
33
+ runnerId: string;
34
+ /** Runner name. */
35
+ name: string;
36
+ /** Region. */
37
+ region: string;
38
+ /** State. */
39
+ state: string;
40
+ /**
41
+ * The key the runner daemon authenticates with. Daytona shows it only at
42
+ * creation, so alchemy keeps it in state as a `Redacted` value.
43
+ */
44
+ apiKey: Redacted.Redacted<string>;
45
+ }
46
+
47
+ export type Runner = Resource<"Daytona.Runner", RunnerProps, RunnerAttributes, never, Providers>;
48
+
49
+ /**
50
+ * A runner: a machine you operate that hosts sandboxes for a custom
51
+ * {@link Region}. Declaring it registers the runner and mints the API key
52
+ * its daemon uses; you then start the daemon on the machine with that key.
53
+ *
54
+ * ### Registering a Runner
55
+ * **Example:** A runner for a custom region
56
+ * ```typescript
57
+ * export const Box1 = Daytona.Runner("Box1", { region: Home });
58
+ * ```
59
+ *
60
+ * @resource
61
+ * @product Region
62
+ */
63
+ export const Runner = declarable<Runner>()(Resource<Runner>("Daytona.Runner"));
64
+
65
+ const regionId = (region: RunnerProps["region"]) => Effect.succeed(resolved(region).regionId);
66
+
67
+ const getById = (id: string) =>
68
+ runners.getRunner({ id }).pipe(Effect.catchTag("RunnerNotFound", () => Effect.undefined));
69
+
70
+ export const RunnerProvider = () =>
71
+ Provider.effect(
72
+ Runner,
73
+ Effect.succeed({
74
+ stables: ["runnerId", "apiKey"],
75
+ nuke: { dependsOn: [] },
76
+ list: Effect.fn(function* () {
77
+ // Organizations without custom regions aren't served runners at all.
78
+ const all = yield* runners
79
+ .listRunners({})
80
+ .pipe(Effect.catchTag("RunnersUnavailable", () => Effect.succeed([])));
81
+ return all.map((r) => ({
82
+ runnerId: r.id,
83
+ name: r.name,
84
+ region: r.region,
85
+ state: r.state,
86
+ apiKey: Redacted.make(""),
87
+ }));
88
+ }),
89
+ diff: Effect.fn(function* ({ id, olds, news, output }) {
90
+ if (!isResolved(news) || output === undefined) return undefined;
91
+ const name = yield* resolveName(
92
+ id,
93
+ news.name,
94
+ news.name === undefined ? output.name : undefined,
95
+ );
96
+ if (
97
+ name !== output.name ||
98
+ (yield* regionId(news.region)) !== output.region ||
99
+ !deepEqual(news.tags ?? [], olds?.tags ?? []) ||
100
+ news.sandboxClass !== olds?.sandboxClass
101
+ ) {
102
+ return { action: "replace", deleteFirst: name === output.name } as const;
103
+ }
104
+ }),
105
+ read: Effect.fn(function* ({ id, olds, output }) {
106
+ const name = yield* resolveName(id, olds?.name, output?.name);
107
+ const found =
108
+ (output ? yield* getById(output.runnerId) : undefined) ??
109
+ (yield* runners.listRunners({})).find((r) => r.name === name);
110
+ if (found === undefined) return undefined;
111
+ const attrs = {
112
+ runnerId: found.id,
113
+ name: found.name,
114
+ region: found.region,
115
+ state: found.state,
116
+ apiKey: output?.apiKey ?? Redacted.make(""),
117
+ };
118
+ return (yield* isOwnedName(id, found.name, output !== undefined)) ? attrs : Unowned(attrs);
119
+ }),
120
+ reconcile: Effect.fn(function* ({ id, news, output }) {
121
+ const name = yield* resolveName(id, news.name, output?.name);
122
+ const region = yield* regionId(news.region);
123
+ // Observe
124
+ let current = output ? yield* getById(output.runnerId) : undefined;
125
+ let apiKey = output?.apiKey;
126
+ // Ensure
127
+ if (current === undefined) {
128
+ const created = yield* runners.createRunner({
129
+ regionId: region,
130
+ name,
131
+ tags: news.tags,
132
+ sandboxClass: news.sandboxClass,
133
+ });
134
+ apiKey = Redacted.isRedacted(created.apiKey)
135
+ ? created.apiKey
136
+ : Redacted.make(created.apiKey);
137
+ current = yield* runners.getRunner({ id: created.id });
138
+ }
139
+ // Sync scheduling flags.
140
+ if ((news.unschedulable ?? false) !== current.unschedulable) {
141
+ current = yield* runners.updateRunnerScheduling({
142
+ id: current.id,
143
+ unschedulable: news.unschedulable ?? false,
144
+ });
145
+ }
146
+ if ((news.draining ?? false) !== (current.draining ?? false)) {
147
+ current = yield* runners.updateRunnerDraining({
148
+ id: current.id,
149
+ draining: news.draining ?? false,
150
+ });
151
+ }
152
+ return {
153
+ runnerId: current.id,
154
+ name: current.name,
155
+ region: current.region,
156
+ state: current.state,
157
+ apiKey: apiKey ?? Redacted.make(""),
158
+ };
159
+ }),
160
+ delete: Effect.fn(function* ({ output }) {
161
+ yield* runners
162
+ .deleteRunner({ id: output.runnerId })
163
+ .pipe(Effect.catchTag("RunnerNotFound", () => Effect.void));
164
+ }),
165
+ }),
166
+ );