packages feed

mu-rpc 0.4.0.1 → 0.5.0.0

raw patch · 5 files changed

+100/−30 lines, 5 filessetup-changedPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Mu.Rpc: OneOf :: serviceName -> [serviceName] -> Service serviceName methodName argName tyRef
+ Mu.Rpc: instance (GHC.TypeLits.KnownSymbol s, Mu.Rpc.KnownSymbols ss) => Mu.Rpc.KnownSymbols (s : ss)
+ Mu.Rpc: instance (GHC.TypeLits.KnownSymbol sname, Mu.Rpc.KnownSymbols elts) => Mu.Rpc.ReflectService ('Mu.Rpc.OneOf sname elts)
+ Mu.Rpc: instance Mu.Rpc.KnownSymbols '[]
+ Mu.Rpc: type Union = 'OneOf
+ Mu.Server: [OneOfSvc] :: (MappingRight chn sname -> m (UnionChoice chn elts)) -> ServiceT chn info ('OneOf sname elts) m '[]
+ Mu.Server: [ProperSvc] :: HandlersT chn info (MappingRight chn sname) methods m hs -> ServiceT chn info ('Service sname methods) m hs
+ Mu.Server: [UnionChoice] :: (InUnion elt elts, Typeable elt) => Proxy elt -> MappingRight chn elt -> UnionChoice chn elts
+ Mu.Server: data ServiceT chn info svc m hs
+ Mu.Server: data UnionChoice chn elts
+ Mu.Server: instance forall serviceName mnm anm (name :: serviceName) (chn :: Mu.Schema.Definition.Mappings serviceName *) (m :: * -> *) (elts :: [serviceName]) (nl :: [(GHC.Types.Symbol, *)]) info (ss :: [Mu.Rpc.Service serviceName mnm anm (Mu.Rpc.TypeRef serviceName)]) (hs :: [[*]]). (Mu.Server.FindService name (Mu.Schema.Definition.MappingRight chn name -> m (Mu.Server.UnionChoice chn elts)) nl, Mu.Server.ToServices chn info ss m hs nl) => Mu.Server.ToServices chn info ('Mu.Rpc.OneOf name elts : ss) m ('[] : hs) nl
+ Mu.Server: union :: forall sname chn m elts. (MappingRight chn sname -> m (UnionChoice chn elts)) -> Named sname (MappingRight chn sname -> m (UnionChoice chn elts))
+ Mu.Server: unionChoice :: forall elt elts chn. (InUnion elt elts, Typeable elt) => MappingRight chn elt -> UnionChoice chn elts
- Mu.Rpc: RpcInfo :: Package Text Text Text TyInfo -> Service Text Text Text TyInfo -> Method Text Text Text TyInfo -> RequestHeaders -> i -> RpcInfo i
+ Mu.Rpc: RpcInfo :: Package Text Text Text TyInfo -> Service Text Text Text TyInfo -> Maybe (Method Text Text Text TyInfo) -> RequestHeaders -> i -> RpcInfo i
- Mu.Rpc: [methodInfo] :: RpcInfo i -> Method Text Text Text TyInfo
+ Mu.Rpc: [methodInfo] :: RpcInfo i -> Maybe (Method Text Text Text TyInfo)
- Mu.Rpc.Examples: type ApolloBookAuthor = '["Book" :-> (String, Integer), "Author" :-> Integer]
+ Mu.Rpc.Examples: type ApolloBookAuthor = '["Book" :-> (String, Integer), "Paper" :-> (String, Integer), "Writing" :-> Either (String, Integer) (String, Integer), "Author" :-> Integer]
- Mu.Rpc.Examples: type ApolloService = 'Package ('Just "apollo") '[Object "Book" '[ObjectField "title" '[] ('RetSingle ('PrimitiveRef String)), ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))], Object "Author" '[ObjectField "name" '[] ('RetSingle ('PrimitiveRef String)), ObjectField "books" '[] ('RetSingle ('ListRef ('ObjectRef "Book")))]]
+ Mu.Rpc.Examples: type ApolloService = 'Package ('Just "apollo") '[Object "Book" '[ObjectField "title" '[] ('RetSingle ('PrimitiveRef String)), ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))], Object "Paper" '[ObjectField "title" '[] ('RetSingle ('PrimitiveRef String)), ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))], Union "Writing" ["Book", "Paper"], Object "Author" '[ObjectField "name" '[] ('RetSingle ('PrimitiveRef String)), ObjectField "writings" '[] ('RetSingle ('ListRef ('ObjectRef "Writing")))]]
- Mu.Server: [:<&>:] :: HandlersT chn info (MappingRight chn sname) methods m hs -> ServicesT chn info rest m hss -> ServicesT chn info ('Service sname methods : rest) m (hs : hss)
+ Mu.Server: [:<&>:] :: ServiceT chn info svc m hs -> ServicesT chn info rest m hss -> ServicesT chn info (svc : rest) m (hs : hss)

Files

Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple+import           Distribution.Simple main = defaultMain
mu-rpc.cabal view
@@ -1,5 +1,5 @@ name:               mu-rpc-version:            0.4.0.1+version:            0.5.0.0 synopsis:           Protocol-independent declaration of services and servers. description:   Protocol-independent declaration of services and servers for mu-haskell.@@ -33,7 +33,7 @@     , conduit           >=1.3.2 && <1.4     , http-types        >=0.12  && <0.13     , mtl               >=2.2   && <2.3-    , mu-schema         ==0.3.*+    , mu-schema         >=0.3   && <0.4     , sop-core          >=0.5   && <0.6     , template-haskell  >=2.14  && <2.17     , text              >=1.2   && <1.3
src/Mu/Rpc.hs view
@@ -20,7 +20,7 @@ -} module Mu.Rpc (   Package', Package(..)-, Service', Service(..), Object+, Service', Service(..), Object, Union , Method', Method(..), ObjectField , LookupService, LookupMethod , TypeRef(..), Argument', Argument(..), Return(..)@@ -56,6 +56,7 @@ data Service serviceName methodName argName tyRef   = Service serviceName             [Method serviceName methodName argName tyRef]+  | OneOf serviceName [serviceName]  -- | A method is defined by its name, arguments, and return type. data Method serviceName methodName argName tyRef@@ -66,6 +67,8 @@ -- Synonyms for GraphQL -- | An object is a set of fields, in GraphQL lingo. type Object = 'Service+-- | A union is one of the objects.+type Union = 'OneOf -- | A field in an object takes some input objects, --   and returns a value or some other object, --   in GraphQL lingo.@@ -76,6 +79,7 @@               :: Service snm mnm anm tr where   LookupService '[] s = TypeError ('Text "could not find method " ':<>: 'ShowType s)   LookupService ('Service s ms ': ss) s = 'Service s ms+  LookupService ('OneOf   s ms ': ss) s = 'OneOf   s ms   LookupService (other         ': ss) s = LookupService ss s  -- | Look up a method in a service definition using its name.@@ -136,7 +140,7 @@   = NoRpcInfo   | RpcInfo { packageInfo :: Package Text Text Text TyInfo             , serviceInfo :: Service Text Text Text TyInfo-            , methodInfo  :: Method  Text Text Text TyInfo+            , methodInfo  :: Maybe (Method Text Text Text TyInfo)             , headers     :: RequestHeaders             , extraInfo   :: i             }@@ -150,10 +154,15 @@ instance Show (RpcInfo i) where   show NoRpcInfo     = "<no info>"-  show (RpcInfo (Package Nothing _) (Service s _) (Method m _ _) _ _)-    = T.unpack (s <> ":" <> m)-  show (RpcInfo (Package (Just p) _) (Service s _) (Method m _ _) _ _)-    = T.unpack (p <> ":" <> s <> ":" <> m)+  show (RpcInfo (Package p _) s m _ _)+    = T.unpack $ showPkg p (showMth m (showSvc s))+    where+      showPkg Nothing    = id+      showPkg (Just pkg) = ((pkg <> ":") <>)+      showMth Nothing                = id+      showMth (Just (Method mt _ _)) = (<> (":" <> mt))+      showSvc (Service sv _) = sv+      showSvc (OneOf   sv _) = sv  class ReflectRpcInfo (p :: Package') (s :: Service') (m :: Method') where   reflectRpcInfo :: Proxy p -> Proxy s -> Proxy m -> RequestHeaders -> i -> RpcInfo i@@ -175,6 +184,13 @@ instance (KnownSymbol s) => KnownMaySymbol ('Just s) where   maySymbolVal _ = Just $ T.pack $ symbolVal (Proxy @s) +class KnownSymbols (m :: [Symbol]) where+  symbolsVal :: Proxy m -> [Text]+instance KnownSymbols '[] where+  symbolsVal _ = []+instance (KnownSymbol s, KnownSymbols ss) => KnownSymbols (s ': ss) where+  symbolsVal _ = T.pack (symbolVal (Proxy @s)) : symbolsVal (Proxy @ss)+ class ReflectServices (ss :: [Service']) where   reflectServices :: Proxy ss -> [Service Text Text Text TyInfo] instance ReflectServices '[] where@@ -204,13 +220,19 @@   reflectRpcInfo _ ps pm req extra     = RpcInfo (Package (maySymbolVal (Proxy @pname))                        (reflectServices (Proxy @ss)))-              (reflectService ps) (reflectMethod pm) req extra+              (reflectService ps) (Just (reflectMethod pm)) req extra  instance (KnownSymbol sname, ReflectMethods ms)          => ReflectService ('Service sname ms) where   reflectService _     = Service (T.pack $ symbolVal (Proxy @sname))               (reflectMethods (Proxy @ms))++instance (KnownSymbol sname, KnownSymbols elts)+         => ReflectService ('OneOf sname elts) where+  reflectService _+    = OneOf (T.pack $ symbolVal (Proxy @sname))+            (symbolsVal (Proxy @elts))  instance (KnownSymbol mname, ReflectArgs args, ReflectReturn r)          => ReflectMethod ('Method mname args r) where
src/Mu/Rpc/Examples.hs view
@@ -105,30 +105,43 @@ type ApolloService   = 'Package ('Just "apollo")       '[ Object "Book"-        '[ ObjectField "title" '[] ('RetSingle ('PrimitiveRef String))-        , ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))-        ]-      , Object "Author"-        '[ ObjectField "name" '[] ('RetSingle ('PrimitiveRef String))-        , ObjectField "books" '[] ('RetSingle ('ListRef ('ObjectRef "Book")))-        ]+         '[ ObjectField "title" '[] ('RetSingle ('PrimitiveRef String))+          , ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))+          ]+      ,  Object "Paper"+         '[ ObjectField "title" '[] ('RetSingle ('PrimitiveRef String))+          , ObjectField "author" '[] ('RetSingle ('ObjectRef "Author"))+          ]+      ,  Union "Writing" ["Book", "Paper"]+      ,  Object "Author"+         '[ ObjectField "name" '[] ('RetSingle ('PrimitiveRef String))+          , ObjectField "writings" '[] ('RetSingle ('ListRef ('ObjectRef "Writing")))+          ]       ]  type ApolloBookAuthor = '[-    "Book"   ':-> (String, Integer)-  , "Author" ':-> Integer+    "Book"    ':-> (String, Integer)+  , "Paper"   ':-> (String, Integer)+  , "Writing" ':-> Either (String, Integer) (String, Integer)+  , "Author"  ':-> Integer   ]  apolloServer :: forall m i. (MonadServer m)              => ServerT ApolloBookAuthor i ApolloService m _ apolloServer   = resolver-      ( object @"Author" ( field @"name"   authorName-                         , field @"books"  authorBooks )+      ( object @"Author" ( field @"name"     authorName+                         , field @"writings" authorWrs )       , object @"Book"   ( field @"author" (pure . snd)-                         , field @"title"  (pure . fst) ) )+                         , field @"title"  (pure . fst) )+      , object @"Paper"  ( field @"author" (pure . snd)+                         , field @"title"  (pure . fst) )+      , union @"Writing" writing )   where     authorName :: Integer -> m String     authorName _ = pure "alex"  -- this would run in the DB-    authorBooks :: Integer -> m [(String, Integer)]-    authorBooks _ = pure []+    authorWrs :: Integer -> m [Either (String, Integer) (String, Integer)]+    authorWrs _ = pure []++    writing (Left  c) = pure $ unionChoice @"Book" c+    writing (Right c) = pure $ unionChoice @"Paper" c
src/Mu/Server.hs view
@@ -1,3 +1,4 @@+{-# language AllowAmbiguousTypes       #-} {-# language CPP                       #-} {-# language ConstraintKinds           #-} {-# language DataKinds                 #-}@@ -54,12 +55,13 @@   -- ** Definitions by name , singleService , method, methodWithInfo-, resolver, object+, resolver, object, union , field, fieldWithInfo+, UnionChoice(..), unionChoice , NamedList(..)   -- ** Definitions by position , SingleServerT, pattern Server-, ServerT(..), ServicesT(..), HandlersT(.., (:<||>:), (:<|>:))+, ServerT(..), ServicesT(..), ServiceT(..), HandlersT(.., (:<||>:), (:<|>:))   -- ** Simple servers using only IO , ServerErrorIO, ServerIO   -- * Errors which might be raised@@ -74,6 +76,7 @@ import           Control.Monad.Except import           Data.Conduit import           Data.Kind+import           Data.Typeable import           GHC.TypeLits  import           Mu.Rpc@@ -151,7 +154,7 @@ pattern Server :: (MappingRight chn sname ~ ())                => HandlersT chn info () methods m hs                -> ServerT chn info ('Package pname '[ 'Service sname methods ]) m '[hs]-pattern Server svr = Services (svr :<&>: S0)+pattern Server svr = Services (ProperSvc svr :<&>: S0)  infixr 3 :<&>: -- | Definition of a complete server for a service.@@ -159,10 +162,32 @@                (s :: [Service snm mnm anm (TypeRef snm)])                (m :: Type -> Type) (hs :: [[Type]]) where   S0 :: ServicesT chn info '[] m '[]-  (:<&>:) :: HandlersT chn info (MappingRight chn sname) methods m hs+  (:<&>:) :: ServiceT chn info svc m hs           -> ServicesT chn info rest m hss-          -> ServicesT chn info ('Service sname methods ': rest) m (hs ': hss)+          -> ServicesT chn info (svc ': rest) m (hs ': hss) +type family InUnion (x :: k) (xs :: [k]) :: Constraint where+  InUnion x '[] = TypeError ('ShowType x ':<>: 'Text " is not part of the union")+  InUnion x (x ': xs) = ()+  InUnion x (y ': xs) = InUnion x xs++data UnionChoice chn elts where+  UnionChoice :: (InUnion elt elts, Typeable elt)+              => Proxy elt -> MappingRight chn elt+              -> UnionChoice chn elts++unionChoice :: forall elt elts chn.+               (InUnion elt elts, Typeable elt)+            => MappingRight chn elt -> UnionChoice chn elts+unionChoice = UnionChoice (Proxy @elt)++-- | Definition of different kinds of services.+data ServiceT chn info svc m hs where+  ProperSvc :: HandlersT chn info (MappingRight chn sname) methods m hs+            -> ServiceT chn info ('Service sname methods) m hs+  OneOfSvc  :: (MappingRight chn sname -> m (UnionChoice chn elts))+            -> ServiceT chn info ('OneOf sname elts) m '[]+ -- | 'HandlersT' is a sequence of handlers. --   Note that the handlers for your service --   must appear __in the same order__ as they@@ -322,6 +347,11 @@   => p -> Named sname (HandlersT chn info (MappingRight chn sname) ms m hs) object nl = Named $ toHandlers $ toNamedList nl +union :: forall sname chn m elts.+         (MappingRight chn sname -> m (UnionChoice chn elts))+      -> Named sname (MappingRight chn sname -> m (UnionChoice chn elts))+union = Named+ -- | Combines the implementation of several GraphQL objects, --   which means a whole Mu service for a GraphQL server. --   Intented to be used with a tuple of 'objects':@@ -412,7 +442,12 @@ instance ( FindService name (HandlersT chn info (MappingRight chn name) methods m h) nl          , ToServices chn info ss m hs nl)          => ToServices chn info ('Service name methods ': ss) m (h ': hs) nl where-  toServices nl = findService (Proxy @name) nl :<&>: toServices nl+  toServices nl = ProperSvc (findService (Proxy @name) nl) :<&>: toServices nl+instance ( FindService name (MappingRight chn name -> m (UnionChoice chn elts)) nl+         , ToServices chn info ss m hs nl)+         => ToServices chn info ('OneOf name elts ': ss) m ('[] ': hs) nl where+  toServices nl = OneOfSvc (findService (Proxy @name) nl) :<&>: toServices nl+  class FindService name h nl | name nl -> h where   findService :: Proxy name -> NamedList nl -> h