packages feed

link-canonical-effectful-0.1.0.0: src/Effectful/Link/Canonical.hs

module Effectful.Link.Canonical
  ( -- * Effect
    LinkCanonical (..),

    -- * Operations
    normalizeLink,
    normalizeWithDefaults,

    -- * Handlers
    runLinkCanonical,

    -- * HTTP effect
    HttpHead (..),
    headRequest,
    runHttpHead,

    -- * Pure normalization (re-export)
    Core.normalizeUri,

    -- * Configuration (re-exports)
    Core.NormConfig (..),
    Core.RedirectConfig (..),
    Core.TrackingConfig (..),
    Core.TrailingSlash (..),
    Core.defaultConfig,
    Core.defaultRedirectConfig,
    Core.defaultTrackingConfig,
    Core.defaultTrackingParams,

    -- * Result types (re-exports)
    Core.NormResult (..),
    Core.NormTrace (..),

    -- * Error types (re-exports)
    Core.NormError (..),
    Core.RedirectError (..),
    Core.HttpClientError (..),

    -- * Domain rules (re-exports)
    Core.DomainRule (..),
    Core.defaultDomainRules,

    -- * Observability (re-exports)
    Core.NormHooks (..),

    -- * URI (re-exports)
    URI,
    mkURI,
  )
where

import Effectful
import Effectful.Dispatch.Dynamic
import Effectful.Link.Canonical.Http (HttpHead (..), headRequest, runHttpHead)
import Link.Canonical qualified as Core
import Text.URI (URI, mkURI)

-- | Effect for URL canonicalization.
--
-- Provides the same two IO-dependent operations as the core library's
-- public API: full normalization with redirect resolution, and a
-- convenience wrapper with default configuration.
data LinkCanonical :: Effect where
  NormalizeLink :: Core.NormConfig -> URI -> LinkCanonical m (Either Core.NormError Core.NormResult)
  NormalizeWithDefaults :: URI -> LinkCanonical m (Either Core.NormError URI)

type instance DispatchOf LinkCanonical = Dynamic

-- | Normalize a URL with full redirect resolution and domain-specific rules.
normalizeLink :: (LinkCanonical :> es) => Core.NormConfig -> URI -> Eff es (Either Core.NormError Core.NormResult)
normalizeLink config uri = send $ NormalizeLink config uri

-- | Normalize a URL using default configuration, returning only the canonical URI.
normalizeWithDefaults :: (LinkCanonical :> es) => URI -> Eff es (Either Core.NormError URI)
normalizeWithDefaults = send . NormalizeWithDefaults

-- | Run the 'LinkCanonical' effect by delegating to the core library.
--
-- Requires 'HttpHead' in the effect stack for redirect resolution.
runLinkCanonical :: (HttpHead :> es) => Eff (LinkCanonical : es) a -> Eff es a
runLinkCanonical = interpret $ \_ -> \case
  NormalizeLink config uri -> Core.normalizeLink config uri
  NormalizeWithDefaults uri -> Core.normalizeWithDefaults uri