-- SPDX-FileCopyrightText: 2026 Alexandra de Wit
--
-- SPDX-License-Identifier: MIT

{- | npm's entry in the ecosystem adapter registry. Every field names a function the
@Ecluse.Core.Registry.Npm.*@ modules export, so no protocol decision is made here.
-}
module Ecluse.Core.Registry.Npm.Adapter (
    npmAdapter,
    npmPublish,
) where

import Ecluse.Core.Ecosystem (Ecosystem (Npm))
import Ecluse.Core.Registry.Adapter.Capability (
    AdapterArtifact (..),
    AdapterMetadata (..),
    AdapterPublish (..),
 )
import Ecluse.Core.Registry.Adapter.Types (AdapterServe (..), RegistryAdapter (..))
import Ecluse.Core.Registry.Npm (relayPublishDocument)
import Ecluse.Core.Registry.Npm.Credential (npmCredential)
import Ecluse.Core.Registry.Npm.Filter (assembleMergedDocument, serialiseMergedDocument)
import Ecluse.Core.Registry.Npm.Maintenance (npmMaintenance)
import Ecluse.Core.Registry.Npm.Metadata (fetchNpmManifest, newNpmMetadataReads, npmChargeFactors)
import Ecluse.Core.Registry.Npm.Project (projectName)
import Ecluse.Core.Registry.Npm.Publish (declaredNames, npmPublishCodec)
import Ecluse.Core.Registry.Npm.Request qualified as NpmRequest
import Ecluse.Core.Registry.Npm.Route qualified as NpmRoute
import Ecluse.Core.Registry.Origin (OriginClient (ocToken), originBaseUrl)

-- | npm's capability record.
npmAdapter :: RegistryAdapter
npmAdapter :: RegistryAdapter
npmAdapter =
    RegistryAdapter
        { adapterEcosystem :: Ecosystem
adapterEcosystem = Ecosystem
Npm
        , adapterServe :: AdapterServe
adapterServe =
            AdapterServe
                { serveRouter :: MountRouter
serveRouter = MountRouter
NpmRoute.npmRouter
                , serveRoutes :: NonEmpty RouteSpec
serveRoutes = NonEmpty RouteSpec
NpmRoute.npmRouteSpecs
                , serveCredential :: CredentialMapping
serveCredential = CredentialMapping
npmCredential
                }
        , adapterMetadata :: AdapterMetadata
adapterMetadata =
            AdapterMetadata
                { metadataNewReads :: forall posture.
TracingPort
-> MetricsPort
-> (PackageName -> MetadataError -> IO ())
-> (PackageName -> [InvalidEntry] -> IO ())
-> (PackageName -> IO ())
-> OriginFor posture
-> MetadataReads posture
metadataNewReads = TracingPort
-> MetricsPort
-> (PackageName -> MetadataError -> IO ())
-> (PackageName -> [InvalidEntry] -> IO ())
-> (PackageName -> IO ())
-> OriginFor posture
-> MetadataReads posture
forall posture.
TracingPort
-> MetricsPort
-> (PackageName -> MetadataError -> IO ())
-> (PackageName -> [InvalidEntry] -> IO ())
-> (PackageName -> IO ())
-> OriginFor posture
-> MetadataReads posture
newNpmMetadataReads
                , metadataAssemble :: Text
-> Map SourceId (Snapshot CachedDoc)
-> MergePlan
-> Maybe CachedDoc
-> CachedDoc
metadataAssemble = Text
-> Map SourceId (Snapshot CachedDoc)
-> MergePlan
-> Maybe CachedDoc
-> CachedDoc
assembleMergedDocument
                , metadataSerialise :: CachedDoc -> Either RenderRefused LByteString
metadataSerialise = CachedDoc -> Either RenderRefused LByteString
serialiseMergedDocument
                , metadataFetchManifest :: ManifestFetch
metadataFetchManifest = ManifestFetch
fetchNpmManifest
                , metadataChargeFactors :: ChargeFactors
metadataChargeFactors = ChargeFactors
npmChargeFactors
                }
        , adapterArtifact :: AdapterArtifact
adapterArtifact =
            AdapterArtifact
                { artifactByFile :: OriginClient
-> PackageName -> Text -> Either UrlFormationError Request
artifactByFile = \OriginClient
origin -> Text
-> Maybe ClientCredential
-> PackageName
-> Text
-> Either UrlFormationError Request
NpmRequest.artifactRequestByFile (OriginClient -> Text
originBaseUrl OriginClient
origin) (OriginClient -> Maybe ClientCredential
ocToken OriginClient
origin)
                , artifactByUrl :: Maybe ClientCredential -> Text -> Either UrlFormationError Request
artifactByUrl = Maybe ClientCredential -> Text -> Either UrlFormationError Request
NpmRequest.artifactRequestByUrl
                , artifactHosts :: [Text]
artifactHosts = [Text]
NpmRequest.npmArtifactHosts
                }
        , adapterProjectName :: ProjectName
adapterProjectName = Either ParseError PackageName -> Maybe PackageName
forall l r. Either l r -> Maybe r
rightToMaybe (Either ParseError PackageName -> Maybe PackageName)
-> (Text -> Either ParseError PackageName) -> ProjectName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either ParseError PackageName
projectName
        , adapterPublish :: Maybe AdapterPublish
adapterPublish = AdapterPublish -> Maybe AdapterPublish
forall a. a -> Maybe a
Just AdapterPublish
npmPublish
        , adapterMaintenance :: AdapterMaintenance
adapterMaintenance = AdapterMaintenance
npmMaintenance
        }

-- | npm's publish capability, named so a consumer of it alone need not unwrap the optional field.
npmPublish :: AdapterPublish
npmPublish :: AdapterPublish
npmPublish =
    AdapterPublish
        { publishRelay :: OriginClient
-> PackageName
-> ByteString
-> IO (Either FetchFault PublishRelayResponse)
publishRelay = OriginClient
-> PackageName
-> ByteString
-> IO (Either FetchFault PublishRelayResponse)
relayPublishDocument
        , publishDeclaredNames :: LByteString -> [Text]
publishDeclaredNames = LByteString -> [Text]
declaredNames
        , publishCodec :: PublishCodec
publishCodec = PublishCodec
npmPublishCodec
        }