packages feed

cachix-api 0.6.0 → 0.7.0

raw patch · 13 files changed

+286/−132 lines, 13 filesdep +asyncdep +unordered-containersdep +uuidPVP ok

version bump matches the API change (PVP)

Dependencies added: async, unordered-containers, uuid, websockets

API changes (from Hackage documentation)

- Cachix.Types.NarInfo: instance Control.DeepSeq.NFData (Nix.NarInfo.Types.NarInfo Data.Text.Internal.Text Data.Text.Internal.Text Data.Text.Internal.Text)
- Cachix.Types.NarInfo: instance Data.Aeson.Types.FromJSON.FromJSON (Nix.NarInfo.Types.NarInfo Data.Text.Internal.Text Data.Text.Internal.Text Data.Text.Internal.Text)
- Cachix.Types.NarInfo: instance Data.Aeson.Types.ToJSON.ToJSON (Nix.NarInfo.Types.NarInfo Data.Text.Internal.Text Data.Text.Internal.Text Data.Text.Internal.Text)
- Cachix.Types.NarInfo: instance Data.Swagger.Internal.Schema.ToSchema (Nix.NarInfo.Types.NarInfo Data.Text.Internal.Text Data.Text.Internal.Text Data.Text.Internal.Text)
+ Cachix.API.Deploy: DeployAPI :: (route :- (CachixAuth :> ("deploy" :> ("activate" :> (ReqBody '[JSON] Deploy :> Post '[JSON] DeployResponse))))) -> DeployAPI route
+ Cachix.API.Deploy: [activate] :: DeployAPI route -> route :- (CachixAuth :> ("deploy" :> ("activate" :> (ReqBody '[JSON] Deploy :> Post '[JSON] DeployResponse))))
+ Cachix.API.Deploy: api :: Proxy API
+ Cachix.API.Deploy: data DeployAPI route
+ Cachix.API.Deploy: instance GHC.Generics.Generic (Cachix.API.Deploy.DeployAPI route)
+ Cachix.API.Deploy: type API = "api" :> "v1" :> ToServantApi DeployAPI
+ Cachix.API.WebSocketSubprotocol: AgentInformation :: Maybe Cache -> UUID -> AgentInformation
+ Cachix.API.WebSocketSubprotocol: AgentRegistered :: AgentInformation -> BackendCommand
+ Cachix.API.WebSocketSubprotocol: Cache :: Text -> Text -> Bool -> Cache
+ Cachix.API.WebSocketSubprotocol: Deployment :: DeploymentDetails -> BackendCommand
+ Cachix.API.WebSocketSubprotocol: DeploymentDetails :: Text -> UUID -> Int64 -> DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: DeploymentFinished :: UUID -> UTCTime -> Bool -> AgentCommand
+ Cachix.API.WebSocketSubprotocol: DeploymentStarted :: UUID -> UTCTime -> AgentCommand
+ Cachix.API.WebSocketSubprotocol: Log :: Text -> UTCTime -> Log
+ Cachix.API.WebSocketSubprotocol: Message :: Text -> cmd -> Maybe UUID -> UUID -> Message cmd
+ Cachix.API.WebSocketSubprotocol: [$sel:agent:Message] :: Message cmd -> Maybe UUID
+ Cachix.API.WebSocketSubprotocol: [$sel:cache:AgentInformation] :: AgentInformation -> Maybe Cache
+ Cachix.API.WebSocketSubprotocol: [$sel:cacheName:Cache] :: Cache -> Text
+ Cachix.API.WebSocketSubprotocol: [$sel:command:Message] :: Message cmd -> cmd
+ Cachix.API.WebSocketSubprotocol: [$sel:hasSucceeded:DeploymentStarted] :: AgentCommand -> Bool
+ Cachix.API.WebSocketSubprotocol: [$sel:id:AgentInformation] :: AgentInformation -> UUID
+ Cachix.API.WebSocketSubprotocol: [$sel:id:DeploymentDetails] :: DeploymentDetails -> UUID
+ Cachix.API.WebSocketSubprotocol: [$sel:id:DeploymentStarted] :: AgentCommand -> UUID
+ Cachix.API.WebSocketSubprotocol: [$sel:id:Message] :: Message cmd -> UUID
+ Cachix.API.WebSocketSubprotocol: [$sel:index:DeploymentDetails] :: DeploymentDetails -> Int64
+ Cachix.API.WebSocketSubprotocol: [$sel:isPublic:Cache] :: Cache -> Bool
+ Cachix.API.WebSocketSubprotocol: [$sel:line:Log] :: Log -> Text
+ Cachix.API.WebSocketSubprotocol: [$sel:method:Message] :: Message cmd -> Text
+ Cachix.API.WebSocketSubprotocol: [$sel:publicKey:Cache] :: Cache -> Text
+ Cachix.API.WebSocketSubprotocol: [$sel:storePath:DeploymentDetails] :: DeploymentDetails -> Text
+ Cachix.API.WebSocketSubprotocol: [$sel:time:DeploymentStarted] :: AgentCommand -> UTCTime
+ Cachix.API.WebSocketSubprotocol: [$sel:time:Log] :: Log -> UTCTime
+ Cachix.API.WebSocketSubprotocol: data AgentCommand
+ Cachix.API.WebSocketSubprotocol: data AgentInformation
+ Cachix.API.WebSocketSubprotocol: data BackendCommand
+ Cachix.API.WebSocketSubprotocol: data Cache
+ Cachix.API.WebSocketSubprotocol: data DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: data Log
+ Cachix.API.WebSocketSubprotocol: data Message cmd
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.AgentCommand
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.AgentInformation
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.BackendCommand
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.Cache
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.API.WebSocketSubprotocol.Log
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.FromJSON.FromJSON cmd => Data.Aeson.Types.FromJSON.FromJSON (Cachix.API.WebSocketSubprotocol.Message cmd)
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.AgentCommand
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.AgentInformation
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.BackendCommand
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.Cache
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.API.WebSocketSubprotocol.Log
+ Cachix.API.WebSocketSubprotocol: instance Data.Aeson.Types.ToJSON.ToJSON cmd => Data.Aeson.Types.ToJSON.ToJSON (Cachix.API.WebSocketSubprotocol.Message cmd)
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq Cachix.API.WebSocketSubprotocol.AgentCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq Cachix.API.WebSocketSubprotocol.AgentInformation
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq Cachix.API.WebSocketSubprotocol.BackendCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq Cachix.API.WebSocketSubprotocol.Cache
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq Cachix.API.WebSocketSubprotocol.DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: instance GHC.Classes.Eq cmd => GHC.Classes.Eq (Cachix.API.WebSocketSubprotocol.Message cmd)
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic (Cachix.API.WebSocketSubprotocol.Message cmd)
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.AgentCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.AgentInformation
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.BackendCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.Cache
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: instance GHC.Generics.Generic Cachix.API.WebSocketSubprotocol.Log
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.AgentCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.AgentInformation
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.BackendCommand
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.Cache
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.DeploymentDetails
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show Cachix.API.WebSocketSubprotocol.Log
+ Cachix.API.WebSocketSubprotocol: instance GHC.Show.Show cmd => GHC.Show.Show (Cachix.API.WebSocketSubprotocol.Message cmd)
+ Cachix.API.WebSocketSubprotocol: parseMessage :: FromJSON cmd => ByteString -> Either Text (Message cmd)
+ Cachix.API.WebSocketSubprotocol: recieveDataConcurrently :: Connection -> (ByteString -> IO ()) -> IO ()
+ Cachix.API.WebSocketSubprotocol: sendMessage :: ToJSON cmd => Connection -> Message cmd -> IO ()
+ Cachix.Types.ContentTypes: instance Servant.API.ContentTypes.MimeRender Servant.API.ContentTypes.PlainText Cachix.Types.ByteStringStreaming.ByteStringStreaming
+ Cachix.Types.ContentTypes: instance Servant.API.ContentTypes.MimeUnrender Servant.API.ContentTypes.PlainText Cachix.Types.ByteStringStreaming.ByteStringStreaming
+ Cachix.Types.Deploy: Deploy :: HashMap Text Text -> Deploy
+ Cachix.Types.Deploy: [agents] :: Deploy -> HashMap Text Text
+ Cachix.Types.Deploy: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.Types.Deploy.Deploy
+ Cachix.Types.Deploy: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.Types.Deploy.Deploy
+ Cachix.Types.Deploy: instance Data.Swagger.Internal.Schema.ToSchema Cachix.Types.Deploy.Deploy
+ Cachix.Types.Deploy: instance GHC.Generics.Generic Cachix.Types.Deploy.Deploy
+ Cachix.Types.Deploy: instance GHC.Show.Show Cachix.Types.Deploy.Deploy
+ Cachix.Types.Deploy: newtype Deploy
+ Cachix.Types.DeployResponse: DeployResponse :: HashMap Text Text -> DeployResponse
+ Cachix.Types.DeployResponse: [agents] :: DeployResponse -> HashMap Text Text
+ Cachix.Types.DeployResponse: instance Control.DeepSeq.NFData Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: instance Data.Swagger.Internal.Schema.ToSchema Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: instance GHC.Generics.Generic Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: instance GHC.Show.Show Cachix.Types.DeployResponse.DeployResponse
+ Cachix.Types.DeployResponse: newtype DeployResponse
+ Cachix.Types.NarInfo: instance Control.DeepSeq.NFData Cachix.Types.NarInfo.CachixNarInfo
+ Cachix.Types.NarInfo: instance Data.Aeson.Types.FromJSON.FromJSON Cachix.Types.NarInfo.CachixNarInfo
+ Cachix.Types.NarInfo: instance Data.Aeson.Types.ToJSON.ToJSON Cachix.Types.NarInfo.CachixNarInfo
+ Cachix.Types.NarInfo: instance Data.Swagger.Internal.Schema.ToSchema Cachix.Types.NarInfo.CachixNarInfo
- Cachix.API: BinaryCacheAPI :: (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nix-cache-info" :> Get '[XNixCacheInfo, JSON] NixCacheInfo))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Get '[XNixNarInfo, JSON] CachixNarInfo))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Head))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nar" :> (Capture "nar" NarFileName :> StreamGet NoFraming XNixNar (ConduitT () ByteStringStreaming (ResourceT IO) ()))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> Get '[JSON] BinaryCache)))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("narinfo" :> (Summary "Given a list of store hashes, return a list of those that are missing" :> (ReqBody '[JSON] [Text] :> Post '[JSON] [Text]))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("narurl" :> (Capture "nar" NarFileName :> Get '[JSON] Text)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> (ReqBody '[JSON] NarInfoCreate :> Post '[JSON] NoContent)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nar" :> (StreamBody NoFraming XNixNar (ConduitT () ByteStringStreaming (ResourceT IO) ()) :> Post '[JSON] NoContent)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("serve" :> (Capture "storehash" Text :> (CaptureAll "filepath" Text :> (Summary "Serve a file from a given store path" :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text] LazyByteStringStreaming))))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("key" :> (ReqBody '[JSON] SigningKeyCreate :> Post '[JSON] NoContent)))))) -> BinaryCacheAPI route
+ Cachix.API: BinaryCacheAPI :: (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nix-cache-info" :> Get '[XNixCacheInfo, JSON] NixCacheInfo))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Get '[XNixNarInfo, JSON] (Headers '[Header "Cache-Control" Text] CachixNarInfo)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Head))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nar" :> (Capture "nar" NarFileName :> StreamGet NoFraming XNixNar (ConduitT () ByteStringStreaming (ResourceT IO) ()))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> Get '[JSON] BinaryCache)))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("narinfo" :> (Summary "Given a list of store hashes, return a list of those that are missing" :> (ReqBody '[JSON] [Text] :> Post '[JSON] [Text]))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("narurl" :> (Capture "nar" NarFileName :> Get '[JSON] Text)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> (ReqBody '[JSON] NarInfoCreate :> Post '[JSON] NoContent)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("nar" :> (StreamBody NoFraming XNixNar (ConduitT () ByteStringStreaming (ResourceT IO) ()) :> Post '[JSON] NoContent)))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("serve" :> (Capture "storehash" Text :> (CaptureAll "filepath" Text :> (Summary "Serve a file from a given store path" :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text, Header "Cache-Control" Text] LazyByteStringStreaming))))))))) -> (route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("key" :> (ReqBody '[JSON] SigningKeyCreate :> Post '[JSON] NoContent)))))) -> BinaryCacheAPI route
- Cachix.API: [narinfo] :: BinaryCacheAPI route -> route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Get '[XNixNarInfo, JSON] CachixNarInfo))))
+ Cachix.API: [narinfo] :: BinaryCacheAPI route -> route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> (Capture "narinfohash" NarInfoHash :> Get '[XNixNarInfo, JSON] (Headers '[Header "Cache-Control" Text] CachixNarInfo)))))
- Cachix.API: [serveNarContent] :: BinaryCacheAPI route -> route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("serve" :> (Capture "storehash" Text :> (CaptureAll "filepath" Text :> (Summary "Serve a file from a given store path" :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text] LazyByteStringStreaming))))))))
+ Cachix.API: [serveNarContent] :: BinaryCacheAPI route -> route :- (CachixAuth :> ("cache" :> (Capture "name" Text :> ("serve" :> (Capture "storehash" Text :> (CaptureAll "filepath" Text :> (Summary "Serve a file from a given store path" :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text, Header "Cache-Control" Text] LazyByteStringStreaming))))))))

Files

CHANGELOG.md view
@@ -7,6 +7,10 @@  ## [Unreleased] +## [0.7.0] - 2022-01-12++- Support Cachix Deploy+ ## [0.6.0] - 2021-01-08  - Support latest stackage nightly
cachix-api.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               cachix-api-version: 0.6.0+version: 0.7.0 synopsis:           Servant HTTP API specification for https://cachix.org homepage:           https://github.com/cachix/cachix#readme bug-reports:        https://github.com/cachix/cachix/issues@@ -38,11 +38,15 @@   import:          defaults   exposed-modules:     Cachix.API+    Cachix.API.Deploy     Cachix.API.Error     Cachix.API.Signing+    Cachix.API.WebSocketSubprotocol     Cachix.Types.BinaryCache     Cachix.Types.ByteStringStreaming     Cachix.Types.ContentTypes+    Cachix.Types.Deploy+    Cachix.Types.DeployResponse     Cachix.Types.NarFileName     Cachix.Types.NarInfo     Cachix.Types.NarInfoCreate@@ -56,6 +60,7 @@   hs-source-dirs:  src   build-depends:     , aeson+    , async     , base                  >=4.7    && <5     , base16-bytestring     , bytestring@@ -81,6 +86,9 @@     , text     , time     , transformers+    , unordered-containers+    , uuid+    , websockets  test-suite cachix-api-test   import:             defaults
src/Cachix/API.hs view
@@ -31,99 +31,98 @@ type CachixAuth = Auth '[Cookie, JWT, BasicAuth] Session  -- Nix CLI + Cachix CLI-data BinaryCacheAPI route-  = BinaryCacheAPI-      { -- https://cache.nixos.org/nix-cache-info-        nixCacheInfo ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "nix-cache-info"-            :> Get '[XNixCacheInfo, JSON] NixCacheInfo.NixCacheInfo,-        -- Hydra: src/lib/Hydra/View/NARInfo.pm-        narinfo ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> Capture "narinfohash" NarInfoHash.NarInfoHash-            :> Get '[XNixNarInfo, JSON] NarInfo.CachixNarInfo,-        narinfoHead ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> Capture "narinfohash" NarInfoHash.NarInfoHash-            :> Head,-        -- Hydra: src/lib/Hydra/View/NixNAR.pm-        nar ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "nar"-            :> Capture "nar" NarFileName-            :> StreamGet NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ()),-        -- cachix specific-        getCache ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> Get '[JSON] BinaryCache.BinaryCache,-        narinfoBulk ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "narinfo"-            :> Summary "Given a list of store hashes, return a list of those that are missing"-            :> ReqBody '[JSON] [Text]-            :> Post '[JSON] [Text],-        narURL ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "narurl"-            :> Capture "nar" NarFileName-            :> Get '[JSON] Text,-        createNarinfo ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> Capture "narinfohash" NarInfoHash.NarInfoHash-            :> ReqBody '[JSON] NarInfoCreate.NarInfoCreate-            :> Post '[JSON] NoContent,-        createNar ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "nar"-            :> StreamBody NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ())-            :> Post '[JSON] NoContent,-        serveNarContent ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "serve"-            :> Capture "storehash" Text-            :> CaptureAll "filepath" Text-            :> Summary "Serve a file from a given store path"-            :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text] ByteStringStreaming.LazyByteStringStreaming),-        createKey ::-          route-            :- CachixAuth-            :> "cache"-            :> Capture "name" Text-            :> "key"-            :> ReqBody '[JSON] SigningKeyCreate.SigningKeyCreate-            :> Post '[JSON] NoContent-      }+data BinaryCacheAPI route = BinaryCacheAPI+  { -- https://cache.nixos.org/nix-cache-info+    nixCacheInfo ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "nix-cache-info"+        :> Get '[XNixCacheInfo, JSON] NixCacheInfo.NixCacheInfo,+    -- Hydra: src/lib/Hydra/View/NARInfo.pm+    narinfo ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> Capture "narinfohash" NarInfoHash.NarInfoHash+        :> Get '[XNixNarInfo, JSON] (Headers '[Header "Cache-Control" Text] NarInfo.CachixNarInfo),+    narinfoHead ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> Capture "narinfohash" NarInfoHash.NarInfoHash+        :> Head,+    -- Hydra: src/lib/Hydra/View/NixNAR.pm+    nar ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "nar"+        :> Capture "nar" NarFileName+        :> StreamGet NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ()),+    -- cachix specific+    getCache ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> Get '[JSON] BinaryCache.BinaryCache,+    narinfoBulk ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "narinfo"+        :> Summary "Given a list of store hashes, return a list of those that are missing"+        :> ReqBody '[JSON] [Text]+        :> Post '[JSON] [Text],+    narURL ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "narurl"+        :> Capture "nar" NarFileName+        :> Get '[JSON] Text,+    createNarinfo ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> Capture "narinfohash" NarInfoHash.NarInfoHash+        :> ReqBody '[JSON] NarInfoCreate.NarInfoCreate+        :> Post '[JSON] NoContent,+    createNar ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "nar"+        :> StreamBody NoFraming XNixNar (ConduitT () ByteStringStreaming.ByteStringStreaming (ResourceT IO) ())+        :> Post '[JSON] NoContent,+    serveNarContent ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "serve"+        :> Capture "storehash" Text+        :> CaptureAll "filepath" Text+        :> Summary "Serve a file from a given store path"+        :> Get '[XNixNar] (Headers '[Header "X-Content-Type-Options" Text, Header "Cache-Control" Text] ByteStringStreaming.LazyByteStringStreaming),+    createKey ::+      route+        :- CachixAuth+        :> "cache"+        :> Capture "name" Text+        :> "key"+        :> ReqBody '[JSON] SigningKeyCreate.SigningKeyCreate+        :> Post '[JSON] NoContent+  }   deriving (Generic)  type API = "api" :> "v1" :> ToServantApi BinaryCacheAPI
+ src/Cachix/API/Deploy.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE TypeOperators #-}++module Cachix.API.Deploy where++import Cachix.API (CachixAuth)+import qualified Cachix.Types.ByteStringStreaming as ByteStringStreaming+import qualified Cachix.Types.Deploy as Deploy+import qualified Cachix.Types.DeployResponse as DeployResponse+import Conduit (ConduitT, ResourceT)+import qualified Data.UUID as UUID+import Protolude+import Servant.API+import Servant.API.Generic++data DeployAPI route = DeployAPI+  { activate ::+      route+        :- CachixAuth+        :> "deploy"+        :> "activate"+        :> ReqBody '[JSON] Deploy.Deploy+        :> Post '[JSON] DeployResponse.DeployResponse+  }+  deriving (Generic)++type API = "api" :> "v1" :> ToServantApi DeployAPI++api :: Proxy API+api = Proxy
+ src/Cachix/API/WebSocketSubprotocol.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DuplicateRecordFields #-}++module Cachix.API.WebSocketSubprotocol where++import qualified Control.Concurrent.Async as Async+import qualified Control.Concurrent.Chan as Chan+import qualified Data.Aeson as Aeson+import Data.Time (UTCTime)+import Data.UUID (UUID)+import qualified Network.WebSockets as WS+import Protolude++data Message cmd = Message+  { method :: Text,+    command :: cmd,+    agent :: Maybe UUID,+    id :: UUID+  }+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++data Cache = Cache+  { cacheName :: Text,+    publicKey :: Text,+    isPublic :: Bool+  }+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++data AgentInformation = AgentInformation+  { cache :: Maybe Cache,+    id :: UUID+  }+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++data DeploymentDetails = DeploymentDetails+  { storePath :: Text,+    id :: UUID,+    index :: Int64+  }+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++data BackendCommand+  = Deployment DeploymentDetails+  | AgentRegistered AgentInformation+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++data AgentCommand+  = DeploymentStarted {id :: UUID, time :: UTCTime}+  | DeploymentFinished {id :: UUID, time :: UTCTime, hasSucceeded :: Bool}+  deriving (Show, Eq, Generic, Aeson.FromJSON, Aeson.ToJSON)++parseMessage :: Aeson.FromJSON cmd => ByteString -> Either Text (Message cmd)+parseMessage body =+  case Aeson.eitherDecodeStrict' body of+    Left err -> Left $ toS err+    Right message -> Right message++sendMessage :: Aeson.ToJSON cmd => WS.Connection -> Message cmd -> IO ()+sendMessage connection cmd =+  WS.sendTextData connection $ Aeson.encode cmd++-- TODO: use Async.replicateConcurrently+recieveDataConcurrently :: WS.Connection -> (ByteString -> IO ()) -> IO ()+recieveDataConcurrently connection m = do+  channel <- Chan.newChan+  Async.race_ (producer channel) (consumer channel)+  where+    producer channel = forever $ do+      payload <- WS.receiveData connection+      Chan.writeChan channel payload+    consumer channel = forever $ do+      payload <- Chan.readChan channel+      m payload++data Log = Log+  { line :: Text,+    time :: UTCTime+  }+  deriving (Generic, Show, Aeson.ToJSON, Aeson.FromJSON)
src/Cachix/Types/BinaryCache.hs view
@@ -5,13 +5,12 @@ import Data.Swagger (ToSchema) import Protolude -data BinaryCache-  = BinaryCache-      { name :: Text,-        uri :: Text,-        isPublic :: Bool,-        publicSigningKeys :: [Text],-        githubUsername :: Text,-        permission :: Permission-      }+data BinaryCache = BinaryCache+  { name :: Text,+    uri :: Text,+    isPublic :: Bool,+    publicSigningKeys :: [Text],+    githubUsername :: Text,+    permission :: Permission+  }   deriving (Show, Generic, FromJSON, ToJSON, ToSchema, NFData)
src/Cachix/Types/ContentTypes.hs view
@@ -49,3 +49,9 @@  instance MimeRender XNixNar ByteStringStreaming.LazyByteStringStreaming where   mimeRender _ = coerce++instance MimeRender PlainText ByteStringStreaming.ByteStringStreaming where+  mimeRender _ = BSL.fromStrict . coerce++instance MimeUnrender PlainText ByteStringStreaming.ByteStringStreaming where+  mimeUnrender _ = Right . coerce . BSL.toStrict
+ src/Cachix/Types/Deploy.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE DeriveAnyClass #-}++module Cachix.Types.Deploy where++import Data.Aeson+  ( FromJSON,+    ToJSON,+  )+import Data.HashMap.Strict+import Data.Swagger (ToSchema)+import Protolude++newtype Deploy = Deploy+  { agents :: HashMap Text Text+  }+  deriving (Show, Generic, FromJSON, ToJSON, ToSchema)
+ src/Cachix/Types/DeployResponse.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE DeriveAnyClass #-}++module Cachix.Types.DeployResponse where++import Data.Aeson+  ( FromJSON,+    ToJSON,+  )+import Data.HashMap.Strict+import Data.Swagger (ToSchema)+import Protolude++newtype DeployResponse = DeployResponse+  { agents :: HashMap Text Text+  }+  deriving (Show, Generic, FromJSON, ToJSON, ToSchema, NFData)
src/Cachix/Types/NarFileName.hs view
@@ -9,11 +9,10 @@ import Servant.API  -- | <hash>.nar.<extension> file-data NarFileName-  = NarFileName-      { contentHash :: Text,-        extension :: Text-      }+data NarFileName = NarFileName+  { contentHash :: Text,+    extension :: Text+  }   deriving (Generic)  instance FromHttpApiData NarFileName where
src/Cachix/Types/NarInfoCreate.hs view
@@ -15,20 +15,19 @@ -- TODO: get rid of c prefix  -- | Client create type-data NarInfoCreate-  = NarInfoCreate-      { -- | \$storePrefix / $storeHash - $storeSuffix-        cStoreHash :: Text,-        -- | \$storePrefix / $storeHash - $storeSuffix-        cStoreSuffix :: Text,-        cNarHash :: Text,-        cNarSize :: Integer,-        cFileHash :: Text,-        cFileSize :: Integer,-        cReferences :: [Text],-        cDeriver :: Text,-        cSig :: Maybe Text-      }+data NarInfoCreate = NarInfoCreate+  { -- | \$storePrefix / $storeHash - $storeSuffix+    cStoreHash :: Text,+    -- | \$storePrefix / $storeHash - $storeSuffix+    cStoreSuffix :: Text,+    cNarHash :: Text,+    cNarSize :: Integer,+    cFileHash :: Text,+    cFileSize :: Integer,+    cReferences :: [Text],+    cDeriver :: Text,+    cSig :: Maybe Text+  }   deriving (Generic, Show, FromJSON, ToJSON, ToSchema)  data NarInfoInvalid
src/Cachix/Types/NixCacheInfo.hs view
@@ -4,10 +4,9 @@ import Data.Swagger (ToSchema) import Protolude -data NixCacheInfo-  = NixCacheInfo-      { storeDir :: Text,-        wantMassQuery :: Integer,-        priority :: Integer-      }+data NixCacheInfo = NixCacheInfo+  { storeDir :: Text,+    wantMassQuery :: Integer,+    priority :: Integer+  }   deriving (Generic, Show, FromJSON, ToJSON, ToSchema, NFData)
src/Cachix/Types/SigningKeyCreate.hs view
@@ -11,8 +11,7 @@ import Protolude  -- | Conveys that a signing secret key was created, by sharing the public key.-newtype SigningKeyCreate-  = SigningKeyCreate-      { publicKey :: Text-      }+newtype SigningKeyCreate = SigningKeyCreate+  { publicKey :: Text+  }   deriving (Show, Generic, FromJSON, ToJSON, ToSchema)