{- |
Module      : Servant.API.Routes.Path
Copyright   : (c) Frederick Pringle, 2025
License     : BSD-3-Clause
Maintainer  : freddyjepringle@gmail.com

Simple representation of URL paths.
-}
module Servant.API.Routes.Path
  ( Path
  , prependPathPart
  , prependCapturePart
  , prependCaptureAllPart
  , renderPath
  , rootPath
  )
where

import qualified Data.Text as T
import Data.Typeable
import "this" Servant.API.Routes.Internal.Path
import "this" Servant.API.Routes.Utils

-- | @"/"@
rootPath :: Path
rootPath :: Path
rootPath = [PathPart] -> Path
Path []

{- | Prepend a simple text path part to an API path.

For example, @prependPathPart "api"@ will transform @\/v2\/users@ to @\/api\/v2\/users@.
-}
prependPathPart :: T.Text -> Path -> Path
prependPathPart :: Text -> Path -> Path
prependPathPart Text
part (Path [PathPart]
parts) =
  [PathPart] -> Path
Path ([PathPart]
splitParts forall a. Semigroup a => a -> a -> a
<> [PathPart]
parts)
  where
    splitParts :: [PathPart]
splitParts = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> PathPart
StringPart forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null) forall a b. (a -> b) -> a -> b
$ Text -> Text -> [Text]
T.splitOn Text
pathSeparator Text
part

{- | Prepend a capture path part of a given type to an API path.
Equivalent to @'Servant.API.Capture' name a :>@.

For example, @prependCapturePart \@Int "id"@ will transform @\/detail@ to @\/\<Int>\/detail@.
-}
prependCapturePart ::
  forall a.
  Typeable a =>
  T.Text ->
  Path ->
  Path
prependCapturePart :: forall a. Typeable a => Text -> Path -> Path
prependCapturePart Text
name (Path [PathPart]
parts) =
  [PathPart] -> Path
Path (PathPart
capture forall a. a -> [a] -> [a]
: [PathPart]
parts)
  where
    capture :: PathPart
capture = Text -> TypeRep -> PathPart
CapturePart Text
name forall a b. (a -> b) -> a -> b
$ forall a. Typeable a => TypeRep
typeRepOf @a

{- | Prepend a capture-all path part of a given type to an API path.
Equivalent to @'Servant.API.CaptureAll' name a :>@.

For example, @prependCaptureAllPart \@Int "id"@ will transform @\/detail@ to @\/\<[Int]>\/detail@.
-}
prependCaptureAllPart ::
  forall a.
  Typeable a =>
  T.Text ->
  Path ->
  Path
prependCaptureAllPart :: forall a. Typeable a => Text -> Path -> Path
prependCaptureAllPart Text
name (Path [PathPart]
parts) =
  [PathPart] -> Path
Path (PathPart
capture forall a. a -> [a] -> [a]
: [PathPart]
parts)
  where
    capture :: PathPart
capture = Text -> TypeRep -> PathPart
CaptureAllPart Text
name forall a b. (a -> b) -> a -> b
$ forall a. Typeable a => TypeRep
typeRepOf @a