@alchemy.run/modal 0.0.0 → 2.0.0-beta.87

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 (499) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +96 -4
  3. package/lib/App.d.ts +143 -0
  4. package/lib/App.d.ts.map +1 -0
  5. package/lib/App.js +198 -0
  6. package/lib/App.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +53 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +209 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/BindingHttp.d.ts +56 -0
  12. package/lib/BindingHttp.d.ts.map +1 -0
  13. package/lib/BindingHttp.js +50 -0
  14. package/lib/BindingHttp.js.map +1 -0
  15. package/lib/Blob.d.ts +34 -0
  16. package/lib/Blob.d.ts.map +1 -0
  17. package/lib/Blob.js +59 -0
  18. package/lib/Blob.js.map +1 -0
  19. package/lib/Bootstrap.d.ts +8 -0
  20. package/lib/Bootstrap.d.ts.map +1 -0
  21. package/lib/Bootstrap.js +26 -0
  22. package/lib/Bootstrap.js.map +1 -0
  23. package/lib/Cbor.d.ts +10 -0
  24. package/lib/Cbor.d.ts.map +1 -0
  25. package/lib/Cbor.js +177 -0
  26. package/lib/Cbor.js.map +1 -0
  27. package/lib/ConnectSandbox.d.ts +64 -0
  28. package/lib/ConnectSandbox.d.ts.map +1 -0
  29. package/lib/ConnectSandbox.js +33 -0
  30. package/lib/ConnectSandbox.js.map +1 -0
  31. package/lib/Container.d.ts +124 -0
  32. package/lib/Container.d.ts.map +1 -0
  33. package/lib/Container.js +1 -0
  34. package/lib/Container.js.map +1 -0
  35. package/lib/Contributions.d.ts +7 -0
  36. package/lib/Contributions.d.ts.map +1 -0
  37. package/lib/Contributions.js +6 -0
  38. package/lib/Contributions.js.map +1 -0
  39. package/lib/CreateDict.d.ts +83 -0
  40. package/lib/CreateDict.d.ts.map +1 -0
  41. package/lib/CreateDict.js +3 -0
  42. package/lib/CreateDict.js.map +1 -0
  43. package/lib/CreateDictHttp.d.ts +33 -0
  44. package/lib/CreateDictHttp.d.ts.map +1 -0
  45. package/lib/CreateDictHttp.js +67 -0
  46. package/lib/CreateDictHttp.js.map +1 -0
  47. package/lib/CreateImage.d.ts +98 -0
  48. package/lib/CreateImage.d.ts.map +1 -0
  49. package/lib/CreateImage.js +3 -0
  50. package/lib/CreateImage.js.map +1 -0
  51. package/lib/CreateImageHttp.d.ts +51 -0
  52. package/lib/CreateImageHttp.d.ts.map +1 -0
  53. package/lib/CreateImageHttp.js +87 -0
  54. package/lib/CreateImageHttp.js.map +1 -0
  55. package/lib/CreateQueue.d.ts +83 -0
  56. package/lib/CreateQueue.d.ts.map +1 -0
  57. package/lib/CreateQueue.js +3 -0
  58. package/lib/CreateQueue.js.map +1 -0
  59. package/lib/CreateQueueHttp.d.ts +31 -0
  60. package/lib/CreateQueueHttp.d.ts.map +1 -0
  61. package/lib/CreateQueueHttp.js +67 -0
  62. package/lib/CreateQueueHttp.js.map +1 -0
  63. package/lib/CreateSandbox.d.ts +186 -0
  64. package/lib/CreateSandbox.d.ts.map +1 -0
  65. package/lib/CreateSandbox.js +3 -0
  66. package/lib/CreateSandbox.js.map +1 -0
  67. package/lib/CreateSandboxHttp.d.ts +17 -0
  68. package/lib/CreateSandboxHttp.d.ts.map +1 -0
  69. package/lib/CreateSandboxHttp.js +117 -0
  70. package/lib/CreateSandboxHttp.js.map +1 -0
  71. package/lib/CreateSecret.d.ts +95 -0
  72. package/lib/CreateSecret.d.ts.map +1 -0
  73. package/lib/CreateSecret.js +3 -0
  74. package/lib/CreateSecret.js.map +1 -0
  75. package/lib/CreateSecretHttp.d.ts +24 -0
  76. package/lib/CreateSecretHttp.d.ts.map +1 -0
  77. package/lib/CreateSecretHttp.js +60 -0
  78. package/lib/CreateSecretHttp.js.map +1 -0
  79. package/lib/CreateVolume.d.ts +84 -0
  80. package/lib/CreateVolume.d.ts.map +1 -0
  81. package/lib/CreateVolume.js +3 -0
  82. package/lib/CreateVolume.js.map +1 -0
  83. package/lib/CreateVolumeHttp.d.ts +32 -0
  84. package/lib/CreateVolumeHttp.d.ts.map +1 -0
  85. package/lib/CreateVolumeHttp.js +69 -0
  86. package/lib/CreateVolumeHttp.js.map +1 -0
  87. package/lib/Credentials.d.ts +32 -0
  88. package/lib/Credentials.d.ts.map +1 -0
  89. package/lib/Credentials.js +44 -0
  90. package/lib/Credentials.js.map +1 -0
  91. package/lib/Dict.d.ts +147 -0
  92. package/lib/Dict.d.ts.map +1 -0
  93. package/lib/Dict.js +175 -0
  94. package/lib/Dict.js.map +1 -0
  95. package/lib/DictClient.d.ts +55 -0
  96. package/lib/DictClient.d.ts.map +1 -0
  97. package/lib/DictClient.js +89 -0
  98. package/lib/DictClient.js.map +1 -0
  99. package/lib/Domain.d.ts +86 -0
  100. package/lib/Domain.d.ts.map +1 -0
  101. package/lib/Domain.js +113 -0
  102. package/lib/Domain.js.map +1 -0
  103. package/lib/Endpoint.d.ts +181 -0
  104. package/lib/Endpoint.d.ts.map +1 -0
  105. package/lib/Endpoint.js +283 -0
  106. package/lib/Endpoint.js.map +1 -0
  107. package/lib/Environment.d.ts +174 -0
  108. package/lib/Environment.d.ts.map +1 -0
  109. package/lib/Environment.js +244 -0
  110. package/lib/Environment.js.map +1 -0
  111. package/lib/FetchServer.d.ts +105 -0
  112. package/lib/FetchServer.d.ts.map +1 -0
  113. package/lib/FetchServer.js +3 -0
  114. package/lib/FetchServer.js.map +1 -0
  115. package/lib/FetchServerHttp.d.ts +21 -0
  116. package/lib/FetchServerHttp.d.ts.map +1 -0
  117. package/lib/FetchServerHttp.js +84 -0
  118. package/lib/FetchServerHttp.js.map +1 -0
  119. package/lib/Function.d.ts +236 -0
  120. package/lib/Function.d.ts.map +1 -0
  121. package/lib/Function.js +273 -0
  122. package/lib/Function.js.map +1 -0
  123. package/lib/FunctionAutoscaler.d.ts +99 -0
  124. package/lib/FunctionAutoscaler.d.ts.map +1 -0
  125. package/lib/FunctionAutoscaler.js +136 -0
  126. package/lib/FunctionAutoscaler.js.map +1 -0
  127. package/lib/FunctionTarget.d.ts +61 -0
  128. package/lib/FunctionTarget.d.ts.map +1 -0
  129. package/lib/FunctionTarget.js +136 -0
  130. package/lib/FunctionTarget.js.map +1 -0
  131. package/lib/Image.d.ts +159 -0
  132. package/lib/Image.d.ts.map +1 -0
  133. package/lib/Image.js +203 -0
  134. package/lib/Image.js.map +1 -0
  135. package/lib/ImageBuild.d.ts +108 -0
  136. package/lib/ImageBuild.d.ts.map +1 -0
  137. package/lib/ImageBuild.js +157 -0
  138. package/lib/ImageBuild.js.map +1 -0
  139. package/lib/ImagePlan.d.ts +31 -0
  140. package/lib/ImagePlan.d.ts.map +1 -0
  141. package/lib/ImagePlan.js +70 -0
  142. package/lib/ImagePlan.js.map +1 -0
  143. package/lib/InferEnv.d.ts +26 -0
  144. package/lib/InferEnv.d.ts.map +1 -0
  145. package/lib/InferEnv.js +1 -0
  146. package/lib/InferEnv.js.map +1 -0
  147. package/lib/InvokeFunction.d.ts +186 -0
  148. package/lib/InvokeFunction.d.ts.map +1 -0
  149. package/lib/InvokeFunction.js +10 -0
  150. package/lib/InvokeFunction.js.map +1 -0
  151. package/lib/InvokeFunctionHttp.d.ts +39 -0
  152. package/lib/InvokeFunctionHttp.d.ts.map +1 -0
  153. package/lib/InvokeFunctionHttp.js +210 -0
  154. package/lib/InvokeFunctionHttp.js.map +1 -0
  155. package/lib/ModalBindings.d.ts +138 -0
  156. package/lib/ModalBindings.d.ts.map +1 -0
  157. package/lib/ModalBindings.js +223 -0
  158. package/lib/ModalBindings.js.map +1 -0
  159. package/lib/MountBucket.d.ts +80 -0
  160. package/lib/MountBucket.d.ts.map +1 -0
  161. package/lib/MountBucket.js +44 -0
  162. package/lib/MountBucket.js.map +1 -0
  163. package/lib/MountVolume.d.ts +77 -0
  164. package/lib/MountVolume.d.ts.map +1 -0
  165. package/lib/MountVolume.js +41 -0
  166. package/lib/MountVolume.js.map +1 -0
  167. package/lib/Mounts.d.ts +134 -0
  168. package/lib/Mounts.d.ts.map +1 -0
  169. package/lib/Mounts.js +87 -0
  170. package/lib/Mounts.js.map +1 -0
  171. package/lib/PersistentSandbox.d.ts +75 -0
  172. package/lib/PersistentSandbox.d.ts.map +1 -0
  173. package/lib/PersistentSandbox.js +93 -0
  174. package/lib/PersistentSandbox.js.map +1 -0
  175. package/lib/Providers.d.ts +23 -0
  176. package/lib/Providers.d.ts.map +1 -0
  177. package/lib/Providers.js +64 -0
  178. package/lib/Providers.js.map +1 -0
  179. package/lib/Proxy.d.ts +94 -0
  180. package/lib/Proxy.d.ts.map +1 -0
  181. package/lib/Proxy.js +132 -0
  182. package/lib/Proxy.js.map +1 -0
  183. package/lib/Queue.d.ts +147 -0
  184. package/lib/Queue.d.ts.map +1 -0
  185. package/lib/Queue.js +177 -0
  186. package/lib/Queue.js.map +1 -0
  187. package/lib/QueueClient.d.ts +64 -0
  188. package/lib/QueueClient.d.ts.map +1 -0
  189. package/lib/QueueClient.js +73 -0
  190. package/lib/QueueClient.js.map +1 -0
  191. package/lib/ReadApp.d.ts +85 -0
  192. package/lib/ReadApp.d.ts.map +1 -0
  193. package/lib/ReadApp.js +3 -0
  194. package/lib/ReadApp.js.map +1 -0
  195. package/lib/ReadAppHttp.d.ts +26 -0
  196. package/lib/ReadAppHttp.d.ts.map +1 -0
  197. package/lib/ReadAppHttp.js +106 -0
  198. package/lib/ReadAppHttp.js.map +1 -0
  199. package/lib/ReadDict.d.ts +39 -0
  200. package/lib/ReadDict.d.ts.map +1 -0
  201. package/lib/ReadDict.js +3 -0
  202. package/lib/ReadDict.js.map +1 -0
  203. package/lib/ReadDictHttp.d.ts +12 -0
  204. package/lib/ReadDictHttp.d.ts.map +1 -0
  205. package/lib/ReadDictHttp.js +23 -0
  206. package/lib/ReadDictHttp.js.map +1 -0
  207. package/lib/ReadFunction.d.ts +73 -0
  208. package/lib/ReadFunction.d.ts.map +1 -0
  209. package/lib/ReadFunction.js +3 -0
  210. package/lib/ReadFunction.js.map +1 -0
  211. package/lib/ReadFunctionHttp.d.ts +25 -0
  212. package/lib/ReadFunctionHttp.d.ts.map +1 -0
  213. package/lib/ReadFunctionHttp.js +63 -0
  214. package/lib/ReadFunctionHttp.js.map +1 -0
  215. package/lib/ReadQueue.d.ts +39 -0
  216. package/lib/ReadQueue.d.ts.map +1 -0
  217. package/lib/ReadQueue.js +3 -0
  218. package/lib/ReadQueue.js.map +1 -0
  219. package/lib/ReadQueueHttp.d.ts +12 -0
  220. package/lib/ReadQueueHttp.d.ts.map +1 -0
  221. package/lib/ReadQueueHttp.js +23 -0
  222. package/lib/ReadQueueHttp.js.map +1 -0
  223. package/lib/ReadServer.d.ts +72 -0
  224. package/lib/ReadServer.d.ts.map +1 -0
  225. package/lib/ReadServer.js +3 -0
  226. package/lib/ReadServer.js.map +1 -0
  227. package/lib/ReadServerHttp.d.ts +25 -0
  228. package/lib/ReadServerHttp.d.ts.map +1 -0
  229. package/lib/ReadServerHttp.js +70 -0
  230. package/lib/ReadServerHttp.js.map +1 -0
  231. package/lib/ReadVolume.d.ts +40 -0
  232. package/lib/ReadVolume.d.ts.map +1 -0
  233. package/lib/ReadVolume.js +3 -0
  234. package/lib/ReadVolume.js.map +1 -0
  235. package/lib/ReadVolumeHttp.d.ts +12 -0
  236. package/lib/ReadVolumeHttp.d.ts.map +1 -0
  237. package/lib/ReadVolumeHttp.js +24 -0
  238. package/lib/ReadVolumeHttp.js.map +1 -0
  239. package/lib/ReadWriteDict.d.ts +39 -0
  240. package/lib/ReadWriteDict.d.ts.map +1 -0
  241. package/lib/ReadWriteDict.js +3 -0
  242. package/lib/ReadWriteDict.js.map +1 -0
  243. package/lib/ReadWriteDictHttp.d.ts +12 -0
  244. package/lib/ReadWriteDictHttp.d.ts.map +1 -0
  245. package/lib/ReadWriteDictHttp.js +23 -0
  246. package/lib/ReadWriteDictHttp.js.map +1 -0
  247. package/lib/ReadWriteQueue.d.ts +40 -0
  248. package/lib/ReadWriteQueue.d.ts.map +1 -0
  249. package/lib/ReadWriteQueue.js +3 -0
  250. package/lib/ReadWriteQueue.js.map +1 -0
  251. package/lib/ReadWriteQueueHttp.d.ts +12 -0
  252. package/lib/ReadWriteQueueHttp.d.ts.map +1 -0
  253. package/lib/ReadWriteQueueHttp.js +23 -0
  254. package/lib/ReadWriteQueueHttp.js.map +1 -0
  255. package/lib/ReadWriteVolume.d.ts +40 -0
  256. package/lib/ReadWriteVolume.d.ts.map +1 -0
  257. package/lib/ReadWriteVolume.js +3 -0
  258. package/lib/ReadWriteVolume.js.map +1 -0
  259. package/lib/ReadWriteVolumeHttp.d.ts +12 -0
  260. package/lib/ReadWriteVolumeHttp.d.ts.map +1 -0
  261. package/lib/ReadWriteVolumeHttp.js +24 -0
  262. package/lib/ReadWriteVolumeHttp.js.map +1 -0
  263. package/lib/RuntimeOwner.d.ts +39 -0
  264. package/lib/RuntimeOwner.d.ts.map +1 -0
  265. package/lib/RuntimeOwner.js +85 -0
  266. package/lib/RuntimeOwner.js.map +1 -0
  267. package/lib/Sandbox.d.ts +215 -0
  268. package/lib/Sandbox.d.ts.map +1 -0
  269. package/lib/Sandbox.js +278 -0
  270. package/lib/Sandbox.js.map +1 -0
  271. package/lib/SandboxClient.d.ts +748 -0
  272. package/lib/SandboxClient.d.ts.map +1 -0
  273. package/lib/SandboxClient.js +710 -0
  274. package/lib/SandboxClient.js.map +1 -0
  275. package/lib/ScaleFunction.d.ts +54 -0
  276. package/lib/ScaleFunction.d.ts.map +1 -0
  277. package/lib/ScaleFunction.js +3 -0
  278. package/lib/ScaleFunction.js.map +1 -0
  279. package/lib/ScaleFunctionHttp.d.ts +21 -0
  280. package/lib/ScaleFunctionHttp.d.ts.map +1 -0
  281. package/lib/ScaleFunctionHttp.js +39 -0
  282. package/lib/ScaleFunctionHttp.js.map +1 -0
  283. package/lib/Secret.d.ts +170 -0
  284. package/lib/Secret.d.ts.map +1 -0
  285. package/lib/Secret.js +196 -0
  286. package/lib/Secret.js.map +1 -0
  287. package/lib/Server.d.ts +155 -0
  288. package/lib/Server.d.ts.map +1 -0
  289. package/lib/Server.js +184 -0
  290. package/lib/Server.js.map +1 -0
  291. package/lib/ServiceUser.d.ts +139 -0
  292. package/lib/ServiceUser.d.ts.map +1 -0
  293. package/lib/ServiceUser.js +210 -0
  294. package/lib/ServiceUser.js.map +1 -0
  295. package/lib/Volume.d.ts +170 -0
  296. package/lib/Volume.d.ts.map +1 -0
  297. package/lib/Volume.js +220 -0
  298. package/lib/Volume.js.map +1 -0
  299. package/lib/VolumeClient.d.ts +53 -0
  300. package/lib/VolumeClient.d.ts.map +1 -0
  301. package/lib/VolumeClient.js +22 -0
  302. package/lib/VolumeClient.js.map +1 -0
  303. package/lib/VolumeFiles.d.ts +94 -0
  304. package/lib/VolumeFiles.d.ts.map +1 -0
  305. package/lib/VolumeFiles.js +139 -0
  306. package/lib/VolumeFiles.js.map +1 -0
  307. package/lib/WebhookToken.d.ts +102 -0
  308. package/lib/WebhookToken.d.ts.map +1 -0
  309. package/lib/WebhookToken.js +176 -0
  310. package/lib/WebhookToken.js.map +1 -0
  311. package/lib/WorkspaceSettings.d.ts +70 -0
  312. package/lib/WorkspaceSettings.d.ts.map +1 -0
  313. package/lib/WorkspaceSettings.js +105 -0
  314. package/lib/WorkspaceSettings.js.map +1 -0
  315. package/lib/WriteApp.d.ts +38 -0
  316. package/lib/WriteApp.d.ts.map +1 -0
  317. package/lib/WriteApp.js +3 -0
  318. package/lib/WriteApp.js.map +1 -0
  319. package/lib/WriteAppHttp.d.ts +23 -0
  320. package/lib/WriteAppHttp.d.ts.map +1 -0
  321. package/lib/WriteAppHttp.js +36 -0
  322. package/lib/WriteAppHttp.js.map +1 -0
  323. package/lib/WriteDict.d.ts +39 -0
  324. package/lib/WriteDict.d.ts.map +1 -0
  325. package/lib/WriteDict.js +3 -0
  326. package/lib/WriteDict.js.map +1 -0
  327. package/lib/WriteDictHttp.d.ts +12 -0
  328. package/lib/WriteDictHttp.d.ts.map +1 -0
  329. package/lib/WriteDictHttp.js +23 -0
  330. package/lib/WriteDictHttp.js.map +1 -0
  331. package/lib/WriteQueue.d.ts +39 -0
  332. package/lib/WriteQueue.d.ts.map +1 -0
  333. package/lib/WriteQueue.js +3 -0
  334. package/lib/WriteQueue.js.map +1 -0
  335. package/lib/WriteQueueHttp.d.ts +12 -0
  336. package/lib/WriteQueueHttp.d.ts.map +1 -0
  337. package/lib/WriteQueueHttp.js +23 -0
  338. package/lib/WriteQueueHttp.js.map +1 -0
  339. package/lib/WriteSecret.d.ts +53 -0
  340. package/lib/WriteSecret.d.ts.map +1 -0
  341. package/lib/WriteSecret.js +3 -0
  342. package/lib/WriteSecret.js.map +1 -0
  343. package/lib/WriteSecretHttp.d.ts +23 -0
  344. package/lib/WriteSecretHttp.d.ts.map +1 -0
  345. package/lib/WriteSecretHttp.js +44 -0
  346. package/lib/WriteSecretHttp.js.map +1 -0
  347. package/lib/WriteVolume.d.ts +39 -0
  348. package/lib/WriteVolume.d.ts.map +1 -0
  349. package/lib/WriteVolume.js +3 -0
  350. package/lib/WriteVolume.js.map +1 -0
  351. package/lib/WriteVolumeHttp.d.ts +12 -0
  352. package/lib/WriteVolumeHttp.d.ts.map +1 -0
  353. package/lib/WriteVolumeHttp.js +24 -0
  354. package/lib/WriteVolumeHttp.js.map +1 -0
  355. package/lib/index.d.ts +80 -0
  356. package/lib/index.d.ts.map +1 -0
  357. package/lib/index.js +78 -0
  358. package/lib/index.js.map +1 -0
  359. package/lib/internal/Declared.d.ts +29 -0
  360. package/lib/internal/Declared.d.ts.map +1 -0
  361. package/lib/internal/Declared.js +31 -0
  362. package/lib/internal/Declared.js.map +1 -0
  363. package/lib/internal/Deploy.d.ts +110 -0
  364. package/lib/internal/Deploy.d.ts.map +1 -0
  365. package/lib/internal/Deploy.js +230 -0
  366. package/lib/internal/Deploy.js.map +1 -0
  367. package/lib/internal/Entrypoint.d.ts +52 -0
  368. package/lib/internal/Entrypoint.d.ts.map +1 -0
  369. package/lib/internal/Entrypoint.js +193 -0
  370. package/lib/internal/Entrypoint.js.map +1 -0
  371. package/lib/internal/Rpc.d.ts +17 -0
  372. package/lib/internal/Rpc.d.ts.map +1 -0
  373. package/lib/internal/Rpc.js +49 -0
  374. package/lib/internal/Rpc.js.map +1 -0
  375. package/lib/internal/RpcAuth.d.ts +41 -0
  376. package/lib/internal/RpcAuth.d.ts.map +1 -0
  377. package/lib/internal/RpcAuth.js +100 -0
  378. package/lib/internal/RpcAuth.js.map +1 -0
  379. package/lib/internal/Runtime.d.ts +127 -0
  380. package/lib/internal/Runtime.d.ts.map +1 -0
  381. package/lib/internal/Runtime.js +246 -0
  382. package/lib/internal/Runtime.js.map +1 -0
  383. package/lib/internal/Tags.d.ts +19 -0
  384. package/lib/internal/Tags.d.ts.map +1 -0
  385. package/lib/internal/Tags.js +33 -0
  386. package/lib/internal/Tags.js.map +1 -0
  387. package/lib/internal/TcpConnect.d.ts +12 -0
  388. package/lib/internal/TcpConnect.d.ts.map +1 -0
  389. package/lib/internal/TcpConnect.js +46 -0
  390. package/lib/internal/TcpConnect.js.map +1 -0
  391. package/lib/internal/Transport.d.ts +13 -0
  392. package/lib/internal/Transport.d.ts.map +1 -0
  393. package/lib/internal/Transport.js +16 -0
  394. package/lib/internal/Transport.js.map +1 -0
  395. package/lib/internal.d.ts +71 -0
  396. package/lib/internal.d.ts.map +1 -0
  397. package/lib/internal.js +102 -0
  398. package/lib/internal.js.map +1 -0
  399. package/package.json +59 -3
  400. package/src/App.ts +262 -0
  401. package/src/AuthProvider.ts +295 -0
  402. package/src/BindingHttp.ts +112 -0
  403. package/src/Blob.ts +71 -0
  404. package/src/Bootstrap.ts +52 -0
  405. package/src/Cbor.ts +158 -0
  406. package/src/ConnectSandbox.ts +99 -0
  407. package/src/Container.ts +121 -0
  408. package/src/Contributions.ts +9 -0
  409. package/src/CreateDict.ts +95 -0
  410. package/src/CreateDictHttp.ts +91 -0
  411. package/src/CreateImage.ts +105 -0
  412. package/src/CreateImageHttp.ts +117 -0
  413. package/src/CreateQueue.ts +95 -0
  414. package/src/CreateQueueHttp.ts +91 -0
  415. package/src/CreateSandbox.ts +228 -0
  416. package/src/CreateSandboxHttp.ts +160 -0
  417. package/src/CreateSecret.ts +109 -0
  418. package/src/CreateSecretHttp.ts +83 -0
  419. package/src/CreateVolume.ts +96 -0
  420. package/src/CreateVolumeHttp.ts +93 -0
  421. package/src/Credentials.ts +74 -0
  422. package/src/Dict.ts +245 -0
  423. package/src/DictClient.ts +166 -0
  424. package/src/Domain.ts +147 -0
  425. package/src/Endpoint.ts +406 -0
  426. package/src/Environment.ts +373 -0
  427. package/src/FetchServer.ts +126 -0
  428. package/src/FetchServerHttp.ts +110 -0
  429. package/src/Function.ts +397 -0
  430. package/src/FunctionAutoscaler.ts +210 -0
  431. package/src/FunctionTarget.ts +181 -0
  432. package/src/Image.ts +281 -0
  433. package/src/ImageBuild.ts +228 -0
  434. package/src/ImagePlan.ts +78 -0
  435. package/src/InferEnv.ts +27 -0
  436. package/src/InvokeFunction.ts +211 -0
  437. package/src/InvokeFunctionHttp.ts +316 -0
  438. package/src/ModalBindings.ts +310 -0
  439. package/src/MountBucket.ts +137 -0
  440. package/src/MountVolume.ts +113 -0
  441. package/src/Mounts.ts +230 -0
  442. package/src/PersistentSandbox.ts +142 -0
  443. package/src/Providers.ts +100 -0
  444. package/src/Proxy.ts +191 -0
  445. package/src/Queue.ts +258 -0
  446. package/src/QueueClient.ts +149 -0
  447. package/src/ReadApp.ts +101 -0
  448. package/src/ReadAppHttp.ts +142 -0
  449. package/src/ReadDict.ts +44 -0
  450. package/src/ReadDictHttp.ts +27 -0
  451. package/src/ReadFunction.ts +107 -0
  452. package/src/ReadFunctionHttp.ts +91 -0
  453. package/src/ReadQueue.ts +44 -0
  454. package/src/ReadQueueHttp.ts +27 -0
  455. package/src/ReadServer.ts +98 -0
  456. package/src/ReadServerHttp.ts +101 -0
  457. package/src/ReadVolume.ts +45 -0
  458. package/src/ReadVolumeHttp.ts +28 -0
  459. package/src/ReadWriteDict.ts +44 -0
  460. package/src/ReadWriteDictHttp.ts +27 -0
  461. package/src/ReadWriteQueue.ts +45 -0
  462. package/src/ReadWriteQueueHttp.ts +27 -0
  463. package/src/ReadWriteVolume.ts +45 -0
  464. package/src/ReadWriteVolumeHttp.ts +28 -0
  465. package/src/RuntimeOwner.ts +111 -0
  466. package/src/Sandbox.ts +402 -0
  467. package/src/SandboxClient.ts +1404 -0
  468. package/src/ScaleFunction.ts +70 -0
  469. package/src/ScaleFunctionHttp.ts +54 -0
  470. package/src/Secret.ts +296 -0
  471. package/src/Server.ts +285 -0
  472. package/src/ServiceUser.ts +295 -0
  473. package/src/Volume.ts +320 -0
  474. package/src/VolumeClient.ts +108 -0
  475. package/src/VolumeFiles.ts +194 -0
  476. package/src/WebhookToken.ts +230 -0
  477. package/src/WorkspaceSettings.ts +160 -0
  478. package/src/WriteApp.ts +43 -0
  479. package/src/WriteAppHttp.ts +51 -0
  480. package/src/WriteDict.ts +44 -0
  481. package/src/WriteDictHttp.ts +27 -0
  482. package/src/WriteQueue.ts +44 -0
  483. package/src/WriteQueueHttp.ts +27 -0
  484. package/src/WriteSecret.ts +60 -0
  485. package/src/WriteSecretHttp.ts +56 -0
  486. package/src/WriteVolume.ts +44 -0
  487. package/src/WriteVolumeHttp.ts +28 -0
  488. package/src/globals.d.ts +2 -0
  489. package/src/index.ts +85 -0
  490. package/src/internal/Declared.ts +80 -0
  491. package/src/internal/Deploy.ts +309 -0
  492. package/src/internal/Entrypoint.ts +198 -0
  493. package/src/internal/Rpc.ts +59 -0
  494. package/src/internal/RpcAuth.ts +132 -0
  495. package/src/internal/Runtime.ts +386 -0
  496. package/src/internal/Tags.ts +44 -0
  497. package/src/internal/TcpConnect.ts +78 -0
  498. package/src/internal/Transport.ts +25 -0
  499. package/src/internal.ts +147 -0
@@ -0,0 +1,295 @@
1
+ import * as environment from "@distilled.cloud/modal/environment";
2
+ import * as service from "@distilled.cloud/modal/service";
3
+ import * as workspace from "@distilled.cloud/modal/workspace";
4
+ import { isResolved } from "alchemy/Diff";
5
+ import * as Provider from "alchemy/Provider";
6
+ import { Resource, type ResourceBinding } 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 { type EnvironmentInput, envNameOf, objectName, seconds } from "./internal.ts";
11
+ import { declarable } from "./internal/Declared.ts";
12
+ import type { Providers } from "./Providers.ts";
13
+ import type { DurationInput } from "./SandboxClient.ts";
14
+
15
+ export class ServiceUserUnexpectedResponse extends Data.TaggedError(
16
+ "Modal.ServiceUserUnexpectedResponse",
17
+ )<{
18
+ readonly message: string;
19
+ }> {}
20
+
21
+ /**
22
+ * The workspace's plan has no service users (Modal's Starter plan). Bindings
23
+ * create one per host; `Modal.DeployerHostIdentity` binds the deployer's token
24
+ * instead.
25
+ */
26
+ export class ServiceUsersNotAvailable extends Data.TaggedError("Modal.ServiceUsersNotAvailable")<{
27
+ readonly message: string;
28
+ }> {}
29
+
30
+ /** A role a scoped service user holds in one environment. */
31
+ export interface ServiceUserEnvironmentRole {
32
+ /** The environment: its name, or a yielded `Modal.Environment`. */
33
+ readonly environment: EnvironmentInput;
34
+ /** `viewer` reads; `contributor` also deploys and writes. */
35
+ readonly role: "viewer" | "contributor";
36
+ }
37
+
38
+ export interface ServiceUserProps {
39
+ /**
40
+ * Service user name, unique in the workspace. If omitted, one is generated
41
+ * from the stack, stage and logical ID. Changing it replaces the user (and
42
+ * its token).
43
+ */
44
+ name?: string;
45
+ /**
46
+ * Limit the user to the environments in {@link environments}. An unscoped
47
+ * user acts on the whole workspace. Changing it replaces the user.
48
+ * @default true
49
+ */
50
+ scoped?: boolean;
51
+ /** Roles of a scoped user, per environment. */
52
+ environments?: ServiceUserEnvironmentRole[];
53
+ /**
54
+ * Expire the user's token after this long. Changing it replaces the user.
55
+ * @default never
56
+ */
57
+ expiresIn?: DurationInput;
58
+ }
59
+
60
+ export interface ServiceUserAttributes {
61
+ /** Service user ID. */
62
+ serviceUserId: string;
63
+ /** Service user name. */
64
+ name: string;
65
+ /** Token ID (`ak-…`), the `MODAL_TOKEN_ID` of the user. */
66
+ tokenId: string;
67
+ /** Token secret (`as-…`), the `MODAL_TOKEN_SECRET` of the user. */
68
+ tokenSecret: Redacted.Redacted<string>;
69
+ /** Whether the user is limited to its environments. */
70
+ scoped: boolean;
71
+ /** Roles by environment name. */
72
+ environments: Record<string, "viewer" | "contributor">;
73
+ }
74
+
75
+ /**
76
+ * A Modal service user: a workspace identity with its own token pair, for
77
+ * CI or another system. A scoped user acts only in the environments you
78
+ * grant it, as a `viewer` or a `contributor`.
79
+ *
80
+ * Modal shows a service user's token secret once, at creation, so a user
81
+ * deleted outside Alchemy is recreated with a new token on the next deploy,
82
+ * and an existing user can't be adopted.
83
+ *
84
+ * ### Creating a service user
85
+ * **Example:** CI that deploys to one environment
86
+ * ```typescript
87
+ * import * as Modal from "@alchemy.run/modal";
88
+ *
89
+ * export const Staging = Modal.Environment("Staging", {});
90
+ * export const Deployer = Modal.ServiceUser("Deployer", {
91
+ * environments: [{ environment: Staging, role: "contributor" }],
92
+ * });
93
+ * ```
94
+ *
95
+ * **Example:** A short-lived, read-only token
96
+ * ```typescript
97
+ * export const Auditor = Modal.ServiceUser("Auditor", {
98
+ * environments: [{ environment: "main", role: "viewer" }],
99
+ * expiresIn: "7 days",
100
+ * });
101
+ * ```
102
+ *
103
+ * ### Using its token
104
+ * **Example:** Hand the pair to a Worker that calls Modal as the user
105
+ * ```typescript
106
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
107
+ * import * as Effect from "effect/Effect";
108
+ *
109
+ * export const Ci = Effect.gen(function* () {
110
+ * const deployer = yield* Deployer;
111
+ * return yield* Cloudflare.Worker("Ci", {
112
+ * main: "./src/ci.ts",
113
+ * env: { MODAL_TOKEN_ID: deployer.tokenId, MODAL_TOKEN_SECRET: deployer.tokenSecret },
114
+ * });
115
+ * });
116
+ * ```
117
+ *
118
+ * @resource
119
+ * @product Workspace
120
+ */
121
+ export const ServiceUser = declarable<ServiceUser>()(Resource<ServiceUser>("Modal.ServiceUser"));
122
+
123
+ export type ServiceUser = Resource<
124
+ "Modal.ServiceUser",
125
+ ServiceUserProps,
126
+ ServiceUserAttributes,
127
+ {
128
+ /**
129
+ * Roles contributed by bindings: a binding on a host grants the host's
130
+ * service user the role it needs on the bound resource's environment
131
+ * (`undefined` is the workspace default). The strongest role per
132
+ * environment wins.
133
+ */
134
+ environments?: Array<{
135
+ readonly environment: string | undefined;
136
+ readonly role: "viewer" | "contributor";
137
+ }>;
138
+ },
139
+ Providers
140
+ >;
141
+
142
+ const ROLE = {
143
+ viewer: "ENVIRONMENT_ROLE_VIEWER",
144
+ contributor: "ENVIRONMENT_ROLE_CONTRIBUTOR",
145
+ } as const;
146
+
147
+ const roleOf = (role: string | undefined) =>
148
+ role === ROLE.viewer ? "viewer" : role === ROLE.contributor ? "contributor" : undefined;
149
+
150
+ /**
151
+ * The roles the props and the bindings ask for, by environment name; the
152
+ * workspace default environment resolves to its name. A `contributor` grant
153
+ * beats a `viewer` grant for the same environment.
154
+ */
155
+ const desiredRoles = Effect.fn(function* (
156
+ props: ServiceUserProps,
157
+ bindings: ReadonlyArray<ResourceBinding<ServiceUser["Binding"]>>,
158
+ ) {
159
+ const entries = [
160
+ ...(props.environments ?? []).map((entry) => ({
161
+ environment: envNameOf(entry.environment),
162
+ role: entry.role,
163
+ })),
164
+ ...bindings
165
+ .filter((binding) => (binding as { action?: string }).action !== "delete")
166
+ .flatMap((binding) => binding.data?.environments ?? []),
167
+ ];
168
+ let defaultName: string | undefined;
169
+ const roles: Record<string, "viewer" | "contributor"> = {};
170
+ for (const entry of entries) {
171
+ let name = entry.environment;
172
+ if (!name) {
173
+ defaultName ??= (yield* workspace.workspaceSettings({})).defaultEnvironmentName ?? "main";
174
+ name = defaultName;
175
+ }
176
+ if (roles[name] !== "contributor") roles[name] = entry.role;
177
+ }
178
+ return roles;
179
+ });
180
+
181
+ export const ServiceUserProvider = () =>
182
+ Provider.effect(
183
+ ServiceUser,
184
+ Effect.gen(function* () {
185
+ const observe = Effect.fn(function* (name: string) {
186
+ const found = yield* service
187
+ .serviceUserInfo({ serviceUserName: name })
188
+ .pipe(Effect.catchTag("ServiceUserNotFound", () => Effect.undefined));
189
+ return found?.serviceUser?.serviceUserId ? found.serviceUser : undefined;
190
+ });
191
+
192
+ return {
193
+ stables: ["serviceUserId", "name", "tokenId", "tokenSecret"],
194
+ diff: Effect.fn(function* ({ id, news, olds, output }) {
195
+ if (!isResolved(news) || output === undefined) return undefined;
196
+ if ((yield* objectName(id, news.name)) !== output.name)
197
+ return { action: "replace" } as const;
198
+ if ((news.scoped ?? true) !== output.scoped) return { action: "replace" } as const;
199
+ if (seconds(news.expiresIn) !== seconds(olds?.expiresIn))
200
+ return { action: "replace" } as const;
201
+ return undefined;
202
+ }),
203
+ read: Effect.fn(function* ({ output }) {
204
+ if (output === undefined) return undefined;
205
+ const found = yield* observe(output.name);
206
+ return found?.serviceUserId === output.serviceUserId ? output : undefined;
207
+ }),
208
+ reconcile: Effect.fn(function* ({ id, news, output, session, bindings }) {
209
+ const name = output?.name ?? (yield* objectName(id, news.name));
210
+ const scoped = news.scoped ?? true;
211
+ // Observe: the user we created still exists (its secret lives only in state).
212
+ let current: Partial<service.ServiceUser> | undefined = yield* observe(name);
213
+ let token =
214
+ current !== undefined &&
215
+ output !== undefined &&
216
+ current.serviceUserId === output.serviceUserId
217
+ ? { tokenId: output.tokenId, tokenSecret: output.tokenSecret }
218
+ : undefined;
219
+ // Ensure: a user we can't read the secret of is replaced by a fresh one.
220
+ if (token === undefined) {
221
+ if (current?.serviceUserId) {
222
+ yield* service
223
+ .deleteServiceUser({ serviceUserId: current.serviceUserId })
224
+ .pipe(Effect.catchTag("ServiceUserNotFound", () => Effect.void));
225
+ }
226
+ yield* session.note(`Creating service user ${name}...`);
227
+ const created = yield* service
228
+ .createServiceUser({
229
+ name,
230
+ scoped,
231
+ expiresInSeconds: seconds(news.expiresIn),
232
+ })
233
+ .pipe(
234
+ Effect.catchTag("ServiceUsersNotAvailable", (e) =>
235
+ Effect.fail(
236
+ new ServiceUsersNotAvailable({
237
+ message: `${e.message ?? "Service users are not available on this plan."} Modal bindings give each host its own service user; on this plan, add Modal.DeployerHostIdentity to the Stack's providers to bind your own token into hosts instead.`,
238
+ }),
239
+ ),
240
+ ),
241
+ );
242
+ if (!created.serviceUserId || !created.tokenId || !created.tokenSecret) {
243
+ return yield* new ServiceUserUnexpectedResponse({
244
+ message: `Modal returned no token for service user ${name}`,
245
+ });
246
+ }
247
+ token = {
248
+ tokenId: created.tokenId,
249
+ tokenSecret: Redacted.isRedacted(created.tokenSecret)
250
+ ? created.tokenSecret
251
+ : Redacted.make(created.tokenSecret),
252
+ };
253
+ current = (yield* observe(name)) ?? { serviceUserId: created.serviceUserId, name };
254
+ }
255
+ const user: Partial<service.ServiceUser> = current ?? {};
256
+ const serviceUserId = user.serviceUserId ?? "";
257
+ // Sync roles against the observed ones; a dropped environment loses access.
258
+ const observed: Record<string, string | undefined> = {};
259
+ for (const entry of user.environmentRoles ?? []) {
260
+ if (entry.environmentName) observed[entry.environmentName] = roleOf(entry.role);
261
+ }
262
+ const desired = scoped ? yield* desiredRoles(news, bindings) : {};
263
+ for (const [env, role] of Object.entries(desired)) {
264
+ if (observed[env] === role) continue;
265
+ yield* environment.setEnvironmentRole({
266
+ environmentName: env,
267
+ serviceUserId,
268
+ role: ROLE[role],
269
+ });
270
+ }
271
+ for (const env of Object.keys(observed)) {
272
+ if (env in desired || observed[env] === undefined) continue;
273
+ yield* environment.setEnvironmentRole({
274
+ environmentName: env,
275
+ serviceUserId,
276
+ role: "ENVIRONMENT_ROLE_NO_ACCESS",
277
+ });
278
+ }
279
+ return {
280
+ serviceUserId,
281
+ name,
282
+ tokenId: token.tokenId,
283
+ tokenSecret: token.tokenSecret,
284
+ scoped,
285
+ environments: desired,
286
+ };
287
+ }),
288
+ delete: Effect.fn(function* ({ output }) {
289
+ yield* service
290
+ .deleteServiceUser({ serviceUserId: output.serviceUserId })
291
+ .pipe(Effect.catchTag("ServiceUserNotFound", () => Effect.void));
292
+ }),
293
+ };
294
+ }),
295
+ );
package/src/Volume.ts ADDED
@@ -0,0 +1,320 @@
1
+ import * as volume from "@distilled.cloud/modal/volume";
2
+ import { Unowned } from "alchemy/AdoptPolicy";
3
+ import { isResolved } from "alchemy/Diff";
4
+ import * as Provider from "alchemy/Provider";
5
+ import { Resource } from "alchemy/Resource";
6
+ import * as Data from "effect/Data";
7
+ import * as Effect from "effect/Effect";
8
+ import {
9
+ type EnvironmentInput,
10
+ envNameOf,
11
+ environmentNames,
12
+ environmentOf,
13
+ isGeneratedName,
14
+ listAll,
15
+ objectName,
16
+ } from "./internal.ts";
17
+ import { declarable } from "./internal/Declared.ts";
18
+ import type { Providers } from "./Providers.ts";
19
+ import { isRuntimeName } from "./RuntimeOwner.ts";
20
+
21
+ export class VolumeUnexpectedResponse extends Data.TaggedError("Modal.VolumeUnexpectedResponse")<{
22
+ readonly message: string;
23
+ }> {}
24
+
25
+ export interface VolumeProps {
26
+ /**
27
+ * Volume name, unique per environment. If omitted, a unique name is
28
+ * generated from the stack, stage and logical ID. Changing it renames the
29
+ * volume in place.
30
+ */
31
+ name?: string;
32
+ /**
33
+ * Environment the volume lives in. Changing it replaces the volume.
34
+ * @default the workspace's default environment
35
+ */
36
+ environment?: EnvironmentInput;
37
+ /**
38
+ * Volume filesystem version. `2` supports many concurrent writers and
39
+ * files of any count; `1` is Modal's original format. Changing it
40
+ * replaces the volume.
41
+ * @default 2
42
+ */
43
+ version?: 1 | 2;
44
+ }
45
+
46
+ export interface VolumeAttributes {
47
+ /** Volume ID (`vo-…`). */
48
+ volumeId: string;
49
+ /** Volume name. */
50
+ name: string;
51
+ /** Environment name, or `undefined` for the workspace default. */
52
+ environment: string | undefined;
53
+ /** Volume filesystem version. */
54
+ version: 1 | 2;
55
+ }
56
+
57
+ /**
58
+ * A Modal Volume: a persistent, shared filesystem that Sandboxes and
59
+ * Functions mount at a path. Writes from one container become visible to
60
+ * others after a commit (Sandboxes commit when they exit).
61
+ *
62
+ * Declare a Volume here for data every deployment shares, such as a model
63
+ * cache or a dataset. For one volume per user or session, create them at
64
+ * runtime with {@link CreateVolume}; to read and write files from a Worker or
65
+ * Lambda without a sandbox, bind {@link ReadWriteVolume}.
66
+ *
67
+ * Modal volumes have no tags. Ownership is inferred from Alchemy state: a
68
+ * volume found under an explicit `name` without prior state is reported as
69
+ * unowned.
70
+ *
71
+ * ### Creating a Volume
72
+ * **Example:** A volume with a generated name
73
+ * ```typescript
74
+ * import * as Modal from "@alchemy.run/modal";
75
+ *
76
+ * export const Cache = Modal.Volume("Cache", {});
77
+ * ```
78
+ *
79
+ * **Example:** A named volume in an environment
80
+ * ```typescript
81
+ * import * as Modal from "@alchemy.run/modal";
82
+ *
83
+ * export const Agents = Modal.Environment("Agents", {});
84
+ * export const Models = Modal.Volume("Models", { name: "model-weights", environment: Agents });
85
+ * ```
86
+ *
87
+ * ### Mounting in a Sandbox
88
+ * **Example:** Mount at `/cache`
89
+ * ```typescript
90
+ * // construction phase
91
+ * const cache = yield* Modal.MountVolume(Cache, { path: "/cache" });
92
+ * const sandboxes = yield* Modal.CreateSandbox(Coder);
93
+ * // per request
94
+ * const sandbox = yield* sandboxes.create({ mounts: [cache] });
95
+ * ```
96
+ *
97
+ * ### Reading files from a Worker
98
+ * **Example:** Bind file access
99
+ * ```typescript
100
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
101
+ * import * as Modal from "@alchemy.run/modal";
102
+ * import * as Effect from "effect/Effect";
103
+ * import * as HttpServerResponse from "effect/http/HttpServerResponse";
104
+ * import { Cache } from "./Storage.ts";
105
+ *
106
+ * export default class Api extends Cloudflare.Worker<Api>()(
107
+ * "Api",
108
+ * { main: import.meta.url },
109
+ * Effect.gen(function* () {
110
+ * const cache = yield* Modal.ReadWriteVolume(Cache);
111
+ * return {
112
+ * fetch: Effect.gen(function* () {
113
+ * yield* cache.writeFile("/hello.txt", "hello");
114
+ * const text = yield* cache.readFileString("/hello.txt");
115
+ * return HttpServerResponse.text(text);
116
+ * }).pipe(Effect.orDie),
117
+ * };
118
+ * }).pipe(Effect.provide(Modal.ReadWriteVolumeHttp)),
119
+ * ) {}
120
+ * ```
121
+ *
122
+ * ### Looking up an existing volume
123
+ * `Volume.lookup` references a volume Alchemy doesn't manage (created with
124
+ * the Modal CLI or by another stack). It is read during plan/deploy, never
125
+ * created, updated or deleted.
126
+ *
127
+ * **Example:** Reference an existing volume
128
+ * ```typescript
129
+ * const weights = Modal.Volume.lookup({ name: "model-weights" });
130
+ * ```
131
+ *
132
+ * @resource
133
+ * @product Volume
134
+ */
135
+ export const Volume = declarable<Volume>()(Resource<Volume>("Modal.Volume"));
136
+
137
+ export type Volume = Resource<
138
+ "Modal.Volume",
139
+ VolumeProps,
140
+ VolumeAttributes,
141
+ never,
142
+ Providers,
143
+ VolumeLookup
144
+ >;
145
+
146
+ /**
147
+ * Props for {@link Volume.lookup}: find a volume this stack
148
+ * doesn't manage by its name.
149
+ */
150
+ export interface VolumeLookup {
151
+ /** Volume name. */
152
+ name: string;
153
+ /**
154
+ * Modal environment the object lives in.
155
+ * @default the workspace's default environment
156
+ */
157
+ environment?: string;
158
+ }
159
+
160
+ const versionToWire = (version: 1 | 2 | undefined): volume.VolumeFsVersion =>
161
+ version === 1 ? "VOLUME_FS_VERSION_V1" : "VOLUME_FS_VERSION_V2";
162
+
163
+ const versionFromWire = (version: string | undefined): 1 | 2 =>
164
+ version === "VOLUME_FS_VERSION_V1" ? 1 : 2;
165
+
166
+ /** A volume by name, or `undefined` when missing. */
167
+ export const lookupVolume = Effect.fn(function* (
168
+ getOrCreate: Effect.Success<typeof volume.volumeGetOrCreate>,
169
+ name: string,
170
+ env: string | undefined,
171
+ ) {
172
+ const found = yield* getOrCreate({
173
+ deploymentName: name,
174
+ environmentName: environmentOf(env),
175
+ objectCreationType: "OBJECT_CREATION_TYPE_UNSPECIFIED",
176
+ }).pipe(Effect.catchTag("VolumeNotFound", () => Effect.undefined));
177
+ if (!found?.volumeId) return undefined;
178
+ return {
179
+ volumeId: found.volumeId,
180
+ name,
181
+ environment: env,
182
+ version: versionFromWire(found.version ?? found.metadata?.version),
183
+ } satisfies VolumeAttributes;
184
+ });
185
+
186
+ /**
187
+ * Get a volume by name, creating it when missing: the one implementation
188
+ * behind {@link Volume}'s reconcile and the runtime {@link CreateVolume}
189
+ * client.
190
+ */
191
+ export const ensureVolume = Effect.fn(function* (
192
+ getOrCreate: Effect.Success<typeof volume.volumeGetOrCreate>,
193
+ name: string,
194
+ env: string | undefined,
195
+ version?: 1 | 2,
196
+ ) {
197
+ const created = yield* getOrCreate({
198
+ deploymentName: name,
199
+ environmentName: environmentOf(env),
200
+ objectCreationType: "OBJECT_CREATION_TYPE_CREATE_IF_MISSING",
201
+ version: versionToWire(version),
202
+ });
203
+ if (!created.volumeId) {
204
+ return yield* new VolumeUnexpectedResponse({
205
+ message: `Modal returned no id for volume ${name}`,
206
+ });
207
+ }
208
+ return {
209
+ volumeId: created.volumeId,
210
+ name: created.metadata?.name ?? name,
211
+ environment: env,
212
+ version: versionFromWire(created.version ?? created.metadata?.version),
213
+ } satisfies VolumeAttributes;
214
+ });
215
+
216
+ export const VolumeProvider = () =>
217
+ Provider.effect(
218
+ Volume,
219
+ Effect.gen(function* () {
220
+ const observe = Effect.fn(function* (
221
+ volumeId: string | undefined,
222
+ name: string,
223
+ env: string | undefined,
224
+ ) {
225
+ if (volumeId !== undefined) {
226
+ const byId = yield* volume
227
+ .volumeGetById({ volumeId })
228
+ .pipe(Effect.catchTag("VolumeNotFound", () => Effect.undefined));
229
+ if (byId?.volumeId) {
230
+ return {
231
+ volumeId: byId.volumeId,
232
+ name: byId.metadata?.name ?? name,
233
+ environment: env,
234
+ version: versionFromWire(byId.metadata?.version),
235
+ } satisfies VolumeAttributes;
236
+ }
237
+ }
238
+ return yield* lookupVolume(yield* volume.volumeGetOrCreate, name, env);
239
+ });
240
+
241
+ return {
242
+ stables: ["volumeId", "environment", "version"],
243
+ diff: Effect.fn(function* ({ news, olds }) {
244
+ if (!isResolved(news)) return undefined;
245
+ if (envNameOf(news.environment) !== envNameOf(olds?.environment))
246
+ return { action: "replace" } as const;
247
+ if ((news.version ?? 2) !== (olds?.version ?? 2)) return { action: "replace" } as const;
248
+ return undefined;
249
+ }),
250
+ lookup: Effect.fn(function* ({ name, environment }) {
251
+ return yield* observe(undefined, name, environment);
252
+ }),
253
+
254
+ read: Effect.fn(function* ({ id, olds, output }) {
255
+ const name = output?.name ?? (yield* objectName(id, olds?.name));
256
+ const observed = yield* observe(output?.volumeId, name, envNameOf(olds?.environment));
257
+ if (!observed) return undefined;
258
+ return output !== undefined || olds?.name === undefined ? observed : Unowned(observed);
259
+ }),
260
+ reconcile: Effect.fn(function* ({ id, news, output, session }) {
261
+ const name = yield* objectName(id, news.name);
262
+ // Observe: the volume we created (by id) or one with the name.
263
+ let current = yield* observe(
264
+ output?.volumeId,
265
+ output?.name ?? name,
266
+ envNameOf(news.environment),
267
+ );
268
+ // Ensure
269
+ if (!current) {
270
+ yield* session.note(`Creating volume ${name}...`);
271
+ current = yield* ensureVolume(
272
+ yield* volume.volumeGetOrCreate,
273
+ name,
274
+ envNameOf(news.environment),
275
+ news.version,
276
+ );
277
+ }
278
+ // Sync the name: a renamed volume keeps its id and files.
279
+ if (current.name !== name) {
280
+ yield* session.note(`Renaming volume ${current.name} to ${name}...`);
281
+ yield* volume.renameVolume({ volumeId: current.volumeId, name });
282
+ current = { ...current, name };
283
+ }
284
+ return current;
285
+ }),
286
+ delete: Effect.fn(function* ({ output }) {
287
+ yield* volume
288
+ .deleteVolume({
289
+ volumeId: output.volumeId,
290
+ environmentName: environmentOf(output.environment),
291
+ })
292
+ .pipe(Effect.catchTag("VolumeNotFound", () => Effect.void));
293
+ }),
294
+ list: Effect.fn(function* () {
295
+ const envs = yield* environmentNames;
296
+ const all: VolumeAttributes[] = [];
297
+ for (const env of envs) {
298
+ const items = yield* listAll(
299
+ (pagination) =>
300
+ volume
301
+ .listVolume({ environmentName: env, pagination })
302
+ .pipe(Effect.map((response) => response.items ?? [])),
303
+ (item) => item.createdAt,
304
+ );
305
+ for (const item of items) {
306
+ const name = item.label ?? item.metadata?.name;
307
+ if (!item.volumeId || !(isGeneratedName(name) || isRuntimeName(name))) continue;
308
+ all.push({
309
+ volumeId: item.volumeId,
310
+ name: name ?? "",
311
+ environment: env,
312
+ version: versionFromWire(item.metadata?.version),
313
+ });
314
+ }
315
+ }
316
+ return all;
317
+ }),
318
+ };
319
+ }),
320
+ );