@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.
- package/LICENSE +201 -0
- package/README.md +96 -4
- 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 +59 -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,373 @@
|
|
|
1
|
+
import * as environment from "@distilled.cloud/modal/environment";
|
|
2
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
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 { isGeneratedName, objectName } from "./internal.ts";
|
|
8
|
+
import { declarable } from "./internal/Declared.ts";
|
|
9
|
+
import type { Providers } from "./Providers.ts";
|
|
10
|
+
|
|
11
|
+
export class EnvironmentUnexpectedResponse extends Data.TaggedError(
|
|
12
|
+
"Modal.EnvironmentUnexpectedResponse",
|
|
13
|
+
)<{
|
|
14
|
+
readonly message: string;
|
|
15
|
+
}> {}
|
|
16
|
+
|
|
17
|
+
/** A member's access to an environment. */
|
|
18
|
+
export type EnvironmentRole = "viewer" | "contributor" | "no-access";
|
|
19
|
+
|
|
20
|
+
const ROLE_TO_WIRE = {
|
|
21
|
+
viewer: "ENVIRONMENT_ROLE_VIEWER",
|
|
22
|
+
contributor: "ENVIRONMENT_ROLE_CONTRIBUTOR",
|
|
23
|
+
"no-access": "ENVIRONMENT_ROLE_NO_ACCESS",
|
|
24
|
+
} as const satisfies Record<EnvironmentRole, environment.EnvironmentRole>;
|
|
25
|
+
|
|
26
|
+
const roleFromWire = (role: string | undefined): EnvironmentRole | undefined =>
|
|
27
|
+
(Object.keys(ROLE_TO_WIRE) as EnvironmentRole[]).find((key) => ROLE_TO_WIRE[key] === role);
|
|
28
|
+
|
|
29
|
+
/** One role assignment: a workspace member or service user, and its role. */
|
|
30
|
+
export type EnvironmentRoleAssignment =
|
|
31
|
+
| { readonly userId: string; readonly role: EnvironmentRole }
|
|
32
|
+
| { readonly serviceUserId: string; readonly role: EnvironmentRole };
|
|
33
|
+
|
|
34
|
+
export interface EnvironmentProps {
|
|
35
|
+
/**
|
|
36
|
+
* Environment name, unique in the workspace. If omitted, a unique name is
|
|
37
|
+
* generated from the stack, stage and logical ID. Changing it renames the
|
|
38
|
+
* environment in place.
|
|
39
|
+
*/
|
|
40
|
+
name?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Suffix of web endpoint URLs in this environment
|
|
43
|
+
* (`<workspace>-<suffix>--<app>.modal.run`).
|
|
44
|
+
* @default the environment name
|
|
45
|
+
*/
|
|
46
|
+
webhookSuffix?: string;
|
|
47
|
+
/** Most tasks (containers) running at once in this environment. */
|
|
48
|
+
maxConcurrentTasks?: number;
|
|
49
|
+
/** Most GPUs in use at once in this environment. */
|
|
50
|
+
maxConcurrentGpus?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Monthly spend limit in US dollars for this environment. Removing it
|
|
53
|
+
* clears the limit. Budgets need a Modal plan that includes them;
|
|
54
|
+
* elsewhere the deploy fails with `EnvironmentBudgetsNotEnabled`.
|
|
55
|
+
*/
|
|
56
|
+
budget?: number;
|
|
57
|
+
/**
|
|
58
|
+
* Require authentication for web endpoints and tunnels in this
|
|
59
|
+
* environment: `true` blocks unauthenticated traffic, `false` allows it,
|
|
60
|
+
* and `undefined` inherits the workspace default.
|
|
61
|
+
*/
|
|
62
|
+
blockUnauthenticatedResources?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Restrict the environment to explicit members (a managed environment).
|
|
65
|
+
* Members without an assignment in {@link roles} get
|
|
66
|
+
* {@link defaultMemberRole}.
|
|
67
|
+
* @default false
|
|
68
|
+
*/
|
|
69
|
+
managed?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Role every workspace member gets in a managed environment unless
|
|
72
|
+
* {@link roles} assigns one.
|
|
73
|
+
*/
|
|
74
|
+
defaultMemberRole?: EnvironmentRole;
|
|
75
|
+
/**
|
|
76
|
+
* Explicit role assignments. Each listed principal gets its role; a
|
|
77
|
+
* principal that was assigned before and is no longer listed falls back
|
|
78
|
+
* to {@link defaultMemberRole}.
|
|
79
|
+
*/
|
|
80
|
+
roles?: EnvironmentRoleAssignment[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface EnvironmentAttributes {
|
|
84
|
+
/** Environment ID (`en-…`). */
|
|
85
|
+
environmentId: string;
|
|
86
|
+
/** Environment name. */
|
|
87
|
+
name: string;
|
|
88
|
+
/** Suffix of web endpoint URLs in this environment. */
|
|
89
|
+
webhookSuffix: string | undefined;
|
|
90
|
+
/** Whether this is the workspace's default environment. */
|
|
91
|
+
isDefault: boolean;
|
|
92
|
+
/** Whether membership is restricted (a managed environment). */
|
|
93
|
+
managed: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A Modal Environment: an isolated namespace inside a workspace for Apps,
|
|
98
|
+
* Volumes, Dicts, Queues, Secrets and Sandboxes, with its own concurrency
|
|
99
|
+
* limits, spend budget and member roles. Objects with the same name in two
|
|
100
|
+
* environments are different objects, so one environment per stage keeps
|
|
101
|
+
* stages apart.
|
|
102
|
+
*
|
|
103
|
+
* Modal environments have no tags. Ownership is inferred from Alchemy
|
|
104
|
+
* state: an environment found under an explicit `name` without prior state
|
|
105
|
+
* is reported as unowned.
|
|
106
|
+
*
|
|
107
|
+
* ### Creating an Environment
|
|
108
|
+
* **Example:** One environment per stage
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
111
|
+
*
|
|
112
|
+
* export const Agents = Modal.Environment("Agents", {});
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* **Example:** Limits and a monthly budget
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
118
|
+
*
|
|
119
|
+
* export const Agents = Modal.Environment("Agents", {
|
|
120
|
+
* maxConcurrentTasks: 50,
|
|
121
|
+
* maxConcurrentGpus: 4,
|
|
122
|
+
* budget: 200,
|
|
123
|
+
* });
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* ### Access control
|
|
127
|
+
* **Example:** A managed environment with explicit roles
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
130
|
+
*
|
|
131
|
+
* export const Production = Modal.Environment("Production", {
|
|
132
|
+
* name: "production",
|
|
133
|
+
* managed: true,
|
|
134
|
+
* defaultMemberRole: "viewer",
|
|
135
|
+
* roles: [{ userId: "us-1234", role: "contributor" }],
|
|
136
|
+
* blockUnauthenticatedResources: true,
|
|
137
|
+
* });
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* ### Using the environment
|
|
141
|
+
* **Example:** Put objects in it
|
|
142
|
+
* ```typescript
|
|
143
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
144
|
+
*
|
|
145
|
+
* export const Agents = Modal.Environment("Agents", {});
|
|
146
|
+
* export const Coder = Modal.App("Coder", { environment: Agents });
|
|
147
|
+
* export const Workspace = Modal.Volume("Workspace", { environment: Agents });
|
|
148
|
+
* ```
|
|
149
|
+
*
|
|
150
|
+
* ### Looking up an existing environment
|
|
151
|
+
* `Environment.lookup` references an environment Alchemy doesn't manage (created with
|
|
152
|
+
* the Modal CLI or by another stack). It is read during plan/deploy, never
|
|
153
|
+
* created, updated or deleted.
|
|
154
|
+
*
|
|
155
|
+
* **Example:** Reference an existing environment
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const staging = Modal.Environment.lookup({ name: "staging" });
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* @resource
|
|
161
|
+
* @product Environment
|
|
162
|
+
*/
|
|
163
|
+
export const Environment = declarable<Environment>()(Resource<Environment>("Modal.Environment"));
|
|
164
|
+
|
|
165
|
+
export type Environment = Resource<
|
|
166
|
+
"Modal.Environment",
|
|
167
|
+
EnvironmentProps,
|
|
168
|
+
EnvironmentAttributes,
|
|
169
|
+
never,
|
|
170
|
+
Providers,
|
|
171
|
+
EnvironmentLookup
|
|
172
|
+
>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Props for {@link Environment.lookup}: find an environment this
|
|
176
|
+
* stack doesn't manage by its name.
|
|
177
|
+
*/
|
|
178
|
+
export interface EnvironmentLookup {
|
|
179
|
+
/** Environment name. */
|
|
180
|
+
name: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const blockToWire = (
|
|
184
|
+
value: boolean | undefined,
|
|
185
|
+
): environment.EnvironmentBlockUnauthenticatedResources =>
|
|
186
|
+
value === undefined
|
|
187
|
+
? "ENVIRONMENT_BLOCK_UNAUTHENTICATED_RESOURCES_INHERIT"
|
|
188
|
+
: value
|
|
189
|
+
? "ENVIRONMENT_BLOCK_UNAUTHENTICATED_RESOURCES_BLOCK"
|
|
190
|
+
: "ENVIRONMENT_BLOCK_UNAUTHENTICATED_RESOURCES_ALLOW";
|
|
191
|
+
|
|
192
|
+
const principalKey = (p: { userId?: string; serviceUserId?: string }) =>
|
|
193
|
+
p.userId ? `user:${p.userId}` : `service:${p.serviceUserId ?? ""}`;
|
|
194
|
+
|
|
195
|
+
export const EnvironmentProvider = () =>
|
|
196
|
+
Provider.effect(
|
|
197
|
+
Environment,
|
|
198
|
+
Effect.gen(function* () {
|
|
199
|
+
const observe = Effect.fn(function* (name: string) {
|
|
200
|
+
const { items } = yield* environment.listEnvironment({});
|
|
201
|
+
return (items ?? []).find((item) => item.name === name);
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const toAttrs = (item: environment.EnvironmentListItem): EnvironmentAttributes => ({
|
|
205
|
+
environmentId: item.environmentId ?? "",
|
|
206
|
+
name: item.name ?? "",
|
|
207
|
+
webhookSuffix: item.webhookSuffix || undefined,
|
|
208
|
+
isDefault: item.default ?? false,
|
|
209
|
+
managed: item.isManaged ?? false,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
stables: ["environmentId"],
|
|
214
|
+
lookup: Effect.fn(function* ({ name }) {
|
|
215
|
+
const item = yield* observe(name);
|
|
216
|
+
return item ? toAttrs(item) : undefined;
|
|
217
|
+
}),
|
|
218
|
+
|
|
219
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
220
|
+
const name = output?.name ?? (yield* objectName(id, olds?.name));
|
|
221
|
+
const item = yield* observe(name);
|
|
222
|
+
if (!item) return undefined;
|
|
223
|
+
const attrs = toAttrs(item);
|
|
224
|
+
return output !== undefined || olds?.name === undefined ? attrs : Unowned(attrs);
|
|
225
|
+
}),
|
|
226
|
+
reconcile: Effect.fn(function* ({ id, news, output, session }) {
|
|
227
|
+
const desiredName = yield* objectName(id, news.name);
|
|
228
|
+
|
|
229
|
+
// Observe: by the previous name (a rename) and the desired name.
|
|
230
|
+
let current =
|
|
231
|
+
(output !== undefined && output.name !== desiredName
|
|
232
|
+
? yield* observe(output.name)
|
|
233
|
+
: undefined) ?? (yield* observe(desiredName));
|
|
234
|
+
|
|
235
|
+
// Ensure
|
|
236
|
+
if (!current) {
|
|
237
|
+
yield* session.note(`Creating environment ${desiredName}...`);
|
|
238
|
+
yield* environment
|
|
239
|
+
.createEnvironment({
|
|
240
|
+
name: desiredName,
|
|
241
|
+
isManaged: news.managed,
|
|
242
|
+
defaultMemberRole: news.defaultMemberRole
|
|
243
|
+
? ROLE_TO_WIRE[news.defaultMemberRole]
|
|
244
|
+
: undefined,
|
|
245
|
+
})
|
|
246
|
+
.pipe(Effect.catchTag("EnvironmentAlreadyExists", () => Effect.void));
|
|
247
|
+
current = yield* observe(desiredName);
|
|
248
|
+
if (!current) {
|
|
249
|
+
return yield* new EnvironmentUnexpectedResponse({
|
|
250
|
+
message: `Modal environment ${desiredName} was not listed after create`,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Sync name, suffix, limits and the unauthenticated-resources policy.
|
|
256
|
+
const desiredBlock = blockToWire(news.blockUnauthenticatedResources);
|
|
257
|
+
const observedBlock = blockToWire(current.blockUnauthenticatedResources);
|
|
258
|
+
if (
|
|
259
|
+
current.name !== desiredName ||
|
|
260
|
+
(news.webhookSuffix !== undefined && current.webhookSuffix !== news.webhookSuffix) ||
|
|
261
|
+
(news.maxConcurrentTasks !== undefined &&
|
|
262
|
+
current.maxConcurrentTasks !== news.maxConcurrentTasks) ||
|
|
263
|
+
(news.maxConcurrentGpus !== undefined &&
|
|
264
|
+
current.maxConcurrentGpus !== news.maxConcurrentGpus) ||
|
|
265
|
+
(news.blockUnauthenticatedResources !== undefined && desiredBlock !== observedBlock)
|
|
266
|
+
) {
|
|
267
|
+
yield* environment.updateEnvironment({
|
|
268
|
+
currentName: current.name,
|
|
269
|
+
name: desiredName,
|
|
270
|
+
webSuffix: news.webhookSuffix,
|
|
271
|
+
maxConcurrentTasks: news.maxConcurrentTasks,
|
|
272
|
+
maxConcurrentGpus: news.maxConcurrentGpus,
|
|
273
|
+
blockUnauthenticatedResources:
|
|
274
|
+
news.blockUnauthenticatedResources === undefined ? undefined : desiredBlock,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
const environmentId = current.environmentId ?? "";
|
|
278
|
+
|
|
279
|
+
// Sync budget against the observed limit. A workspace without
|
|
280
|
+
// budgets has none to clear; asking for one there fails with
|
|
281
|
+
// `EnvironmentBudgetsNotEnabled`.
|
|
282
|
+
const budget = yield* environment
|
|
283
|
+
.environmentGetBudget({ environmentId })
|
|
284
|
+
.pipe(
|
|
285
|
+
Effect.catchTag("EnvironmentBudgetsNotEnabled", () =>
|
|
286
|
+
Effect.succeed<Partial<environment.EnvironmentGetBudgetResponse>>({}),
|
|
287
|
+
),
|
|
288
|
+
);
|
|
289
|
+
if (news.budget !== undefined && budget.cycleBudgetDollars !== news.budget) {
|
|
290
|
+
yield* environment.environmentSetBudget({
|
|
291
|
+
environmentId,
|
|
292
|
+
cycleBudgetDollars: news.budget,
|
|
293
|
+
});
|
|
294
|
+
} else if (news.budget === undefined && budget.cycleBudgetDollars !== undefined) {
|
|
295
|
+
yield* environment.environmentSetBudget({ environmentId, clearBudget: true });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Sync managed mode and the default member role.
|
|
299
|
+
const managed = news.managed ?? false;
|
|
300
|
+
if ((current.isManaged ?? false) !== managed) {
|
|
301
|
+
yield* environment.environmentSetManaged({
|
|
302
|
+
environmentId,
|
|
303
|
+
managed,
|
|
304
|
+
defaultMemberRole: news.defaultMemberRole
|
|
305
|
+
? ROLE_TO_WIRE[news.defaultMemberRole]
|
|
306
|
+
: undefined,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (
|
|
310
|
+
news.defaultMemberRole !== undefined &&
|
|
311
|
+
roleFromWire(current.defaultMemberRole) !== news.defaultMemberRole
|
|
312
|
+
) {
|
|
313
|
+
yield* environment.environmentSetDefaultMemberRole({
|
|
314
|
+
environmentId,
|
|
315
|
+
defaultMemberRole: ROLE_TO_WIRE[news.defaultMemberRole],
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Sync explicit role assignments against the observed principals:
|
|
320
|
+
// listed principals get their role, and any other principal with
|
|
321
|
+
// an explicit assignment falls back to the default member role.
|
|
322
|
+
if (news.roles !== undefined) {
|
|
323
|
+
const observed = yield* environment.environmentGetRoles({ environmentId });
|
|
324
|
+
const principals = observed.principalRoles ?? [];
|
|
325
|
+
const desired = new Map(
|
|
326
|
+
news.roles.map((assignment) => [principalKey(assignment), assignment]),
|
|
327
|
+
);
|
|
328
|
+
for (const assignment of desired.values()) {
|
|
329
|
+
const match = principals.find((p) => principalKey(p) === principalKey(assignment));
|
|
330
|
+
if (
|
|
331
|
+
match === undefined ||
|
|
332
|
+
match.hasRoleAssignment !== true ||
|
|
333
|
+
roleFromWire(match.role) !== assignment.role
|
|
334
|
+
) {
|
|
335
|
+
yield* environment.setEnvironmentRole({
|
|
336
|
+
environmentId,
|
|
337
|
+
...("userId" in assignment
|
|
338
|
+
? { userId: assignment.userId }
|
|
339
|
+
: { serviceUserId: assignment.serviceUserId }),
|
|
340
|
+
role: ROLE_TO_WIRE[assignment.role],
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
for (const principal of principals) {
|
|
345
|
+
if (principal.hasRoleAssignment !== true || desired.has(principalKey(principal))) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
yield* environment.setEnvironmentRole({
|
|
349
|
+
environmentId,
|
|
350
|
+
userId: principal.userId || undefined,
|
|
351
|
+
serviceUserId: principal.serviceUserId || undefined,
|
|
352
|
+
role: "ENVIRONMENT_ROLE_UNSPECIFIED",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const final = yield* observe(desiredName);
|
|
358
|
+
return toAttrs(final ?? current);
|
|
359
|
+
}),
|
|
360
|
+
delete: Effect.fn(function* ({ output }) {
|
|
361
|
+
yield* environment
|
|
362
|
+
.deleteEnvironment({ name: output.name })
|
|
363
|
+
.pipe(Effect.catchTag("EnvironmentNotFound", () => Effect.void));
|
|
364
|
+
}),
|
|
365
|
+
list: Effect.fn(function* () {
|
|
366
|
+
const { items } = yield* environment.listEnvironment({});
|
|
367
|
+
return (items ?? [])
|
|
368
|
+
.filter((item) => !item.default && isGeneratedName(item.name))
|
|
369
|
+
.map(toAttrs);
|
|
370
|
+
}),
|
|
371
|
+
};
|
|
372
|
+
}),
|
|
373
|
+
);
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import type { Input } from "alchemy/Input";
|
|
3
|
+
import type { Rpc } from "alchemy/Rpc";
|
|
4
|
+
import type { RuntimeContext } from "alchemy/RuntimeContext";
|
|
5
|
+
import type * as Effect from "effect/Effect";
|
|
6
|
+
import type * as HttpClientError from "effect/http/HttpClientError";
|
|
7
|
+
import type * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
8
|
+
import type * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
9
|
+
import type { Endpoint } from "./Endpoint.ts";
|
|
10
|
+
import type { ServerUrlMissing } from "./FetchServerHttp.ts";
|
|
11
|
+
import type { Function } from "./Function.ts";
|
|
12
|
+
import type { Server } from "./Server.ts";
|
|
13
|
+
|
|
14
|
+
/** Send requests to a deployed Modal Server, web Function or model Endpoint. */
|
|
15
|
+
export interface ServerClient {
|
|
16
|
+
/** The server's URL. */
|
|
17
|
+
readonly url: Effect.Effect<string, ServerUrlMissing, RuntimeContext>;
|
|
18
|
+
/**
|
|
19
|
+
* Send a request: its path and query are kept, the host is the server's,
|
|
20
|
+
* and Modal's proxy auth headers are added.
|
|
21
|
+
*/
|
|
22
|
+
fetch(
|
|
23
|
+
request: HttpClientRequest.HttpClientRequest,
|
|
24
|
+
): Effect.Effect<
|
|
25
|
+
HttpClientResponse.HttpClientResponse,
|
|
26
|
+
ServerUrlMissing | HttpClientError.HttpClientError,
|
|
27
|
+
RuntimeContext
|
|
28
|
+
>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The client {@link FetchServer} returns: `url` and `fetch`, plus the RPC
|
|
33
|
+
* methods of a `Modal.Server` program (everything it returns besides
|
|
34
|
+
* `fetch` and `run`).
|
|
35
|
+
*/
|
|
36
|
+
export type FetchClient<Shape> = ServerClient & Omit<Shape, "fetch" | "run" | "url">;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Call a `Modal.Server`, a `Modal.Function` with `web`, or a model
|
|
40
|
+
* `Modal.Endpoint` from any runtime. Servers and endpoints require Modal's
|
|
41
|
+
* proxy auth by default: the binding creates a `Modal.WebhookToken` for the
|
|
42
|
+
* host and sends its `Modal-Key` / `Modal-Secret` headers with every request.
|
|
43
|
+
*
|
|
44
|
+
* A `Modal.Server` program's RPC methods come back on the client too. Each
|
|
45
|
+
* call is a `POST /__rpc__/<method>` to the Server through Modal's proxy,
|
|
46
|
+
* with the arguments and result as JSON; a method that returns a `Stream`
|
|
47
|
+
* streams. The binding gives the host its own key for the Server, which
|
|
48
|
+
* every method call carries: the Server answers methods only for callers
|
|
49
|
+
* bound to it. It serves them only behind proxy auth, so an
|
|
50
|
+
* `unauthenticated` Server answers them with `404`.
|
|
51
|
+
*
|
|
52
|
+
* ### Call a Server
|
|
53
|
+
* **Example:** From a Cloudflare Worker
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import * as Cloudflare from "@alchemy.run/cloudflare";
|
|
56
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
57
|
+
* import * as Effect from "effect/Effect";
|
|
58
|
+
* import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
59
|
+
* import * as HttpServerResponse from "effect/http/HttpServerResponse";
|
|
60
|
+
* import Api from "./Api.ts";
|
|
61
|
+
*
|
|
62
|
+
* export default class Gateway extends Cloudflare.Worker<Gateway>()(
|
|
63
|
+
* "Gateway",
|
|
64
|
+
* { main: import.meta.url },
|
|
65
|
+
* Effect.gen(function* () {
|
|
66
|
+
* const api = yield* Modal.FetchServer(Api);
|
|
67
|
+
* return {
|
|
68
|
+
* fetch: Effect.gen(function* () {
|
|
69
|
+
* const response = yield* api.fetch(HttpClientRequest.get("/health"));
|
|
70
|
+
* return HttpServerResponse.text(yield* response.text, { status: response.status });
|
|
71
|
+
* }).pipe(Effect.orDie),
|
|
72
|
+
* };
|
|
73
|
+
* }).pipe(Effect.provide(Modal.FetchServerHttp)),
|
|
74
|
+
* ) {}
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* ### Call a Server's methods
|
|
78
|
+
* **Example:** RPC methods next to `fetch`
|
|
79
|
+
* ```typescript
|
|
80
|
+
* // src/Api.ts
|
|
81
|
+
* export default class Api extends Modal.Server<Api>()(
|
|
82
|
+
* "Api",
|
|
83
|
+
* { main: import.meta.url, app: Backend },
|
|
84
|
+
* Effect.gen(function* () {
|
|
85
|
+
* return {
|
|
86
|
+
* greet: Effect.fn(function* (name: string) {
|
|
87
|
+
* return `hello ${name}`;
|
|
88
|
+
* }),
|
|
89
|
+
* fetch: Effect.succeed(HttpServerResponse.text("ok")),
|
|
90
|
+
* };
|
|
91
|
+
* }),
|
|
92
|
+
* ) {}
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* **Example:** Call them from a Cloudflare Worker
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const api = yield* Modal.FetchServer(Api);
|
|
98
|
+
* const greeting = yield* api.greet("modal");
|
|
99
|
+
* ```
|
|
100
|
+
*
|
|
101
|
+
* @binding
|
|
102
|
+
* @product Server
|
|
103
|
+
*/
|
|
104
|
+
export interface FetchServer extends Binding.Service<
|
|
105
|
+
FetchServer,
|
|
106
|
+
"Modal.FetchServer",
|
|
107
|
+
(server: Server | Function | Endpoint) => Effect.Effect<ServerClient>
|
|
108
|
+
> {}
|
|
109
|
+
|
|
110
|
+
/** FetchServer's call signatures, typed from the target's program. */
|
|
111
|
+
export interface FetchServerCall {
|
|
112
|
+
/** A `Modal.Server` of the Stack: `url`, `fetch` and its program's RPC methods. */
|
|
113
|
+
<Shape, Req = never>(
|
|
114
|
+
server: (Server & Rpc<Shape>) | Effect.Effect<Server & Rpc<Shape>, never, Req>,
|
|
115
|
+
): Effect.Effect<FetchClient<Shape>, never, FetchServer | Req>;
|
|
116
|
+
/** A web Function, a model Endpoint, or an async Server: `url` and `fetch`. */
|
|
117
|
+
<Req = never>(
|
|
118
|
+
server:
|
|
119
|
+
| Input<Server | Function | Endpoint>
|
|
120
|
+
| Effect.Effect<Server | Function | Endpoint, never, Req>,
|
|
121
|
+
): Effect.Effect<ServerClient, never, FetchServer | Req>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const FetchServer = Binding.Service<FetchServer>(
|
|
125
|
+
"Modal.FetchServer",
|
|
126
|
+
) as unknown as FetchServerCall & FetchServer;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as Binding from "alchemy/Binding";
|
|
2
|
+
import { makeFetchRpcStub } from "alchemy/Rpc";
|
|
3
|
+
import { CurrentRuntimeContext } from "alchemy/RuntimeContext";
|
|
4
|
+
import * as Data from "effect/Data";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as HttpClient from "effect/http/HttpClient";
|
|
7
|
+
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
8
|
+
import * as Layer from "effect/Layer";
|
|
9
|
+
import * as Redacted from "effect/Redacted";
|
|
10
|
+
import type { Endpoint } from "./Endpoint.ts";
|
|
11
|
+
import { FetchServer, type ServerClient } from "./FetchServer.ts";
|
|
12
|
+
import type { Function } from "./Function.ts";
|
|
13
|
+
import { RPC_KEY_HEADER, RpcCaller } from "./internal/RpcAuth.ts";
|
|
14
|
+
import * as ModalBindings from "./ModalBindings.ts";
|
|
15
|
+
import type { Server } from "./Server.ts";
|
|
16
|
+
import { WebhookToken } from "./WebhookToken.ts";
|
|
17
|
+
|
|
18
|
+
/** The server has no URL (a Function without `web`, or a deploy still in progress). */
|
|
19
|
+
export class ServerUrlMissing extends Data.TaggedError("Modal.ServerUrlMissing")<{
|
|
20
|
+
readonly message: string;
|
|
21
|
+
}> {}
|
|
22
|
+
|
|
23
|
+
/** Env the host's proxy auth token is bound under. */
|
|
24
|
+
const PROXY_ENV = { key: "MODAL_PROXY_KEY", secret: "MODAL_PROXY_SECRET" } as const;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* {@link FetchServer} over HTTP. Creates one `Modal.WebhookToken` per host
|
|
28
|
+
* (`<host>ProxyAuth`) and binds its header pair into the host's env.
|
|
29
|
+
*
|
|
30
|
+
* @layer
|
|
31
|
+
* @product Server
|
|
32
|
+
* @provides Modal.FetchServer
|
|
33
|
+
*/
|
|
34
|
+
export const FetchServerHttp = Layer.effect(
|
|
35
|
+
FetchServer,
|
|
36
|
+
Effect.gen(function* () {
|
|
37
|
+
// No Modal API calls: the client only needs the host's HTTP client.
|
|
38
|
+
const http = yield* ModalBindings.withCredentials(HttpClient.HttpClient);
|
|
39
|
+
const bind = yield* ModalBindings.Bind;
|
|
40
|
+
const runtime = yield* CurrentRuntimeContext;
|
|
41
|
+
// Deploy only: a host bundle never creates the token.
|
|
42
|
+
const Token = globalThis.__ALCHEMY_RUNTIME__ ? undefined : yield* WebhookToken;
|
|
43
|
+
const caller = yield* RpcCaller;
|
|
44
|
+
|
|
45
|
+
return Effect.fn("Modal.FetchServer")(function* (server: Server | Function | Endpoint) {
|
|
46
|
+
if (!globalThis.__ALCHEMY_RUNTIME__) {
|
|
47
|
+
const host = yield* Binding.Host;
|
|
48
|
+
if (host !== undefined && Token !== undefined) {
|
|
49
|
+
const token = yield* Token(`${host.LogicalId}ProxyAuth`, {});
|
|
50
|
+
yield* bind`Modal.FetchServer(${server})`({
|
|
51
|
+
env: { [PROXY_ENV.key]: token.tokenId, [PROXY_ENV.secret]: token.tokenSecret },
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// This host's key for the Server's RPC methods (minted at deploy).
|
|
56
|
+
const key = yield* caller(server);
|
|
57
|
+
const url = yield* server.url;
|
|
58
|
+
const resolvedUrl = Effect.flatMap(url, (value) =>
|
|
59
|
+
value
|
|
60
|
+
? Effect.succeed(value)
|
|
61
|
+
: Effect.fail(
|
|
62
|
+
new ServerUrlMissing({
|
|
63
|
+
message:
|
|
64
|
+
"The server has no URL: deploy it as a Modal.Server, a Modal.Function with web, or a Modal.Endpoint",
|
|
65
|
+
}),
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
const headers = Effect.gen(function* () {
|
|
69
|
+
if (runtime === undefined) return {};
|
|
70
|
+
const key = yield* runtime.get<string>(PROXY_ENV.key);
|
|
71
|
+
const secret = yield* runtime.get<string | Redacted.Redacted<string>>(PROXY_ENV.secret);
|
|
72
|
+
if (key === undefined || secret === undefined) return {};
|
|
73
|
+
return {
|
|
74
|
+
"Modal-Key": key,
|
|
75
|
+
"Modal-Secret": Redacted.isRedacted(secret) ? Redacted.value(secret) : secret,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
const client = {
|
|
79
|
+
url: resolvedUrl,
|
|
80
|
+
fetch: (request) =>
|
|
81
|
+
Effect.gen(function* () {
|
|
82
|
+
const base = yield* resolvedUrl;
|
|
83
|
+
const target = new URL(request.url, "http://server");
|
|
84
|
+
// The Stack's own deployed server (allowed raw HTTP).
|
|
85
|
+
return yield* http.execute(
|
|
86
|
+
request.pipe(
|
|
87
|
+
HttpClientRequest.setUrl(
|
|
88
|
+
`${base.replace(/\/$/, "")}${target.pathname}${target.search}`,
|
|
89
|
+
),
|
|
90
|
+
HttpClientRequest.setHeaders(yield* headers),
|
|
91
|
+
),
|
|
92
|
+
);
|
|
93
|
+
}),
|
|
94
|
+
} satisfies ServerClient;
|
|
95
|
+
// Every other member is an RPC method of the Server's program.
|
|
96
|
+
return makeFetchRpcStub<ServerClient>({
|
|
97
|
+
// RPC calls carry the key; the Server serves only callers it issued keys to.
|
|
98
|
+
fetch: (request) =>
|
|
99
|
+
Effect.flatMap(key, (value) =>
|
|
100
|
+
client.fetch(
|
|
101
|
+
value === undefined
|
|
102
|
+
? request
|
|
103
|
+
: request.pipe(HttpClientRequest.setHeader(RPC_KEY_HEADER, value)),
|
|
104
|
+
),
|
|
105
|
+
),
|
|
106
|
+
base: client,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}),
|
|
110
|
+
);
|