@vibesdotdev/integrations-digitalocean 0.0.0-stage → 1.0.0-rc.2

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 (323) hide show
  1. package/LICENSE +126 -0
  2. package/README.md +78 -2
  3. package/dist/ai/index.d.ts +4 -0
  4. package/dist/ai/index.d.ts.map +1 -0
  5. package/dist/ai/index.js +4 -0
  6. package/dist/ai/index.js.map +1 -0
  7. package/dist/ai/inference.transport.impl.d.ts +5 -0
  8. package/dist/ai/inference.transport.impl.d.ts.map +1 -0
  9. package/dist/ai/inference.transport.impl.js +54 -0
  10. package/dist/ai/inference.transport.impl.js.map +1 -0
  11. package/dist/ai/provider.plugin.d.ts +6 -0
  12. package/dist/ai/provider.plugin.d.ts.map +1 -0
  13. package/dist/ai/provider.plugin.js +126 -0
  14. package/dist/ai/provider.plugin.js.map +1 -0
  15. package/dist/ai/providers/cloud/frontier/digitalocean/config/schemas/index.d.ts +62 -0
  16. package/dist/ai/providers/cloud/frontier/digitalocean/config/schemas/index.d.ts.map +1 -0
  17. package/dist/ai/providers/cloud/frontier/digitalocean/config/schemas/index.js +73 -0
  18. package/dist/ai/providers/cloud/frontier/digitalocean/config/schemas/index.js.map +1 -0
  19. package/dist/ai/providers/cloud/frontier/digitalocean/index.d.ts +2 -0
  20. package/dist/ai/providers/cloud/frontier/digitalocean/index.d.ts.map +1 -0
  21. package/dist/ai/providers/cloud/frontier/digitalocean/index.js +2 -0
  22. package/dist/ai/providers/cloud/frontier/digitalocean/index.js.map +1 -0
  23. package/dist/ai/providers/cloud/frontier/digitalocean/provider.digitalocean.descriptor.d.ts +183 -0
  24. package/dist/ai/providers/cloud/frontier/digitalocean/provider.digitalocean.descriptor.d.ts.map +1 -0
  25. package/dist/ai/providers/cloud/frontier/digitalocean/provider.digitalocean.descriptor.js +66 -0
  26. package/dist/ai/providers/cloud/frontier/digitalocean/provider.digitalocean.descriptor.js.map +1 -0
  27. package/dist/apps/api-client.d.ts +45 -0
  28. package/dist/apps/api-client.d.ts.map +1 -0
  29. package/dist/apps/api-client.js +47 -0
  30. package/dist/apps/api-client.js.map +1 -0
  31. package/dist/apps/build-spec.d.ts +44 -0
  32. package/dist/apps/build-spec.d.ts.map +1 -0
  33. package/dist/apps/build-spec.js +463 -0
  34. package/dist/apps/build-spec.js.map +1 -0
  35. package/dist/apps/deploy-client.d.ts +42 -0
  36. package/dist/apps/deploy-client.d.ts.map +1 -0
  37. package/dist/apps/deploy-client.js +300 -0
  38. package/dist/apps/deploy-client.js.map +1 -0
  39. package/dist/apps/index.d.ts +5 -0
  40. package/dist/apps/index.d.ts.map +1 -0
  41. package/dist/apps/index.js +4 -0
  42. package/dist/apps/index.js.map +1 -0
  43. package/dist/apps/types.d.ts +204 -0
  44. package/dist/apps/types.d.ts.map +1 -0
  45. package/dist/apps/types.js +13 -0
  46. package/dist/apps/types.js.map +1 -0
  47. package/dist/client/control-plane.d.ts +49 -0
  48. package/dist/client/control-plane.d.ts.map +1 -0
  49. package/dist/client/control-plane.js +85 -0
  50. package/dist/client/control-plane.js.map +1 -0
  51. package/dist/client/do-fetch.d.ts +41 -0
  52. package/dist/client/do-fetch.d.ts.map +1 -0
  53. package/dist/client/do-fetch.js +199 -0
  54. package/dist/client/do-fetch.js.map +1 -0
  55. package/dist/client/errors.d.ts +6 -0
  56. package/dist/client/errors.d.ts.map +1 -0
  57. package/dist/client/errors.js +34 -0
  58. package/dist/client/errors.js.map +1 -0
  59. package/dist/client/factory.d.ts +53 -0
  60. package/dist/client/factory.d.ts.map +1 -0
  61. package/dist/client/factory.js +220 -0
  62. package/dist/client/factory.js.map +1 -0
  63. package/dist/client/helpers.d.ts +5 -0
  64. package/dist/client/helpers.d.ts.map +1 -0
  65. package/dist/client/helpers.js +8 -0
  66. package/dist/client/helpers.js.map +1 -0
  67. package/dist/client/index.d.ts +12 -0
  68. package/dist/client/index.d.ts.map +1 -0
  69. package/dist/client/index.js +10 -0
  70. package/dist/client/index.js.map +1 -0
  71. package/dist/client/paginated.d.ts +19 -0
  72. package/dist/client/paginated.d.ts.map +1 -0
  73. package/dist/client/paginated.js +56 -0
  74. package/dist/client/paginated.js.map +1 -0
  75. package/dist/client/retry.d.ts +34 -0
  76. package/dist/client/retry.d.ts.map +1 -0
  77. package/dist/client/retry.js +53 -0
  78. package/dist/client/retry.js.map +1 -0
  79. package/dist/config/digitalocean.config.descriptor.d.ts +197 -0
  80. package/dist/config/digitalocean.config.descriptor.d.ts.map +1 -0
  81. package/dist/config/digitalocean.config.descriptor.js +59 -0
  82. package/dist/config/digitalocean.config.descriptor.js.map +1 -0
  83. package/dist/credentials/index.d.ts +38 -0
  84. package/dist/credentials/index.d.ts.map +1 -0
  85. package/dist/credentials/index.js +56 -0
  86. package/dist/credentials/index.js.map +1 -0
  87. package/dist/databases/index.d.ts +82 -0
  88. package/dist/databases/index.d.ts.map +1 -0
  89. package/dist/databases/index.js +57 -0
  90. package/dist/databases/index.js.map +1 -0
  91. package/dist/digitalocean-friction.policy.d.ts +29 -0
  92. package/dist/digitalocean-friction.policy.d.ts.map +1 -0
  93. package/dist/digitalocean-friction.policy.js +21 -0
  94. package/dist/digitalocean-friction.policy.js.map +1 -0
  95. package/dist/digitalocean.plugin.d.ts +3 -0
  96. package/dist/digitalocean.plugin.d.ts.map +1 -0
  97. package/dist/digitalocean.plugin.js +27 -0
  98. package/dist/digitalocean.plugin.js.map +1 -0
  99. package/dist/droplets/index.d.ts +106 -0
  100. package/dist/droplets/index.d.ts.map +1 -0
  101. package/dist/droplets/index.js +227 -0
  102. package/dist/droplets/index.js.map +1 -0
  103. package/dist/index.d.ts +35 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +32 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/inference-control-plane/index.d.ts +63 -0
  108. package/dist/inference-control-plane/index.d.ts.map +1 -0
  109. package/dist/inference-control-plane/index.js +93 -0
  110. package/dist/inference-control-plane/index.js.map +1 -0
  111. package/dist/infra/billing.d.ts +26 -0
  112. package/dist/infra/billing.d.ts.map +1 -0
  113. package/dist/infra/billing.js +43 -0
  114. package/dist/infra/billing.js.map +1 -0
  115. package/dist/infra/credentials.d.ts +11 -0
  116. package/dist/infra/credentials.d.ts.map +1 -0
  117. package/dist/infra/credentials.js +15 -0
  118. package/dist/infra/credentials.js.map +1 -0
  119. package/dist/infra/deployment-provider/deploy-secrets.d.ts +10 -0
  120. package/dist/infra/deployment-provider/deploy-secrets.d.ts.map +1 -0
  121. package/dist/infra/deployment-provider/deploy-secrets.js +66 -0
  122. package/dist/infra/deployment-provider/deploy-secrets.js.map +1 -0
  123. package/dist/infra/deployment-provider/digitalocean-deployment-provider.impl.d.ts +97 -0
  124. package/dist/infra/deployment-provider/digitalocean-deployment-provider.impl.d.ts.map +1 -0
  125. package/dist/infra/deployment-provider/digitalocean-deployment-provider.impl.js +242 -0
  126. package/dist/infra/deployment-provider/digitalocean-deployment-provider.impl.js.map +1 -0
  127. package/dist/infra/deployment-provider/image-publish.d.ts +39 -0
  128. package/dist/infra/deployment-provider/image-publish.d.ts.map +1 -0
  129. package/dist/infra/deployment-provider/image-publish.js +146 -0
  130. package/dist/infra/deployment-provider/image-publish.js.map +1 -0
  131. package/dist/infra/deployment-provider.descriptor.d.ts +34 -0
  132. package/dist/infra/deployment-provider.descriptor.d.ts.map +1 -0
  133. package/dist/infra/deployment-provider.descriptor.js +9 -0
  134. package/dist/infra/deployment-provider.descriptor.js.map +1 -0
  135. package/dist/infra/digitalocean-infra.plugin.d.ts +101 -0
  136. package/dist/infra/digitalocean-infra.plugin.d.ts.map +1 -0
  137. package/dist/infra/digitalocean-infra.plugin.js +283 -0
  138. package/dist/infra/digitalocean-infra.plugin.js.map +1 -0
  139. package/dist/infra/doks/clients.d.ts +183 -0
  140. package/dist/infra/doks/clients.d.ts.map +1 -0
  141. package/dist/infra/doks/clients.js +172 -0
  142. package/dist/infra/doks/clients.js.map +1 -0
  143. package/dist/infra/doks/digitalocean.d.ts +34 -0
  144. package/dist/infra/doks/digitalocean.d.ts.map +1 -0
  145. package/dist/infra/doks/digitalocean.js +267 -0
  146. package/dist/infra/doks/digitalocean.js.map +1 -0
  147. package/dist/infra/doks/service-release-schemas.d.ts +1037 -0
  148. package/dist/infra/doks/service-release-schemas.d.ts.map +1 -0
  149. package/dist/infra/doks/service-release-schemas.js +51 -0
  150. package/dist/infra/doks/service-release-schemas.js.map +1 -0
  151. package/dist/infra/doks/service-release.d.ts +415 -0
  152. package/dist/infra/doks/service-release.d.ts.map +1 -0
  153. package/dist/infra/doks/service-release.js +3201 -0
  154. package/dist/infra/doks/service-release.js.map +1 -0
  155. package/dist/infra/doks/worker.d.ts +14 -0
  156. package/dist/infra/doks/worker.d.ts.map +1 -0
  157. package/dist/infra/doks/worker.js +343 -0
  158. package/dist/infra/doks/worker.js.map +1 -0
  159. package/dist/infra/droplet.impl.d.ts +172 -0
  160. package/dist/infra/droplet.impl.d.ts.map +1 -0
  161. package/dist/infra/droplet.impl.js +379 -0
  162. package/dist/infra/droplet.impl.js.map +1 -0
  163. package/dist/infra/functions.impl.d.ts +123 -0
  164. package/dist/infra/functions.impl.d.ts.map +1 -0
  165. package/dist/infra/functions.impl.js +202 -0
  166. package/dist/infra/functions.impl.js.map +1 -0
  167. package/dist/infra/index.d.ts +15 -0
  168. package/dist/infra/index.d.ts.map +1 -0
  169. package/dist/infra/index.js +12 -0
  170. package/dist/infra/index.js.map +1 -0
  171. package/dist/infra/inventory.d.ts +7 -0
  172. package/dist/infra/inventory.d.ts.map +1 -0
  173. package/dist/infra/inventory.js +259 -0
  174. package/dist/infra/inventory.js.map +1 -0
  175. package/dist/infra/kubernetes-log-stream.d.ts +5 -0
  176. package/dist/infra/kubernetes-log-stream.d.ts.map +1 -0
  177. package/dist/infra/kubernetes-log-stream.js +186 -0
  178. package/dist/infra/kubernetes-log-stream.js.map +1 -0
  179. package/dist/infra/kubernetes-logs.d.ts +33 -0
  180. package/dist/infra/kubernetes-logs.d.ts.map +1 -0
  181. package/dist/infra/kubernetes-logs.descriptor.d.ts +14 -0
  182. package/dist/infra/kubernetes-logs.descriptor.d.ts.map +1 -0
  183. package/dist/infra/kubernetes-logs.descriptor.js +28 -0
  184. package/dist/infra/kubernetes-logs.descriptor.js.map +1 -0
  185. package/dist/infra/kubernetes-logs.js +196 -0
  186. package/dist/infra/kubernetes-logs.js.map +1 -0
  187. package/dist/infra/utilization.d.ts +44 -0
  188. package/dist/infra/utilization.d.ts.map +1 -0
  189. package/dist/infra/utilization.js +108 -0
  190. package/dist/infra/utilization.js.map +1 -0
  191. package/dist/kubernetes/authority.d.ts +40 -0
  192. package/dist/kubernetes/authority.d.ts.map +1 -0
  193. package/dist/kubernetes/authority.js +90 -0
  194. package/dist/kubernetes/authority.js.map +1 -0
  195. package/dist/kubernetes/encoding.d.ts +4 -0
  196. package/dist/kubernetes/encoding.d.ts.map +1 -0
  197. package/dist/kubernetes/encoding.js +8 -0
  198. package/dist/kubernetes/encoding.js.map +1 -0
  199. package/dist/kubernetes/index.d.ts +105 -0
  200. package/dist/kubernetes/index.d.ts.map +1 -0
  201. package/dist/kubernetes/index.js +99 -0
  202. package/dist/kubernetes/index.js.map +1 -0
  203. package/dist/kubernetes/transport.d.ts +11 -0
  204. package/dist/kubernetes/transport.d.ts.map +1 -0
  205. package/dist/kubernetes/transport.js +27 -0
  206. package/dist/kubernetes/transport.js.map +1 -0
  207. package/dist/network/index.d.ts +24 -0
  208. package/dist/network/index.d.ts.map +1 -0
  209. package/dist/network/index.js +16 -0
  210. package/dist/network/index.js.map +1 -0
  211. package/dist/registry/index.d.ts +39 -0
  212. package/dist/registry/index.d.ts.map +1 -0
  213. package/dist/registry/index.js +20 -0
  214. package/dist/registry/index.js.map +1 -0
  215. package/dist/schemas/app-deployment.d.ts +1474 -0
  216. package/dist/schemas/app-deployment.d.ts.map +1 -0
  217. package/dist/schemas/app-deployment.js +156 -0
  218. package/dist/schemas/app-deployment.js.map +1 -0
  219. package/dist/schemas/app-platform.d.ts +755 -0
  220. package/dist/schemas/app-platform.d.ts.map +1 -0
  221. package/dist/schemas/app-platform.js +253 -0
  222. package/dist/schemas/app-platform.js.map +1 -0
  223. package/dist/schemas/cache-database.d.ts +210 -0
  224. package/dist/schemas/cache-database.d.ts.map +1 -0
  225. package/dist/schemas/cache-database.js +105 -0
  226. package/dist/schemas/cache-database.js.map +1 -0
  227. package/dist/schemas/control-plane.d.ts +456 -0
  228. package/dist/schemas/control-plane.d.ts.map +1 -0
  229. package/dist/schemas/control-plane.js +123 -0
  230. package/dist/schemas/control-plane.js.map +1 -0
  231. package/dist/schemas/credential-use.d.ts +714 -0
  232. package/dist/schemas/credential-use.d.ts.map +1 -0
  233. package/dist/schemas/credential-use.js +73 -0
  234. package/dist/schemas/credential-use.js.map +1 -0
  235. package/dist/schemas/doks-worker.d.ts +4071 -0
  236. package/dist/schemas/doks-worker.d.ts.map +1 -0
  237. package/dist/schemas/doks-worker.js +330 -0
  238. package/dist/schemas/doks-worker.js.map +1 -0
  239. package/dist/schemas/droplet.d.ts +110 -0
  240. package/dist/schemas/droplet.d.ts.map +1 -0
  241. package/dist/schemas/droplet.js +22 -0
  242. package/dist/schemas/droplet.js.map +1 -0
  243. package/dist/schemas/functions.d.ts +22 -0
  244. package/dist/schemas/functions.d.ts.map +1 -0
  245. package/dist/schemas/functions.js +25 -0
  246. package/dist/schemas/functions.js.map +1 -0
  247. package/dist/schemas/gitea-git-hosting.d.ts +20 -0
  248. package/dist/schemas/gitea-git-hosting.d.ts.map +1 -0
  249. package/dist/schemas/gitea-git-hosting.js +26 -0
  250. package/dist/schemas/gitea-git-hosting.js.map +1 -0
  251. package/dist/schemas/http.d.ts +2594 -0
  252. package/dist/schemas/http.d.ts.map +1 -0
  253. package/dist/schemas/http.js +4548 -0
  254. package/dist/schemas/http.js.map +1 -0
  255. package/dist/schemas/infra-kinds.d.ts +113 -0
  256. package/dist/schemas/infra-kinds.d.ts.map +1 -0
  257. package/dist/schemas/infra-kinds.js +93 -0
  258. package/dist/schemas/infra-kinds.js.map +1 -0
  259. package/dist/schemas/kubernetes-responses.d.ts +457 -0
  260. package/dist/schemas/kubernetes-responses.d.ts.map +1 -0
  261. package/dist/schemas/kubernetes-responses.js +681 -0
  262. package/dist/schemas/kubernetes-responses.js.map +1 -0
  263. package/dist/schemas/kubernetes.d.ts +143 -0
  264. package/dist/schemas/kubernetes.d.ts.map +1 -0
  265. package/dist/schemas/kubernetes.js +68 -0
  266. package/dist/schemas/kubernetes.js.map +1 -0
  267. package/dist/schemas/logs.d.ts +15 -0
  268. package/dist/schemas/logs.d.ts.map +1 -0
  269. package/dist/schemas/logs.js +11 -0
  270. package/dist/schemas/logs.js.map +1 -0
  271. package/dist/schemas/object-storage.d.ts +167 -0
  272. package/dist/schemas/object-storage.d.ts.map +1 -0
  273. package/dist/schemas/object-storage.js +124 -0
  274. package/dist/schemas/object-storage.js.map +1 -0
  275. package/dist/schemas/service-settings.d.ts +9 -0
  276. package/dist/schemas/service-settings.d.ts.map +1 -0
  277. package/dist/schemas/service-settings.js +21 -0
  278. package/dist/schemas/service-settings.js.map +1 -0
  279. package/dist/schemas/utilization.d.ts +57 -0
  280. package/dist/schemas/utilization.d.ts.map +1 -0
  281. package/dist/schemas/utilization.js +58 -0
  282. package/dist/schemas/utilization.js.map +1 -0
  283. package/dist/schemas/worker-status.d.ts +22 -0
  284. package/dist/schemas/worker-status.d.ts.map +1 -0
  285. package/dist/schemas/worker-status.js +14 -0
  286. package/dist/schemas/worker-status.js.map +1 -0
  287. package/dist/schemas/worker.d.ts +125 -0
  288. package/dist/schemas/worker.d.ts.map +1 -0
  289. package/dist/schemas/worker.js +129 -0
  290. package/dist/schemas/worker.js.map +1 -0
  291. package/dist/secrets/app-platform/app-credentials.impl.d.ts +14 -0
  292. package/dist/secrets/app-platform/app-credentials.impl.d.ts.map +1 -0
  293. package/dist/secrets/app-platform/app-credentials.impl.js +237 -0
  294. package/dist/secrets/app-platform/app-credentials.impl.js.map +1 -0
  295. package/dist/secrets/container-registry/image-publish-settings.descriptor.d.ts +11 -0
  296. package/dist/secrets/container-registry/image-publish-settings.descriptor.d.ts.map +1 -0
  297. package/dist/secrets/container-registry/image-publish-settings.descriptor.js +26 -0
  298. package/dist/secrets/container-registry/image-publish-settings.descriptor.js.map +1 -0
  299. package/dist/secrets/doks-secret.descriptor.d.ts +18 -0
  300. package/dist/secrets/doks-secret.descriptor.d.ts.map +1 -0
  301. package/dist/secrets/doks-secret.descriptor.js +35 -0
  302. package/dist/secrets/doks-secret.descriptor.js.map +1 -0
  303. package/dist/secrets/doks-secret.impl.d.ts +98 -0
  304. package/dist/secrets/doks-secret.impl.d.ts.map +1 -0
  305. package/dist/secrets/doks-secret.impl.js +451 -0
  306. package/dist/secrets/doks-secret.impl.js.map +1 -0
  307. package/dist/secrets/index.d.ts +4 -0
  308. package/dist/secrets/index.d.ts.map +1 -0
  309. package/dist/secrets/index.js +4 -0
  310. package/dist/secrets/index.js.map +1 -0
  311. package/dist/secrets/secrets-backend-doks.plugin.d.ts +3 -0
  312. package/dist/secrets/secrets-backend-doks.plugin.d.ts.map +1 -0
  313. package/dist/secrets/secrets-backend-doks.plugin.js +35 -0
  314. package/dist/secrets/secrets-backend-doks.plugin.js.map +1 -0
  315. package/dist/storage/index.d.ts +50 -0
  316. package/dist/storage/index.d.ts.map +1 -0
  317. package/dist/storage/index.js +92 -0
  318. package/dist/storage/index.js.map +1 -0
  319. package/dist/storage/spaces-keys.d.ts +25 -0
  320. package/dist/storage/spaces-keys.d.ts.map +1 -0
  321. package/dist/storage/spaces-keys.js +32 -0
  322. package/dist/storage/spaces-keys.js.map +1 -0
  323. package/package.json +172 -4
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Implementation: infra/worker -> digitalocean-functions
3
+ *
4
+ * Provider that reconciles DigitalOcean Functions for a worker descriptor.
5
+ * Two delivery modes are supported (selected via the descriptor's
6
+ * `config.mode`):
7
+ *
8
+ * - `app-platform`: attach the function as a `functions[]` component on
9
+ * an App Platform App. This is the recommended path because it shares
10
+ * the App's region, env, secrets, alerts, log destinations, and
11
+ * deploy lifecycle with the rest of the application. The reconciler
12
+ * calls into `@vibesdotdev/integrations-digitalocean/apps` to read the
13
+ * existing App spec and produce an updated spec containing the
14
+ * function component. Applying the spec is delegated to the App
15
+ * Platform deploy client (the same one that handles services/workers/
16
+ * jobs), so this impl never mutates the App directly — it returns a
17
+ * plan + an `apply()` that the runtime can drive.
18
+ *
19
+ * - `namespace`: a standalone Functions namespace package. The DO
20
+ * Functions namespace API surface lives outside the App Platform
21
+ * control plane; we model the descriptor here but the reconciler
22
+ * leaves namespace mutation as a TODO (returns `unsupported`) until
23
+ * the connector-side namespace client lands. This keeps the runtime
24
+ * contract stable — descriptors are valid today, with a clear error
25
+ * surface if you try to apply the standalone path.
26
+ *
27
+ * Inventory + status reads use the App Platform read client
28
+ * (`DigitalOceanAppsClient`) and surface the function-component summary
29
+ * via the same `runtime/inventory` path as other DO resources.
30
+ */
31
+ import * as z from 'zod/v4';
32
+ import { type FunctionComponent } from '../schemas/functions.ts';
33
+ import type { DigitalOceanAppsClient, DoApp, DoAppSpec } from '../apps/index.ts';
34
+ export declare const DigitalOceanFunctionsDescriptorSchema: z.ZodObject<{
35
+ kind: z.ZodLiteral<"infra/worker">;
36
+ id: z.ZodString;
37
+ name: z.ZodOptional<z.ZodString>;
38
+ description: z.ZodOptional<z.ZodString>;
39
+ entrypoint: z.ZodOptional<z.ZodString>;
40
+ queues: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ concurrency: z.ZodOptional<z.ZodNumber>;
42
+ env: z.ZodOptional<z.ZodArray<z.ZodObject<{
43
+ name: z.ZodString;
44
+ value: z.ZodOptional<z.ZodString>;
45
+ secret: z.ZodOptional<z.ZodBoolean>;
46
+ storeKey: z.ZodOptional<z.ZodString>;
47
+ }, z.core.$strip>>>;
48
+ config: z.ZodObject<{
49
+ namespace: z.ZodOptional<z.ZodString>;
50
+ mode: z.ZodDefault<z.ZodEnum<{
51
+ namespace: "namespace";
52
+ "app-platform": "app-platform";
53
+ }>>;
54
+ region: z.ZodOptional<z.ZodString>;
55
+ appName: z.ZodOptional<z.ZodString>;
56
+ sourceDir: z.ZodOptional<z.ZodString>;
57
+ github: z.ZodOptional<z.ZodObject<{
58
+ repo: z.ZodString;
59
+ branch: z.ZodDefault<z.ZodString>;
60
+ deployOnPush: z.ZodDefault<z.ZodBoolean>;
61
+ }, z.core.$strip>>;
62
+ environmentSlug: z.ZodOptional<z.ZodString>;
63
+ label: z.ZodOptional<z.ZodString>;
64
+ memoryMb: z.ZodOptional<z.ZodNumber>;
65
+ timeoutSeconds: z.ZodOptional<z.ZodNumber>;
66
+ adapter: z.ZodLiteral<"digitalocean-functions">;
67
+ }, z.core.$strip>;
68
+ }, z.core.$strip>;
69
+ export type DigitalOceanFunctionsDescriptorInput = z.input<typeof DigitalOceanFunctionsDescriptorSchema>;
70
+ export type DigitalOceanFunctionsDescriptor = z.infer<typeof DigitalOceanFunctionsDescriptorSchema>;
71
+ export interface DigitalOceanFunctionsPlanAction {
72
+ op: 'create-component' | 'update-component' | 'unchanged' | 'unsupported';
73
+ componentName: string;
74
+ reason?: string;
75
+ diff?: {
76
+ before?: FunctionComponent;
77
+ after?: FunctionComponent;
78
+ };
79
+ }
80
+ export interface DigitalOceanFunctionsPlan {
81
+ mode: 'app-platform' | 'namespace';
82
+ appName?: string;
83
+ componentName: string;
84
+ actions: DigitalOceanFunctionsPlanAction[];
85
+ /**
86
+ * Resulting App spec when applied. Undefined for the `namespace` mode
87
+ * because the namespace path mutates the Functions API, not an App spec.
88
+ */
89
+ nextAppSpec?: DoAppSpec;
90
+ }
91
+ export interface DigitalOceanFunctionsApplyResult {
92
+ mode: 'app-platform' | 'namespace';
93
+ componentName: string;
94
+ appId?: string;
95
+ updatedSpec?: DoAppSpec;
96
+ skipped?: boolean;
97
+ reason?: string;
98
+ }
99
+ export interface DigitalOceanFunctionsPlanContext {
100
+ apps?: DigitalOceanAppsClient;
101
+ }
102
+ export interface DigitalOceanFunctionsApplyContext {
103
+ apps?: DigitalOceanAppsClient;
104
+ /** Optional callback for status updates while the reconciler runs. */
105
+ onLine?: (stream: 'stdout' | 'stderr', line: string) => void;
106
+ }
107
+ /**
108
+ * Build a plan for a functions descriptor. The plan is pure — it can be
109
+ * computed without making API calls when the caller passes the existing
110
+ * App spec via `existingApp`. When `apps` is provided, the planner reads
111
+ * the App by name to produce a real diff.
112
+ */
113
+ export declare function planDigitalOceanFunctions(descriptor: DigitalOceanFunctionsDescriptor, ctx?: DigitalOceanFunctionsPlanContext & {
114
+ existingApp?: DoApp;
115
+ }): Promise<DigitalOceanFunctionsPlan>;
116
+ /**
117
+ * Apply a functions plan. For the `app-platform` mode, this updates the
118
+ * App spec via the apps client. For the `namespace` mode, this returns
119
+ * `skipped: true` with a reason — the standalone namespace path is not
120
+ * yet implemented and the caller (CLI/routine) should surface the reason.
121
+ */
122
+ export declare function reconcileDigitalOceanFunctions(descriptor: DigitalOceanFunctionsDescriptor, ctx?: DigitalOceanFunctionsApplyContext): Promise<DigitalOceanFunctionsApplyResult>;
123
+ //# sourceMappingURL=functions.impl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.impl.d.ts","sourceRoot":"","sources":["../../src/infra/functions.impl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAG1F,OAAO,KAAK,EAAE,sBAAsB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEjF,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqBhD,CAAC;AACH,MAAM,MAAM,oCAAoC,GAAG,CAAC,CAAC,KAAK,CACzD,OAAO,qCAAqC,CAC5C,CAAC;AACF,MAAM,MAAM,+BAA+B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qCAAqC,CAAC,CAAC;AAEpG,MAAM,WAAW,+BAA+B;IAC/C,EAAE,EAAE,kBAAkB,GAAG,kBAAkB,GAAG,WAAW,GAAG,aAAa,CAAC;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,iBAAiB,CAAC;QAC3B,KAAK,CAAC,EAAE,iBAAiB,CAAC;KAC1B,CAAC;CACF;AAED,MAAM,WAAW,yBAAyB;IACzC,IAAI,EAAE,cAAc,GAAG,WAAW,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,+BAA+B,EAAE,CAAC;IAC3C;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,gCAAgC;IAChD,IAAI,EAAE,cAAc,GAAG,WAAW,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gCAAgC;IAChD,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC9B;AAED,MAAM,WAAW,iCAAiC;IACjD,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,sEAAsE;IACtE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7D;AAiCD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC9C,UAAU,EAAE,+BAA+B,EAC3C,GAAG,GAAE,gCAAgC,GAAG;IAAE,WAAW,CAAC,EAAE,KAAK,CAAA;CAAO,GAClE,OAAO,CAAC,yBAAyB,CAAC,CAkEpC;AAED;;;;;GAKG;AACH,wBAAsB,8BAA8B,CACnD,UAAU,EAAE,+BAA+B,EAC3C,GAAG,GAAE,iCAAsC,GACzC,OAAO,CAAC,gCAAgC,CAAC,CAmD3C"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Implementation: infra/worker -> digitalocean-functions
3
+ *
4
+ * Provider that reconciles DigitalOcean Functions for a worker descriptor.
5
+ * Two delivery modes are supported (selected via the descriptor's
6
+ * `config.mode`):
7
+ *
8
+ * - `app-platform`: attach the function as a `functions[]` component on
9
+ * an App Platform App. This is the recommended path because it shares
10
+ * the App's region, env, secrets, alerts, log destinations, and
11
+ * deploy lifecycle with the rest of the application. The reconciler
12
+ * calls into `@vibesdotdev/integrations-digitalocean/apps` to read the
13
+ * existing App spec and produce an updated spec containing the
14
+ * function component. Applying the spec is delegated to the App
15
+ * Platform deploy client (the same one that handles services/workers/
16
+ * jobs), so this impl never mutates the App directly — it returns a
17
+ * plan + an `apply()` that the runtime can drive.
18
+ *
19
+ * - `namespace`: a standalone Functions namespace package. The DO
20
+ * Functions namespace API surface lives outside the App Platform
21
+ * control plane; we model the descriptor here but the reconciler
22
+ * leaves namespace mutation as a TODO (returns `unsupported`) until
23
+ * the connector-side namespace client lands. This keeps the runtime
24
+ * contract stable — descriptors are valid today, with a clear error
25
+ * surface if you try to apply the standalone path.
26
+ *
27
+ * Inventory + status reads use the App Platform read client
28
+ * (`DigitalOceanAppsClient`) and surface the function-component summary
29
+ * via the same `runtime/inventory` path as other DO resources.
30
+ */
31
+ import * as z from 'zod/v4';
32
+ import { FunctionComponentSchema } from "../schemas/functions.js";
33
+ import { DigitalOceanJsonBodySchema } from "../schemas/control-plane.js";
34
+ import { DigitalOceanFunctionsWorkerConfigSchema } from "../schemas/worker.js";
35
+ export const DigitalOceanFunctionsDescriptorSchema = z.object({
36
+ kind: z.literal('infra/worker'),
37
+ id: z.string().min(1),
38
+ name: z.string().optional(),
39
+ description: z.string().optional(),
40
+ entrypoint: z.string().min(1).optional(),
41
+ queues: z.array(z.string().min(1)).optional(),
42
+ concurrency: z.number().int().positive().optional(),
43
+ env: z
44
+ .array(z.object({
45
+ name: z.string().regex(/^[_A-Z0-9]+$/),
46
+ value: z.string().optional(),
47
+ secret: z.boolean().optional(),
48
+ storeKey: z.string().min(1).optional()
49
+ }))
50
+ .optional(),
51
+ config: DigitalOceanFunctionsWorkerConfigSchema.extend({
52
+ adapter: z.literal('digitalocean-functions')
53
+ })
54
+ });
55
+ function componentNameFor(descriptor) {
56
+ return descriptor.name ?? descriptor.id;
57
+ }
58
+ function buildFunctionComponent(descriptor) {
59
+ const c = descriptor.config;
60
+ const component = {
61
+ name: componentNameFor(descriptor),
62
+ source_dir: c.sourceDir,
63
+ environment_slug: c.environmentSlug,
64
+ github: c.github
65
+ ? {
66
+ repo: c.github.repo,
67
+ branch: c.github.branch,
68
+ deploy_on_push: c.github.deployOnPush
69
+ }
70
+ : undefined,
71
+ envs: descriptor.env?.map((req) => ({
72
+ key: req.name,
73
+ value: req.value,
74
+ scope: 'RUN_AND_BUILD_TIME',
75
+ type: req.secret ? 'SECRET' : 'GENERAL'
76
+ }))
77
+ };
78
+ return FunctionComponentSchema.parse(DigitalOceanJsonBodySchema.parse(component));
79
+ }
80
+ function specsEqual(a, b) {
81
+ return JSON.stringify(a) === JSON.stringify(b);
82
+ }
83
+ /**
84
+ * Build a plan for a functions descriptor. The plan is pure — it can be
85
+ * computed without making API calls when the caller passes the existing
86
+ * App spec via `existingApp`. When `apps` is provided, the planner reads
87
+ * the App by name to produce a real diff.
88
+ */
89
+ export async function planDigitalOceanFunctions(descriptor, ctx = {}) {
90
+ const config = descriptor.config;
91
+ const componentName = componentNameFor(descriptor);
92
+ if (config.mode === 'namespace') {
93
+ return {
94
+ mode: 'namespace',
95
+ componentName,
96
+ actions: [
97
+ {
98
+ op: 'unsupported',
99
+ componentName,
100
+ reason: 'Standalone DigitalOcean Functions namespace deployment is not yet wired. Use mode="app-platform" to attach the function to an App Platform App.'
101
+ }
102
+ ]
103
+ };
104
+ }
105
+ if (!config.appName) {
106
+ return {
107
+ mode: 'app-platform',
108
+ componentName,
109
+ actions: [
110
+ {
111
+ op: 'unsupported',
112
+ componentName,
113
+ reason: 'config.appName is required when mode="app-platform" so the reconciler knows which App to update.'
114
+ }
115
+ ]
116
+ };
117
+ }
118
+ const existingApp = ctx.existingApp;
119
+ const desired = buildFunctionComponent(descriptor);
120
+ const nextSpec = existingApp?.spec
121
+ ? structuredClone(existingApp.spec)
122
+ : { name: config.appName };
123
+ const functions = (nextSpec.functions ??= []);
124
+ const existingIdx = functions.findIndex((fn) => FunctionComponentSchema.parse(fn).name === componentName);
125
+ const actions = [];
126
+ if (existingIdx < 0) {
127
+ functions.push(desired);
128
+ actions.push({ op: 'create-component', componentName, diff: { after: desired } });
129
+ }
130
+ else {
131
+ const before = FunctionComponentSchema.parse(functions[existingIdx]);
132
+ if (specsEqual(before, desired)) {
133
+ actions.push({ op: 'unchanged', componentName });
134
+ }
135
+ else {
136
+ functions[existingIdx] = desired;
137
+ actions.push({ op: 'update-component', componentName, diff: { before, after: desired } });
138
+ }
139
+ }
140
+ return {
141
+ mode: 'app-platform',
142
+ appName: config.appName,
143
+ componentName,
144
+ actions,
145
+ nextAppSpec: nextSpec
146
+ };
147
+ }
148
+ /**
149
+ * Apply a functions plan. For the `app-platform` mode, this updates the
150
+ * App spec via the apps client. For the `namespace` mode, this returns
151
+ * `skipped: true` with a reason — the standalone namespace path is not
152
+ * yet implemented and the caller (CLI/routine) should surface the reason.
153
+ */
154
+ export async function reconcileDigitalOceanFunctions(descriptor, ctx = {}) {
155
+ const inventory = ctx.apps ? await ctx.apps.list() : [];
156
+ const current = inventory.find((app) => app.spec?.name === descriptor.config.appName);
157
+ const plan = await planDigitalOceanFunctions(descriptor, { existingApp: current });
158
+ if (plan.mode === 'namespace' || plan.actions[0]?.op === 'unsupported') {
159
+ const reason = plan.actions[0]?.reason ?? 'unsupported';
160
+ ctx.onLine?.('stderr', `[functions ${plan.componentName}] skipped: ${reason}`);
161
+ return { mode: plan.mode, componentName: plan.componentName, skipped: true, reason };
162
+ }
163
+ if (plan.actions.every((a) => a.op === 'unchanged')) {
164
+ ctx.onLine?.('stdout', `[functions ${plan.componentName}] unchanged`);
165
+ return {
166
+ mode: 'app-platform',
167
+ componentName: plan.componentName,
168
+ updatedSpec: plan.nextAppSpec,
169
+ skipped: true,
170
+ reason: 'no diff'
171
+ };
172
+ }
173
+ if (!ctx.apps || !plan.nextAppSpec) {
174
+ return {
175
+ mode: 'app-platform',
176
+ componentName: plan.componentName,
177
+ updatedSpec: plan.nextAppSpec,
178
+ skipped: true,
179
+ reason: 'no apps client provided'
180
+ };
181
+ }
182
+ const existing = current;
183
+ if (!existing) {
184
+ const created = await ctx.apps.create(plan.nextAppSpec);
185
+ ctx.onLine?.('stdout', `[functions ${plan.componentName}] created App ${created.id}`);
186
+ return {
187
+ mode: 'app-platform',
188
+ componentName: plan.componentName,
189
+ appId: created.id,
190
+ updatedSpec: created.spec
191
+ };
192
+ }
193
+ const finalApp = await ctx.apps.update(existing.id, plan.nextAppSpec);
194
+ ctx.onLine?.('stdout', `[functions ${plan.componentName}] updated App ${finalApp.id}`);
195
+ return {
196
+ mode: 'app-platform',
197
+ componentName: plan.componentName,
198
+ appId: finalApp.id,
199
+ updatedSpec: finalApp.spec ?? plan.nextAppSpec
200
+ };
201
+ }
202
+ //# sourceMappingURL=functions.impl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.impl.js","sourceRoot":"","sources":["../../src/infra/functions.impl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export { default as digitalOceanInfraPlugin } from './digitalocean-infra.plugin.ts';
2
+ export { DigitalOceanImagePublishSettingsSchema, DigitalOceanReleaseOptionsSchema, SanitizedAppSpecEvidenceSchema } from '../schemas/app-deployment.ts';
3
+ export type { DigitalOceanImagePublishSettings, DigitalOceanReleaseOptions, SanitizedAppSpecEvidence } from '../schemas/app-deployment.ts';
4
+ export { DigitalOceanDoksWorkerAdapterSchema, DigitalOceanDoksWorkerCredentialDeliveryOwnerSchema, DigitalOceanDoksWorkerCreateOptionsSchema, DigitalOceanDoksWorkerExecutionInputSchema, DigitalOceanDoksWorkerExecutionOwnerSchema, DigitalOceanDoksWorkerInfraImplementationSchema, DigitalOceanDoksWorkerSourceOperationAnnotationsSchema } from '../schemas/doks-worker.ts';
5
+ export type { DigitalOceanDoksWorkerAdapter, DigitalOceanDoksWorkerCreateOptions, DigitalOceanDoksWorkerExecutionInput, DigitalOceanDoksWorkerExecutionOwner, DigitalOceanDoksWorkerInfraImplementation, DigitalOceanDoksWorkerPlan } from '../schemas/doks-worker.ts';
6
+ export { DigitalOceanDoksWorkerStatusSchema } from '../schemas/worker-status.ts';
7
+ export type { DigitalOceanDoksWorkerStatus } from '../schemas/worker-status.ts';
8
+ export { DigitalOceanBillingClient } from './billing.ts';
9
+ export { DigitalOceanUtilizationClient } from './utilization.ts';
10
+ export { createDigitalOceanProviderControlPlaneClient } from './credentials.ts';
11
+ export * from './droplet.impl.ts';
12
+ export * from './functions.impl.ts';
13
+ export * from './inventory.ts';
14
+ export * from './doks/service-release.ts';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACpF,OAAO,EACN,sCAAsC,EACtC,gCAAgC,EAChC,8BAA8B,EAC9B,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACX,gCAAgC,EAChC,0BAA0B,EAC1B,wBAAwB,EACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACN,mCAAmC,EACnC,mDAAmD,EACnD,yCAAyC,EACzC,0CAA0C,EAC1C,0CAA0C,EAC1C,+CAA+C,EAC/C,sDAAsD,EACtD,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACX,6BAA6B,EAC7B,mCAAmC,EACnC,oCAAoC,EACpC,oCAAoC,EACpC,yCAAyC,EACzC,0BAA0B,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AACjF,YAAY,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,4CAA4C,EAAE,MAAM,kBAAkB,CAAC;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { default as digitalOceanInfraPlugin } from "./digitalocean-infra.plugin.js";
2
+ export { DigitalOceanImagePublishSettingsSchema, DigitalOceanReleaseOptionsSchema, SanitizedAppSpecEvidenceSchema } from "../schemas/app-deployment.js";
3
+ export { DigitalOceanDoksWorkerAdapterSchema, DigitalOceanDoksWorkerCredentialDeliveryOwnerSchema, DigitalOceanDoksWorkerCreateOptionsSchema, DigitalOceanDoksWorkerExecutionInputSchema, DigitalOceanDoksWorkerExecutionOwnerSchema, DigitalOceanDoksWorkerInfraImplementationSchema, DigitalOceanDoksWorkerSourceOperationAnnotationsSchema } from "../schemas/doks-worker.js";
4
+ export { DigitalOceanDoksWorkerStatusSchema } from "../schemas/worker-status.js";
5
+ export { DigitalOceanBillingClient } from "./billing.js";
6
+ export { DigitalOceanUtilizationClient } from "./utilization.js";
7
+ export { createDigitalOceanProviderControlPlaneClient } from "./credentials.js";
8
+ export * from "./droplet.impl.js";
9
+ export * from "./functions.impl.js";
10
+ export * from "./inventory.js";
11
+ export * from "./doks/service-release.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infra/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACpF,OAAO,EACN,sCAAsC,EACtC,gCAAgC,EAChC,8BAA8B,EAC9B,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EACN,mCAAmC,EACnC,mDAAmD,EACnD,yCAAyC,EACzC,0CAA0C,EAC1C,0CAA0C,EAC1C,+CAA+C,EAC/C,sDAAsD,EACtD,MAAM,2BAA2B,CAAC;AASnC,OAAO,EAAE,kCAAkC,EAAE,MAAM,6BAA6B,CAAC;AAEjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,4CAA4C,EAAE,MAAM,kBAAkB,CAAC;AAChF,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type VibesRuntime } from '@vibesdotdev/kernel';
2
+ import type { InventoryImplementation } from '@vibesdotdev/infra-core/kinds';
3
+ import type { DigitalOceanControlPlaneClient } from '../client/control-plane.ts';
4
+ export declare function createDigitalOceanInventoryImplementation(runtime: VibesRuntime, options?: {
5
+ client?: DigitalOceanControlPlaneClient;
6
+ }): Promise<InventoryImplementation>;
7
+ //# sourceMappingURL=inventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../src/infra/inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,KAAK,EACX,uBAAuB,EAGvB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AA2BjF,wBAAsB,yCAAyC,CAC9D,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,8BAA8B,CAAA;CAAE,GACnD,OAAO,CAAC,uBAAuB,CAAC,CAuPlC"}
@@ -0,0 +1,259 @@
1
+ import { settle } from '@vibesdotdev/kernel';
2
+ import { sanitizeInfraProviderFailure } from '@vibesdotdev/infra-core';
3
+ import { DigitalOceanKubernetesClient } from "../kubernetes/index.js";
4
+ import { DigitalOceanDropletsClient } from "../droplets/index.js";
5
+ import { DigitalOceanStorageClient, DigitalOceanSpacesKeysClient } from "../storage/index.js";
6
+ import { DigitalOceanAppsClient } from "../apps/index.js";
7
+ import { DigitalOceanNetworkClient } from "../network/index.js";
8
+ import { DigitalOceanContainerRegistryClient } from "../registry/index.js";
9
+ import { createDigitalOceanProviderControlPlaneClient } from "./credentials.js";
10
+ const SPACES_KEY_KIND = 'infra/object-storage-credential';
11
+ export async function createDigitalOceanInventoryImplementation(runtime, options) {
12
+ // The control-plane client is injectable so this module can be exercised
13
+ // without resolving an operator credential; production callers pass nothing
14
+ // and get the canonical credential path.
15
+ const controlPlane = options?.client ??
16
+ (await createDigitalOceanProviderControlPlaneClient(runtime));
17
+ const kubernetes = new DigitalOceanKubernetesClient(controlPlane);
18
+ const droplets = new DigitalOceanDropletsClient(controlPlane);
19
+ const storage = new DigitalOceanStorageClient(controlPlane);
20
+ const spacesKeys = new DigitalOceanSpacesKeysClient(controlPlane);
21
+ const apps = new DigitalOceanAppsClient(controlPlane);
22
+ const network = new DigitalOceanNetworkClient(controlPlane);
23
+ const registry = new DigitalOceanContainerRegistryClient(controlPlane);
24
+ const collectors = [
25
+ {
26
+ kind: 'infra/kubernetes-cluster',
27
+ collect: async () => (await kubernetes.listClusters()).map((cluster) => ({
28
+ id: cluster.id,
29
+ kind: 'infra/kubernetes-cluster',
30
+ name: cluster.name,
31
+ region: cluster.region,
32
+ status: cluster.status.state,
33
+ tags: cluster.tags,
34
+ createdAt: cluster.created_at,
35
+ raw: {
36
+ version: cluster.version,
37
+ ha: cluster.ha ?? false,
38
+ autoUpgrade: cluster.auto_upgrade ?? false,
39
+ surgeUpgrade: cluster.surge_upgrade ?? false,
40
+ registryEnabled: cluster.registry_enabled ?? false,
41
+ clusterSubnet: cluster.cluster_subnet,
42
+ serviceSubnet: cluster.service_subnet,
43
+ vpcId: cluster.vpc_uuid,
44
+ nodePools: cluster.node_pools.map((pool) => ({
45
+ id: pool.id,
46
+ name: pool.name,
47
+ size: pool.size,
48
+ count: pool.count,
49
+ autoScale: pool.auto_scale ?? false,
50
+ minNodes: pool.min_nodes,
51
+ maxNodes: pool.max_nodes
52
+ }))
53
+ }
54
+ }))
55
+ },
56
+ {
57
+ kind: 'infra/compute-instance',
58
+ collect: async () => (await droplets.list()).map((droplet) => ({
59
+ id: String(droplet.id),
60
+ kind: 'infra/compute-instance',
61
+ name: droplet.name,
62
+ region: droplet.region.slug,
63
+ status: droplet.status,
64
+ // A DOKS worker carries `k8s:<cluster-id>`; anything else is a
65
+ // standalone droplet somebody has to own by hand.
66
+ managedBy: kubernetesClusterTag(droplet.tags) ?? undefined,
67
+ tags: droplet.tags,
68
+ createdAt: droplet.created_at,
69
+ raw: {
70
+ size: droplet.size_slug,
71
+ vcpus: droplet.vcpus,
72
+ memoryMb: droplet.memory,
73
+ diskGb: droplet.disk,
74
+ image: droplet.image?.slug ?? droplet.image?.distribution,
75
+ publicIps: publicIps(droplet.networks?.v4),
76
+ backupsEnabled: featureEnabled(droplet, 'backups'),
77
+ monitoringEnabled: featureEnabled(droplet, 'monitoring')
78
+ }
79
+ }))
80
+ },
81
+ {
82
+ kind: 'infra/load-balancer',
83
+ collect: async () => (await network.listLoadBalancers()).map((lb) => ({
84
+ id: lb.id,
85
+ kind: 'infra/load-balancer',
86
+ name: lb.name,
87
+ region: lb.region?.slug,
88
+ status: lb.status,
89
+ createdAt: lb.created_at,
90
+ raw: {
91
+ ip: lb.ip,
92
+ size: lb.size ?? lb.size_unit,
93
+ dropletCount: lb.droplet_ids?.length ?? 0,
94
+ dropletIds: lb.droplet_ids ?? [],
95
+ tag: lb.tag || undefined,
96
+ forwardingRules: (lb.forwarding_rules ?? []).map((rule) => `${rule.entry_protocol}:${rule.entry_port}->${rule.target_protocol}:${rule.target_port}`)
97
+ }
98
+ }))
99
+ },
100
+ {
101
+ kind: 'infra/volume',
102
+ collect: async () => (await storage.listVolumes()).map((volume) => ({
103
+ id: volume.id,
104
+ kind: 'infra/volume',
105
+ name: volume.name,
106
+ region: volume.region.slug,
107
+ // An unattached volume bills exactly like an attached one.
108
+ status: volume.droplet_ids.length > 0 ? 'attached' : 'detached',
109
+ tags: volume.tags,
110
+ createdAt: volume.created_at,
111
+ raw: {
112
+ sizeGb: volume.size_gigabytes,
113
+ dropletIds: volume.droplet_ids,
114
+ filesystemType: volume.filesystem_type
115
+ }
116
+ }))
117
+ },
118
+ {
119
+ kind: 'infra/snapshot',
120
+ collect: async () => (await droplets.listSnapshots()).map((snapshot) => ({
121
+ id: snapshot.id,
122
+ kind: 'infra/snapshot',
123
+ name: snapshot.name,
124
+ region: snapshot.regions?.[0],
125
+ createdAt: snapshot.created_at,
126
+ raw: {
127
+ sizeGb: snapshot.size_gigabytes,
128
+ resourceType: snapshot.resource_type,
129
+ resourceId: snapshot.resource_id,
130
+ regions: snapshot.regions ?? []
131
+ }
132
+ }))
133
+ },
134
+ {
135
+ kind: 'infra/web-app',
136
+ collect: async () => (await apps.list()).map((app) => ({
137
+ id: app.id,
138
+ kind: 'infra/web-app',
139
+ name: app.spec?.name,
140
+ region: app.spec?.region,
141
+ status: app.active_deployment?.phase ?? 'unknown',
142
+ createdAt: app.created_at,
143
+ raw: {
144
+ liveUrl: app.live_url,
145
+ defaultIngress: app.default_ingress,
146
+ activeDeploymentId: app.active_deployment?.id,
147
+ inProgressDeploymentPhase: app.in_progress_deployment?.phase,
148
+ updatedAt: app.updated_at
149
+ }
150
+ }))
151
+ },
152
+ {
153
+ kind: 'infra/container-registry',
154
+ collect: async () => {
155
+ const found = await registry.get();
156
+ if (!found)
157
+ return [];
158
+ const repositories = await registry.listRepositories(found.registry.name);
159
+ // tag_count and manifest_count diverge as soon as an image is
160
+ // overwritten: the old manifest loses its tag but keeps its blobs.
161
+ // Reporting the difference is the point — it is invisible in the
162
+ // console and bills as storage until a garbage collection runs.
163
+ const untagged = repositories.reduce((total, repo) => total + Math.max((repo.manifest_count ?? 0) - (repo.tag_count ?? 0), 0), 0);
164
+ return [
165
+ {
166
+ id: found.registry.name,
167
+ kind: 'infra/container-registry',
168
+ name: found.registry.name,
169
+ region: found.registry.region,
170
+ status: found.registry.read_only ? 'read-only' : 'active',
171
+ createdAt: found.registry.created_at,
172
+ raw: {
173
+ storageUsageBytes: found.registry.storage_usage_bytes,
174
+ storageUsageUpdatedAt: found.registry.storage_usage_updated_at,
175
+ includedStorageBytes: found.subscription?.tier?.included_storage_bytes,
176
+ tier: found.subscription?.tier?.slug,
177
+ repositoryCount: repositories.length,
178
+ untaggedManifestCount: untagged,
179
+ repositories: repositories.map((repo) => ({
180
+ name: repo.name,
181
+ tagCount: repo.tag_count ?? 0,
182
+ manifestCount: repo.manifest_count ?? 0,
183
+ latestUpdatedAt: repo.latest_manifest?.updated_at
184
+ }))
185
+ }
186
+ }
187
+ ];
188
+ }
189
+ },
190
+ {
191
+ kind: SPACES_KEY_KIND,
192
+ collect: async () =>
193
+ // Names, grants and creation dates only. The access key id is an
194
+ // identifier, not a credential, and the secret is never returned by
195
+ // this endpoint at all — but a `fullaccess` grant from a retired
196
+ // project is a finding, so the grant has to be reported.
197
+ (await spacesKeys.list()).map((key) => ({
198
+ id: key.access_key,
199
+ kind: SPACES_KEY_KIND,
200
+ name: key.name,
201
+ status: grantSummary(key.grants),
202
+ createdAt: key.created_at,
203
+ raw: {
204
+ grants: (key.grants ?? []).map((grant) => ({
205
+ bucket: grant.bucket || '*',
206
+ permission: grant.permission
207
+ }))
208
+ }
209
+ }))
210
+ }
211
+ ];
212
+ return {
213
+ async collect(opts) {
214
+ const requested = new Set(opts?.kinds ?? []);
215
+ const selected = collectors.filter((collector) => requested.size === 0 || requested.has(collector.kind));
216
+ const resources = [];
217
+ // One failing endpoint must not blank the whole inventory: a token
218
+ // scoped without registry read still has to report its droplets, and
219
+ // the gap is reported as a row rather than as silence.
220
+ for (const collector of selected) {
221
+ const result = await settle(() => collector.collect());
222
+ if (result.ok)
223
+ resources.push(...result.value);
224
+ else
225
+ resources.push({
226
+ id: collector.kind,
227
+ kind: 'infra/inventory-error',
228
+ name: collector.kind,
229
+ status: 'error',
230
+ raw: { message: sanitizeInfraProviderFailure(result.cause).message }
231
+ });
232
+ }
233
+ return {
234
+ provider: 'digitalocean',
235
+ collectedAt: new Date().toISOString(),
236
+ resources,
237
+ credentialPath: 'canonical-config'
238
+ };
239
+ }
240
+ };
241
+ }
242
+ /** The `k8s:<cluster-id>` tag DOKS puts on every worker it owns. */
243
+ function kubernetesClusterTag(tags) {
244
+ const tag = (tags ?? []).find((t) => t.startsWith('k8s:') && t !== 'k8s:worker');
245
+ return tag ? tag.slice('k8s:'.length) : null;
246
+ }
247
+ function publicIps(v4) {
248
+ return (v4 ?? []).filter((n) => n.type === 'public').map((n) => n.ip_address);
249
+ }
250
+ function featureEnabled(droplet, feature) {
251
+ const features = droplet.features;
252
+ return Array.isArray(features) && features.includes(feature);
253
+ }
254
+ function grantSummary(grants) {
255
+ if (!grants || grants.length === 0)
256
+ return 'no-grants';
257
+ return grants.some((grant) => grant.permission === 'fullaccess') ? 'fullaccess' : 'scoped';
258
+ }
259
+ //# sourceMappingURL=inventory.js.map