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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
package/src/Mounts.ts ADDED
@@ -0,0 +1,230 @@
1
+ import type * as sandbox from "@distilled.cloud/modal/sandbox";
2
+ import { checkMountSupport, collectMountCapabilities, type MountCapability } from "alchemy/Mount";
3
+ import * as Output from "alchemy/Output";
4
+ import * as Data from "effect/Data";
5
+ import * as Effect from "effect/Effect";
6
+ import type { Ref } from "./Container.ts";
7
+
8
+ /** A value known at deploy, or an Effect that reads it at runtime. */
9
+ type Lazy<T> = T | Effect.Effect<T>;
10
+
11
+ /** A volume entry's options besides the volume: Modal's own volume mount fields. */
12
+ export interface VolumeMountOptions {
13
+ /** Absolute path the volume is mounted at. */
14
+ readonly path: string;
15
+ /** Mount read-only. */
16
+ readonly readOnly?: boolean;
17
+ /** Mount this directory of the volume instead of its root. */
18
+ readonly subPath?: string;
19
+ }
20
+
21
+ /** A bucket entry's options besides the bucket: Modal's own cloud bucket mount fields. */
22
+ export interface BucketMountOptions {
23
+ /** Absolute path the bucket is mounted at. */
24
+ readonly path: string;
25
+ /**
26
+ * The bucket's storage API.
27
+ * @default "r2" for a Cloudflare R2 bucket, "s3" otherwise
28
+ */
29
+ readonly type?: "s3" | "r2" | "gcp";
30
+ /**
31
+ * S3-compatible endpoint.
32
+ * @default the account endpoint, for a Cloudflare R2 bucket
33
+ */
34
+ readonly endpointUrl?: string;
35
+ /** Mount only keys under this prefix. */
36
+ readonly keyPrefix?: string;
37
+ /** Mount read-only. */
38
+ readonly readOnly?: boolean;
39
+ /** Assume this AWS role with Modal's OIDC identity instead of a secret. */
40
+ readonly oidcAuthRoleArn?: string;
41
+ }
42
+
43
+ /** The fields of a bucket resource a mount reads: AWS S3, Cloudflare R2, GCS. */
44
+ export interface BucketLike {
45
+ readonly bucketName: string;
46
+ /** Cloudflare R2: the account the bucket's endpoint is under. */
47
+ readonly accountId?: string;
48
+ /** Cloudflare R2: `"eu"` or `"fedramp"` buckets have their own endpoint. */
49
+ readonly jurisdiction?: string;
50
+ }
51
+
52
+ /**
53
+ * A `Modal.Volume` mounted at `path`. In Stack props the volume is the
54
+ * declared `Modal.Volume`; at runtime it's a handle (`CreateVolume`) or
55
+ * the reference `Modal.MountVolume` returns.
56
+ */
57
+ export interface VolumeMount<V = Ref<{ readonly volumeId: string }>> extends VolumeMountOptions {
58
+ readonly volume: V;
59
+ }
60
+
61
+ /**
62
+ * A cloud bucket mounted at `path` with Modal's cloud bucket mounts: a
63
+ * bucket name, or a bucket resource of another provider (an AWS S3 Bucket,
64
+ * a Cloudflare R2 Bucket). Without `oidcAuthRoleArn`, `secret` holds the
65
+ * bucket's keys (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`, or GCS HMAC
66
+ * keys).
67
+ */
68
+ export interface BucketMount<
69
+ B = string | Ref<BucketLike>,
70
+ S = Ref<{ readonly secretId: string }>,
71
+ > extends BucketMountOptions {
72
+ readonly bucket: B;
73
+ readonly secret?: S;
74
+ }
75
+
76
+ /** A mount in Stack props (`Modal.Function`, `Server`, `Sandbox`, `PersistentSandbox`). */
77
+ export type Mount = VolumeMount | BucketMount;
78
+
79
+ /** The volume of a runtime mount entry: a volume handle, or a `MountVolume` reference. */
80
+ export interface MountedVolume {
81
+ readonly volumeId: Lazy<string>;
82
+ }
83
+
84
+ /** The bucket of a runtime mount entry, as `MountBucket` resolves it. */
85
+ export interface MountedBucket {
86
+ readonly bucketName: Lazy<string>;
87
+ readonly endpointUrl?: Lazy<string | undefined>;
88
+ readonly type?: "s3" | "r2" | "gcp";
89
+ }
90
+
91
+ /** A mount for `sandboxes.create`: a plain entry over handles, or a `Mount<Noun>` reference. */
92
+ export type SandboxMount =
93
+ | VolumeMount<MountedVolume>
94
+ | BucketMount<string | MountedBucket, { readonly secretId: Lazy<string> }>;
95
+
96
+ /** A mount entry referenced a resource that isn't bound into this runtime. */
97
+ export class MountNotBound extends Data.TaggedError("Modal.MountNotBound")<{
98
+ readonly path: string;
99
+ readonly message: string;
100
+ }> {}
101
+
102
+ /** Modal's mount fields for a set of entries. */
103
+ export interface ModalMounts {
104
+ readonly volumeMounts: sandbox.VolumeMount[];
105
+ readonly cloudBucketMounts: sandbox.CloudBucketMount[];
106
+ }
107
+
108
+ const BUCKET_TYPE = { s3: "S3", r2: "R2", gcp: "GCP" } as const;
109
+
110
+ /** Cloudflare R2's S3 endpoint for an account (and jurisdiction). */
111
+ export const r2Endpoint = (accountId: string, jurisdiction?: string): string =>
112
+ `https://${accountId}${
113
+ jurisdiction && jurisdiction !== "default" ? `.${jurisdiction}` : ""
114
+ }.r2.cloudflarestorage.com`;
115
+
116
+ const value = <T>(input: Lazy<T> | undefined, path: string) =>
117
+ Output.isOutput(input)
118
+ ? Effect.fail(
119
+ new MountNotBound({
120
+ path,
121
+ message: `The mount at ${path} references a declared resource; bind it with Modal.MountVolume or Modal.MountBucket`,
122
+ }),
123
+ )
124
+ : Effect.isEffect(input)
125
+ ? (input as Effect.Effect<T>)
126
+ : Effect.succeed(input as T);
127
+
128
+ const field = (record: unknown, key: string): unknown =>
129
+ typeof record === "object" && record !== null
130
+ ? (record as Record<string, unknown>)[key]
131
+ : undefined;
132
+
133
+ /**
134
+ * Modal's `volumeMounts` and `cloudBucketMounts` for mount entries whose
135
+ * resources are resolved: attributes at reconcile, handles or `Mount<Noun>`
136
+ * references at runtime.
137
+ */
138
+ export const modalMountsOf = (
139
+ mounts: ReadonlyArray<Mount | SandboxMount> | undefined,
140
+ ): Effect.Effect<ModalMounts, MountNotBound> =>
141
+ Effect.gen(function* () {
142
+ const volumeMounts: sandbox.VolumeMount[] = [];
143
+ const cloudBucketMounts: sandbox.CloudBucketMount[] = [];
144
+ for (const mount of mounts ?? []) {
145
+ if ("volume" in mount) {
146
+ const volumeId = yield* value(field(mount.volume, "volumeId") as Lazy<string>, mount.path);
147
+ volumeMounts.push({
148
+ mountPath: mount.path,
149
+ volumeId,
150
+ readOnly: mount.readOnly,
151
+ subPath: mount.subPath,
152
+ allowBackgroundCommits: true,
153
+ });
154
+ continue;
155
+ }
156
+ const bucket = mount.bucket;
157
+ const bucketName =
158
+ typeof bucket === "string"
159
+ ? bucket
160
+ : yield* value(field(bucket, "bucketName") as Lazy<string>, mount.path);
161
+ const accountId = field(bucket, "accountId");
162
+ const isR2 = typeof accountId === "string";
163
+ const endpointUrl =
164
+ mount.endpointUrl ??
165
+ (isR2
166
+ ? r2Endpoint(accountId, field(bucket, "jurisdiction") as string | undefined)
167
+ : yield* value(field(bucket, "endpointUrl") as Lazy<string | undefined>, mount.path));
168
+ const type =
169
+ mount.type ?? (field(bucket, "type") as BucketMount["type"]) ?? (isR2 ? "r2" : undefined);
170
+ const secretId = mount.secret
171
+ ? yield* value(field(mount.secret, "secretId") as Lazy<string>, mount.path)
172
+ : undefined;
173
+ cloudBucketMounts.push({
174
+ mountPath: mount.path,
175
+ bucketName,
176
+ bucketType: type ? BUCKET_TYPE[type] : undefined,
177
+ bucketEndpointUrl: endpointUrl,
178
+ credentialsSecretId: secretId,
179
+ keyPrefix: mount.keyPrefix,
180
+ readOnly: mount.readOnly,
181
+ oidcAuthRoleArn: mount.oidcAuthRoleArn,
182
+ });
183
+ }
184
+ return { volumeMounts, cloudBucketMounts };
185
+ });
186
+
187
+ /**
188
+ * What a Modal runtime's `mounts` binding contract holds: volume and bucket
189
+ * entries (`Modal.MountVolume`, `Modal.MountBucket`), and the install lines
190
+ * of other providers' mount clients (`alchemy/Mount`).
191
+ */
192
+ export type MountContract = ReadonlyArray<Mount | MountCapability>;
193
+
194
+ /** A host's binding data, for its `mounts` slice. */
195
+ export type MountBindings = ReadonlyArray<{ readonly data: { readonly mounts?: MountContract } }>;
196
+
197
+ const isCapability = (entry: Mount | MountCapability): entry is MountCapability =>
198
+ "install" in entry && "id" in entry;
199
+
200
+ /** The volume and bucket entries a host's bindings contributed, in binding order. */
201
+ export const boundMounts = (bindings: MountBindings): ReadonlyArray<Mount> =>
202
+ bindings.flatMap((binding) =>
203
+ (binding.data.mounts ?? []).filter((entry): entry is Mount => !isCapability(entry)),
204
+ );
205
+
206
+ /** The mount clients other providers' bindings asked the host's image to install. */
207
+ export const boundCapabilities = (bindings: MountBindings): ReadonlyArray<MountCapability> =>
208
+ collectMountCapabilities(
209
+ bindings.map((binding) => ({
210
+ data: { mounts: (binding.data.mounts ?? []).filter(isCapability) },
211
+ })),
212
+ );
213
+
214
+ /**
215
+ * What a Modal container provides to mount clients. Modal runs containers
216
+ * under gVisor without `CAP_SYS_ADMIN`: `/dev/fuse` exists, but `mount`
217
+ * fails with permission denied, for FUSE and NFS alike.
218
+ */
219
+ export const MODAL_MOUNT_SUPPORT = { fuse: false, nfs: false } as const;
220
+
221
+ /** Fail when a mount client needs what a Modal container can't provide. */
222
+ export const checkModalMounts = (host: string, capabilities: ReadonlyArray<MountCapability>) => {
223
+ const unsupported = checkMountSupport(
224
+ host,
225
+ capabilities,
226
+ MODAL_MOUNT_SUPPORT,
227
+ "Mount Modal volumes and cloud buckets with Modal.MountVolume and Modal.MountBucket instead.",
228
+ );
229
+ return unsupported === undefined ? Effect.void : Effect.fail(unsupported);
230
+ };
@@ -0,0 +1,142 @@
1
+ import * as persistent from "@distilled.cloud/modal/persistent";
2
+ import { deepEqual, isResolved } from "alchemy/Diff";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Resource } from "alchemy/Resource";
5
+ import * as Effect from "effect/Effect";
6
+ import { envNameOf } from "./internal.ts";
7
+ import { declarable } from "./internal/Declared.ts";
8
+ import type { Mount } from "./Mounts.ts";
9
+ import type { Providers } from "./Providers.ts";
10
+ import {
11
+ createPersistentSandbox,
12
+ persistentSandboxHandle,
13
+ SandboxOps,
14
+ type PersistentSandboxCreateOptions,
15
+ } from "./SandboxClient.ts";
16
+
17
+ export interface PersistentSandboxProps extends Omit<PersistentSandboxCreateOptions, "mounts"> {
18
+ /**
19
+ * Volumes and cloud buckets mounted into every session:
20
+ * `[{ volume: Home, path: "/home/user" }]`. Changing them replaces the box.
21
+ */
22
+ mounts?: Mount[];
23
+ /** The App the box runs in (`Modal.App`). Changing it replaces the box. */
24
+ app: { readonly appId: string; readonly name?: string; readonly environment?: unknown };
25
+ }
26
+
27
+ export interface PersistentSandboxAttributes {
28
+ /** Persistent sandbox ID; pass it (or this resource) to `sandboxes.persistent(...)`. */
29
+ persistentSandboxId: string;
30
+ /** The App the box runs in. */
31
+ appId: string;
32
+ /** Name of that App. */
33
+ appName: string | undefined;
34
+ /** Environment of that App. */
35
+ environment: string | undefined;
36
+ }
37
+
38
+ /**
39
+ * A Modal persistent sandbox: one box whose filesystem outlives its
40
+ * sessions. Each session is a regular sandbox that runs up to an hour and
41
+ * pauses after five idle minutes; the next `session()` resumes it from the
42
+ * last session's filesystem. Use it for a long-lived workspace, such as a
43
+ * shared dev box or an agent's home, that the Stack owns.
44
+ *
45
+ * Modal's persistent sandboxes are experimental: they don't take a name,
46
+ * GPUs, `env`, tags or memory snapshots yet. Changing any prop replaces the
47
+ * box (and its files).
48
+ *
49
+ * ### Creating a box
50
+ * **Example:** A dev box on a warm base image
51
+ * ```typescript
52
+ * import * as Modal from "@alchemy.run/modal";
53
+ * import { Coder, Warm } from "./Coder.ts";
54
+ *
55
+ * export const DevBox = Modal.PersistentSandbox("DevBox", { app: Coder, image: Warm, workdir: "/work" });
56
+ * ```
57
+ *
58
+ * ### Using it at runtime
59
+ * **Example:** Resume it from a Worker
60
+ * ```typescript
61
+ * // construction phase
62
+ * const sandboxes = yield* Modal.CreateSandbox(Coder);
63
+ * const devBoxId = yield* (yield* DevBox).persistentSandboxId;
64
+ * // in fetch:
65
+ * const session = yield* (yield* sandboxes.persistent(yield* devBoxId)).session();
66
+ * const result = yield* session.exec(["git", "status"]);
67
+ * ```
68
+ *
69
+ * @resource
70
+ * @product Sandbox
71
+ */
72
+ export const PersistentSandbox = declarable<PersistentSandbox>()(
73
+ Resource<PersistentSandbox>("Modal.PersistentSandbox"),
74
+ );
75
+
76
+ export type PersistentSandbox = Resource<
77
+ "Modal.PersistentSandbox",
78
+ PersistentSandboxProps,
79
+ PersistentSandboxAttributes,
80
+ never,
81
+ Providers
82
+ >;
83
+
84
+ const appOf = (value: PersistentSandboxProps["app"]) => ({
85
+ appId: value.appId,
86
+ appName: value.name,
87
+ environment: envNameOf(value.environment as never),
88
+ });
89
+
90
+ export const PersistentSandboxProvider = () =>
91
+ Provider.effect(
92
+ PersistentSandbox,
93
+ Effect.gen(function* () {
94
+ return {
95
+ stables: ["persistentSandboxId", "appId"],
96
+ diff: Effect.fn(function* ({ news, olds }) {
97
+ if (!isResolved(news) || olds === undefined) return undefined;
98
+ // Modal can't change a persistent sandbox's definition.
99
+ return deepEqual(news, olds) ? undefined : ({ action: "replace" } as const);
100
+ }),
101
+ read: Effect.fn(function* ({ output }) {
102
+ if (output === undefined) return undefined;
103
+ const found = yield* persistent
104
+ .getPersistentSandbox({ persistentSandboxId: output.persistentSandboxId })
105
+ .pipe(Effect.catchTag("PersistentSandboxNotFound", () => Effect.undefined));
106
+ return found?.persistentSandboxId ? output : undefined;
107
+ }),
108
+ reconcile: Effect.fn(function* ({ news, output, session }) {
109
+ const app = appOf(news.app);
110
+ // Observe: the box still exists.
111
+ if (output !== undefined) {
112
+ const found = yield* persistent
113
+ .getPersistentSandbox({ persistentSandboxId: output.persistentSandboxId })
114
+ .pipe(Effect.catchTag("PersistentSandboxNotFound", () => Effect.undefined));
115
+ if (found?.persistentSandboxId) return output;
116
+ }
117
+ // Ensure.
118
+ yield* session.note("Creating persistent sandbox...");
119
+ const { app: _app, ...options } = news;
120
+ // Resolved by the engine: every mount's resource is attributes by now.
121
+ const handle = yield* createPersistentSandbox(
122
+ yield* SandboxOps,
123
+ app,
124
+ options as PersistentSandboxCreateOptions,
125
+ );
126
+ return {
127
+ persistentSandboxId: handle.persistentSandboxId,
128
+ appId: app.appId,
129
+ appName: app.appName,
130
+ environment: app.environment,
131
+ };
132
+ }),
133
+ delete: Effect.fn(function* ({ output }) {
134
+ yield* persistentSandboxHandle(
135
+ yield* SandboxOps,
136
+ output.persistentSandboxId,
137
+ output,
138
+ ).terminate();
139
+ }),
140
+ };
141
+ }),
142
+ );
@@ -0,0 +1,100 @@
1
+ import { CredentialsStoreLive } from "alchemy/Auth/Credentials";
2
+ import { ProfileStoreLive } from "alchemy/Auth/Profile";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Random, RandomProvider } from "alchemy/Random";
5
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
6
+ import * as Layer from "effect/Layer";
7
+ import { App, AppProvider } from "./App.ts";
8
+ import { ModalAuth } from "./AuthProvider.ts";
9
+ import * as Credentials from "./Credentials.ts";
10
+ import { Dict, DictProvider } from "./Dict.ts";
11
+ import { Domain, DomainProvider } from "./Domain.ts";
12
+ import { Endpoint, EndpointProvider } from "./Endpoint.ts";
13
+ import { Environment, EnvironmentProvider } from "./Environment.ts";
14
+ import { Function, FunctionProvider } from "./Function.ts";
15
+ import { FunctionAutoscaler, FunctionAutoscalerProvider } from "./FunctionAutoscaler.ts";
16
+ import { Image, ImageProvider } from "./Image.ts";
17
+ import { PersistentSandbox, PersistentSandboxProvider } from "./PersistentSandbox.ts";
18
+ import { Proxy, ProxyProvider } from "./Proxy.ts";
19
+ import { Queue, QueueProvider } from "./Queue.ts";
20
+ import { Sandbox, SandboxProvider } from "./Sandbox.ts";
21
+ import { Secret, SecretProvider } from "./Secret.ts";
22
+ import { Server, ServerProvider } from "./Server.ts";
23
+ import { ServiceUser, ServiceUserProvider } from "./ServiceUser.ts";
24
+ import { Volume, VolumeProvider } from "./Volume.ts";
25
+ import { WebhookToken, WebhookTokenProvider } from "./WebhookToken.ts";
26
+ import { WorkspaceSettings, WorkspaceSettingsProvider } from "./WorkspaceSettings.ts";
27
+
28
+ /**
29
+ * Service tag bundling every Modal provider + auth + credentials. Use
30
+ * `Modal.providers()` to materialize the full layer.
31
+ */
32
+ export class Providers extends Provider.ProviderCollection<Providers>()("Modal") {}
33
+
34
+ export type ProviderRequirements = Layer.Services<ReturnType<typeof providers>>;
35
+
36
+ /**
37
+ * Every Modal resource provider, the Modal AuthProvider registration (so
38
+ * `alchemy profile edit` can configure it), and credential resolution.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * Alchemy.Stack("App", { providers: Modal.providers() }, ...)
43
+ * ```
44
+ */
45
+ export const providers = () =>
46
+ Layer.effect(
47
+ Providers,
48
+ Provider.collection([
49
+ App,
50
+ Dict,
51
+ Domain,
52
+ Endpoint,
53
+ Environment,
54
+ Function,
55
+ FunctionAutoscaler,
56
+ Image,
57
+ PersistentSandbox,
58
+ Proxy,
59
+ Queue,
60
+ // Each RPC binding mints its caller's key (`Modal.InvokeFunction`, `Modal.FetchServer`).
61
+ Random,
62
+ Sandbox,
63
+ Secret,
64
+ Server,
65
+ ServiceUser,
66
+ Volume,
67
+ WebhookToken,
68
+ WorkspaceSettings,
69
+ ]),
70
+ ).pipe(
71
+ Layer.provide(
72
+ Layer.mergeAll(
73
+ AppProvider(),
74
+ DictProvider(),
75
+ DomainProvider(),
76
+ EndpointProvider(),
77
+ EnvironmentProvider(),
78
+ FunctionProvider(),
79
+ FunctionAutoscalerProvider(),
80
+ ImageProvider(),
81
+ PersistentSandboxProvider(),
82
+ ProxyProvider(),
83
+ QueueProvider(),
84
+ RandomProvider(),
85
+ SandboxProvider(),
86
+ SecretProvider(),
87
+ ServerProvider(),
88
+ ServiceUserProvider(),
89
+ VolumeProvider(),
90
+ WebhookTokenProvider(),
91
+ WorkspaceSettingsProvider(),
92
+ ),
93
+ ),
94
+ Layer.provideMerge(Credentials.fromAuthProvider()),
95
+ Layer.provideMerge(FetchHttpClient.layer),
96
+ Layer.provideMerge(ModalAuth),
97
+ Layer.provideMerge(ProfileStoreLive),
98
+ Layer.provideMerge(CredentialsStoreLive),
99
+ Layer.orDie,
100
+ );
package/src/Proxy.ts ADDED
@@ -0,0 +1,191 @@
1
+ import * as proxy from "@distilled.cloud/modal/proxy";
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
+ environmentOf,
12
+ isGeneratedName,
13
+ objectName,
14
+ } from "./internal.ts";
15
+ import { declarable } from "./internal/Declared.ts";
16
+ import type { Providers } from "./Providers.ts";
17
+
18
+ export class ProxyUnexpectedResponse extends Data.TaggedError("Modal.ProxyUnexpectedResponse")<{
19
+ readonly message: string;
20
+ }> {}
21
+
22
+ export interface ProxyProps {
23
+ /**
24
+ * Proxy name, unique per environment. If omitted, a unique name is
25
+ * generated from the stack, stage and logical ID. Changing it replaces the
26
+ * proxy.
27
+ */
28
+ name?: string;
29
+ /**
30
+ * Environment the proxy lives in. Changing it replaces the proxy.
31
+ * @default the workspace's default environment
32
+ */
33
+ environment?: EnvironmentInput;
34
+ /**
35
+ * Region the proxy's IPs come from (e.g. `us-east-1`). Changing it
36
+ * replaces the proxy.
37
+ */
38
+ region?: string;
39
+ /**
40
+ * Number of static egress IPs. Traffic through the proxy leaves from one
41
+ * of them.
42
+ * @default 1
43
+ */
44
+ ips?: number;
45
+ }
46
+
47
+ export interface ProxyAttributes {
48
+ /** Proxy ID (`pr-…`). */
49
+ proxyId: string;
50
+ /** Proxy name. */
51
+ name: string;
52
+ /** Environment name, or `undefined` for the workspace default. */
53
+ environment: string | undefined;
54
+ /** Region of the proxy's IPs. */
55
+ region: string | undefined;
56
+ /** The static egress IPs, for allowlists on the systems a sandbox calls. */
57
+ ips: string[];
58
+ }
59
+
60
+ /**
61
+ * A Modal Proxy: static egress IPs for Sandboxes and Functions. Traffic from
62
+ * a sandbox created with `proxy` leaves from these IPs, so a database or API
63
+ * can allowlist them.
64
+ *
65
+ * Proxies are a Modal Team plan feature. Modal proxies have no tags;
66
+ * ownership is inferred from Alchemy state.
67
+ *
68
+ * ### Creating a Proxy
69
+ * **Example:** One static IP
70
+ * ```typescript
71
+ * import * as Modal from "@alchemy.run/modal";
72
+ *
73
+ * export const Egress = Modal.Proxy("Egress", {});
74
+ * ```
75
+ *
76
+ * **Example:** Two IPs in a region
77
+ * ```typescript
78
+ * import * as Modal from "@alchemy.run/modal";
79
+ *
80
+ * export const Egress = Modal.Proxy("Egress", { region: "us-east-1", ips: 2 });
81
+ * ```
82
+ *
83
+ * ### Routing a Sandbox through it
84
+ * **Example:** Pass the proxy when creating a sandbox
85
+ * ```typescript
86
+ * const sandbox = yield* sandboxes.create({ proxy: egress });
87
+ * ```
88
+ *
89
+ * @resource
90
+ * @product Proxy
91
+ */
92
+ export const Proxy = declarable<Proxy>()(Resource<Proxy>("Modal.Proxy"));
93
+
94
+ export type Proxy = Resource<"Modal.Proxy", ProxyProps, ProxyAttributes, never, Providers>;
95
+
96
+ const toAttrs = (p: proxy.Proxy, env: string | undefined): ProxyAttributes => ({
97
+ proxyId: p.proxyId ?? "",
98
+ name: p.name ?? "",
99
+ environment: env,
100
+ region: p.region || undefined,
101
+ ips: (p.proxyIps ?? []).flatMap((ip) => (ip.proxyIp ? [ip.proxyIp] : [])),
102
+ });
103
+
104
+ export const ProxyProvider = () =>
105
+ Provider.effect(
106
+ Proxy,
107
+ Effect.gen(function* () {
108
+ const observe = Effect.fn(function* (name: string, env: string | undefined) {
109
+ const found = yield* proxy
110
+ .getProxy({ name, environmentName: environmentOf(env) })
111
+ .pipe(Effect.catchTag("ProxyNotFound", () => Effect.undefined));
112
+ return found?.proxy?.proxyId ? found.proxy : undefined;
113
+ });
114
+
115
+ return {
116
+ stables: ["proxyId", "name", "environment", "region"],
117
+ diff: Effect.fn(function* ({ id, news, olds, output }) {
118
+ if (!isResolved(news)) return undefined;
119
+ if (envNameOf(news.environment) !== envNameOf(olds?.environment))
120
+ return { action: "replace" } as const;
121
+ if (news.region !== olds?.region) return { action: "replace" } as const;
122
+ const name = yield* objectName(id, news.name);
123
+ if (output !== undefined && name !== output.name) return { action: "replace" } as const;
124
+ return undefined;
125
+ }),
126
+ read: Effect.fn(function* ({ id, olds, output }) {
127
+ const name = output?.name ?? (yield* objectName(id, olds?.name));
128
+ const env = output?.environment ?? envNameOf(olds?.environment);
129
+ const found = yield* observe(name, env);
130
+ if (!found) return undefined;
131
+ const attrs = toAttrs(found, env);
132
+ return output !== undefined || olds?.name === undefined ? attrs : Unowned(attrs);
133
+ }),
134
+ reconcile: Effect.fn(function* ({ id, news, output, session }) {
135
+ const name = output?.name ?? (yield* objectName(id, news.name));
136
+ // Observe
137
+ let current = yield* observe(name, envNameOf(news.environment));
138
+ // Ensure
139
+ if (!current) {
140
+ yield* session.note(`Creating proxy ${name}...`);
141
+ const created = yield* proxy
142
+ .createProxy({
143
+ name,
144
+ environmentName: environmentOf(envNameOf(news.environment)),
145
+ region: news.region,
146
+ })
147
+ .pipe(
148
+ Effect.map((response) => response.proxy),
149
+ Effect.catchTag("ProxyAlreadyExists", () =>
150
+ observe(name, envNameOf(news.environment)),
151
+ ),
152
+ );
153
+ if (!created?.proxyId) {
154
+ return yield* new ProxyUnexpectedResponse({
155
+ message: `Modal returned no proxy for ${name}`,
156
+ });
157
+ }
158
+ current = created;
159
+ }
160
+ // Sync the IP count against the observed IPs.
161
+ const desired = news.ips ?? 1;
162
+ const observed = (current.proxyIps ?? []).flatMap((ip) =>
163
+ ip.proxyIp ? [ip.proxyIp] : [],
164
+ );
165
+ for (let i = observed.length; i < desired; i++) {
166
+ yield* session.note(`Adding an IP to proxy ${name}...`);
167
+ yield* proxy.proxyAddIp({ proxyId: current.proxyId });
168
+ }
169
+ for (const ip of observed.slice(desired)) {
170
+ yield* session.note(`Removing IP ${ip} from proxy ${name}...`);
171
+ yield* proxy
172
+ .proxyRemoveIp({ proxyIp: ip })
173
+ .pipe(Effect.catchTag("ProxyNotFound", () => Effect.void));
174
+ }
175
+ const final = (yield* observe(name, envNameOf(news.environment))) ?? current;
176
+ return toAttrs(final, envNameOf(news.environment));
177
+ }),
178
+ delete: Effect.fn(function* ({ output }) {
179
+ yield* proxy
180
+ .deleteProxy({ proxyId: output.proxyId })
181
+ .pipe(Effect.catchTag("ProxyNotFound", () => Effect.void));
182
+ }),
183
+ list: Effect.fn(function* () {
184
+ const { proxies } = yield* proxy.listProxy({});
185
+ return (proxies ?? [])
186
+ .filter((p) => p.proxyId && isGeneratedName(p.name))
187
+ .map((p) => toAttrs(p, p.environmentName || undefined));
188
+ }),
189
+ };
190
+ }),
191
+ );