@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,83 @@
|
|
|
1
|
+
import * as secret from "@distilled.cloud/modal/secret";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { makeOpenModalBinding } from "./BindingHttp.ts";
|
|
5
|
+
import { CreateSecret, type SecretsClientOf } from "./CreateSecret.ts";
|
|
6
|
+
import type { Environment } from "./Environment.ts";
|
|
7
|
+
import { environmentOf, listAll, operations } from "./internal.ts";
|
|
8
|
+
import { ownedName, type RuntimeOwner, RuntimeOwnerOf, unownedName } from "./RuntimeOwner.ts";
|
|
9
|
+
import { lookupSecret, putSecret } from "./Secret.ts";
|
|
10
|
+
|
|
11
|
+
/** The operations the client calls, resolved by `ModalBindings.withCredentials`. */
|
|
12
|
+
export const SecretsOps = operations({
|
|
13
|
+
getOrCreate: secret.secretGetOrCreate,
|
|
14
|
+
delete: secret.deleteSecret,
|
|
15
|
+
list: secret.listSecret,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export type SecretsOps = Effect.Success<typeof SecretsOps>;
|
|
19
|
+
|
|
20
|
+
/** A secrets client over an environment name resolved per call. */
|
|
21
|
+
export const makeSecretsClient = (
|
|
22
|
+
environment: Effect.Effect<string | undefined>,
|
|
23
|
+
ops: SecretsOps,
|
|
24
|
+
owner: Effect.Effect<RuntimeOwner | undefined> = Effect.undefined,
|
|
25
|
+
): SecretsClientOf<never> => ({
|
|
26
|
+
put: (name, env) =>
|
|
27
|
+
Effect.flatMap(Effect.all([environment, owner]), ([e, stamp]) =>
|
|
28
|
+
putSecret(ops.getOrCreate, ownedName(stamp, name), e, env),
|
|
29
|
+
),
|
|
30
|
+
get: (name) =>
|
|
31
|
+
Effect.flatMap(Effect.all([environment, owner]), ([e, stamp]) =>
|
|
32
|
+
lookupSecret(ops.getOrCreate, ownedName(stamp, name), e),
|
|
33
|
+
),
|
|
34
|
+
delete: (name) =>
|
|
35
|
+
Effect.gen(function* () {
|
|
36
|
+
const env = yield* environment;
|
|
37
|
+
const found = yield* lookupSecret(ops.getOrCreate, ownedName(yield* owner, name), env);
|
|
38
|
+
if (!found) return;
|
|
39
|
+
yield* ops
|
|
40
|
+
.delete({ secretId: found.secretId })
|
|
41
|
+
.pipe(Effect.catchTag("SecretNotFound", () => Effect.void));
|
|
42
|
+
}),
|
|
43
|
+
list: () =>
|
|
44
|
+
Effect.gen(function* () {
|
|
45
|
+
const env = yield* environment;
|
|
46
|
+
const stamp = yield* owner;
|
|
47
|
+
const items = yield* listAll(
|
|
48
|
+
(pagination) =>
|
|
49
|
+
ops
|
|
50
|
+
.list({ environmentName: environmentOf(env), pagination })
|
|
51
|
+
.pipe(Effect.map((response) => response.items ?? [])),
|
|
52
|
+
(item) => item.createdAt,
|
|
53
|
+
);
|
|
54
|
+
return items.flatMap((item) => {
|
|
55
|
+
const name = item.label ?? item.metadata?.name;
|
|
56
|
+
const own = name ? unownedName(stamp, name) : undefined;
|
|
57
|
+
return own ? [own] : [];
|
|
58
|
+
});
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* {@link CreateSecret} over Modal's API. Grants the host's identity (a scoped
|
|
64
|
+
* `Modal.ServiceUser`) the `contributor` role on the environment.
|
|
65
|
+
*
|
|
66
|
+
* @layer
|
|
67
|
+
* @product Secret
|
|
68
|
+
* @provides Modal.CreateSecret
|
|
69
|
+
*/
|
|
70
|
+
export const CreateSecretHttp = Layer.effect(
|
|
71
|
+
CreateSecret,
|
|
72
|
+
makeOpenModalBinding({
|
|
73
|
+
tag: "Modal.CreateSecret",
|
|
74
|
+
operations: SecretsOps,
|
|
75
|
+
role: "contributor",
|
|
76
|
+
environmentOf: (environment?: Environment) => environment?.name,
|
|
77
|
+
make: Effect.fn(function* (ops, environment?: Environment) {
|
|
78
|
+
const name = environment ? yield* environment.name : Effect.undefined;
|
|
79
|
+
const owner = yield* RuntimeOwnerOf();
|
|
80
|
+
return makeSecretsClient(name, ops, owner);
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
);
|
|
@@ -0,0 +1,96 @@
|
|
|
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 { VolumesOps } from "./CreateVolumeHttp.ts";
|
|
5
|
+
import type { Environment } from "./Environment.ts";
|
|
6
|
+
import type { ErrorOf, OpError } from "./internal.ts";
|
|
7
|
+
import type { ensureVolume, lookupVolume } from "./Volume.ts";
|
|
8
|
+
import type { VolumeAttributes } from "./Volume.ts";
|
|
9
|
+
import type { ReadWriteVolumeClient } from "./VolumeClient.ts";
|
|
10
|
+
|
|
11
|
+
/** A volume created or found at runtime: its attributes plus a read-write client. */
|
|
12
|
+
export interface VolumeHandle extends ReadWriteVolumeClient {
|
|
13
|
+
readonly volumeId: Effect.Effect<string>;
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** The attributes, to pass where a `Modal.Volume` is accepted (e.g. sandbox mounts). */
|
|
16
|
+
readonly attributes: VolumeAttributes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Get, create, list and delete volumes by name in one environment. */
|
|
20
|
+
export interface VolumesClientOf<R> {
|
|
21
|
+
/** The volume named `name`, created when missing (Modal's own get-or-create). */
|
|
22
|
+
getOrCreate(name: string): Effect.Effect<VolumeHandle, ErrorOf<typeof ensureVolume>, R>;
|
|
23
|
+
/** The volume named `name`, or `undefined`. */
|
|
24
|
+
get(name: string): Effect.Effect<VolumeHandle | undefined, ErrorOf<typeof lookupVolume>, R>;
|
|
25
|
+
/** Delete the volume named `name` (no-op when missing). */
|
|
26
|
+
delete(
|
|
27
|
+
name: string,
|
|
28
|
+
): Effect.Effect<
|
|
29
|
+
void,
|
|
30
|
+
| ErrorOf<typeof lookupVolume>
|
|
31
|
+
| Exclude<OpError<VolumesOps, "delete">, { readonly _tag: "VolumeNotFound" }>,
|
|
32
|
+
R
|
|
33
|
+
>;
|
|
34
|
+
/** Names of every volume in the environment. */
|
|
35
|
+
list(): Effect.Effect<ReadonlyArray<string>, OpError<VolumesOps, "list">, R>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A VolumesClient whose calls run inside a deployed runtime. */
|
|
39
|
+
export type VolumesClient = VolumesClientOf<RuntimeContext>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create volumes 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 volume has only a name, so the tags become
|
|
53
|
+
* its name prefix, `Modal.runtimePrefix({ stack, stage, id })`: list them
|
|
54
|
+
* with `modal volume list` and delete the ones whose name starts with it.
|
|
55
|
+
*
|
|
56
|
+
* ### One volume 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 volumes = yield* Modal.CreateVolume(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 home = yield* volumes.getOrCreate(`user-${user}`);
|
|
78
|
+
* yield* home.writeFile("/notes.md", "hello");
|
|
79
|
+
* const sandbox = yield* sandboxes.create({ mounts: [{ volume: home, path: "/home/user" }] });
|
|
80
|
+
* return HttpServerResponse.text("ok");
|
|
81
|
+
* }).pipe(Effect.orDie),
|
|
82
|
+
* };
|
|
83
|
+
* }).pipe(Effect.provide(Layer.mergeAll(Modal.CreateVolumeHttp, Modal.CreateSandboxHttp))),
|
|
84
|
+
* ) {}
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @binding
|
|
88
|
+
* @product Volume
|
|
89
|
+
*/
|
|
90
|
+
export interface CreateVolume extends Binding.Service<
|
|
91
|
+
CreateVolume,
|
|
92
|
+
"Modal.CreateVolume",
|
|
93
|
+
(environment?: Environment) => Effect.Effect<VolumesClient>
|
|
94
|
+
> {}
|
|
95
|
+
|
|
96
|
+
export const CreateVolume = Binding.Service<CreateVolume>("Modal.CreateVolume");
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as volume from "@distilled.cloud/modal/volume";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
import * as Layer from "effect/Layer";
|
|
4
|
+
import { makeOpenModalBinding } from "./BindingHttp.ts";
|
|
5
|
+
import { CreateVolume, type VolumeHandle, type VolumesClientOf } from "./CreateVolume.ts";
|
|
6
|
+
import type { Environment } from "./Environment.ts";
|
|
7
|
+
import { environmentOf, listAll, operations } from "./internal.ts";
|
|
8
|
+
import { ownedName, type RuntimeOwner, RuntimeOwnerOf, unownedName } from "./RuntimeOwner.ts";
|
|
9
|
+
import { ensureVolume, lookupVolume, type VolumeAttributes } from "./Volume.ts";
|
|
10
|
+
import { makeReadWriteVolumeClient } from "./VolumeClient.ts";
|
|
11
|
+
import { VolumeFileOps } from "./VolumeFiles.ts";
|
|
12
|
+
|
|
13
|
+
/** The operations the client calls, resolved by `ModalBindings.withCredentials`. */
|
|
14
|
+
export const VolumesOps = operations({
|
|
15
|
+
getOrCreate: volume.volumeGetOrCreate,
|
|
16
|
+
delete: volume.deleteVolume,
|
|
17
|
+
list: volume.listVolume,
|
|
18
|
+
client: VolumeFileOps,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export type VolumesOps = Effect.Success<typeof VolumesOps>;
|
|
22
|
+
|
|
23
|
+
const handleOf = (attributes: VolumeAttributes, ops: VolumesOps, name: string): VolumeHandle => ({
|
|
24
|
+
...makeReadWriteVolumeClient(Effect.succeed(attributes.volumeId), ops.client),
|
|
25
|
+
volumeId: Effect.succeed(attributes.volumeId),
|
|
26
|
+
name,
|
|
27
|
+
attributes,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/** A volumes client over an environment name resolved per call. */
|
|
31
|
+
export const makeVolumesClient = (
|
|
32
|
+
environment: Effect.Effect<string | undefined>,
|
|
33
|
+
ops: VolumesOps,
|
|
34
|
+
owner: Effect.Effect<RuntimeOwner | undefined> = Effect.undefined,
|
|
35
|
+
): VolumesClientOf<never> => ({
|
|
36
|
+
getOrCreate: (name) =>
|
|
37
|
+
Effect.flatMap(Effect.all([environment, owner]), ([env, stamp]) =>
|
|
38
|
+
ensureVolume(ops.getOrCreate, ownedName(stamp, name), env),
|
|
39
|
+
).pipe(Effect.map((attributes) => handleOf(attributes, ops, name))),
|
|
40
|
+
get: (name) =>
|
|
41
|
+
Effect.flatMap(Effect.all([environment, owner]), ([env, stamp]) =>
|
|
42
|
+
lookupVolume(ops.getOrCreate, ownedName(stamp, name), env),
|
|
43
|
+
).pipe(Effect.map((attributes) => (attributes ? handleOf(attributes, ops, name) : undefined))),
|
|
44
|
+
delete: (name) =>
|
|
45
|
+
Effect.gen(function* () {
|
|
46
|
+
const env = yield* environment;
|
|
47
|
+
const found = yield* lookupVolume(ops.getOrCreate, ownedName(yield* owner, name), env);
|
|
48
|
+
if (!found) return;
|
|
49
|
+
yield* ops
|
|
50
|
+
.delete({ volumeId: found.volumeId, environmentName: environmentOf(env) })
|
|
51
|
+
.pipe(Effect.catchTag("VolumeNotFound", () => Effect.void));
|
|
52
|
+
}),
|
|
53
|
+
list: () =>
|
|
54
|
+
Effect.gen(function* () {
|
|
55
|
+
const env = yield* environment;
|
|
56
|
+
const stamp = yield* owner;
|
|
57
|
+
const items = yield* listAll(
|
|
58
|
+
(pagination) =>
|
|
59
|
+
ops
|
|
60
|
+
.list({ environmentName: environmentOf(env), pagination })
|
|
61
|
+
.pipe(Effect.map((response) => response.items ?? [])),
|
|
62
|
+
(item) => item.createdAt,
|
|
63
|
+
);
|
|
64
|
+
return items.flatMap((item) => {
|
|
65
|
+
const name = item.label ?? item.metadata?.name;
|
|
66
|
+
const own = name ? unownedName(stamp, name) : undefined;
|
|
67
|
+
return own ? [own] : [];
|
|
68
|
+
});
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* {@link CreateVolume} over Modal's API. Grants the host's identity (a scoped
|
|
74
|
+
* `Modal.ServiceUser`) the `contributor` role on the environment.
|
|
75
|
+
*
|
|
76
|
+
* @layer
|
|
77
|
+
* @product Volume
|
|
78
|
+
* @provides Modal.CreateVolume
|
|
79
|
+
*/
|
|
80
|
+
export const CreateVolumeHttp = Layer.effect(
|
|
81
|
+
CreateVolume,
|
|
82
|
+
makeOpenModalBinding({
|
|
83
|
+
tag: "Modal.CreateVolume",
|
|
84
|
+
operations: VolumesOps,
|
|
85
|
+
role: "contributor",
|
|
86
|
+
environmentOf: (environment?: Environment) => environment?.name,
|
|
87
|
+
make: Effect.fn(function* (ops, environment?: Environment) {
|
|
88
|
+
const name = environment ? yield* environment.name : Effect.undefined;
|
|
89
|
+
const owner = yield* RuntimeOwnerOf();
|
|
90
|
+
return makeVolumesClient(name, ops, owner);
|
|
91
|
+
}),
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ConfigError } from "@distilled.cloud/core/errors";
|
|
2
|
+
import { withAuthToken } from "@distilled.cloud/modal/AuthToken";
|
|
3
|
+
import { Credentials, DEFAULT_API_BASE_URL } from "@distilled.cloud/modal/Credentials";
|
|
4
|
+
import { lazyCredentials } from "alchemy/Auth/Resolve";
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as Layer from "effect/Layer";
|
|
7
|
+
import * as Redacted from "effect/Redacted";
|
|
8
|
+
import { MODAL_AUTH_PROVIDER_NAME, type ModalResolvedCredentials } from "./AuthProvider.ts";
|
|
9
|
+
import { ModalTransport } from "./internal/Transport.ts";
|
|
10
|
+
|
|
11
|
+
export { withAuthToken } from "@distilled.cloud/modal/AuthToken";
|
|
12
|
+
export {
|
|
13
|
+
Credentials,
|
|
14
|
+
CredentialsFromEnv,
|
|
15
|
+
DEFAULT_API_BASE_URL,
|
|
16
|
+
} from "@distilled.cloud/modal/Credentials";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Build Modal `Credentials` that resolve through the Alchemy AuthProvider:
|
|
20
|
+
* `MODAL_TOKEN_ID` / `MODAL_TOKEN_SECRET` when set, otherwise the selected
|
|
21
|
+
* profile. Resolution is deferred until the first API call, so building the
|
|
22
|
+
* provider layers never needs a profile.
|
|
23
|
+
*/
|
|
24
|
+
export const fromAuthProvider = () =>
|
|
25
|
+
withAuthTokens(
|
|
26
|
+
Layer.effect(
|
|
27
|
+
Credentials,
|
|
28
|
+
lazyCredentials<ModalResolvedCredentials, ConfigError>()(
|
|
29
|
+
MODAL_AUTH_PROVIDER_NAME,
|
|
30
|
+
(creds) => ({
|
|
31
|
+
tokenId: creds.tokenId,
|
|
32
|
+
tokenSecret: creds.tokenSecret,
|
|
33
|
+
apiBaseUrl: creds.apiBaseUrl,
|
|
34
|
+
}),
|
|
35
|
+
),
|
|
36
|
+
),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Add Modal's short-lived auth token (the `x-modal-auth-token` JWT its V2
|
|
41
|
+
* sandbox RPCs and input plane need) to a token pair's `Credentials`.
|
|
42
|
+
*/
|
|
43
|
+
export const withAuthTokens = <E, R>(
|
|
44
|
+
credentials: Layer.Layer<Credentials, E, R>,
|
|
45
|
+
): Layer.Layer<Credentials, E, R> =>
|
|
46
|
+
withAuthToken.pipe(Layer.provide(Layer.mergeAll(credentials, ModalTransport)));
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Build Modal `Credentials` from an explicit token pair, e.g. in a test or a
|
|
50
|
+
* script that already holds one.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* Effect.provide(Modal.fromToken({ tokenId: "ak-…", tokenSecret: "as-…" }))
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const fromToken = (input: {
|
|
58
|
+
tokenId: string | Redacted.Redacted<string>;
|
|
59
|
+
tokenSecret: string | Redacted.Redacted<string>;
|
|
60
|
+
apiBaseUrl?: string;
|
|
61
|
+
}): Layer.Layer<Credentials> =>
|
|
62
|
+
withAuthTokens(
|
|
63
|
+
Layer.succeed(
|
|
64
|
+
Credentials,
|
|
65
|
+
Effect.succeed({
|
|
66
|
+
tokenId: typeof input.tokenId === "string" ? Redacted.make(input.tokenId) : input.tokenId,
|
|
67
|
+
tokenSecret:
|
|
68
|
+
typeof input.tokenSecret === "string"
|
|
69
|
+
? Redacted.make(input.tokenSecret)
|
|
70
|
+
: input.tokenSecret,
|
|
71
|
+
apiBaseUrl: input.apiBaseUrl ?? DEFAULT_API_BASE_URL,
|
|
72
|
+
}),
|
|
73
|
+
),
|
|
74
|
+
);
|
package/src/Dict.ts
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import * as dict from "@distilled.cloud/modal/dict";
|
|
2
|
+
import { Unowned } from "alchemy/AdoptPolicy";
|
|
3
|
+
import { isResolved } from "alchemy/Diff";
|
|
4
|
+
import * as Provider from "alchemy/Provider";
|
|
5
|
+
import { Resource } from "alchemy/Resource";
|
|
6
|
+
import * as Data from "effect/Data";
|
|
7
|
+
import * as Effect from "effect/Effect";
|
|
8
|
+
import {
|
|
9
|
+
type EnvironmentInput,
|
|
10
|
+
envNameOf,
|
|
11
|
+
environmentNames,
|
|
12
|
+
environmentOf,
|
|
13
|
+
isGeneratedName,
|
|
14
|
+
listAll,
|
|
15
|
+
objectName,
|
|
16
|
+
} from "./internal.ts";
|
|
17
|
+
import { declarable } from "./internal/Declared.ts";
|
|
18
|
+
import type { Providers } from "./Providers.ts";
|
|
19
|
+
import { isRuntimeName } from "./RuntimeOwner.ts";
|
|
20
|
+
|
|
21
|
+
export class DictUnexpectedResponse extends Data.TaggedError("Modal.DictUnexpectedResponse")<{
|
|
22
|
+
readonly message: string;
|
|
23
|
+
}> {}
|
|
24
|
+
|
|
25
|
+
export interface DictProps {
|
|
26
|
+
/**
|
|
27
|
+
* Dict name, unique per environment. If omitted, a unique name is
|
|
28
|
+
* generated from the stack, stage and logical ID. Changing it replaces the
|
|
29
|
+
* dict (Modal can't rename dicts).
|
|
30
|
+
*/
|
|
31
|
+
name?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Environment the dict lives in. Changing it replaces the dict.
|
|
34
|
+
* @default the workspace's default environment
|
|
35
|
+
*/
|
|
36
|
+
environment?: EnvironmentInput;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface DictAttributes {
|
|
40
|
+
/** Dict ID (`di-…`). */
|
|
41
|
+
dictId: string;
|
|
42
|
+
/** Dict name. */
|
|
43
|
+
name: string;
|
|
44
|
+
/** Environment name, or `undefined` for the workspace default. */
|
|
45
|
+
environment: string | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A Modal Dict: a distributed key-value store shared by every container,
|
|
50
|
+
* Sandbox and client in the workspace. Entries expire 7 days after their
|
|
51
|
+
* last write.
|
|
52
|
+
*
|
|
53
|
+
* Bind it with {@link ReadDict}, {@link WriteDict} or {@link ReadWriteDict}
|
|
54
|
+
* to use it from a Worker, Lambda or any other runtime. Values travel as
|
|
55
|
+
* bytes: the bindings encode them as JSON by default.
|
|
56
|
+
*
|
|
57
|
+
* Modal dicts have no tags. Ownership is inferred from Alchemy state: a
|
|
58
|
+
* dict found under an explicit `name` without prior state is reported as
|
|
59
|
+
* unowned.
|
|
60
|
+
*
|
|
61
|
+
* ### Creating a Dict
|
|
62
|
+
* **Example:** A dict with a generated name
|
|
63
|
+
* ```typescript
|
|
64
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
65
|
+
*
|
|
66
|
+
* export const Results = Modal.Dict("Results", {});
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* **Example:** A named dict in an environment
|
|
70
|
+
* ```typescript
|
|
71
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
72
|
+
*
|
|
73
|
+
* export const Agents = Modal.Environment("Agents", {});
|
|
74
|
+
* export const Sessions = Modal.Dict("Sessions", { name: "sessions", environment: Agents });
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* ### Reading and writing from a Worker
|
|
78
|
+
* **Example:** Bind read and write access
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import * as Cloudflare from "@alchemy.run/cloudflare";
|
|
81
|
+
* import * as Modal from "@alchemy.run/modal";
|
|
82
|
+
* import * as Effect from "effect/Effect";
|
|
83
|
+
* import * as HttpServerResponse from "effect/http/HttpServerResponse";
|
|
84
|
+
* import { Results } from "./Storage.ts";
|
|
85
|
+
*
|
|
86
|
+
* export default class Api extends Cloudflare.Worker<Api>()(
|
|
87
|
+
* "Api",
|
|
88
|
+
* { main: import.meta.url },
|
|
89
|
+
* Effect.gen(function* () {
|
|
90
|
+
* const results = yield* Modal.ReadWriteDict(Results);
|
|
91
|
+
* return {
|
|
92
|
+
* fetch: Effect.gen(function* () {
|
|
93
|
+
* yield* results.put("last-run", { ok: true });
|
|
94
|
+
* const last = yield* results.get("last-run");
|
|
95
|
+
* return yield* HttpServerResponse.json(last ?? null);
|
|
96
|
+
* }).pipe(Effect.orDie),
|
|
97
|
+
* };
|
|
98
|
+
* }).pipe(Effect.provide(Modal.ReadWriteDictHttp)),
|
|
99
|
+
* ) {}
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* ### Looking up an existing dict
|
|
103
|
+
* `Dict.lookup` references a dict Alchemy doesn't manage (created with
|
|
104
|
+
* the Modal CLI or by another stack). It is read during plan/deploy, never
|
|
105
|
+
* created, updated or deleted.
|
|
106
|
+
*
|
|
107
|
+
* **Example:** Reference an existing dict
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const cache = Modal.Dict.lookup({ name: "cache" });
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @resource
|
|
113
|
+
* @product Dict
|
|
114
|
+
*/
|
|
115
|
+
export const Dict = declarable<Dict>()(Resource<Dict>("Modal.Dict"));
|
|
116
|
+
|
|
117
|
+
export type Dict = Resource<"Modal.Dict", DictProps, DictAttributes, never, Providers, DictLookup>;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Props for {@link Dict.lookup}: find a dict this stack
|
|
121
|
+
* doesn't manage by its name.
|
|
122
|
+
*/
|
|
123
|
+
export interface DictLookup {
|
|
124
|
+
/** Dict name. */
|
|
125
|
+
name: string;
|
|
126
|
+
/**
|
|
127
|
+
* Modal environment the object lives in.
|
|
128
|
+
* @default the workspace's default environment
|
|
129
|
+
*/
|
|
130
|
+
environment?: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A dict by name, or `undefined` when missing. */
|
|
134
|
+
export const lookupDict = Effect.fn(function* (
|
|
135
|
+
getOrCreate: Effect.Success<typeof dict.dictGetOrCreate>,
|
|
136
|
+
name: string,
|
|
137
|
+
env: string | undefined,
|
|
138
|
+
) {
|
|
139
|
+
const found = yield* getOrCreate({
|
|
140
|
+
deploymentName: name,
|
|
141
|
+
environmentName: environmentOf(env),
|
|
142
|
+
objectCreationType: "OBJECT_CREATION_TYPE_UNSPECIFIED",
|
|
143
|
+
}).pipe(Effect.catchTag("DictNotFound", () => Effect.undefined));
|
|
144
|
+
if (!found?.dictId) return undefined;
|
|
145
|
+
return { dictId: found.dictId, name, environment: env } satisfies DictAttributes;
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Get a dict by name, creating it when missing: the one implementation behind
|
|
150
|
+
* {@link Dict}'s reconcile and the runtime {@link CreateDict} client.
|
|
151
|
+
*/
|
|
152
|
+
export const ensureDict = Effect.fn(function* (
|
|
153
|
+
getOrCreate: Effect.Success<typeof dict.dictGetOrCreate>,
|
|
154
|
+
name: string,
|
|
155
|
+
env: string | undefined,
|
|
156
|
+
) {
|
|
157
|
+
const created = yield* getOrCreate({
|
|
158
|
+
deploymentName: name,
|
|
159
|
+
environmentName: environmentOf(env),
|
|
160
|
+
objectCreationType: "OBJECT_CREATION_TYPE_CREATE_IF_MISSING",
|
|
161
|
+
});
|
|
162
|
+
if (!created.dictId) {
|
|
163
|
+
return yield* new DictUnexpectedResponse({ message: `Modal returned no id for dict ${name}` });
|
|
164
|
+
}
|
|
165
|
+
return { dictId: created.dictId, name, environment: env } satisfies DictAttributes;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export const DictProvider = () =>
|
|
169
|
+
Provider.effect(
|
|
170
|
+
Dict,
|
|
171
|
+
Effect.gen(function* () {
|
|
172
|
+
const observe = Effect.fn(function* (
|
|
173
|
+
dictId: string | undefined,
|
|
174
|
+
name: string,
|
|
175
|
+
env: string | undefined,
|
|
176
|
+
) {
|
|
177
|
+
if (dictId !== undefined) {
|
|
178
|
+
const byId = yield* dict
|
|
179
|
+
.dictGetById({ dictId })
|
|
180
|
+
.pipe(Effect.catchTag("DictNotFound", () => Effect.undefined));
|
|
181
|
+
if (byId?.dictId) {
|
|
182
|
+
return {
|
|
183
|
+
dictId: byId.dictId,
|
|
184
|
+
name: byId.metadata?.name ?? name,
|
|
185
|
+
environment: env,
|
|
186
|
+
} satisfies DictAttributes;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return yield* lookupDict(yield* dict.dictGetOrCreate, name, env);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
stables: ["dictId", "name", "environment"],
|
|
194
|
+
diff: Effect.fn(function* ({ id, news, olds, output }) {
|
|
195
|
+
if (!isResolved(news)) return undefined;
|
|
196
|
+
if (envNameOf(news.environment) !== envNameOf(olds?.environment))
|
|
197
|
+
return { action: "replace" } as const;
|
|
198
|
+
const name = yield* objectName(id, news.name);
|
|
199
|
+
if (output !== undefined && name !== output.name) return { action: "replace" } as const;
|
|
200
|
+
return undefined;
|
|
201
|
+
}),
|
|
202
|
+
lookup: Effect.fn(function* ({ name, environment }) {
|
|
203
|
+
return yield* observe(undefined, name, environment);
|
|
204
|
+
}),
|
|
205
|
+
|
|
206
|
+
read: Effect.fn(function* ({ id, olds, output }) {
|
|
207
|
+
const name = output?.name ?? (yield* objectName(id, olds?.name));
|
|
208
|
+
const observed = yield* observe(output?.dictId, name, envNameOf(olds?.environment));
|
|
209
|
+
if (!observed) return undefined;
|
|
210
|
+
return output !== undefined || olds?.name === undefined ? observed : Unowned(observed);
|
|
211
|
+
}),
|
|
212
|
+
reconcile: Effect.fn(function* ({ id, news, output, session }) {
|
|
213
|
+
const name = output?.name ?? (yield* objectName(id, news.name));
|
|
214
|
+
const current = yield* observe(output?.dictId, name, envNameOf(news.environment));
|
|
215
|
+
if (current) return current;
|
|
216
|
+
yield* session.note(`Creating dict ${name}...`);
|
|
217
|
+
return yield* ensureDict(yield* dict.dictGetOrCreate, name, envNameOf(news.environment));
|
|
218
|
+
}),
|
|
219
|
+
delete: Effect.fn(function* ({ output }) {
|
|
220
|
+
yield* dict
|
|
221
|
+
.deleteDict({ dictId: output.dictId })
|
|
222
|
+
.pipe(Effect.catchTag("DictNotFound", () => Effect.void));
|
|
223
|
+
}),
|
|
224
|
+
list: Effect.fn(function* () {
|
|
225
|
+
const envs = yield* environmentNames;
|
|
226
|
+
const all: DictAttributes[] = [];
|
|
227
|
+
for (const env of envs) {
|
|
228
|
+
const items = yield* listAll(
|
|
229
|
+
(pagination) =>
|
|
230
|
+
dict
|
|
231
|
+
.listDict({ environmentName: env, pagination })
|
|
232
|
+
.pipe(Effect.map((response) => response.dicts ?? [])),
|
|
233
|
+
(item) => item.createdAt,
|
|
234
|
+
);
|
|
235
|
+
for (const item of items) {
|
|
236
|
+
if (!item.dictId || !(isGeneratedName(item.name) || isRuntimeName(item.name)))
|
|
237
|
+
continue;
|
|
238
|
+
all.push({ dictId: item.dictId, name: item.name ?? "", environment: env });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return all;
|
|
242
|
+
}),
|
|
243
|
+
};
|
|
244
|
+
}),
|
|
245
|
+
);
|