-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Wire.API.Deprecated
  ( Deprecated,
  )
where

import Control.Lens
import Data.Kind (Type)
import Data.Metrics.Servant
import Data.OpenApi hiding (HasServer)
import Imports
import Servant
import Servant.Client
import Servant.OpenApi

-- Annotate that the route is deprecated
data Deprecated deriving (Typeable)

-- All of these instances are very similar to the instances
-- for Summary. These don't impact the API directly, but are
-- for marking the deprecated flag in the openapi output.
instance (HasLink sub) => HasLink (Deprecated :> sub :: Type) where
  type MkLink (Deprecated :> sub) a = MkLink sub a
  toLink :: forall a.
(Link -> a)
-> Proxy (Deprecated :> sub)
-> Link
-> MkLink (Deprecated :> sub) a
toLink =
    let simpleToLink :: (Link -> a) -> Proxy (Deprecated :> sub) -> Link -> MkLink sub a
simpleToLink Link -> a
toA Proxy (Deprecated :> sub)
_ = (Link -> a) -> Proxy sub -> Link -> MkLink sub a
forall a. (Link -> a) -> Proxy sub -> Link -> MkLink sub a
forall {k} (endpoint :: k) a.
HasLink endpoint =>
(Link -> a) -> Proxy endpoint -> Link -> MkLink endpoint a
toLink Link -> a
toA (Proxy sub
forall {k} (t :: k). Proxy t
Proxy :: Proxy sub)
     in (Link -> a) -> Proxy (Deprecated :> sub) -> Link -> MkLink sub a
(Link -> a)
-> Proxy (Deprecated :> sub)
-> Link
-> MkLink (Deprecated :> sub) a
simpleToLink

instance (HasOpenApi api) => HasOpenApi (Deprecated :> api :: Type) where
  toOpenApi :: Proxy (Deprecated :> api) -> OpenApi
toOpenApi Proxy (Deprecated :> api)
_ =
    Proxy api -> OpenApi
forall {k} (api :: k). HasOpenApi api => Proxy api -> OpenApi
toOpenApi (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @api)
      OpenApi -> (OpenApi -> OpenApi) -> OpenApi
forall a b. a -> (a -> b) -> b
& (Operation -> Identity Operation) -> OpenApi -> Identity OpenApi
Traversal' OpenApi Operation
allOperations ((Operation -> Identity Operation) -> OpenApi -> Identity OpenApi)
-> ((Maybe Bool -> Identity (Maybe Bool))
    -> Operation -> Identity Operation)
-> (Maybe Bool -> Identity (Maybe Bool))
-> OpenApi
-> Identity OpenApi
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe Bool -> Identity (Maybe Bool))
-> Operation -> Identity Operation
forall s a. HasDeprecated s a => Lens' s a
Lens' Operation (Maybe Bool)
deprecated ((Maybe Bool -> Identity (Maybe Bool))
 -> OpenApi -> Identity OpenApi)
-> Bool -> OpenApi -> OpenApi
forall s t a b. ASetter s t a (Maybe b) -> b -> s -> t
?~ Bool
True

instance (HasServer api ctx) => HasServer (Deprecated :> api) ctx where
  type ServerT (Deprecated :> api) m = ServerT api m
  route :: forall env.
Proxy (Deprecated :> api)
-> Context ctx
-> Delayed env (Server (Deprecated :> api))
-> Router env
route Proxy (Deprecated :> api)
_ = Proxy api
-> Context ctx
-> Delayed env (Server api)
-> Router' env RoutingApplication
forall env.
Proxy api -> Context ctx -> Delayed env (Server api) -> Router env
forall {k} (api :: k) (context :: [*]) env.
HasServer api context =>
Proxy api
-> Context context -> Delayed env (Server api) -> Router env
route (Proxy api
 -> Context ctx
 -> Delayed env (Server api)
 -> Router' env RoutingApplication)
-> Proxy api
-> Context ctx
-> Delayed env (Server api)
-> Router' env RoutingApplication
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @api
  hoistServerWithContext :: forall (m :: * -> *) (n :: * -> *).
Proxy (Deprecated :> api)
-> Proxy ctx
-> (forall x. m x -> n x)
-> ServerT (Deprecated :> api) m
-> ServerT (Deprecated :> api) n
hoistServerWithContext Proxy (Deprecated :> api)
_ Proxy ctx
pc forall x. m x -> n x
nt ServerT (Deprecated :> api) m
s = Proxy api
-> Proxy ctx
-> (forall x. m x -> n x)
-> ServerT api m
-> ServerT api n
forall {k} (api :: k) (context :: [*]) (m :: * -> *) (n :: * -> *).
HasServer api context =>
Proxy api
-> Proxy context
-> (forall x. m x -> n x)
-> ServerT api m
-> ServerT api n
forall (m :: * -> *) (n :: * -> *).
Proxy api
-> Proxy ctx
-> (forall x. m x -> n x)
-> ServerT api m
-> ServerT api n
hoistServerWithContext (forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @api) Proxy ctx
pc m x -> n x
forall x. m x -> n x
nt ServerT api m
ServerT (Deprecated :> api) m
s

instance (HasClient m api) => HasClient m (Deprecated :> api) where
  type Client m (Deprecated :> api) = Client m api
  clientWithRoute :: Proxy m
-> Proxy (Deprecated :> api)
-> Request
-> Client m (Deprecated :> api)
clientWithRoute Proxy m
pm Proxy (Deprecated :> api)
_ = Proxy m -> Proxy api -> Request -> Client m api
forall (m :: * -> *) api.
HasClient m api =>
Proxy m -> Proxy api -> Request -> Client m api
clientWithRoute Proxy m
pm (Proxy api
forall {k} (t :: k). Proxy t
Proxy :: Proxy api)
  hoistClientMonad :: forall (mon :: * -> *) (mon' :: * -> *).
Proxy m
-> Proxy (Deprecated :> api)
-> (forall x. mon x -> mon' x)
-> Client mon (Deprecated :> api)
-> Client mon' (Deprecated :> api)
hoistClientMonad Proxy m
pm Proxy (Deprecated :> api)
_ forall x. mon x -> mon' x
f Client mon (Deprecated :> api)
cl = Proxy m
-> Proxy api
-> (forall x. mon x -> mon' x)
-> Client mon api
-> Client mon' api
forall (m :: * -> *) api (mon :: * -> *) (mon' :: * -> *).
HasClient m api =>
Proxy m
-> Proxy api
-> (forall x. mon x -> mon' x)
-> Client mon api
-> Client mon' api
forall (mon :: * -> *) (mon' :: * -> *).
Proxy m
-> Proxy api
-> (forall x. mon x -> mon' x)
-> Client mon api
-> Client mon' api
hoistClientMonad Proxy m
pm (Proxy api
forall {k} (t :: k). Proxy t
Proxy :: Proxy api) mon x -> mon' x
forall x. mon x -> mon' x
f Client mon api
Client mon (Deprecated :> api)
cl

instance (RoutesToPaths rest) => RoutesToPaths (Deprecated :> rest) where
  getRoutes :: Forest PathSegment
getRoutes = forall rest. RoutesToPaths rest => Forest PathSegment
forall {k} (routes :: k).
RoutesToPaths routes =>
Forest PathSegment
getRoutes @rest