module Ecluse.Core.Registry.Publish (
PublishCodec (..),
MirrorTransport (..),
MirrorPublish (..),
newMirrorPublish,
) where
import Network.HTTP.Client (
HttpException,
Manager,
Request,
Response (responseStatus),
httpLbs,
)
import Network.HTTP.Types.Status (statusCode)
import UnliftIO (try)
import Ecluse.Core.Credential (Secret)
import Ecluse.Core.Fault.Http (classifyTransport)
import Ecluse.Core.Package (PackageName)
import Ecluse.Core.Registry (
FetchFault (FetchUrlUnformable),
MirrorArtifact,
ParseError,
PublishFault (PublishTransport, PublishUrlUnformable),
RegistryResponse,
UrlFormationError,
)
import Ecluse.Core.Registry.Exchange (boundedFetch)
import Ecluse.Core.Security (Limits)
import Ecluse.Core.Version (Version)
data PublishCodec = PublishCodec
{ PublishCodec
-> Text
-> Maybe Secret
-> PackageName
-> Either UrlFormationError Request
pcProbeRequest :: Text -> Maybe Secret -> PackageName -> Either UrlFormationError Request
, PublishCodec -> RegistryResponse -> Either ParseError [Version]
pcParseVersionList :: RegistryResponse -> Either ParseError [Version]
, PublishCodec
-> Text
-> Maybe Secret
-> PackageName
-> Version
-> MirrorArtifact
-> ByteString
-> Either UrlFormationError Request
pcPublishRequest :: Text -> Maybe Secret -> PackageName -> Version -> MirrorArtifact -> ByteString -> Either UrlFormationError Request
, PublishCodec -> Int -> Either PublishFault ()
pcPublishOutcome :: Int -> Either PublishFault ()
}
data MirrorTransport = MirrorTransport
{ MirrorTransport -> Manager
ptManager :: Manager
, MirrorTransport -> IO (Maybe Secret)
ptMintToken :: IO (Maybe Secret)
, MirrorTransport -> Limits
ptLimits :: Limits
}
data MirrorPublish = MirrorPublish
{ MirrorPublish
-> PackageName -> IO (Either FetchFault RegistryResponse)
mpProbeMetadata :: PackageName -> IO (Either FetchFault RegistryResponse)
, MirrorPublish -> RegistryResponse -> Either ParseError [Version]
mpParseVersionList :: RegistryResponse -> Either ParseError [Version]
, MirrorPublish
-> PackageName
-> Version
-> MirrorArtifact
-> ByteString
-> IO (Either PublishFault ())
mpPublishArtifact :: PackageName -> Version -> MirrorArtifact -> ByteString -> IO (Either PublishFault ())
}
newMirrorPublish :: MirrorTransport -> Text -> PublishCodec -> MirrorPublish
newMirrorPublish :: MirrorTransport -> Text -> PublishCodec -> MirrorPublish
newMirrorPublish MirrorTransport
transport Text
targetUrl PublishCodec
codec =
MirrorPublish
{ mpProbeMetadata :: PackageName -> IO (Either FetchFault RegistryResponse)
mpProbeMetadata = MirrorTransport
-> Text
-> PublishCodec
-> PackageName
-> IO (Either FetchFault RegistryResponse)
probeMetadata MirrorTransport
transport Text
targetUrl PublishCodec
codec
, mpParseVersionList :: RegistryResponse -> Either ParseError [Version]
mpParseVersionList = PublishCodec -> RegistryResponse -> Either ParseError [Version]
pcParseVersionList PublishCodec
codec
, mpPublishArtifact :: PackageName
-> Version
-> MirrorArtifact
-> ByteString
-> IO (Either PublishFault ())
mpPublishArtifact = MirrorTransport
-> Text
-> PublishCodec
-> PackageName
-> Version
-> MirrorArtifact
-> ByteString
-> IO (Either PublishFault ())
publishArtifact MirrorTransport
transport Text
targetUrl PublishCodec
codec
}
probeMetadata :: MirrorTransport -> Text -> PublishCodec -> PackageName -> IO (Either FetchFault RegistryResponse)
probeMetadata :: MirrorTransport
-> Text
-> PublishCodec
-> PackageName
-> IO (Either FetchFault RegistryResponse)
probeMetadata MirrorTransport
transport Text
targetUrl PublishCodec
codec PackageName
name = do
token <- MirrorTransport -> IO (Maybe Secret)
ptMintToken MirrorTransport
transport
case pcProbeRequest codec targetUrl token name of
Left UrlFormationError
urlErr -> Either FetchFault RegistryResponse
-> IO (Either FetchFault RegistryResponse)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FetchFault -> Either FetchFault RegistryResponse
forall a b. a -> Either a b
Left (UrlFormationError -> FetchFault
FetchUrlUnformable UrlFormationError
urlErr))
Right Request
request ->
Manager
-> Limits -> Request -> IO (Either FetchFault RegistryResponse)
boundedFetch (MirrorTransport -> Manager
ptManager MirrorTransport
transport) (MirrorTransport -> Limits
ptLimits MirrorTransport
transport) Request
request
publishArtifact :: MirrorTransport -> Text -> PublishCodec -> PackageName -> Version -> MirrorArtifact -> ByteString -> IO (Either PublishFault ())
publishArtifact :: MirrorTransport
-> Text
-> PublishCodec
-> PackageName
-> Version
-> MirrorArtifact
-> ByteString
-> IO (Either PublishFault ())
publishArtifact MirrorTransport
transport Text
targetUrl PublishCodec
codec PackageName
name Version
version MirrorArtifact
artifact ByteString
bytes = do
token <- MirrorTransport -> IO (Maybe Secret)
ptMintToken MirrorTransport
transport
case pcPublishRequest codec targetUrl token name version artifact bytes of
Left UrlFormationError
urlErr -> Either PublishFault () -> IO (Either PublishFault ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (PublishFault -> Either PublishFault ()
forall a b. a -> Either a b
Left (UrlFormationError -> PublishFault
PublishUrlUnformable UrlFormationError
urlErr))
Right Request
request ->
IO (Response ByteString)
-> IO (Either HttpException (Response ByteString))
forall (m :: * -> *) e a.
(MonadUnliftIO m, Exception e) =>
m a -> m (Either e a)
try (Request -> Manager -> IO (Response ByteString)
httpLbs Request
request (MirrorTransport -> Manager
ptManager MirrorTransport
transport)) IO (Either HttpException (Response ByteString))
-> (Either HttpException (Response ByteString)
-> Either PublishFault ())
-> IO (Either PublishFault ())
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \case
Left (HttpException
err :: HttpException) -> PublishFault -> Either PublishFault ()
forall a b. a -> Either a b
Left (TransportFault -> PublishFault
PublishTransport (HttpException -> TransportFault
classifyTransport HttpException
err))
Right Response ByteString
response -> PublishCodec -> Int -> Either PublishFault ()
pcPublishOutcome PublishCodec
codec (Status -> Int
statusCode (Response ByteString -> Status
forall body. Response body -> Status
responseStatus Response ByteString
response))