@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,397 @@
1
+ import type * as functions from "@distilled.cloud/modal/functions";
2
+ import { Platform, type Main, type MainRpc } from "alchemy/Platform";
3
+ import * as Provider from "alchemy/Provider";
4
+ import type { Resource } from "alchemy/Resource";
5
+ import type { HostRuntimeContext, ServerHost } from "alchemy/Runtime/Process";
6
+ import * as Data from "effect/Data";
7
+ import * as Effect from "effect/Effect";
8
+ import type { ContainerProps } from "./Container.ts";
9
+ import { seconds } from "./internal.ts";
10
+ import { ENTRYPOINT, RPC_SERVE_ENV } from "./internal/Entrypoint.ts";
11
+ import { createModalRuntimeContext, rpcMethodNamesOf } from "./internal/Rpc.ts";
12
+ import {
13
+ resolveContainerProps,
14
+ runtimeLifecycle,
15
+ type RuntimeAttributes,
16
+ } from "./internal/Runtime.ts";
17
+ import type { MountContract } from "./Mounts.ts";
18
+ import type { Providers } from "./Providers.ts";
19
+ import type { DurationInput } from "./SandboxClient.ts";
20
+
21
+ /** Serve the function on the web at a `*.modal.run` URL. */
22
+ export interface WebEndpointOptions {
23
+ /**
24
+ * Label in the URL (`https://<workspace>--<label>.modal.run`).
25
+ * @default "<app>-<function>"
26
+ */
27
+ label?: string;
28
+ /**
29
+ * Require Modal's proxy auth headers (`Modal-Key` / `Modal-Secret`, from a
30
+ * `Modal.WebhookToken`) on every request.
31
+ * @default false
32
+ */
33
+ requiresProxyAuth?: boolean;
34
+ /** Custom domains (verified `Modal.Domain`s) that also serve the endpoint. */
35
+ customDomains?: string[];
36
+ }
37
+
38
+ /** Run the function on a schedule: a cron expression, or a fixed period. */
39
+ export type FunctionSchedule =
40
+ | {
41
+ /** Cron expression (`"0 9 * * 1-5"`). */
42
+ readonly cron: string;
43
+ /** IANA time zone the expression is read in. @default "UTC" */
44
+ readonly timezone?: string;
45
+ }
46
+ | {
47
+ /** Time between runs (`"1 hour"`, or seconds). */
48
+ readonly period: DurationInput;
49
+ };
50
+
51
+ /** Retry failed calls. */
52
+ export interface FunctionRetries {
53
+ /** Retries after the first failure. */
54
+ readonly maxRetries: number;
55
+ /** Delay multiplier per retry; `1` is a fixed delay. @default 2 */
56
+ readonly backoffCoefficient?: number;
57
+ /** Delay before the first retry. @default 1 second */
58
+ readonly initialDelay?: DurationInput;
59
+ /** Longest delay between retries, at most 60 seconds. @default 60 seconds */
60
+ readonly maxDelay?: DurationInput;
61
+ }
62
+
63
+ export interface FunctionProps extends ContainerProps {
64
+ /**
65
+ * Serve the program's `fetch` handler on the web instead of taking calls.
66
+ * The URL is the `url` attribute.
67
+ */
68
+ web?: boolean | WebEndpointOptions;
69
+ /**
70
+ * Run on a schedule. Each tick arrives at the program's `fetch` handler
71
+ * as `POST /__modal/schedule`.
72
+ */
73
+ schedule?: FunctionSchedule;
74
+ /** Retry failed calls: a count, or a backoff policy. Not for web functions. */
75
+ retries?: number | FunctionRetries;
76
+ /** Most inputs one container handles at once. @default 1 */
77
+ maxConcurrentInputs?: number;
78
+ /** Inputs per container the autoscaler aims for (at most `maxConcurrentInputs`). */
79
+ targetConcurrentInputs?: number;
80
+ /** Shut each container down after it handles one input. */
81
+ singleUseContainers?: boolean;
82
+ }
83
+
84
+ export interface FunctionAttributes extends RuntimeAttributes {
85
+ /** The web endpoint's URL, for a function with `web`. */
86
+ url: string | undefined;
87
+ /** The program's RPC methods, which `Modal.InvokeFunction` calls. */
88
+ methods: string[];
89
+ }
90
+
91
+ /** A Function's program returns RPC methods and also asks for `web` or a `schedule`. */
92
+ export class FunctionRpcConflict extends Data.TaggedError("Modal.FunctionRpcConflict")<{
93
+ readonly message: string;
94
+ }> {}
95
+
96
+ export type Function = Resource<
97
+ "Modal.Function",
98
+ FunctionProps,
99
+ FunctionAttributes,
100
+ { env?: Record<string, any>; mounts?: MountContract; rpcCallers?: string[] },
101
+ Providers
102
+ >;
103
+
104
+ export type FunctionServices = ServerHost;
105
+ /**
106
+ * What the program returns: `fetch` for HTTP, and any other functions,
107
+ * its RPC methods.
108
+ */
109
+ export type FunctionShape =
110
+ | Main<FunctionServices>
111
+ | (Exclude<Main<FunctionServices>, void> & MainRpc<FunctionServices>);
112
+ export type FunctionRuntimeContext = HostRuntimeContext;
113
+
114
+ /**
115
+ * A Modal Function running your program: Modal scales its containers with
116
+ * demand (to zero when idle), and the function takes calls, runs on a
117
+ * schedule, or serves the web.
118
+ *
119
+ * Alchemy bundles `main`, builds it into an image on Modal's builder (no
120
+ * Docker), and deploys the function into its `Modal.App`. Modal starts each
121
+ * container with its Python entrypoint; Alchemy's entrypoint starts your
122
+ * program and hands it work:
123
+ *
124
+ * - the program's RPC methods (every function it returns besides `fetch`)
125
+ * become the function's methods: `Modal.InvokeFunction` calls them with
126
+ * typed arguments and results, and Modal queues, retries and autoscales
127
+ * the calls;
128
+ * - with `web`, Modal routes the function's `*.modal.run` URL to the
129
+ * program's `fetch` handler;
130
+ * - a `schedule` tick arrives at `fetch` as `POST /__modal/schedule`.
131
+ *
132
+ * A function serves one of these. To serve methods next to `fetch`, use a
133
+ * `Modal.Server`. The program's env, including the credentials its
134
+ * bindings need, goes into a Modal Secret, never into the image.
135
+ *
136
+ * ### Effect program
137
+ * **Example:** A function other runtimes call
138
+ * ```typescript
139
+ * // src/Embed.ts
140
+ * import * as Modal from "@alchemy.run/modal";
141
+ * import * as Effect from "effect/Effect";
142
+ * import { Inference } from "./Inference.ts";
143
+ *
144
+ * export default class Embed extends Modal.Function<Embed>()(
145
+ * "Embed",
146
+ * { main: import.meta.url, app: Inference },
147
+ * Effect.gen(function* () {
148
+ * return {
149
+ * embed: Effect.fn(function* (text: string) {
150
+ * return { tokens: text.split(/\s+/).length };
151
+ * }),
152
+ * };
153
+ * }),
154
+ * ) {}
155
+ * ```
156
+ *
157
+ * **Example:** Call it from a Cloudflare Worker
158
+ * ```typescript
159
+ * const embed = yield* Modal.InvokeFunction(Embed);
160
+ * const { tokens } = yield* embed.embed("hello modal");
161
+ * ```
162
+ *
163
+ * ### Async program
164
+ * **Example:** A plain HTTP server, no Effect (it runs on Bun)
165
+ * ```typescript
166
+ * // src/Embed.ts
167
+ * import * as Modal from "@alchemy.run/modal";
168
+ * import { Inference } from "./Inference.ts";
169
+ *
170
+ * export const Embed = Modal.Function("Embed", {
171
+ * main: "./src/embed-server.ts",
172
+ * app: Inference,
173
+ * env: { MODEL: "small" },
174
+ * });
175
+ * export type EmbedEnv = Modal.InferEnv<typeof Embed>;
176
+ * ```
177
+ *
178
+ * ```typescript
179
+ * // src/embed-server.ts
180
+ * import type { EmbedEnv } from "./Embed.ts";
181
+ *
182
+ * const env = process.env as unknown as EmbedEnv;
183
+ *
184
+ * Bun.serve({
185
+ * port: Number(process.env.PORT),
186
+ * async fetch(request) {
187
+ * const { args } = (await request.json()) as { args: [string] };
188
+ * return Response.json({ model: env.MODEL, tokens: args[0].split(/\s+/).length });
189
+ * },
190
+ * });
191
+ * ```
192
+ *
193
+ * ### Web endpoints
194
+ * **Example:** Serve `fetch` at a `*.modal.run` URL
195
+ * ```typescript
196
+ * export default class Api extends Modal.Function<Api>()(
197
+ * "Api",
198
+ * { main: import.meta.url, app: Inference, web: true },
199
+ * Effect.gen(function* () {
200
+ * return { fetch: Effect.succeed(HttpServerResponse.text("hello from Modal")) };
201
+ * }),
202
+ * ) {}
203
+ * ```
204
+ *
205
+ * **Example:** Behind Modal's proxy auth
206
+ * ```typescript
207
+ * export default class Admin extends Modal.Function<Admin>()(
208
+ * "Admin",
209
+ * { main: import.meta.url, app: Inference, web: { requiresProxyAuth: true, label: "admin" } },
210
+ * program,
211
+ * ) {}
212
+ * ```
213
+ *
214
+ * ### Schedules
215
+ * **Example:** Run every morning
216
+ * ```typescript
217
+ * export default class Digest extends Modal.Function<Digest>()(
218
+ * "Digest",
219
+ * { main: import.meta.url, app: Inference, schedule: { cron: "0 9 * * *", timezone: "Europe/London" } },
220
+ * Effect.gen(function* () {
221
+ * return {
222
+ * fetch: Effect.gen(function* () {
223
+ * yield* Effect.log("sending the digest");
224
+ * return yield* HttpServerResponse.json(null);
225
+ * }),
226
+ * };
227
+ * }),
228
+ * ) {}
229
+ * ```
230
+ *
231
+ * ### GPUs, volumes and scaling
232
+ * **Example:** A warm GPU function reading weights from a volume
233
+ * ```typescript
234
+ * export default class Generate extends Modal.Function<Generate>()(
235
+ * "Generate",
236
+ * {
237
+ * main: import.meta.url,
238
+ * app: Inference,
239
+ * gpu: "L4",
240
+ * mounts: [{ volume: Weights, path: "/models" }],
241
+ * minContainers: 1,
242
+ * scaledownWindow: 300,
243
+ * maxConcurrentInputs: 8,
244
+ * timeout: "10 minutes",
245
+ * },
246
+ * program,
247
+ * ) {}
248
+ * ```
249
+ *
250
+ * @resource
251
+ * @product Function
252
+ */
253
+ export const Function: Platform<Function, FunctionServices, FunctionShape, FunctionRuntimeContext> =
254
+ Platform("Modal.Function", {
255
+ createRuntimeContext: createModalRuntimeContext("Modal.Function"),
256
+ transformProps: resolveContainerProps,
257
+ });
258
+
259
+ const bootstrapEntry =
260
+ (handler: string) =>
261
+ (importPath: string): string =>
262
+ `
263
+ import { bootstrap } from "@alchemy.run/modal/Bootstrap";
264
+ import { ${handler} as entrypoint } from ${JSON.stringify(importPath)};
265
+
266
+ await bootstrap(entrypoint);
267
+ `;
268
+
269
+ const scheduleOf = (schedule: FunctionSchedule | undefined): functions.Schedule | undefined =>
270
+ schedule === undefined
271
+ ? undefined
272
+ : "cron" in schedule
273
+ ? { cron: { cronString: schedule.cron, timezone: schedule.timezone ?? "UTC" } }
274
+ : { period: { seconds: seconds(schedule.period) } };
275
+
276
+ const retriesOf = (
277
+ retries: number | FunctionRetries | undefined,
278
+ ): functions.FunctionRetryPolicy | undefined =>
279
+ retries === undefined
280
+ ? undefined
281
+ : typeof retries === "number"
282
+ ? { retries, backoffCoefficient: 1, initialDelayMs: 1000, maxDelayMs: 60_000 }
283
+ : {
284
+ retries: retries.maxRetries,
285
+ backoffCoefficient: retries.backoffCoefficient ?? 2,
286
+ initialDelayMs: Math.round((seconds(retries.initialDelay) ?? 1) * 1000),
287
+ maxDelayMs: Math.round((seconds(retries.maxDelay) ?? 60) * 1000),
288
+ };
289
+
290
+ /** How a Function differs from the other runtimes: a call, schedule or web function. */
291
+ const definitionOf = (
292
+ props: FunctionProps,
293
+ context: { readonly port: number; readonly startupTimeout: number },
294
+ ): functions.Function => {
295
+ const methods = rpcMethodNamesOf(props.env);
296
+ if (methods.length > 0) {
297
+ // One method per RPC method: callers send its name as the input's
298
+ // `method_name`, and the entrypoint's `Rpc` class forwards it to the
299
+ // program's `/__rpc__/<method>`.
300
+ const formats = ["DATA_FORMAT_PICKLE", "DATA_FORMAT_CBOR"];
301
+ return {
302
+ implementationName: ENTRYPOINT.rpc,
303
+ isClass: true,
304
+ methodDefinitions: Object.fromEntries(
305
+ methods.map((name) => [
306
+ name,
307
+ {
308
+ functionName: name,
309
+ functionType: "FUNCTION_TYPE_FUNCTION",
310
+ supportedInputFormats: formats,
311
+ supportedOutputFormats: formats,
312
+ },
313
+ ]),
314
+ ),
315
+ supportedInputFormats: formats,
316
+ supportedOutputFormats: formats,
317
+ retryPolicy: retriesOf(props.retries),
318
+ maxConcurrentInputs: props.maxConcurrentInputs ?? 0,
319
+ targetConcurrentInputs: props.targetConcurrentInputs ?? 0,
320
+ singleUseContainers: props.singleUseContainers,
321
+ maxInputs: props.singleUseContainers ? 1 : 0,
322
+ };
323
+ }
324
+ if (props.web) {
325
+ const web = props.web === true ? {} : props.web;
326
+ return {
327
+ implementationName: ENTRYPOINT.web,
328
+ webhookConfig: {
329
+ type: "WEBHOOK_TYPE_WEB_SERVER",
330
+ webServerPort: context.port,
331
+ webServerStartupTimeout: context.startupTimeout,
332
+ requestedSuffix: web.label,
333
+ requiresProxyAuth: web.requiresProxyAuth,
334
+ customDomains: web.customDomains?.map((name) => ({ name })),
335
+ },
336
+ supportedInputFormats: ["DATA_FORMAT_ASGI"],
337
+ supportedOutputFormats: ["DATA_FORMAT_ASGI", "DATA_FORMAT_GENERATOR_DONE"],
338
+ schedule: scheduleOf(props.schedule),
339
+ maxConcurrentInputs: props.maxConcurrentInputs ?? 0,
340
+ targetConcurrentInputs: props.targetConcurrentInputs ?? 0,
341
+ singleUseContainers: props.singleUseContainers,
342
+ maxInputs: props.singleUseContainers ? 1 : 0,
343
+ };
344
+ }
345
+ return {
346
+ implementationName: props.schedule ? ENTRYPOINT.schedule : ENTRYPOINT.call,
347
+ supportedInputFormats: ["DATA_FORMAT_PICKLE", "DATA_FORMAT_CBOR"],
348
+ supportedOutputFormats: ["DATA_FORMAT_PICKLE", "DATA_FORMAT_CBOR"],
349
+ schedule: scheduleOf(props.schedule),
350
+ retryPolicy: retriesOf(props.retries),
351
+ maxConcurrentInputs: props.maxConcurrentInputs ?? 0,
352
+ targetConcurrentInputs: props.targetConcurrentInputs ?? 0,
353
+ singleUseContainers: props.singleUseContainers,
354
+ maxInputs: props.singleUseContainers ? 1 : 0,
355
+ };
356
+ };
357
+
358
+ export const FunctionProvider = () =>
359
+ Provider.effect(
360
+ Function,
361
+ Effect.gen(function* () {
362
+ const lifecycle = yield* runtimeLifecycle<FunctionProps>({
363
+ type: "Modal.Function",
364
+ definition: definitionOf,
365
+ bootstrap: bootstrapEntry,
366
+ // Modal authenticates every call of a class function, so its
367
+ // program serves RPC (see `createModalRuntimeContext`).
368
+ env: (props): Record<string, string> =>
369
+ rpcMethodNamesOf(props.env).length > 0 ? { [RPC_SERVE_ENV]: "1" } : {},
370
+ });
371
+ return {
372
+ stables: lifecycle.stables,
373
+ diff: lifecycle.diff,
374
+ read: Effect.fn(function* ({ output }) {
375
+ const found = yield* lifecycle.read({ output });
376
+ return found === undefined ? undefined : (output as FunctionAttributes);
377
+ }),
378
+ reconcile: Effect.fn(function* ({ id, news, output, session, bindings }) {
379
+ const methods = rpcMethodNamesOf(news.env);
380
+ if (methods.length > 0 && (news.web || news.schedule)) {
381
+ return yield* new FunctionRpcConflict({
382
+ message: `${id} returns RPC methods (${methods.join(", ")}) and sets ${news.web ? "web" : "schedule"}: a Modal.Function serves calls to its methods, a web endpoint or a schedule. Serve methods next to fetch with a Modal.Server.`,
383
+ });
384
+ }
385
+ const { attributes, metadata } = yield* lifecycle.reconcile({
386
+ id,
387
+ news,
388
+ output,
389
+ session,
390
+ bindings,
391
+ });
392
+ return { ...attributes, url: news.web ? metadata?.webUrl : undefined, methods };
393
+ }),
394
+ delete: lifecycle.delete,
395
+ };
396
+ }),
397
+ );
@@ -0,0 +1,210 @@
1
+ import * as functions from "@distilled.cloud/modal/functions";
2
+ import { isResolved } from "alchemy/Diff";
3
+ import * as Provider from "alchemy/Provider";
4
+ import { Resource } from "alchemy/Resource";
5
+ import * as Data from "effect/Data";
6
+ import * as Effect from "effect/Effect";
7
+ import { type EnvironmentInput, envNameOf, environmentOf, seconds } from "./internal.ts";
8
+ import { declarable } from "./internal/Declared.ts";
9
+ import type { Providers } from "./Providers.ts";
10
+
11
+ export class FunctionAutoscalerUnexpectedResponse extends Data.TaggedError(
12
+ "Modal.FunctionAutoscalerUnexpectedResponse",
13
+ )<{
14
+ readonly message: string;
15
+ }> {}
16
+
17
+ export interface FunctionAutoscalerProps {
18
+ /** Name of the deployed App that defines the function. */
19
+ app: string;
20
+ /**
21
+ * The function's name in the App (`"f"` for `@app.function() def f`, or
22
+ * `"Model.*"` for a class). Changing it, the app or the environment
23
+ * replaces this resource.
24
+ */
25
+ function: string;
26
+ /**
27
+ * Environment the App is deployed in.
28
+ * @default the workspace's default environment
29
+ */
30
+ environment?: EnvironmentInput;
31
+ /** Containers kept running even with no inputs (`min_containers`). */
32
+ minContainers?: number;
33
+ /** Most containers the function runs at once (`max_containers`). */
34
+ maxContainers?: number;
35
+ /** Extra idle containers kept ready while the function is busy (`buffer_containers`). */
36
+ bufferContainers?: number;
37
+ /** How long an idle container stays up before scaling down (`scaledown_window`). */
38
+ scaledownWindow?: number | string;
39
+ /** Sustained demand needed before scaling up (`scaleup_window`). */
40
+ scaleupWindow?: number | string;
41
+ /** Inputs each container handles at once before more are added. */
42
+ targetConcurrency?: number;
43
+ }
44
+
45
+ /** The autoscaler settings Modal stores for a function. */
46
+ export interface AutoscalerSettingsState {
47
+ minContainers?: number;
48
+ maxContainers?: number;
49
+ bufferContainers?: number;
50
+ scaledownWindow?: number;
51
+ scaleupWindow?: number;
52
+ targetConcurrency?: number;
53
+ }
54
+
55
+ export interface FunctionAutoscalerAttributes {
56
+ /** Function ID (`fu-…`). */
57
+ functionId: string;
58
+ /** The settings in effect after the last deploy. */
59
+ settings: AutoscalerSettingsState;
60
+ /** The settings found before the first deploy, restored on destroy. */
61
+ original: AutoscalerSettingsState;
62
+ }
63
+
64
+ /**
65
+ * Autoscaling settings for a Modal Function deployed with Modal's Python
66
+ * client (`modal deploy`): warm containers, a container cap, buffer
67
+ * containers and scale-down timing, changed without redeploying the app.
68
+ *
69
+ * For a `Modal.Function` or `Modal.Server` of the Stack, set these on the
70
+ * resource itself. This resource adjusts a function deployed outside the
71
+ * Stack, and restores
72
+ * the settings it found when destroyed. Modal resets overrides like these
73
+ * when the app is redeployed, so redeploying the app and then this stack
74
+ * applies them again.
75
+ *
76
+ * ### Keeping containers warm
77
+ * **Example:** Two warm containers during business hours
78
+ * ```typescript
79
+ * import * as Modal from "@alchemy.run/modal";
80
+ *
81
+ * export const Warm = Modal.FunctionAutoscaler("Warm", {
82
+ * app: "inference",
83
+ * function: "Model.*",
84
+ * minContainers: 2,
85
+ * bufferContainers: 1,
86
+ * scaledownWindow: "5 minutes",
87
+ * });
88
+ * ```
89
+ *
90
+ * @resource
91
+ * @product Function
92
+ */
93
+ export const FunctionAutoscaler = declarable<FunctionAutoscaler>()(
94
+ Resource<FunctionAutoscaler>("Modal.FunctionAutoscaler"),
95
+ );
96
+
97
+ export type FunctionAutoscaler = Resource<
98
+ "Modal.FunctionAutoscaler",
99
+ FunctionAutoscalerProps,
100
+ FunctionAutoscalerAttributes,
101
+ never,
102
+ Providers
103
+ >;
104
+
105
+ const fromWire = (s: functions.AutoscalerSettings | undefined): AutoscalerSettingsState => ({
106
+ minContainers: s?.minContainers,
107
+ maxContainers: s?.maxContainers,
108
+ bufferContainers: s?.bufferContainers,
109
+ scaledownWindow: s?.scaledownWindow,
110
+ scaleupWindow: s?.scaleupWindow,
111
+ targetConcurrency: s?.targetConcurrency,
112
+ });
113
+
114
+ const toWire = (s: AutoscalerSettingsState): functions.AutoscalerSettings => ({
115
+ minContainers: s.minContainers,
116
+ maxContainers: s.maxContainers,
117
+ bufferContainers: s.bufferContainers,
118
+ scaledownWindow: s.scaledownWindow,
119
+ scaleupWindow: s.scaleupWindow,
120
+ targetConcurrency: s.targetConcurrency,
121
+ });
122
+
123
+ const desiredOf = (news: FunctionAutoscalerProps): AutoscalerSettingsState => ({
124
+ minContainers: news.minContainers,
125
+ maxContainers: news.maxContainers,
126
+ bufferContainers: news.bufferContainers,
127
+ scaledownWindow: seconds(news.scaledownWindow),
128
+ scaleupWindow: seconds(news.scaleupWindow),
129
+ targetConcurrency: news.targetConcurrency,
130
+ });
131
+
132
+ export const FunctionAutoscalerProvider = () =>
133
+ Provider.effect(
134
+ FunctionAutoscaler,
135
+ Effect.gen(function* () {
136
+ const lookup = Effect.fn(function* (news: FunctionAutoscalerProps) {
137
+ const found = yield* functions
138
+ .getFunction({
139
+ appName: news.app,
140
+ objectTag: news.function,
141
+ environmentName: environmentOf(envNameOf(news.environment)),
142
+ })
143
+ .pipe(Effect.catchTag("FunctionNotFound", () => Effect.undefined));
144
+ return found?.functionId;
145
+ });
146
+
147
+ const current = Effect.fn(function* (functionId: string) {
148
+ const { autoscalerConfiguration } = yield* functions.functionGetSchedulingParams({
149
+ functionId,
150
+ });
151
+ return autoscalerConfiguration;
152
+ });
153
+
154
+ return {
155
+ stables: ["functionId", "original"],
156
+ diff: Effect.fn(function* ({ news, olds }) {
157
+ if (!isResolved(news)) return undefined;
158
+ if (
159
+ news.app !== olds?.app ||
160
+ news.function !== olds?.function ||
161
+ envNameOf(news.environment) !== envNameOf(olds?.environment)
162
+ ) {
163
+ return { action: "replace" } as const;
164
+ }
165
+ return undefined;
166
+ }),
167
+ read: Effect.fn(function* ({ olds, output }) {
168
+ if (output === undefined || olds === undefined) return undefined;
169
+ const config = yield* current(output.functionId).pipe(
170
+ Effect.catchTag("FunctionNotFound", () => Effect.undefined),
171
+ );
172
+ if (!config) return undefined;
173
+ return { ...output, settings: fromWire(config.settings) };
174
+ }),
175
+ reconcile: Effect.fn(function* ({ news, output, session }) {
176
+ // Observe: the function (by name; its id changes on redeploy) and
177
+ // the settings in effect.
178
+ const functionId = yield* lookup(news);
179
+ if (!functionId) {
180
+ return yield* new FunctionAutoscalerUnexpectedResponse({
181
+ message: `Modal function ${news.app}.${news.function} isn't deployed${envNameOf(news.environment) ? ` in ${envNameOf(news.environment)}` : ""}`,
182
+ });
183
+ }
184
+ const config = yield* current(functionId);
185
+ const observed = fromWire(config?.settings);
186
+ const original = output?.original ?? fromWire(config?.staticSettings ?? config?.settings);
187
+ // Sync only the settings that differ.
188
+ const desired = desiredOf(news);
189
+ const changed = (Object.keys(desired) as (keyof AutoscalerSettingsState)[]).some(
190
+ (key) => desired[key] !== undefined && desired[key] !== observed[key],
191
+ );
192
+ if (!changed) return { functionId, settings: observed, original };
193
+ yield* session.note(`Updating autoscaler of ${news.app}.${news.function}...`);
194
+ const { currentSettings } = yield* functions.functionUpdateSchedulingParams({
195
+ functionId,
196
+ settings: toWire(desired),
197
+ });
198
+ return { functionId, settings: fromWire(currentSettings), original };
199
+ }),
200
+ delete: Effect.fn(function* ({ output }) {
201
+ yield* functions
202
+ .functionUpdateSchedulingParams({
203
+ functionId: output.functionId,
204
+ settings: toWire(output.original),
205
+ })
206
+ .pipe(Effect.catchTag("FunctionNotFound", () => Effect.void));
207
+ }),
208
+ };
209
+ }),
210
+ );