@alchemy.run/modal 0.0.0-stage → 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.
- package/LICENSE +201 -0
- package/README.md +100 -2
- package/lib/App.d.ts +143 -0
- package/lib/App.d.ts.map +1 -0
- package/lib/App.js +198 -0
- package/lib/App.js.map +1 -0
- package/lib/AuthProvider.d.ts +53 -0
- package/lib/AuthProvider.d.ts.map +1 -0
- package/lib/AuthProvider.js +209 -0
- package/lib/AuthProvider.js.map +1 -0
- package/lib/BindingHttp.d.ts +56 -0
- package/lib/BindingHttp.d.ts.map +1 -0
- package/lib/BindingHttp.js +50 -0
- package/lib/BindingHttp.js.map +1 -0
- package/lib/Blob.d.ts +34 -0
- package/lib/Blob.d.ts.map +1 -0
- package/lib/Blob.js +59 -0
- package/lib/Blob.js.map +1 -0
- package/lib/Bootstrap.d.ts +8 -0
- package/lib/Bootstrap.d.ts.map +1 -0
- package/lib/Bootstrap.js +26 -0
- package/lib/Bootstrap.js.map +1 -0
- package/lib/Cbor.d.ts +10 -0
- package/lib/Cbor.d.ts.map +1 -0
- package/lib/Cbor.js +177 -0
- package/lib/Cbor.js.map +1 -0
- package/lib/ConnectSandbox.d.ts +64 -0
- package/lib/ConnectSandbox.d.ts.map +1 -0
- package/lib/ConnectSandbox.js +33 -0
- package/lib/ConnectSandbox.js.map +1 -0
- package/lib/Container.d.ts +124 -0
- package/lib/Container.d.ts.map +1 -0
- package/lib/Container.js +1 -0
- package/lib/Container.js.map +1 -0
- package/lib/Contributions.d.ts +7 -0
- package/lib/Contributions.d.ts.map +1 -0
- package/lib/Contributions.js +6 -0
- package/lib/Contributions.js.map +1 -0
- package/lib/CreateDict.d.ts +83 -0
- package/lib/CreateDict.d.ts.map +1 -0
- package/lib/CreateDict.js +3 -0
- package/lib/CreateDict.js.map +1 -0
- package/lib/CreateDictHttp.d.ts +33 -0
- package/lib/CreateDictHttp.d.ts.map +1 -0
- package/lib/CreateDictHttp.js +67 -0
- package/lib/CreateDictHttp.js.map +1 -0
- package/lib/CreateImage.d.ts +98 -0
- package/lib/CreateImage.d.ts.map +1 -0
- package/lib/CreateImage.js +3 -0
- package/lib/CreateImage.js.map +1 -0
- package/lib/CreateImageHttp.d.ts +51 -0
- package/lib/CreateImageHttp.d.ts.map +1 -0
- package/lib/CreateImageHttp.js +87 -0
- package/lib/CreateImageHttp.js.map +1 -0
- package/lib/CreateQueue.d.ts +83 -0
- package/lib/CreateQueue.d.ts.map +1 -0
- package/lib/CreateQueue.js +3 -0
- package/lib/CreateQueue.js.map +1 -0
- package/lib/CreateQueueHttp.d.ts +31 -0
- package/lib/CreateQueueHttp.d.ts.map +1 -0
- package/lib/CreateQueueHttp.js +67 -0
- package/lib/CreateQueueHttp.js.map +1 -0
- package/lib/CreateSandbox.d.ts +186 -0
- package/lib/CreateSandbox.d.ts.map +1 -0
- package/lib/CreateSandbox.js +3 -0
- package/lib/CreateSandbox.js.map +1 -0
- package/lib/CreateSandboxHttp.d.ts +17 -0
- package/lib/CreateSandboxHttp.d.ts.map +1 -0
- package/lib/CreateSandboxHttp.js +117 -0
- package/lib/CreateSandboxHttp.js.map +1 -0
- package/lib/CreateSecret.d.ts +95 -0
- package/lib/CreateSecret.d.ts.map +1 -0
- package/lib/CreateSecret.js +3 -0
- package/lib/CreateSecret.js.map +1 -0
- package/lib/CreateSecretHttp.d.ts +24 -0
- package/lib/CreateSecretHttp.d.ts.map +1 -0
- package/lib/CreateSecretHttp.js +60 -0
- package/lib/CreateSecretHttp.js.map +1 -0
- package/lib/CreateVolume.d.ts +84 -0
- package/lib/CreateVolume.d.ts.map +1 -0
- package/lib/CreateVolume.js +3 -0
- package/lib/CreateVolume.js.map +1 -0
- package/lib/CreateVolumeHttp.d.ts +32 -0
- package/lib/CreateVolumeHttp.d.ts.map +1 -0
- package/lib/CreateVolumeHttp.js +69 -0
- package/lib/CreateVolumeHttp.js.map +1 -0
- package/lib/Credentials.d.ts +32 -0
- package/lib/Credentials.d.ts.map +1 -0
- package/lib/Credentials.js +44 -0
- package/lib/Credentials.js.map +1 -0
- package/lib/Dict.d.ts +147 -0
- package/lib/Dict.d.ts.map +1 -0
- package/lib/Dict.js +175 -0
- package/lib/Dict.js.map +1 -0
- package/lib/DictClient.d.ts +55 -0
- package/lib/DictClient.d.ts.map +1 -0
- package/lib/DictClient.js +89 -0
- package/lib/DictClient.js.map +1 -0
- package/lib/Domain.d.ts +86 -0
- package/lib/Domain.d.ts.map +1 -0
- package/lib/Domain.js +113 -0
- package/lib/Domain.js.map +1 -0
- package/lib/Endpoint.d.ts +181 -0
- package/lib/Endpoint.d.ts.map +1 -0
- package/lib/Endpoint.js +283 -0
- package/lib/Endpoint.js.map +1 -0
- package/lib/Environment.d.ts +174 -0
- package/lib/Environment.d.ts.map +1 -0
- package/lib/Environment.js +244 -0
- package/lib/Environment.js.map +1 -0
- package/lib/FetchServer.d.ts +105 -0
- package/lib/FetchServer.d.ts.map +1 -0
- package/lib/FetchServer.js +3 -0
- package/lib/FetchServer.js.map +1 -0
- package/lib/FetchServerHttp.d.ts +21 -0
- package/lib/FetchServerHttp.d.ts.map +1 -0
- package/lib/FetchServerHttp.js +84 -0
- package/lib/FetchServerHttp.js.map +1 -0
- package/lib/Function.d.ts +236 -0
- package/lib/Function.d.ts.map +1 -0
- package/lib/Function.js +273 -0
- package/lib/Function.js.map +1 -0
- package/lib/FunctionAutoscaler.d.ts +99 -0
- package/lib/FunctionAutoscaler.d.ts.map +1 -0
- package/lib/FunctionAutoscaler.js +136 -0
- package/lib/FunctionAutoscaler.js.map +1 -0
- package/lib/FunctionTarget.d.ts +61 -0
- package/lib/FunctionTarget.d.ts.map +1 -0
- package/lib/FunctionTarget.js +136 -0
- package/lib/FunctionTarget.js.map +1 -0
- package/lib/Image.d.ts +159 -0
- package/lib/Image.d.ts.map +1 -0
- package/lib/Image.js +203 -0
- package/lib/Image.js.map +1 -0
- package/lib/ImageBuild.d.ts +108 -0
- package/lib/ImageBuild.d.ts.map +1 -0
- package/lib/ImageBuild.js +157 -0
- package/lib/ImageBuild.js.map +1 -0
- package/lib/ImagePlan.d.ts +31 -0
- package/lib/ImagePlan.d.ts.map +1 -0
- package/lib/ImagePlan.js +70 -0
- package/lib/ImagePlan.js.map +1 -0
- package/lib/InferEnv.d.ts +26 -0
- package/lib/InferEnv.d.ts.map +1 -0
- package/lib/InferEnv.js +1 -0
- package/lib/InferEnv.js.map +1 -0
- package/lib/InvokeFunction.d.ts +186 -0
- package/lib/InvokeFunction.d.ts.map +1 -0
- package/lib/InvokeFunction.js +10 -0
- package/lib/InvokeFunction.js.map +1 -0
- package/lib/InvokeFunctionHttp.d.ts +39 -0
- package/lib/InvokeFunctionHttp.d.ts.map +1 -0
- package/lib/InvokeFunctionHttp.js +210 -0
- package/lib/InvokeFunctionHttp.js.map +1 -0
- package/lib/ModalBindings.d.ts +138 -0
- package/lib/ModalBindings.d.ts.map +1 -0
- package/lib/ModalBindings.js +223 -0
- package/lib/ModalBindings.js.map +1 -0
- package/lib/MountBucket.d.ts +80 -0
- package/lib/MountBucket.d.ts.map +1 -0
- package/lib/MountBucket.js +44 -0
- package/lib/MountBucket.js.map +1 -0
- package/lib/MountVolume.d.ts +77 -0
- package/lib/MountVolume.d.ts.map +1 -0
- package/lib/MountVolume.js +41 -0
- package/lib/MountVolume.js.map +1 -0
- package/lib/Mounts.d.ts +134 -0
- package/lib/Mounts.d.ts.map +1 -0
- package/lib/Mounts.js +87 -0
- package/lib/Mounts.js.map +1 -0
- package/lib/PersistentSandbox.d.ts +75 -0
- package/lib/PersistentSandbox.d.ts.map +1 -0
- package/lib/PersistentSandbox.js +93 -0
- package/lib/PersistentSandbox.js.map +1 -0
- package/lib/Providers.d.ts +23 -0
- package/lib/Providers.d.ts.map +1 -0
- package/lib/Providers.js +64 -0
- package/lib/Providers.js.map +1 -0
- package/lib/Proxy.d.ts +94 -0
- package/lib/Proxy.d.ts.map +1 -0
- package/lib/Proxy.js +132 -0
- package/lib/Proxy.js.map +1 -0
- package/lib/Queue.d.ts +147 -0
- package/lib/Queue.d.ts.map +1 -0
- package/lib/Queue.js +177 -0
- package/lib/Queue.js.map +1 -0
- package/lib/QueueClient.d.ts +64 -0
- package/lib/QueueClient.d.ts.map +1 -0
- package/lib/QueueClient.js +73 -0
- package/lib/QueueClient.js.map +1 -0
- package/lib/ReadApp.d.ts +85 -0
- package/lib/ReadApp.d.ts.map +1 -0
- package/lib/ReadApp.js +3 -0
- package/lib/ReadApp.js.map +1 -0
- package/lib/ReadAppHttp.d.ts +26 -0
- package/lib/ReadAppHttp.d.ts.map +1 -0
- package/lib/ReadAppHttp.js +106 -0
- package/lib/ReadAppHttp.js.map +1 -0
- package/lib/ReadDict.d.ts +39 -0
- package/lib/ReadDict.d.ts.map +1 -0
- package/lib/ReadDict.js +3 -0
- package/lib/ReadDict.js.map +1 -0
- package/lib/ReadDictHttp.d.ts +12 -0
- package/lib/ReadDictHttp.d.ts.map +1 -0
- package/lib/ReadDictHttp.js +23 -0
- package/lib/ReadDictHttp.js.map +1 -0
- package/lib/ReadFunction.d.ts +73 -0
- package/lib/ReadFunction.d.ts.map +1 -0
- package/lib/ReadFunction.js +3 -0
- package/lib/ReadFunction.js.map +1 -0
- package/lib/ReadFunctionHttp.d.ts +25 -0
- package/lib/ReadFunctionHttp.d.ts.map +1 -0
- package/lib/ReadFunctionHttp.js +63 -0
- package/lib/ReadFunctionHttp.js.map +1 -0
- package/lib/ReadQueue.d.ts +39 -0
- package/lib/ReadQueue.d.ts.map +1 -0
- package/lib/ReadQueue.js +3 -0
- package/lib/ReadQueue.js.map +1 -0
- package/lib/ReadQueueHttp.d.ts +12 -0
- package/lib/ReadQueueHttp.d.ts.map +1 -0
- package/lib/ReadQueueHttp.js +23 -0
- package/lib/ReadQueueHttp.js.map +1 -0
- package/lib/ReadServer.d.ts +72 -0
- package/lib/ReadServer.d.ts.map +1 -0
- package/lib/ReadServer.js +3 -0
- package/lib/ReadServer.js.map +1 -0
- package/lib/ReadServerHttp.d.ts +25 -0
- package/lib/ReadServerHttp.d.ts.map +1 -0
- package/lib/ReadServerHttp.js +70 -0
- package/lib/ReadServerHttp.js.map +1 -0
- package/lib/ReadVolume.d.ts +40 -0
- package/lib/ReadVolume.d.ts.map +1 -0
- package/lib/ReadVolume.js +3 -0
- package/lib/ReadVolume.js.map +1 -0
- package/lib/ReadVolumeHttp.d.ts +12 -0
- package/lib/ReadVolumeHttp.d.ts.map +1 -0
- package/lib/ReadVolumeHttp.js +24 -0
- package/lib/ReadVolumeHttp.js.map +1 -0
- package/lib/ReadWriteDict.d.ts +39 -0
- package/lib/ReadWriteDict.d.ts.map +1 -0
- package/lib/ReadWriteDict.js +3 -0
- package/lib/ReadWriteDict.js.map +1 -0
- package/lib/ReadWriteDictHttp.d.ts +12 -0
- package/lib/ReadWriteDictHttp.d.ts.map +1 -0
- package/lib/ReadWriteDictHttp.js +23 -0
- package/lib/ReadWriteDictHttp.js.map +1 -0
- package/lib/ReadWriteQueue.d.ts +40 -0
- package/lib/ReadWriteQueue.d.ts.map +1 -0
- package/lib/ReadWriteQueue.js +3 -0
- package/lib/ReadWriteQueue.js.map +1 -0
- package/lib/ReadWriteQueueHttp.d.ts +12 -0
- package/lib/ReadWriteQueueHttp.d.ts.map +1 -0
- package/lib/ReadWriteQueueHttp.js +23 -0
- package/lib/ReadWriteQueueHttp.js.map +1 -0
- package/lib/ReadWriteVolume.d.ts +40 -0
- package/lib/ReadWriteVolume.d.ts.map +1 -0
- package/lib/ReadWriteVolume.js +3 -0
- package/lib/ReadWriteVolume.js.map +1 -0
- package/lib/ReadWriteVolumeHttp.d.ts +12 -0
- package/lib/ReadWriteVolumeHttp.d.ts.map +1 -0
- package/lib/ReadWriteVolumeHttp.js +24 -0
- package/lib/ReadWriteVolumeHttp.js.map +1 -0
- package/lib/RuntimeOwner.d.ts +39 -0
- package/lib/RuntimeOwner.d.ts.map +1 -0
- package/lib/RuntimeOwner.js +85 -0
- package/lib/RuntimeOwner.js.map +1 -0
- package/lib/Sandbox.d.ts +215 -0
- package/lib/Sandbox.d.ts.map +1 -0
- package/lib/Sandbox.js +278 -0
- package/lib/Sandbox.js.map +1 -0
- package/lib/SandboxClient.d.ts +748 -0
- package/lib/SandboxClient.d.ts.map +1 -0
- package/lib/SandboxClient.js +710 -0
- package/lib/SandboxClient.js.map +1 -0
- package/lib/ScaleFunction.d.ts +54 -0
- package/lib/ScaleFunction.d.ts.map +1 -0
- package/lib/ScaleFunction.js +3 -0
- package/lib/ScaleFunction.js.map +1 -0
- package/lib/ScaleFunctionHttp.d.ts +21 -0
- package/lib/ScaleFunctionHttp.d.ts.map +1 -0
- package/lib/ScaleFunctionHttp.js +39 -0
- package/lib/ScaleFunctionHttp.js.map +1 -0
- package/lib/Secret.d.ts +170 -0
- package/lib/Secret.d.ts.map +1 -0
- package/lib/Secret.js +196 -0
- package/lib/Secret.js.map +1 -0
- package/lib/Server.d.ts +155 -0
- package/lib/Server.d.ts.map +1 -0
- package/lib/Server.js +184 -0
- package/lib/Server.js.map +1 -0
- package/lib/ServiceUser.d.ts +139 -0
- package/lib/ServiceUser.d.ts.map +1 -0
- package/lib/ServiceUser.js +210 -0
- package/lib/ServiceUser.js.map +1 -0
- package/lib/Volume.d.ts +170 -0
- package/lib/Volume.d.ts.map +1 -0
- package/lib/Volume.js +220 -0
- package/lib/Volume.js.map +1 -0
- package/lib/VolumeClient.d.ts +53 -0
- package/lib/VolumeClient.d.ts.map +1 -0
- package/lib/VolumeClient.js +22 -0
- package/lib/VolumeClient.js.map +1 -0
- package/lib/VolumeFiles.d.ts +94 -0
- package/lib/VolumeFiles.d.ts.map +1 -0
- package/lib/VolumeFiles.js +139 -0
- package/lib/VolumeFiles.js.map +1 -0
- package/lib/WebhookToken.d.ts +102 -0
- package/lib/WebhookToken.d.ts.map +1 -0
- package/lib/WebhookToken.js +176 -0
- package/lib/WebhookToken.js.map +1 -0
- package/lib/WorkspaceSettings.d.ts +70 -0
- package/lib/WorkspaceSettings.d.ts.map +1 -0
- package/lib/WorkspaceSettings.js +105 -0
- package/lib/WorkspaceSettings.js.map +1 -0
- package/lib/WriteApp.d.ts +38 -0
- package/lib/WriteApp.d.ts.map +1 -0
- package/lib/WriteApp.js +3 -0
- package/lib/WriteApp.js.map +1 -0
- package/lib/WriteAppHttp.d.ts +23 -0
- package/lib/WriteAppHttp.d.ts.map +1 -0
- package/lib/WriteAppHttp.js +36 -0
- package/lib/WriteAppHttp.js.map +1 -0
- package/lib/WriteDict.d.ts +39 -0
- package/lib/WriteDict.d.ts.map +1 -0
- package/lib/WriteDict.js +3 -0
- package/lib/WriteDict.js.map +1 -0
- package/lib/WriteDictHttp.d.ts +12 -0
- package/lib/WriteDictHttp.d.ts.map +1 -0
- package/lib/WriteDictHttp.js +23 -0
- package/lib/WriteDictHttp.js.map +1 -0
- package/lib/WriteQueue.d.ts +39 -0
- package/lib/WriteQueue.d.ts.map +1 -0
- package/lib/WriteQueue.js +3 -0
- package/lib/WriteQueue.js.map +1 -0
- package/lib/WriteQueueHttp.d.ts +12 -0
- package/lib/WriteQueueHttp.d.ts.map +1 -0
- package/lib/WriteQueueHttp.js +23 -0
- package/lib/WriteQueueHttp.js.map +1 -0
- package/lib/WriteSecret.d.ts +53 -0
- package/lib/WriteSecret.d.ts.map +1 -0
- package/lib/WriteSecret.js +3 -0
- package/lib/WriteSecret.js.map +1 -0
- package/lib/WriteSecretHttp.d.ts +23 -0
- package/lib/WriteSecretHttp.d.ts.map +1 -0
- package/lib/WriteSecretHttp.js +44 -0
- package/lib/WriteSecretHttp.js.map +1 -0
- package/lib/WriteVolume.d.ts +39 -0
- package/lib/WriteVolume.d.ts.map +1 -0
- package/lib/WriteVolume.js +3 -0
- package/lib/WriteVolume.js.map +1 -0
- package/lib/WriteVolumeHttp.d.ts +12 -0
- package/lib/WriteVolumeHttp.d.ts.map +1 -0
- package/lib/WriteVolumeHttp.js +24 -0
- package/lib/WriteVolumeHttp.js.map +1 -0
- package/lib/index.d.ts +80 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +78 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/Declared.d.ts +29 -0
- package/lib/internal/Declared.d.ts.map +1 -0
- package/lib/internal/Declared.js +31 -0
- package/lib/internal/Declared.js.map +1 -0
- package/lib/internal/Deploy.d.ts +110 -0
- package/lib/internal/Deploy.d.ts.map +1 -0
- package/lib/internal/Deploy.js +230 -0
- package/lib/internal/Deploy.js.map +1 -0
- package/lib/internal/Entrypoint.d.ts +52 -0
- package/lib/internal/Entrypoint.d.ts.map +1 -0
- package/lib/internal/Entrypoint.js +193 -0
- package/lib/internal/Entrypoint.js.map +1 -0
- package/lib/internal/Rpc.d.ts +17 -0
- package/lib/internal/Rpc.d.ts.map +1 -0
- package/lib/internal/Rpc.js +49 -0
- package/lib/internal/Rpc.js.map +1 -0
- package/lib/internal/RpcAuth.d.ts +41 -0
- package/lib/internal/RpcAuth.d.ts.map +1 -0
- package/lib/internal/RpcAuth.js +100 -0
- package/lib/internal/RpcAuth.js.map +1 -0
- package/lib/internal/Runtime.d.ts +127 -0
- package/lib/internal/Runtime.d.ts.map +1 -0
- package/lib/internal/Runtime.js +246 -0
- package/lib/internal/Runtime.js.map +1 -0
- package/lib/internal/Tags.d.ts +19 -0
- package/lib/internal/Tags.d.ts.map +1 -0
- package/lib/internal/Tags.js +33 -0
- package/lib/internal/Tags.js.map +1 -0
- package/lib/internal/TcpConnect.d.ts +12 -0
- package/lib/internal/TcpConnect.d.ts.map +1 -0
- package/lib/internal/TcpConnect.js +46 -0
- package/lib/internal/TcpConnect.js.map +1 -0
- package/lib/internal/Transport.d.ts +13 -0
- package/lib/internal/Transport.d.ts.map +1 -0
- package/lib/internal/Transport.js +16 -0
- package/lib/internal/Transport.js.map +1 -0
- package/lib/internal.d.ts +71 -0
- package/lib/internal.d.ts.map +1 -0
- package/lib/internal.js +102 -0
- package/lib/internal.js.map +1 -0
- package/package.json +75 -3
- package/src/App.ts +262 -0
- package/src/AuthProvider.ts +295 -0
- package/src/BindingHttp.ts +112 -0
- package/src/Blob.ts +71 -0
- package/src/Bootstrap.ts +52 -0
- package/src/Cbor.ts +158 -0
- package/src/ConnectSandbox.ts +99 -0
- package/src/Container.ts +121 -0
- package/src/Contributions.ts +9 -0
- package/src/CreateDict.ts +95 -0
- package/src/CreateDictHttp.ts +91 -0
- package/src/CreateImage.ts +105 -0
- package/src/CreateImageHttp.ts +117 -0
- package/src/CreateQueue.ts +95 -0
- package/src/CreateQueueHttp.ts +91 -0
- package/src/CreateSandbox.ts +228 -0
- package/src/CreateSandboxHttp.ts +160 -0
- package/src/CreateSecret.ts +109 -0
- package/src/CreateSecretHttp.ts +83 -0
- package/src/CreateVolume.ts +96 -0
- package/src/CreateVolumeHttp.ts +93 -0
- package/src/Credentials.ts +74 -0
- package/src/Dict.ts +245 -0
- package/src/DictClient.ts +166 -0
- package/src/Domain.ts +147 -0
- package/src/Endpoint.ts +406 -0
- package/src/Environment.ts +373 -0
- package/src/FetchServer.ts +126 -0
- package/src/FetchServerHttp.ts +110 -0
- package/src/Function.ts +397 -0
- package/src/FunctionAutoscaler.ts +210 -0
- package/src/FunctionTarget.ts +181 -0
- package/src/Image.ts +281 -0
- package/src/ImageBuild.ts +228 -0
- package/src/ImagePlan.ts +78 -0
- package/src/InferEnv.ts +27 -0
- package/src/InvokeFunction.ts +211 -0
- package/src/InvokeFunctionHttp.ts +316 -0
- package/src/ModalBindings.ts +310 -0
- package/src/MountBucket.ts +137 -0
- package/src/MountVolume.ts +113 -0
- package/src/Mounts.ts +230 -0
- package/src/PersistentSandbox.ts +142 -0
- package/src/Providers.ts +100 -0
- package/src/Proxy.ts +191 -0
- package/src/Queue.ts +258 -0
- package/src/QueueClient.ts +149 -0
- package/src/ReadApp.ts +101 -0
- package/src/ReadAppHttp.ts +142 -0
- package/src/ReadDict.ts +44 -0
- package/src/ReadDictHttp.ts +27 -0
- package/src/ReadFunction.ts +107 -0
- package/src/ReadFunctionHttp.ts +91 -0
- package/src/ReadQueue.ts +44 -0
- package/src/ReadQueueHttp.ts +27 -0
- package/src/ReadServer.ts +98 -0
- package/src/ReadServerHttp.ts +101 -0
- package/src/ReadVolume.ts +45 -0
- package/src/ReadVolumeHttp.ts +28 -0
- package/src/ReadWriteDict.ts +44 -0
- package/src/ReadWriteDictHttp.ts +27 -0
- package/src/ReadWriteQueue.ts +45 -0
- package/src/ReadWriteQueueHttp.ts +27 -0
- package/src/ReadWriteVolume.ts +45 -0
- package/src/ReadWriteVolumeHttp.ts +28 -0
- package/src/RuntimeOwner.ts +111 -0
- package/src/Sandbox.ts +402 -0
- package/src/SandboxClient.ts +1404 -0
- package/src/ScaleFunction.ts +70 -0
- package/src/ScaleFunctionHttp.ts +54 -0
- package/src/Secret.ts +296 -0
- package/src/Server.ts +285 -0
- package/src/ServiceUser.ts +295 -0
- package/src/Volume.ts +320 -0
- package/src/VolumeClient.ts +108 -0
- package/src/VolumeFiles.ts +194 -0
- package/src/WebhookToken.ts +230 -0
- package/src/WorkspaceSettings.ts +160 -0
- package/src/WriteApp.ts +43 -0
- package/src/WriteAppHttp.ts +51 -0
- package/src/WriteDict.ts +44 -0
- package/src/WriteDictHttp.ts +27 -0
- package/src/WriteQueue.ts +44 -0
- package/src/WriteQueueHttp.ts +27 -0
- package/src/WriteSecret.ts +60 -0
- package/src/WriteSecretHttp.ts +56 -0
- package/src/WriteVolume.ts +44 -0
- package/src/WriteVolumeHttp.ts +28 -0
- package/src/globals.d.ts +2 -0
- package/src/index.ts +85 -0
- package/src/internal/Declared.ts +80 -0
- package/src/internal/Deploy.ts +309 -0
- package/src/internal/Entrypoint.ts +198 -0
- package/src/internal/Rpc.ts +59 -0
- package/src/internal/RpcAuth.ts +132 -0
- package/src/internal/Runtime.ts +386 -0
- package/src/internal/Tags.ts +44 -0
- package/src/internal/TcpConnect.ts +78 -0
- package/src/internal/Transport.ts +25 -0
- package/src/internal.ts +147 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import { makeModalBinding } from "./BindingHttp.ts";
|
|
6
|
+
import type { PersistentSandbox } from "./PersistentSandbox.ts";
|
|
7
|
+
import {
|
|
8
|
+
persistentSandboxHandle,
|
|
9
|
+
type PersistentSandboxHandleOf,
|
|
10
|
+
SandboxOps,
|
|
11
|
+
} from "./SandboxClient.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A declared `Modal.PersistentSandbox`, reached from a runtime: its id, and
|
|
15
|
+
* the box's session API.
|
|
16
|
+
*/
|
|
17
|
+
export interface ConnectedPersistentSandbox extends Omit<
|
|
18
|
+
PersistentSandboxHandleOf<RuntimeContext>,
|
|
19
|
+
"persistentSandboxId"
|
|
20
|
+
> {
|
|
21
|
+
/** The box's id (`ps-…`). */
|
|
22
|
+
readonly persistentSandboxId: Effect.Effect<string>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Connect to a declared `Modal.PersistentSandbox` from any runtime. The
|
|
27
|
+
* handle follows Modal's session API: `session()` returns the running
|
|
28
|
+
* session, resuming the box from its last session's filesystem when it's
|
|
29
|
+
* paused, and every session is a full sandbox handle (`exec`, `files`,
|
|
30
|
+
* snapshots).
|
|
31
|
+
*
|
|
32
|
+
* ### Use a persistent box
|
|
33
|
+
* **Example:** From a Cloudflare Worker
|
|
34
|
+
* ```typescript
|
|
35
|
+
* import * as Cloudflare from "@alchemy.run/cloudflare";
|
|
36
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
37
|
+
* import * as Effect from "effect/Effect";
|
|
38
|
+
* import * as HttpServerResponse from "effect/http/HttpServerResponse";
|
|
39
|
+
* import { DevBox } from "./DevBox.ts";
|
|
40
|
+
*
|
|
41
|
+
* export default class Shell extends Cloudflare.Worker<Shell>()(
|
|
42
|
+
* "Shell",
|
|
43
|
+
* { main: import.meta.url, compatibility: { flags: ["nodejs_compat"] } },
|
|
44
|
+
* Effect.gen(function* () {
|
|
45
|
+
* const box = yield* Modal.ConnectSandbox(DevBox);
|
|
46
|
+
* return {
|
|
47
|
+
* fetch: Effect.gen(function* () {
|
|
48
|
+
* const session = yield* box.session();
|
|
49
|
+
* const status = yield* session.exec("git status");
|
|
50
|
+
* return HttpServerResponse.text(status.stdout);
|
|
51
|
+
* }).pipe(Effect.orDie),
|
|
52
|
+
* };
|
|
53
|
+
* }).pipe(Effect.provide(Modal.ConnectSandboxHttp)),
|
|
54
|
+
* ) {}
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* @binding
|
|
58
|
+
* @product Sandbox
|
|
59
|
+
*/
|
|
60
|
+
export interface ConnectSandbox extends Binding.Service<
|
|
61
|
+
ConnectSandbox,
|
|
62
|
+
"Modal.ConnectSandbox",
|
|
63
|
+
(box: PersistentSandbox) => Effect.Effect<ConnectedPersistentSandbox>
|
|
64
|
+
> {}
|
|
65
|
+
|
|
66
|
+
export const ConnectSandbox = Binding.Service<ConnectSandbox>("Modal.ConnectSandbox");
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* {@link ConnectSandbox} over Modal's API. Grants the runtime's identity the
|
|
70
|
+
* `contributor` role on the box's environment.
|
|
71
|
+
*
|
|
72
|
+
* @layer
|
|
73
|
+
* @product Sandbox
|
|
74
|
+
* @provides Modal.ConnectSandbox
|
|
75
|
+
*/
|
|
76
|
+
export const ConnectSandboxHttp = Layer.effect(
|
|
77
|
+
ConnectSandbox,
|
|
78
|
+
makeModalBinding({
|
|
79
|
+
tag: "Modal.ConnectSandbox",
|
|
80
|
+
operations: SandboxOps,
|
|
81
|
+
role: "contributor",
|
|
82
|
+
make: Effect.fn(function* (box: PersistentSandbox, ops) {
|
|
83
|
+
const persistentSandboxId = yield* box.persistentSandboxId;
|
|
84
|
+
const environment = yield* box.environment;
|
|
85
|
+
// The box's identity resolves at runtime, on each call.
|
|
86
|
+
const handle = Effect.map(Effect.all([persistentSandboxId, environment]), ([id, env]) =>
|
|
87
|
+
persistentSandboxHandle(ops, id, { environment: env }),
|
|
88
|
+
);
|
|
89
|
+
return {
|
|
90
|
+
persistentSandboxId,
|
|
91
|
+
session: () => Effect.flatMap(handle, (h) => h.session()),
|
|
92
|
+
terminate: () => Effect.flatMap(handle, (h) => h.terminate()),
|
|
93
|
+
} satisfies ConnectedPersistentSandbox;
|
|
94
|
+
}),
|
|
95
|
+
}),
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
/** {@link ConnectSandboxHttp}: Modal has one transport, so both names provide it. */
|
|
99
|
+
export const ConnectSandboxLive = ConnectSandboxHttp;
|
package/src/Container.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type * as Bundle from "alchemy/Bundle/Bundle";
|
|
2
|
+
import type { PlatformProps } from "alchemy/Platform";
|
|
3
|
+
import type * as Effect from "effect/Effect";
|
|
4
|
+
import type { App } from "./App.ts";
|
|
5
|
+
import type { Mount } from "./Mounts.ts";
|
|
6
|
+
import type { Providers } from "./Providers.ts";
|
|
7
|
+
import type { DurationInput } from "./SandboxClient.ts";
|
|
8
|
+
|
|
9
|
+
/** A resource, or the module-scope Effect that declares it. */
|
|
10
|
+
export type Ref<T> = T | Effect.Effect<T, never, Providers>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Container settings shared by `Modal.Function` and `Modal.Server`: the
|
|
14
|
+
* program, the image it runs on, and Modal's resource, scaling and
|
|
15
|
+
* placement options.
|
|
16
|
+
*/
|
|
17
|
+
export interface ContainerProps extends PlatformProps {
|
|
18
|
+
/**
|
|
19
|
+
* Module entrypoint, bundled into the image. Typically `import.meta.url`.
|
|
20
|
+
* A change to the bundle builds a new image.
|
|
21
|
+
*/
|
|
22
|
+
main: string;
|
|
23
|
+
/** The App the function is deployed in. Changing it replaces the function. */
|
|
24
|
+
app: Ref<App>;
|
|
25
|
+
/**
|
|
26
|
+
* Name of the function in its App, unique per App. Changing it replaces
|
|
27
|
+
* the function.
|
|
28
|
+
* @default the logical ID
|
|
29
|
+
*/
|
|
30
|
+
name?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Base image the bundle runs on. It needs Bun on the `PATH`; Alchemy adds
|
|
33
|
+
* Python (see {@link python}).
|
|
34
|
+
* @default "oven/bun:1"
|
|
35
|
+
*/
|
|
36
|
+
image?: string;
|
|
37
|
+
/** Dockerfile lines run on the base before the bundle is added. */
|
|
38
|
+
commands?: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Standalone Python added to the image. Modal starts every Function
|
|
41
|
+
* container with its Python entrypoint, which then starts the program.
|
|
42
|
+
* Set `false` when the base image already has Python 3.10+ on the `PATH`.
|
|
43
|
+
* @default "3.12"
|
|
44
|
+
*/
|
|
45
|
+
python?: string | false;
|
|
46
|
+
/**
|
|
47
|
+
* Port the program listens on.
|
|
48
|
+
* @default 8000
|
|
49
|
+
*/
|
|
50
|
+
port?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Named export to load from `main`.
|
|
53
|
+
* @default "default"
|
|
54
|
+
*/
|
|
55
|
+
handler?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Extra environment variables for the program. Stored, with the bindings'
|
|
58
|
+
* env, in a Modal Secret attached to the function.
|
|
59
|
+
*/
|
|
60
|
+
env?: Record<string, any>;
|
|
61
|
+
/** Bundler options. */
|
|
62
|
+
build?: Bundle.BundleConfig;
|
|
63
|
+
/** Secrets whose variables the program sees as environment variables. */
|
|
64
|
+
secrets?: Array<Ref<{ readonly secretId: string }>>;
|
|
65
|
+
/**
|
|
66
|
+
* Volumes and cloud buckets mounted into every container:
|
|
67
|
+
* `{ volume: Data, path: "/data" }`, `{ bucket: Uploads, path: "/uploads", secret: R2Keys }`.
|
|
68
|
+
* `Modal.MountVolume` and `Modal.MountBucket` add more from the program.
|
|
69
|
+
*/
|
|
70
|
+
mounts?: Mount[];
|
|
71
|
+
/** CPU cores to reserve (fractional allowed). */
|
|
72
|
+
cpu?: number;
|
|
73
|
+
/** Most CPU cores a container may use. */
|
|
74
|
+
cpuLimit?: number;
|
|
75
|
+
/** Memory in MiB to reserve. */
|
|
76
|
+
memory?: number;
|
|
77
|
+
/** Most memory in MiB a container may use. */
|
|
78
|
+
memoryLimit?: number;
|
|
79
|
+
/** GPU: `"T4"`, `"L4"`, `"A10G"`, `"A100-80GB"`, `"H100"`, ..., with an optional `":<count>"`. */
|
|
80
|
+
gpu?: string;
|
|
81
|
+
/** Ephemeral disk in MiB. */
|
|
82
|
+
ephemeralDisk?: number;
|
|
83
|
+
/**
|
|
84
|
+
* Most time one input (a call, a request) may run.
|
|
85
|
+
* @default 300 seconds
|
|
86
|
+
*/
|
|
87
|
+
timeout?: DurationInput;
|
|
88
|
+
/**
|
|
89
|
+
* Most time a container may take to start.
|
|
90
|
+
* @default the timeout
|
|
91
|
+
*/
|
|
92
|
+
startupTimeout?: DurationInput;
|
|
93
|
+
/** Containers kept running even with no traffic. @default 0 */
|
|
94
|
+
minContainers?: number;
|
|
95
|
+
/** Most containers running at once. */
|
|
96
|
+
maxContainers?: number;
|
|
97
|
+
/** Idle containers kept on top of demand while the function is busy. */
|
|
98
|
+
bufferContainers?: number;
|
|
99
|
+
/** Seconds of sustained demand before scaling up. */
|
|
100
|
+
scaleupWindow?: number;
|
|
101
|
+
/** Seconds a container may stay idle before it scales down. */
|
|
102
|
+
scaledownWindow?: number;
|
|
103
|
+
/** Regions containers may run in (`"us-east"`, `"eu"`, ...). */
|
|
104
|
+
regions?: string[];
|
|
105
|
+
/** Cloud provider containers run on. */
|
|
106
|
+
cloud?: "aws" | "gcp" | "oci" | "auto";
|
|
107
|
+
/** Run on non-preemptible capacity (costs more). */
|
|
108
|
+
nonpreemptible?: boolean;
|
|
109
|
+
/** A `Modal.Proxy` outbound traffic goes through (static egress IPs). */
|
|
110
|
+
proxy?: Ref<{ readonly proxyId: string }>;
|
|
111
|
+
/** Block all outbound network access. */
|
|
112
|
+
blockNetwork?: boolean;
|
|
113
|
+
/** Stop the program from calling Modal's API with the container's identity. */
|
|
114
|
+
restrictModalAccess?: boolean;
|
|
115
|
+
/** Snapshot the container's memory after startup, so cold starts restore it. */
|
|
116
|
+
enableMemorySnapshot?: boolean;
|
|
117
|
+
/** Enable IPv6 networking between the function's containers. */
|
|
118
|
+
i6pn?: boolean;
|
|
119
|
+
/** Pin Modal's image builder version (`"2025.06"`). */
|
|
120
|
+
builderVersion?: string;
|
|
121
|
+
}
|
|
@@ -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 { DictsOps } from "./CreateDictHttp.ts";
|
|
5
|
+
import type { ensureDict, lookupDict } from "./Dict.ts";
|
|
6
|
+
import type { DictAttributes } from "./Dict.ts";
|
|
7
|
+
import type { ReadWriteDictClient } from "./DictClient.ts";
|
|
8
|
+
import type { Environment } from "./Environment.ts";
|
|
9
|
+
import type { ErrorOf, OpError } from "./internal.ts";
|
|
10
|
+
|
|
11
|
+
/** A dict created or found at runtime: its attributes plus a read-write client. */
|
|
12
|
+
export interface DictHandle extends ReadWriteDictClient {
|
|
13
|
+
readonly dictId: Effect.Effect<string>;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** The attributes, to pass where a `Modal.Dict` is accepted (e.g. sandbox mounts). */
|
|
16
|
+
readonly attributes: DictAttributes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Get, create, list and delete dicts by name in one environment. */
|
|
20
|
+
export interface DictsClientOf<R> {
|
|
21
|
+
/** The dict named `name`, created when missing (Modal's own get-or-create). */
|
|
22
|
+
getOrCreate(name: string): Effect.Effect<DictHandle, ErrorOf<typeof ensureDict>, R>;
|
|
23
|
+
/** The dict named `name`, or `undefined`. */
|
|
24
|
+
get(name: string): Effect.Effect<DictHandle | undefined, ErrorOf<typeof lookupDict>, R>;
|
|
25
|
+
/** Delete the dict named `name` (no-op when missing). */
|
|
26
|
+
delete(
|
|
27
|
+
name: string,
|
|
28
|
+
): Effect.Effect<
|
|
29
|
+
void,
|
|
30
|
+
| ErrorOf<typeof lookupDict>
|
|
31
|
+
| Exclude<OpError<DictsOps, "delete">, { readonly _tag: "DictNotFound" }>,
|
|
32
|
+
R
|
|
33
|
+
>;
|
|
34
|
+
/** Names of every dict in the environment. */
|
|
35
|
+
list(): Effect.Effect<ReadonlyArray<string>, OpError<DictsOps, "list">, R>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A DictsClient whose calls run inside a deployed runtime. */
|
|
39
|
+
export type DictsClient = DictsClientOf<RuntimeContext>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create dicts 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 dict has only a name, so the tags become
|
|
53
|
+
* its name prefix, `Modal.runtimePrefix({ stack, stage, id })`: list them
|
|
54
|
+
* with `modal dict list` and delete the ones whose name starts with it.
|
|
55
|
+
*
|
|
56
|
+
* ### One dict 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 dicts = yield* Modal.CreateDict(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 state = yield* dicts.getOrCreate(`state-${user}`);
|
|
78
|
+
* yield* state.put("lastSeen", Date.now());
|
|
79
|
+
* return HttpServerResponse.text("ok");
|
|
80
|
+
* }).pipe(Effect.orDie),
|
|
81
|
+
* };
|
|
82
|
+
* }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateDictHttp, Modal.CreateSandboxHttp))),
|
|
83
|
+
* ) {}
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @binding
|
|
87
|
+
* @product Dict
|
|
88
|
+
*/
|
|
89
|
+
export interface CreateDict extends Binding.Service<
|
|
90
|
+
CreateDict,
|
|
91
|
+
"Modal.CreateDict",
|
|
92
|
+
(environment?: Environment) => Effect.Effect<DictsClient>
|
|
93
|
+
> {}
|
|
94
|
+
|
|
95
|
+
export const CreateDict = Binding.Service<CreateDict>("Modal.CreateDict");
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as dict from "@distilled.cloud/modal/dict";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { makeOpenModalBinding } from "./BindingHttp.ts";
|
|
5
|
+
import { CreateDict, type DictHandle, type DictsClientOf } from "./CreateDict.ts";
|
|
6
|
+
import { ensureDict, lookupDict, type DictAttributes } from "./Dict.ts";
|
|
7
|
+
import { DictOps, makeReadWriteDictClient } from "./DictClient.ts";
|
|
8
|
+
import type { Environment } from "./Environment.ts";
|
|
9
|
+
import { environmentOf, listAll, operations } from "./internal.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 DictsOps = operations({
|
|
14
|
+
getOrCreate: dict.dictGetOrCreate,
|
|
15
|
+
delete: dict.deleteDict,
|
|
16
|
+
list: dict.listDict,
|
|
17
|
+
client: DictOps,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export type DictsOps = Effect.Success<typeof DictsOps>;
|
|
21
|
+
|
|
22
|
+
const handleOf = (attributes: DictAttributes, ops: DictsOps, name: string): DictHandle => ({
|
|
23
|
+
...makeReadWriteDictClient(Effect.succeed(attributes.dictId), ops.client),
|
|
24
|
+
dictId: Effect.succeed(attributes.dictId),
|
|
25
|
+
name,
|
|
26
|
+
attributes,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/** A dicts client over an environment name resolved per call. */
|
|
30
|
+
export const makeDictsClient = (
|
|
31
|
+
environment: Effect.Effect<string | undefined>,
|
|
32
|
+
ops: DictsOps,
|
|
33
|
+
owner: Effect.Effect<RuntimeOwner | undefined> = Effect.undefined,
|
|
34
|
+
): DictsClientOf<never> => ({
|
|
35
|
+
getOrCreate: (name) =>
|
|
36
|
+
Effect.flatMap(Effect.all([environment, owner]), ([env, stamp]) =>
|
|
37
|
+
ensureDict(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
|
+
lookupDict(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* lookupDict(ops.getOrCreate, ownedName(yield* owner, name), env);
|
|
47
|
+
if (!found) return;
|
|
48
|
+
yield* ops
|
|
49
|
+
.delete({ dictId: found.dictId })
|
|
50
|
+
.pipe(Effect.catchTag("DictNotFound", () => 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.dicts ?? [])),
|
|
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 CreateDict} 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 Dict
|
|
76
|
+
* @provides Modal.CreateDict
|
|
77
|
+
*/
|
|
78
|
+
export const CreateDictHttp = Layer.effect(
|
|
79
|
+
CreateDict,
|
|
80
|
+
makeOpenModalBinding({
|
|
81
|
+
tag: "Modal.CreateDict",
|
|
82
|
+
operations: DictsOps,
|
|
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 makeDictsClient(name, ops, owner);
|
|
89
|
+
}),
|
|
90
|
+
}),
|
|
91
|
+
);
|
|
@@ -0,0 +1,105 @@
|
|
|
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 { buildFromOptions, ImagesOps } from "./CreateImageHttp.ts";
|
|
6
|
+
import type { ErrorOf, OpError } from "./internal.ts";
|
|
7
|
+
|
|
8
|
+
/** What to build: Modal's image inputs, in memory (no build context directory). */
|
|
9
|
+
export interface ImageBuildOptions {
|
|
10
|
+
/** Start from a registry image. */
|
|
11
|
+
readonly image?: string;
|
|
12
|
+
/** Start from a Modal image (a deploy-time `Modal.Image`, or a snapshot). */
|
|
13
|
+
readonly from?: { readonly imageId: string };
|
|
14
|
+
/** A whole Dockerfile as text (`FROM` included). Exclusive with `image`/`from`. */
|
|
15
|
+
readonly dockerfile?: string;
|
|
16
|
+
/** Dockerfile lines appended to the build. */
|
|
17
|
+
readonly commands?: ReadonlyArray<string>;
|
|
18
|
+
/** Files the commands `COPY`, by path relative to the build context. */
|
|
19
|
+
readonly files?: Record<string, string | Uint8Array>;
|
|
20
|
+
/** Secrets the build steps see as environment variables. */
|
|
21
|
+
readonly secrets?: ReadonlyArray<{ readonly secretId: string }>;
|
|
22
|
+
/** Run the build on a GPU. */
|
|
23
|
+
readonly gpu?: string;
|
|
24
|
+
/** Rebuild even when Modal has the same image cached. */
|
|
25
|
+
readonly force?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Build images in one App at runtime. */
|
|
29
|
+
export interface ImagesClient {
|
|
30
|
+
/**
|
|
31
|
+
* Build an image (or return the cached one: Modal content-addresses
|
|
32
|
+
* builds) and wait until it's ready. Fails with `Modal.ImageBuildFailed`.
|
|
33
|
+
*/
|
|
34
|
+
build(
|
|
35
|
+
options: ImageBuildOptions,
|
|
36
|
+
): Effect.Effect<{ readonly imageId: string }, ErrorOf<typeof buildFromOptions>, RuntimeContext>;
|
|
37
|
+
/** The image published under `tag`, or `undefined`. */
|
|
38
|
+
fromTag(
|
|
39
|
+
tag: string,
|
|
40
|
+
): Effect.Effect<
|
|
41
|
+
{ readonly imageId: string } | undefined,
|
|
42
|
+
OpError<ImagesOps, "getByTag">,
|
|
43
|
+
RuntimeContext
|
|
44
|
+
>;
|
|
45
|
+
/** Publish an image under `tag` (moving the tag if it points elsewhere). */
|
|
46
|
+
publish(
|
|
47
|
+
image: { readonly imageId: string },
|
|
48
|
+
tag: string,
|
|
49
|
+
): Effect.Effect<void, OpError<ImagesOps, "publish">, RuntimeContext>;
|
|
50
|
+
/** Remove a published tag (`name` or `name:tag`); the image itself stays. */
|
|
51
|
+
unpublish(tag: string): Effect.Effect<void, OpError<ImagesOps, "deleteName">, RuntimeContext>;
|
|
52
|
+
/** Delete an image. */
|
|
53
|
+
delete(image: {
|
|
54
|
+
readonly imageId: string;
|
|
55
|
+
}): Effect.Effect<void, OpError<ImagesOps, "delete">, RuntimeContext>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Build Modal Images at runtime, e.g. one per repository a user connects,
|
|
60
|
+
* from the same inputs a `Modal.Image` takes. Modal builds remotely; the
|
|
61
|
+
* runtime needs no Docker.
|
|
62
|
+
*
|
|
63
|
+
* ### An image per repository
|
|
64
|
+
* **Example:** From a Cloudflare Worker
|
|
65
|
+
* ```typescript
|
|
66
|
+
* import * as Cloudflare from "@alchemy.run/cloudflare";
|
|
67
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
68
|
+
* import * as Effect from "effect/Effect";
|
|
69
|
+
* import * as Layer from "effect/Layer";
|
|
70
|
+
* import { HttpServerRequest } from "effect/http/HttpServerRequest";
|
|
71
|
+
* import * as HttpServerResponse from "effect/http/HttpServerResponse";
|
|
72
|
+
* import { Coder } from "./Coder.ts";
|
|
73
|
+
*
|
|
74
|
+
* export default class Api extends Cloudflare.Worker<Api>()(
|
|
75
|
+
* "Api",
|
|
76
|
+
* { main: import.meta.url },
|
|
77
|
+
* Effect.gen(function* () {
|
|
78
|
+
* const images = yield* Modal.CreateImage(Coder);
|
|
79
|
+
* const sandboxes = yield* Modal.CreateSandbox(Coder);
|
|
80
|
+
* return {
|
|
81
|
+
* fetch: Effect.gen(function* () {
|
|
82
|
+
* const request = yield* HttpServerRequest;
|
|
83
|
+
* const repo = request.headers["x-repo"] ?? "alchemy-run/alchemy";
|
|
84
|
+
* const image = yield* images.build({
|
|
85
|
+
* image: "node:22-bookworm",
|
|
86
|
+
* commands: [`RUN git clone https://github.com/${repo} /work`],
|
|
87
|
+
* });
|
|
88
|
+
* const sandbox = yield* sandboxes.create({ image });
|
|
89
|
+
* return HttpServerResponse.text(sandbox.sandboxId);
|
|
90
|
+
* }).pipe(Effect.orDie),
|
|
91
|
+
* };
|
|
92
|
+
* }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateImageHttp, Modal.CreateSandboxHttp))),
|
|
93
|
+
* ) {}
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @binding
|
|
97
|
+
* @product Image
|
|
98
|
+
*/
|
|
99
|
+
export interface CreateImage extends Binding.Service<
|
|
100
|
+
CreateImage,
|
|
101
|
+
"Modal.CreateImage",
|
|
102
|
+
(app: App) => Effect.Effect<ImagesClient>
|
|
103
|
+
> {}
|
|
104
|
+
|
|
105
|
+
export const CreateImage = Binding.Service<CreateImage>("Modal.CreateImage");
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as DockerfileParser from "@alchemy.run/docker/DockerfileParser";
|
|
2
|
+
import * as image from "@distilled.cloud/modal/image";
|
|
3
|
+
import * as Effect from "effect/Effect";
|
|
4
|
+
import * as Layer from "effect/Layer";
|
|
5
|
+
import type { App } from "./App.ts";
|
|
6
|
+
import { makeModalBinding } from "./BindingHttp.ts";
|
|
7
|
+
import { CreateImage, type ImageBuildOptions, type ImagesClient } from "./CreateImage.ts";
|
|
8
|
+
import { buildImage, ImageBuildOps } from "./ImageBuild.ts";
|
|
9
|
+
import { operations } from "./internal.ts";
|
|
10
|
+
|
|
11
|
+
/** The operations the client calls, resolved by `ModalBindings.withCredentials`. */
|
|
12
|
+
const ImagesOps = operations({
|
|
13
|
+
build: ImageBuildOps,
|
|
14
|
+
getByTag: image.imageGetByTag,
|
|
15
|
+
publish: image.publishImage,
|
|
16
|
+
deleteName: image.deleteImageName,
|
|
17
|
+
delete: image.deleteImage,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export type ImagesOps = Effect.Success<typeof ImagesOps>;
|
|
21
|
+
|
|
22
|
+
const toBytes = (data: string | Uint8Array) =>
|
|
23
|
+
Effect.sync(() => (typeof data === "string" ? new TextEncoder().encode(data) : data));
|
|
24
|
+
|
|
25
|
+
/** Build one image from runtime options in `appId`. */
|
|
26
|
+
export const buildFromOptions = Effect.fn(function* (
|
|
27
|
+
ops: ImageBuildOps,
|
|
28
|
+
appId: string,
|
|
29
|
+
options: ImageBuildOptions,
|
|
30
|
+
) {
|
|
31
|
+
// Parsed to normalize it; Modal's builder rejects what it can't run.
|
|
32
|
+
// (The plan-time capability check lives with BuildPlan, which imports the
|
|
33
|
+
// bundler and so stays out of runtime bundles.)
|
|
34
|
+
const parsed =
|
|
35
|
+
options.dockerfile !== undefined
|
|
36
|
+
? yield* DockerfileParser.parse(options.dockerfile)
|
|
37
|
+
: undefined;
|
|
38
|
+
const dockerfile = parsed ? DockerfileParser.renderLines(parsed) : [];
|
|
39
|
+
const extra = options.commands ?? [];
|
|
40
|
+
const commands = [...dockerfile, ...extra];
|
|
41
|
+
const contextFiles = yield* Effect.forEach(
|
|
42
|
+
Object.entries(options.files ?? {}),
|
|
43
|
+
([filename, data]) => Effect.map(toBytes(data), (bytes) => ({ filename, data: bytes })),
|
|
44
|
+
);
|
|
45
|
+
const imageId = yield* buildImage(ops, appId, {
|
|
46
|
+
dockerTag: options.dockerfile
|
|
47
|
+
? undefined
|
|
48
|
+
: options.from
|
|
49
|
+
? undefined
|
|
50
|
+
: (options.image ?? "debian:bookworm-slim"),
|
|
51
|
+
baseImageId: options.dockerfile ? undefined : options.from?.imageId,
|
|
52
|
+
commands,
|
|
53
|
+
contextFiles,
|
|
54
|
+
secretIds: options.secrets?.map((s) => s.secretId),
|
|
55
|
+
gpu: options.gpu,
|
|
56
|
+
forceBuild: options.force,
|
|
57
|
+
});
|
|
58
|
+
return { imageId };
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/** An images client over an app id resolved per call. */
|
|
62
|
+
export const makeImagesClient = (
|
|
63
|
+
appId: Effect.Effect<string>,
|
|
64
|
+
ops: ImagesOps,
|
|
65
|
+
environment: Effect.Effect<string | undefined> = Effect.undefined,
|
|
66
|
+
): ImagesClient => ({
|
|
67
|
+
fromTag: (tag) =>
|
|
68
|
+
Effect.gen(function* () {
|
|
69
|
+
const env = yield* environment;
|
|
70
|
+
const found = yield* ops
|
|
71
|
+
.getByTag({ tag, environmentName: env ?? "" })
|
|
72
|
+
.pipe(Effect.catchTag("ImageNotFound", () => Effect.undefined));
|
|
73
|
+
return found?.imageId ? { imageId: found.imageId } : undefined;
|
|
74
|
+
}),
|
|
75
|
+
publish: (target, tag) =>
|
|
76
|
+
Effect.gen(function* () {
|
|
77
|
+
const env = yield* environment;
|
|
78
|
+
yield* ops.publish({ imageId: target.imageId, tag, environmentName: env ?? "" });
|
|
79
|
+
}),
|
|
80
|
+
unpublish: (tag) =>
|
|
81
|
+
Effect.gen(function* () {
|
|
82
|
+
const env = yield* environment;
|
|
83
|
+
// Modal deletes only an explicit `name:tag`; a bare name is `name:latest`.
|
|
84
|
+
const named = /:[^/]*$/.test(tag) ? tag : `${tag}:latest`;
|
|
85
|
+
yield* ops
|
|
86
|
+
.deleteName({ tag: env ? `${env}/${named}` : named })
|
|
87
|
+
.pipe(Effect.catchTag("ImageNotFound", () => Effect.void));
|
|
88
|
+
}),
|
|
89
|
+
build: (options) => Effect.flatMap(appId, (id) => buildFromOptions(ops.build, id, options)),
|
|
90
|
+
delete: (target) =>
|
|
91
|
+
ops.delete({ imageId: target.imageId }).pipe(
|
|
92
|
+
Effect.catchTag("ImageNotFound", () => Effect.void),
|
|
93
|
+
Effect.asVoid,
|
|
94
|
+
),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* {@link CreateImage} over Modal's API. Grants the host's identity (a scoped
|
|
99
|
+
* `Modal.ServiceUser`) the `contributor` role on the App's environment.
|
|
100
|
+
*
|
|
101
|
+
* @layer
|
|
102
|
+
* @product Image
|
|
103
|
+
* @provides Modal.CreateImage
|
|
104
|
+
*/
|
|
105
|
+
export const CreateImageHttp = Layer.effect(
|
|
106
|
+
CreateImage,
|
|
107
|
+
makeModalBinding({
|
|
108
|
+
tag: "Modal.CreateImage",
|
|
109
|
+
operations: ImagesOps,
|
|
110
|
+
role: "contributor",
|
|
111
|
+
make: Effect.fn(function* (app: App, ops) {
|
|
112
|
+
const appId = yield* app.appId;
|
|
113
|
+
const environment = yield* app.environment;
|
|
114
|
+
return makeImagesClient(appId, ops, environment);
|
|
115
|
+
}),
|
|
116
|
+
}),
|
|
117
|
+
);
|