git.iko.soy/typeable/servant-prune
on main help sign in
Initial commit
commita3671cfb49f533d3ba1bed6a490fbbd886525b8c authormniip <mniip@mniip.com> dateThu 27 Oct 2022, 13:44 (4 years ago)
4 files changed+78
.gitignore+3 LICENSE+2 servant-prune.cabal+19 src/Servant/API/TypeLevel/Prune.hs+54
.gitignorenew file+3
@@ -0,0 +1,3 @@
1+.stack-work
2+*~
3+*.swp
LICENSEnew file+2
@@ -0,0 +1,2 @@
1+Copyright © 2022, Antorica LLC
2+All rights reserved
servant-prune.cabalnew file+19
@@ -0,0 +1,19 @@
1+cabal-version: 2.4
2+name: servant-prune
3+version: 0.1.0.0
4+synopsis: Filter servant APIs
5+description: Filter servant APIs.
6+license-file: LICENSE
7+build-type: Simple
8+
9+library
10+ hs-source-dirs: src
11+ ghc-options: -Wall -Wextra -Werror
12+ exposed-modules: Servant.API.TypeLevel.Prune
13+ default-language: Haskell2010
14+ default-extensions: DataKinds
15+ , PolyKinds
16+ , TypeFamilies
17+ , TypeOperators
18+ build-depends: base
19+ , servant
src/Servant/API/TypeLevel/Prune.hsnew file+54
@@ -0,0 +1,54 @@
1+{-# LANGUAGE UndecidableInstances #-}
2+module Servant.API.TypeLevel.Prune
3+ ( Prune
4+ , Wild
5+ )
6+ where
7+
8+import Servant.API
9+import Servant.API.TypeLevel
10+
11+
12+-- | On the left hand side of 'IsElem' and 'Prune',
13+-- @UVerb ... ... '[Wild]@ will match any return result type.
14+data Wild
15+type instance IsElem' (UVerb m ct '[Wild]) (Verb m s ct' _) = IsSubList ct ct'
16+type instance IsElem' (UVerb m ct '[Wild]) (UVerb m ct' _) = IsSubList ct ct'
17+
18+type instance IsElem' sa (Description _ :> sb) = IsElem sa sb
19+type instance IsElem' sa (AuthProtect _ :> sb) = IsElem sa sb
20+type instance IsElem' sa (QueryParam' _ _ _ :> sb) = IsElem sa sb
21+
22+-- | Restrict the API in @api@ to the endpoints in @mask@. This works similarly
23+-- to 'IsElem' in that the @mask@ doesn't have to specify non-path parameters.
24+-- Additionally, 'Wild' can be used as a wildcard for the return type of a
25+-- request.
26+type family Prune (mask :: *) (api :: *) :: * where
27+ -- The instances mimic 'IsElem' and the 'IsElem'' instances above
28+ Prune sa (sb :<|> sc) = Prune sa sb ?<|> Prune sa sc
29+ Prune (e :> sa) (e :> sb) = e ?> Prune sa sb
30+ Prune sa (Header sym x :> sb) = Header sym x ?> Prune sa sb
31+ Prune sa (ReqBody y x :> sb) = ReqBody y x ?> Prune sa sb
32+ Prune (CaptureAll z y :> sa) (CaptureAll x y :> sb) = CaptureAll x y ?> Prune sa sb
33+ Prune (Capture z y :> sa) (Capture x y :> sb) = Capture x y ?> Prune sa sb
34+ Prune sa (QueryParam' x y z :> sb) = QueryParam' x y z ?> Prune sa sb
35+ Prune sa (QueryParams x y :> sb) = QueryParams x y ?> Prune sa sb
36+ Prune sa (QueryFlag x :> sb) = QueryFlag x ?> Prune sa sb
37+ Prune sa (Fragment x :> sb) = Fragment x ?> Prune sa sb
38+ Prune sa (Description x :> sb) = Description x ?> Prune sa sb
39+ Prune sa (AuthProtect x :> sb) = AuthProtect x ?> Prune sa sb
40+ Prune (Verb m s ct typ) (Verb m s ct typ) = Verb m s ct typ
41+ Prune (UVerb m ct typs) (UVerb m ct typs) = UVerb m ct typs
42+ Prune (UVerb m ct '[Wild]) (Verb m s ct typ) = Verb m s ct typ
43+ Prune (UVerb m ct '[Wild]) (UVerb m ct typs) = UVerb m ct typs
44+ Prune (sa :<|> sb) sc = Prune sa sc ?<|> Prune sb sc
45+ Prune sa sb = EmptyAPI
46+
47+type family (?>) (path :: k) (api :: *) :: * where
48+ path ?> EmptyAPI = EmptyAPI
49+ path ?> api = path :> api
50+
51+type family (?<|>) (api :: *) (api' :: *) :: * where
52+ EmptyAPI ?<|> sa = sa
53+ sa ?<|> EmptyAPI = sa
54+ sa ?<|> sb = sa :<|> sb