@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
@@ -0,0 +1,95 @@
1
+ import * as Binding from "alchemy/Binding";
2
+ import type { RuntimeContext } from "alchemy/RuntimeContext";
3
+ import type * as Effect from "effect/Effect";
4
+ import type { QueuesOps } from "./CreateQueueHttp.ts";
5
+ import type { Environment } from "./Environment.ts";
6
+ import type { ErrorOf, OpError } from "./internal.ts";
7
+ import type { ensureQueue, lookupQueue } from "./Queue.ts";
8
+ import type { QueueAttributes } from "./Queue.ts";
9
+ import type { ReadWriteQueueClient } from "./QueueClient.ts";
10
+
11
+ /** A queue created or found at runtime: its attributes plus a read-write client. */
12
+ export interface QueueHandle extends ReadWriteQueueClient {
13
+ readonly queueId: Effect.Effect<string>;
14
+ readonly name: string;
15
+ /** The attributes, to pass where a `Modal.Queue` is accepted (e.g. sandbox mounts). */
16
+ readonly attributes: QueueAttributes;
17
+ }
18
+
19
+ /** Get, create, list and delete queues by name in one environment. */
20
+ export interface QueuesClientOf<R> {
21
+ /** The queue named `name`, created when missing (Modal's own get-or-create). */
22
+ getOrCreate(name: string): Effect.Effect<QueueHandle, ErrorOf<typeof ensureQueue>, R>;
23
+ /** The queue named `name`, or `undefined`. */
24
+ get(name: string): Effect.Effect<QueueHandle | undefined, ErrorOf<typeof lookupQueue>, R>;
25
+ /** Delete the queue named `name` (no-op when missing). */
26
+ delete(
27
+ name: string,
28
+ ): Effect.Effect<
29
+ void,
30
+ | ErrorOf<typeof lookupQueue>
31
+ | Exclude<OpError<QueuesOps, "delete">, { readonly _tag: "QueueNotFound" }>,
32
+ R
33
+ >;
34
+ /** Names of every queue in the environment. */
35
+ list(): Effect.Effect<ReadonlyArray<string>, OpError<QueuesOps, "list">, R>;
36
+ }
37
+
38
+ /** A QueuesClient whose calls run inside a deployed runtime. */
39
+ export type QueuesClient = QueuesClientOf<RuntimeContext>;
40
+
41
+ /**
42
+ * Create queues by name at runtime: one per user, session or task.
43
+ * Modal's native shape is get-or-create by name, so `getOrCreate` is
44
+ * idempotent and safe to call on every request.
45
+ *
46
+ * Bind it to a `Modal.Environment` to keep these runtime objects in their
47
+ * own namespace (or to nothing, for the workspace's default environment).
48
+ * They aren't in Alchemy state: deleting the environment removes them.
49
+ *
50
+ * Objects created at run time are tagged with the stack, stage and binding
51
+ * (`alchemy::stack`, `alchemy::stage`, `alchemy::id`) and are not deleted when
52
+ * the stack is destroyed. A Modal queue has only a name, so the tags become
53
+ * its name prefix, `Modal.runtimePrefix({ stack, stage, id })`: list them
54
+ * with `modal queue list` and delete the ones whose name starts with it.
55
+ *
56
+ * ### One queue per user
57
+ * **Example:** From a Cloudflare Worker
58
+ * ```typescript
59
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
60
+ * import * as Modal from "@alchemy.run/modal";
61
+ * import * as Effect from "effect/Effect";
62
+ * import * as Layer from "effect/Layer";
63
+ * import { HttpServerRequest } from "effect/http/HttpServerRequest";
64
+ * import * as HttpServerResponse from "effect/http/HttpServerResponse";
65
+ * import { Agents, Coder } from "./Coder.ts";
66
+ *
67
+ * export default class Api extends Cloudflare.Worker<Api>()(
68
+ * "Api",
69
+ * { main: import.meta.url },
70
+ * Effect.gen(function* () {
71
+ * const queues = yield* Modal.CreateQueue(Agents);
72
+ * const sandboxes = yield* Modal.CreateSandbox(Coder);
73
+ * return {
74
+ * fetch: Effect.gen(function* () {
75
+ * const request = yield* HttpServerRequest;
76
+ * const user = request.headers["x-user"] ?? "anonymous";
77
+ * const inbox = yield* queues.getOrCreate(`inbox-${user}`);
78
+ * yield* inbox.put({ task: "review" });
79
+ * return HttpServerResponse.text("ok");
80
+ * }).pipe(Effect.orDie),
81
+ * };
82
+ * }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateQueueHttp, Modal.CreateSandboxHttp))),
83
+ * ) {}
84
+ * ```
85
+ *
86
+ * @binding
87
+ * @product Queue
88
+ */
89
+ export interface CreateQueue extends Binding.Service<
90
+ CreateQueue,
91
+ "Modal.CreateQueue",
92
+ (environment?: Environment) => Effect.Effect<QueuesClient>
93
+ > {}
94
+
95
+ export const CreateQueue = Binding.Service<CreateQueue>("Modal.CreateQueue");
@@ -0,0 +1,91 @@
1
+ import * as queue from "@distilled.cloud/modal/queue";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Layer from "effect/Layer";
4
+ import { makeOpenModalBinding } from "./BindingHttp.ts";
5
+ import { CreateQueue, type QueueHandle, type QueuesClientOf } from "./CreateQueue.ts";
6
+ import type { Environment } from "./Environment.ts";
7
+ import { environmentOf, listAll, operations } from "./internal.ts";
8
+ import { ensureQueue, lookupQueue, type QueueAttributes } from "./Queue.ts";
9
+ import { QueueOps, makeReadWriteQueueClient } from "./QueueClient.ts";
10
+ import { ownedName, type RuntimeOwner, RuntimeOwnerOf, unownedName } from "./RuntimeOwner.ts";
11
+
12
+ /** The operations the client calls, resolved by `ModalBindings.withCredentials`. */
13
+ export const QueuesOps = operations({
14
+ getOrCreate: queue.queueGetOrCreate,
15
+ delete: queue.deleteQueue,
16
+ list: queue.listQueue,
17
+ client: QueueOps,
18
+ });
19
+
20
+ export type QueuesOps = Effect.Success<typeof QueuesOps>;
21
+
22
+ const handleOf = (attributes: QueueAttributes, ops: QueuesOps, name: string): QueueHandle => ({
23
+ ...makeReadWriteQueueClient(Effect.succeed(attributes.queueId), ops.client),
24
+ queueId: Effect.succeed(attributes.queueId),
25
+ name,
26
+ attributes,
27
+ });
28
+
29
+ /** A queues client over an environment name resolved per call. */
30
+ export const makeQueuesClient = (
31
+ environment: Effect.Effect<string | undefined>,
32
+ ops: QueuesOps,
33
+ owner: Effect.Effect<RuntimeOwner | undefined> = Effect.undefined,
34
+ ): QueuesClientOf<never> => ({
35
+ getOrCreate: (name) =>
36
+ Effect.flatMap(Effect.all([environment, owner]), ([env, stamp]) =>
37
+ ensureQueue(ops.getOrCreate, ownedName(stamp, name), env),
38
+ ).pipe(Effect.map((attributes) => handleOf(attributes, ops, name))),
39
+ get: (name) =>
40
+ Effect.flatMap(Effect.all([environment, owner]), ([env, stamp]) =>
41
+ lookupQueue(ops.getOrCreate, ownedName(stamp, name), env),
42
+ ).pipe(Effect.map((attributes) => (attributes ? handleOf(attributes, ops, name) : undefined))),
43
+ delete: (name) =>
44
+ Effect.gen(function* () {
45
+ const env = yield* environment;
46
+ const found = yield* lookupQueue(ops.getOrCreate, ownedName(yield* owner, name), env);
47
+ if (!found) return;
48
+ yield* ops
49
+ .delete({ queueId: found.queueId })
50
+ .pipe(Effect.catchTag("QueueNotFound", () => Effect.void));
51
+ }),
52
+ list: () =>
53
+ Effect.gen(function* () {
54
+ const env = yield* environment;
55
+ const stamp = yield* owner;
56
+ const items = yield* listAll(
57
+ (pagination) =>
58
+ ops
59
+ .list({ environmentName: environmentOf(env), pagination })
60
+ .pipe(Effect.map((response) => response.queues ?? [])),
61
+ (item) => item.createdAt,
62
+ );
63
+ return items.flatMap((item) => {
64
+ const own = item.name ? unownedName(stamp, item.name) : undefined;
65
+ return own ? [own] : [];
66
+ });
67
+ }),
68
+ });
69
+
70
+ /**
71
+ * {@link CreateQueue} over Modal's API. Grants the host's identity (a scoped
72
+ * `Modal.ServiceUser`) the `contributor` role on the environment.
73
+ *
74
+ * @layer
75
+ * @product Queue
76
+ * @provides Modal.CreateQueue
77
+ */
78
+ export const CreateQueueHttp = Layer.effect(
79
+ CreateQueue,
80
+ makeOpenModalBinding({
81
+ tag: "Modal.CreateQueue",
82
+ operations: QueuesOps,
83
+ role: "contributor",
84
+ environmentOf: (environment?: Environment) => environment?.name,
85
+ make: Effect.fn(function* (ops, environment?: Environment) {
86
+ const name = environment ? yield* environment.name : Effect.undefined;
87
+ const owner = yield* RuntimeOwnerOf();
88
+ return makeQueuesClient(name, ops, owner);
89
+ }),
90
+ }),
91
+ );
@@ -0,0 +1,228 @@
1
+ import * as Binding from "alchemy/Binding";
2
+ import type { RuntimeContext } from "alchemy/RuntimeContext";
3
+ import type * as Effect from "effect/Effect";
4
+ import type { App } from "./App.ts";
5
+ import type { Image } from "./Image.ts";
6
+ import type { ErrorOf } from "./internal.ts";
7
+ import type { Sandbox } from "./Sandbox.ts";
8
+ import type {
9
+ createPersistentSandbox,
10
+ createSandbox,
11
+ listSandboxes,
12
+ PersistentSandboxCreateOptions,
13
+ PersistentSandboxHandle,
14
+ restoreSandbox,
15
+ SandboxCreateOptions,
16
+ SandboxHandle,
17
+ sandboxFromName,
18
+ SandboxOpError,
19
+ } from "./SandboxClient.ts";
20
+
21
+ export type {
22
+ ExecOptions,
23
+ PersistentSandboxCreateOptions,
24
+ PersistentSandboxHandle,
25
+ ExecResult,
26
+ HeaderReplacement,
27
+ SandboxCreateOptions,
28
+ SandboxFileEntry,
29
+ SandboxHandle,
30
+ SandboxTunnel,
31
+ } from "./SandboxClient.ts";
32
+
33
+ /** A sandbox as `list` reports it. */
34
+ export interface SandboxSummary {
35
+ readonly sandboxId: string;
36
+ readonly name: string | undefined;
37
+ readonly createdAt: number | undefined;
38
+ readonly tags: Record<string, string>;
39
+ }
40
+
41
+ /** Sandbox cost for one combination of tag values. */
42
+ export interface SandboxUsageGroup {
43
+ /** The grouped tags' values. */
44
+ readonly tags: Record<string, string>;
45
+ /** Total cost in USD. */
46
+ readonly cost: number;
47
+ /** Cost by resource (`cpu`, `memory`, `gpu`, ...). */
48
+ readonly costByResource: Record<string, number>;
49
+ }
50
+
51
+ /** Create and find sandboxes in one App. Every handle method calls Modal. */
52
+ export interface SandboxesClient {
53
+ /** The App sandboxes are created in. */
54
+ readonly appId: Effect.Effect<string>;
55
+ /** Create a sandbox. Modal's own sandbox parameters; the bound image is the default `image`. */
56
+ create(
57
+ options?: SandboxCreateOptions,
58
+ ): Effect.Effect<SandboxHandle, ErrorOf<typeof createSandbox>, RuntimeContext>;
59
+ /** A running sandbox by name, or `undefined`. */
60
+ fromName(
61
+ name: string,
62
+ ): Effect.Effect<SandboxHandle | undefined, ErrorOf<typeof sandboxFromName>, RuntimeContext>;
63
+ /** A sandbox by id. */
64
+ fromId(sandboxId: string): Effect.Effect<SandboxHandle>;
65
+ /** Running sandboxes of the App, optionally filtered by tags. */
66
+ list(options?: {
67
+ readonly tags?: Record<string, string>;
68
+ readonly includeFinished?: boolean;
69
+ }): Effect.Effect<ReadonlyArray<SandboxSummary>, ErrorOf<typeof listSandboxes>, RuntimeContext>;
70
+ /**
71
+ * Create a persistent sandbox: one box whose filesystem outlives its
72
+ * sessions. Each session runs up to an hour and pauses after five idle
73
+ * minutes; `session()` resumes it from where it stopped.
74
+ */
75
+ createPersistent(
76
+ options?: PersistentSandboxCreateOptions,
77
+ ): Effect.Effect<
78
+ PersistentSandboxHandle,
79
+ ErrorOf<typeof createPersistentSandbox>,
80
+ RuntimeContext
81
+ >;
82
+ /** A persistent sandbox by id (a `Modal.PersistentSandbox`, or one `createPersistent` made). */
83
+ persistent(
84
+ box: string | { readonly persistentSandboxId: string },
85
+ ): Effect.Effect<PersistentSandboxHandle>;
86
+ /**
87
+ * What the App's sandboxes cost over a time range, grouped by tag values
88
+ * (`groupByTags: ["user"]` gives one group per user). Modal reports
89
+ * whole hours: `since` rounds down and `until` (default now) up to the
90
+ * hour.
91
+ */
92
+ usage(query: {
93
+ readonly since: Date | string | number;
94
+ readonly until?: Date | string | number;
95
+ readonly groupByTags?: ReadonlyArray<string>;
96
+ readonly tags?: Record<string, string>;
97
+ }): Effect.Effect<ReadonlyArray<SandboxUsageGroup>, SandboxOpError<"usage">, RuntimeContext>;
98
+ /** Start a new sandbox from a memory snapshot (`handle.snapshotMemory()`). */
99
+ restore(
100
+ snapshot: { readonly snapshotId: string },
101
+ options?: { readonly name?: string },
102
+ ): Effect.Effect<
103
+ SandboxHandle,
104
+ ErrorOf<typeof restoreSandbox> | SandboxOpError<"setTags">,
105
+ RuntimeContext
106
+ >;
107
+ }
108
+
109
+ /**
110
+ * Create and drive Modal Sandboxes from any runtime: a Worker, a Lambda, a
111
+ * Durable Object, or a script.
112
+ *
113
+ * Bind it to an App (sandboxes boot from the image you pass to `create`) or
114
+ * to an Image (it is the default image, and sandboxes go in the image's
115
+ * App). A sandbox lives at most 24 hours; to keep work across sandboxes, use
116
+ * a Volume, or snapshot it (`snapshotFilesystem`, `snapshotMemory`) and
117
+ * start the next one from the snapshot.
118
+ *
119
+ * Sandboxes are runtime objects: they aren't in Alchemy state. Stopping the
120
+ * App (destroying the `Modal.App` resource) terminates every sandbox in it.
121
+ *
122
+ * Objects created at run time are tagged with the stack, stage and binding
123
+ * (`alchemy::stack`, `alchemy::stage`, `alchemy::id`) and are not deleted when
124
+ * the stack is destroyed. List them by those tags to clean them up:
125
+ * `sandboxes.list({ tags: { "alchemy::stack": "my-app" } })`, or Modal's
126
+ * `SandboxList` with `tags`. Your own `tags` merge under the three. A
127
+ * persistent sandbox takes neither tags nor a name, so it carries no owner;
128
+ * it lives in the App.
129
+ *
130
+ * ### Create a sandbox per request
131
+ * **Example:** Run a command and terminate
132
+ * ```typescript
133
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
134
+ * import * as Modal from "@alchemy.run/modal";
135
+ * import * as Effect from "effect/Effect";
136
+ * import * as HttpServerResponse from "effect/http/HttpServerResponse";
137
+ * import { Warm } from "./Coder.ts";
138
+ *
139
+ * export default class Api extends Cloudflare.Worker<Api>()(
140
+ * "Api",
141
+ * { main: import.meta.url },
142
+ * Effect.gen(function* () {
143
+ * const sandboxes = yield* Modal.CreateSandbox(Warm);
144
+ * return {
145
+ * fetch: Effect.gen(function* () {
146
+ * const sandbox = yield* Effect.acquireRelease(
147
+ * sandboxes.create({ timeout: "10 minutes" }),
148
+ * (sandbox) => Effect.ignore(sandbox.terminate()),
149
+ * );
150
+ * const test = yield* sandbox.exec(["pnpm", "test"], { cwd: "/work" });
151
+ * return yield* HttpServerResponse.json(test);
152
+ * }).pipe(Effect.scoped, Effect.orDie),
153
+ * };
154
+ * }).pipe(Effect.provide(Modal.CreateSandboxHttp)),
155
+ * ) {}
156
+ * ```
157
+ *
158
+ * ### One sandbox per session
159
+ * **Example:** Find it by name, else create it
160
+ * ```typescript
161
+ * const sandbox =
162
+ * (yield* sandboxes.fromName(`session-${user}`)) ??
163
+ * (yield* sandboxes.create({ name: `session-${user}`, idleTimeout: "10 minutes" }));
164
+ * ```
165
+ *
166
+ * ### Secrets the sandbox never sees
167
+ * **Example:** Inject an API key into outbound requests
168
+ * ```typescript
169
+ * // construction phase: read the Secret's id
170
+ * const openaiId = yield* (yield* OpenAI).secretId;
171
+ * // in a handler
172
+ * const openai = { secretId: yield* openaiId };
173
+ * const sandbox = yield* sandboxes.create({
174
+ * outboundPolicy: {
175
+ * routes: [
176
+ * {
177
+ * https: {
178
+ * domains: ["api.openai.com"],
179
+ * headerReplacements: [{ secret: openai, headers: { Authorization: "Bearer $OPENAI_API_KEY" } }],
180
+ * },
181
+ * },
182
+ * { any: { redirect: "block" } },
183
+ * ],
184
+ * },
185
+ * });
186
+ * ```
187
+ *
188
+ * ### A cloud identity, not a key
189
+ * **Example:** Assume an AWS role with the token Modal signs
190
+ * ```typescript
191
+ * const sandbox = yield* sandboxes.create({
192
+ * image: "amazon/aws-cli",
193
+ * includeOidcIdentityToken: true,
194
+ * });
195
+ * // MODAL_IDENTITY_TOKEN is an OIDC token from https://oidc.modal.com
196
+ * const role = yield* sandbox.exec(
197
+ * `aws sts assume-role-with-web-identity --role-arn ${roleArn} --role-session-name sandbox --web-identity-token "$MODAL_IDENTITY_TOKEN"`,
198
+ * );
199
+ * ```
200
+ *
201
+ * ### Persistent sandboxes
202
+ * **Example:** A box per user that keeps its files between sessions
203
+ * ```typescript
204
+ * const box = yield* sandboxes.createPersistent({ image: "node:22-bookworm" });
205
+ * const session = yield* box.session();
206
+ * yield* session.exec("echo hi >> /root/notes.txt");
207
+ * // later, from any request: resumes the box if it paused
208
+ * const again = yield* (yield* sandboxes.persistent(box.persistentSandboxId)).session();
209
+ * ```
210
+ *
211
+ * ### Snapshots
212
+ * **Example:** Save a warmed sandbox and boot the next one from it
213
+ * ```typescript
214
+ * yield* sandbox.exec(["pnpm", "install"], { cwd: "/work" });
215
+ * const image = yield* sandbox.snapshotFilesystem();
216
+ * const next = yield* sandboxes.create({ image });
217
+ * ```
218
+ *
219
+ * @binding
220
+ * @product Sandbox
221
+ */
222
+ export interface CreateSandbox extends Binding.Service<
223
+ CreateSandbox,
224
+ "Modal.CreateSandbox",
225
+ (target: App | Image | Sandbox) => Effect.Effect<SandboxesClient>
226
+ > {}
227
+
228
+ export const CreateSandbox = Binding.Service<CreateSandbox>("Modal.CreateSandbox");
@@ -0,0 +1,160 @@
1
+ import * as Effect from "effect/Effect";
2
+ import * as Layer from "effect/Layer";
3
+ import type { App } from "./App.ts";
4
+ import { makeModalBinding } from "./BindingHttp.ts";
5
+ import { CreateSandbox, type SandboxesClient, type SandboxUsageGroup } from "./CreateSandbox.ts";
6
+ import type { Image } from "./Image.ts";
7
+ import { timestampOf } from "./internal.ts";
8
+ import { type RuntimeOwner, RuntimeOwnerOf, runtimeTags } from "./RuntimeOwner.ts";
9
+ import type { Sandbox } from "./Sandbox.ts";
10
+ import {
11
+ createPersistentSandbox,
12
+ createSandbox,
13
+ listSandboxes,
14
+ persistentSandboxHandle,
15
+ restoreSandbox,
16
+ SandboxOps,
17
+ sandboxFromName,
18
+ sandboxHandle,
19
+ type SandboxTarget,
20
+ } from "./SandboxClient.ts";
21
+
22
+ const HOUR_MS = 3_600_000;
23
+
24
+ /** A time rounded to an hour boundary, as Modal's usage query wants it. */
25
+ const hourOf = (value: Date | string | number, round: (n: number) => number): string =>
26
+ timestampOf(round(new Date(value).getTime() / HOUR_MS) * HOUR_MS);
27
+
28
+ /** A sandboxes client over a target resolved per call. */
29
+ export const makeSandboxesClient = (
30
+ target: Effect.Effect<SandboxTarget>,
31
+ ops: SandboxOps,
32
+ owner: Effect.Effect<RuntimeOwner | undefined> = Effect.undefined,
33
+ ): SandboxesClient => ({
34
+ appId: Effect.map(target, (t) => t.appId),
35
+ create: (options) =>
36
+ Effect.flatMap(Effect.all([target, owner]), ([t, o]) =>
37
+ createSandbox(ops, t, {
38
+ ...options,
39
+ // The owner's tags win over a user tag of the same key.
40
+ tags: o === undefined ? options?.tags : { ...options?.tags, ...runtimeTags(o) },
41
+ }),
42
+ ),
43
+ fromName: (name) => Effect.flatMap(target, (t) => sandboxFromName(ops, t, name)),
44
+ fromId: (sandboxId) => Effect.map(target, (t) => sandboxHandle(ops, sandboxId, t)),
45
+ list: (options) => Effect.flatMap(target, (t) => listSandboxes(ops, t, options)),
46
+ usage: (query) =>
47
+ Effect.gen(function* () {
48
+ const t = yield* target;
49
+ const groups: Array<SandboxUsageGroup> = [];
50
+ let pageToken: string | undefined;
51
+ for (let page = 0; page < 100; page++) {
52
+ const response = yield* ops.usage({
53
+ appId: t.appId,
54
+ // Modal reports usage by whole hours.
55
+ since: hourOf(query.since, Math.floor),
56
+ until: query.until === undefined ? undefined : hourOf(query.until, Math.ceil),
57
+ groupByTags: query.groupByTags ? [...query.groupByTags] : undefined,
58
+ tags: query.tags,
59
+ pageToken,
60
+ });
61
+ for (const group of response.groups ?? []) {
62
+ groups.push({
63
+ tags: Object.fromEntries(
64
+ Object.entries(group.tags ?? {}).map(([key, value]) => [key, value?.value ?? ""]),
65
+ ),
66
+ cost: group.cost ?? 0,
67
+ costByResource: Object.fromEntries(
68
+ Object.entries(group.costByResource ?? {}).map(([key, value]) => [key, value ?? 0]),
69
+ ),
70
+ });
71
+ }
72
+ pageToken = response.nextPageToken || undefined;
73
+ if (pageToken === undefined) break;
74
+ }
75
+ return groups;
76
+ }),
77
+ createPersistent: (options) =>
78
+ Effect.flatMap(target, (t) => createPersistentSandbox(ops, t, options)),
79
+ persistent: (box) =>
80
+ Effect.map(target, (t) =>
81
+ persistentSandboxHandle(ops, typeof box === "string" ? box : box.persistentSandboxId, t),
82
+ ),
83
+ restore: (snapshot, options) =>
84
+ Effect.gen(function* () {
85
+ const restored = yield* restoreSandbox(ops, yield* target, snapshot, options);
86
+ const o = yield* owner;
87
+ if (o !== undefined) yield* restored.setTags(runtimeTags(o));
88
+ return restored;
89
+ }),
90
+ });
91
+
92
+ const isImage = (target: App | Image | Sandbox): target is Image => target.Type === "Modal.Image";
93
+ const isProgram = (target: App | Image | Sandbox): target is Sandbox =>
94
+ target.Type === "Modal.Sandbox";
95
+
96
+ /**
97
+ * {@link CreateSandbox} over Modal's API. Grants the host's identity (a scoped
98
+ * `Modal.ServiceUser`) the `contributor` role on the App's environment.
99
+ *
100
+ * @layer
101
+ * @product Sandbox
102
+ * @provides Modal.CreateSandbox
103
+ */
104
+ export const CreateSandboxHttp = Layer.effect(
105
+ CreateSandbox,
106
+ makeModalBinding({
107
+ tag: "Modal.CreateSandbox",
108
+ operations: SandboxOps,
109
+ role: "contributor",
110
+ make: Effect.fn(function* (resource: App | Image | Sandbox, ops) {
111
+ const owner = yield* RuntimeOwnerOf();
112
+ if (isProgram(resource)) {
113
+ const imageId = yield* resource.imageId;
114
+ const appId = yield* resource.appId;
115
+ const appName = yield* resource.appName;
116
+ const environment = yield* resource.environment;
117
+ const secretId = yield* resource.secretId;
118
+ const command = yield* resource.command;
119
+ const port = yield* resource.port;
120
+ const mounts = yield* resource.mounts;
121
+ const target = Effect.all({
122
+ imageId,
123
+ appId,
124
+ appName,
125
+ environment,
126
+ secretId,
127
+ command,
128
+ port,
129
+ mounts,
130
+ }).pipe(
131
+ Effect.map((t): SandboxTarget => ({
132
+ imageId: t.imageId,
133
+ appId: t.appId,
134
+ appName: t.appName,
135
+ environment: t.environment,
136
+ program: { secretId: t.secretId, command: t.command, port: t.port, mounts: t.mounts },
137
+ })),
138
+ );
139
+ return makeSandboxesClient(target, ops, owner);
140
+ }
141
+ if (isImage(resource)) {
142
+ const imageId = yield* resource.imageId;
143
+ const appId = yield* resource.appId;
144
+ const appName = yield* resource.appName;
145
+ const environment = yield* resource.environment;
146
+ const target = Effect.all({ imageId, appId, appName, environment }).pipe(
147
+ Effect.map((t): SandboxTarget => t),
148
+ );
149
+ return makeSandboxesClient(target, ops, owner);
150
+ }
151
+ const appId = yield* resource.appId;
152
+ const appName = yield* resource.name;
153
+ const environment = yield* resource.environment;
154
+ const target = Effect.all({ appId, appName, environment }).pipe(
155
+ Effect.map((t): SandboxTarget => t),
156
+ );
157
+ return makeSandboxesClient(target, ops, owner);
158
+ }),
159
+ }),
160
+ );
@@ -0,0 +1,109 @@
1
+ import * as Binding from "alchemy/Binding";
2
+ import type { RuntimeContext } from "alchemy/RuntimeContext";
3
+ import type * as Effect from "effect/Effect";
4
+ import type * as Redacted from "effect/Redacted";
5
+ import type { SecretsOps } from "./CreateSecretHttp.ts";
6
+ import type { Environment } from "./Environment.ts";
7
+ import type { ErrorOf, OpError } from "./internal.ts";
8
+ import type { lookupSecret, putSecret } from "./Secret.ts";
9
+ import type { SecretAttributes } from "./Secret.ts";
10
+
11
+ /** Write, find, list and delete secrets by name in one environment. */
12
+ export interface SecretsClientOf<R> {
13
+ /**
14
+ * Create or overwrite the secret named `name` with `env`. Returns its
15
+ * attributes, to pass as a sandbox `secrets` entry or in an outbound
16
+ * header replacement.
17
+ */
18
+ put(
19
+ name: string,
20
+ env: Record<string, string | Redacted.Redacted<string>>,
21
+ ): Effect.Effect<SecretAttributes, ErrorOf<typeof putSecret>, R>;
22
+ /** The secret named `name` (its variable names, never its values), or `undefined`. */
23
+ get(name: string): Effect.Effect<SecretAttributes | undefined, ErrorOf<typeof lookupSecret>, R>;
24
+ /** Delete the secret named `name` (no-op when missing). */
25
+ delete(
26
+ name: string,
27
+ ): Effect.Effect<
28
+ void,
29
+ | ErrorOf<typeof lookupSecret>
30
+ | Exclude<OpError<SecretsOps, "delete">, { readonly _tag: "SecretNotFound" }>,
31
+ R
32
+ >;
33
+ /** Names of every secret in the environment. */
34
+ list(): Effect.Effect<ReadonlyArray<string>, OpError<SecretsOps, "list">, R>;
35
+ }
36
+
37
+ /** A SecretsClient whose calls run inside a deployed runtime. */
38
+ export type SecretsClient = SecretsClientOf<RuntimeContext>;
39
+
40
+ /**
41
+ * Store secrets by name at runtime, such as one per user, and hand them to
42
+ * that user's sandboxes. With an outbound header replacement the sandbox
43
+ * never sees the value: Modal adds it to matching requests on the way out.
44
+ *
45
+ * Bind it to a `Modal.Environment` to keep these runtime secrets in their
46
+ * own namespace. They aren't in Alchemy state: deleting the environment
47
+ * removes them.
48
+ *
49
+ * Objects created at run time are tagged with the stack, stage and binding
50
+ * (`alchemy::stack`, `alchemy::stage`, `alchemy::id`) and are not deleted when
51
+ * the stack is destroyed. A Modal secret has only a name, so the tags become
52
+ * its name prefix, `Modal.runtimePrefix({ stack, stage, id })`: list them
53
+ * with `modal secret list` and delete the ones whose name starts with it.
54
+ *
55
+ * ### A user's token, injected at egress
56
+ * **Example:** From a Cloudflare Worker
57
+ * ```typescript
58
+ * import * as Cloudflare from "@alchemy.run/cloudflare";
59
+ * import * as Modal from "@alchemy.run/modal";
60
+ * import * as Effect from "effect/Effect";
61
+ * import * as Layer from "effect/Layer";
62
+ * import { HttpServerRequest } from "effect/http/HttpServerRequest";
63
+ * import * as HttpServerResponse from "effect/http/HttpServerResponse";
64
+ * import { Agents, Coder } from "./Coder.ts";
65
+ *
66
+ * export default class Api extends Cloudflare.Worker<Api>()(
67
+ * "Api",
68
+ * { main: import.meta.url },
69
+ * Effect.gen(function* () {
70
+ * const secrets = yield* Modal.CreateSecret(Agents);
71
+ * const sandboxes = yield* Modal.CreateSandbox(Coder);
72
+ * return {
73
+ * fetch: Effect.gen(function* () {
74
+ * const request = yield* HttpServerRequest;
75
+ * const user = request.headers["x-user"] ?? "anonymous";
76
+ * const github = yield* secrets.put(`github-${user}`, {
77
+ * GITHUB_TOKEN: request.headers["x-github-token"] ?? "",
78
+ * });
79
+ * const sandbox = yield* sandboxes.create({
80
+ * outboundPolicy: {
81
+ * routes: [
82
+ * {
83
+ * https: {
84
+ * domains: ["api.github.com"],
85
+ * headerReplacements: [{ secret: github, headers: { Authorization: "Bearer $GITHUB_TOKEN" } }],
86
+ * },
87
+ * },
88
+ * { tls: { domains: ["github.com"] } },
89
+ * { any: { redirect: "block" } },
90
+ * ],
91
+ * },
92
+ * });
93
+ * return HttpServerResponse.text(sandbox.sandboxId);
94
+ * }).pipe(Effect.orDie),
95
+ * };
96
+ * }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateSecretHttp, Modal.CreateSandboxHttp))),
97
+ * ) {}
98
+ * ```
99
+ *
100
+ * @binding
101
+ * @product Secret
102
+ */
103
+ export interface CreateSecret extends Binding.Service<
104
+ CreateSecret,
105
+ "Modal.CreateSecret",
106
+ (environment?: Environment) => Effect.Effect<SecretsClient>
107
+ > {}
108
+
109
+ export const CreateSecret = Binding.Service<CreateSecret>("Modal.CreateSecret");