1 {-# OPTIONS_GHC -fprint-potential-instances #-}
3 {-# LANGUAGE DeriveAnyClass #-}
4 {-# LANGUAGE DuplicateRecordFields #-} -- permit duplications for field names in multiple constructors
5 {-# LANGUAGE KindSignatures #-} -- for use of Endpoint (name :: Symbol)
6 {-# LANGUAGE PartialTypeSignatures #-} -- to automatically use suggested type hole signatures during compilation
7 {-# LANGUAGE TypeOperators #-}
9 module Gargantext.API.GraphQL where
11 import Data.ByteString.Lazy.Char8
14 import Data.Map.Strict (Map)
18 import Data.Morpheus.Server
21 import Data.Morpheus.Subscriptions
26 import Data.Morpheus.Types
32 import Data.Morpheus.Server.Types
37 import Data.Text (Text)
38 import Gargantext.API.Admin.Auth.Types (AuthenticatedUser)
39 import Gargantext.API.Admin.Orchestrator.Types (JobLog)
40 import Gargantext.API.Prelude (HasJobEnv')
41 import qualified Gargantext.API.GraphQL.Annuaire as GQLA
42 import qualified Gargantext.API.GraphQL.AsyncTask as GQLAT
43 import qualified Gargantext.API.GraphQL.Context as GQLCTX
44 import qualified Gargantext.API.GraphQL.IMT as GQLIMT
45 import qualified Gargantext.API.GraphQL.NLP as GQLNLP
46 import qualified Gargantext.API.GraphQL.Node as GQLNode
47 import qualified Gargantext.API.GraphQL.User as GQLUser
48 import qualified Gargantext.API.GraphQL.UserInfo as GQLUserInfo
49 import qualified Gargantext.API.GraphQL.TreeFirstLevel as GQLTree
50 import qualified Gargantext.API.GraphQL.Team as GQLTeam
51 import Gargantext.API.Prelude (GargM, GargError)
52 import Gargantext.API.Types
53 import Gargantext.Core.NLP (HasNLPServer)
54 import Gargantext.Database.Prelude (CmdCommon)
55 import Gargantext.Prelude
56 import GHC.Generics (Generic)
66 import qualified Servant.Auth as SA
67 import qualified Servant.Auth.Server as SAS
68 import Gargantext.API.Admin.Types (HasSettings)
71 -- | Represents possible GraphQL queries.
74 { annuaire_contacts :: GQLA.AnnuaireContactArgs -> m [GQLA.AnnuaireContact]
75 , context_ngrams :: GQLCTX.ContextNgramsArgs -> m [Text]
76 , contexts :: GQLCTX.NodeContextArgs -> m [GQLCTX.NodeContextGQL]
77 , contexts_for_ngrams :: GQLCTX.ContextsForNgramsArgs -> m [GQLCTX.ContextGQL]
78 , imt_schools :: GQLIMT.SchoolsArgs -> m [GQLIMT.School]
79 , job_logs :: GQLAT.JobLogArgs -> m (Map Int JobLog)
80 , languages :: GQLNLP.LanguagesArgs -> m GQLNLP.LanguagesMap
81 , nodes :: GQLNode.NodeArgs -> m [GQLNode.Node]
82 , nodes_corpus :: GQLNode.CorpusArgs -> m [GQLNode.Corpus]
83 , node_parent :: GQLNode.NodeParentArgs -> m [GQLNode.Node]
84 , user_infos :: GQLUserInfo.UserInfoArgs -> m [GQLUserInfo.UserInfo]
85 , users :: GQLUser.UserArgs -> m [GQLUser.User m]
86 , tree :: GQLTree.TreeArgs -> m (GQLTree.TreeFirstLevel m)
87 , team :: GQLTeam.TeamArgs -> m GQLTeam.Team
88 } deriving (Generic, GQLType)
92 { update_user_info :: GQLUserInfo.UserInfoMArgs -> m Int
93 , update_user_pubmed_api_key :: GQLUser.UserPubmedAPIKeyMArgs -> m Int
94 , delete_team_membership :: GQLTeam.TeamDeleteMArgs -> m [Int]
95 , update_node_context_category :: GQLCTX.NodeContextCategoryMArgs -> m [Int]
96 } deriving (Generic, GQLType)
98 -- | Possible GraphQL Events, i.e. here we describe how we will
99 -- manipulate the data.
100 type EVENT m = Event Channel (Contet m)
102 -- | Channels are possible actions to call when manipulating the data.
106 deriving (Eq, Show, Generic, Hashable)
108 -- | This type describes what data we will operate on.
110 = UserContet [GQLUser.User m]
111 | UserInfoContet [GQLUserInfo.UserInfo]
113 -- | The main GraphQL resolver: how queries, mutations and
114 -- subscriptions are handled.
116 :: (CmdCommon env, HasNLPServer env, HasJobEnv' env, HasSettings env)
117 => RootResolver (GargM env GargError) e Query Mutation Undefined
120 { queryResolver = Query { annuaire_contacts = GQLA.resolveAnnuaireContacts
121 , context_ngrams = GQLCTX.resolveContextNgrams
122 , contexts = GQLCTX.resolveNodeContext
123 , contexts_for_ngrams = GQLCTX.resolveContextsForNgrams
124 , imt_schools = GQLIMT.resolveSchools
125 , job_logs = GQLAT.resolveJobLogs
126 , languages = GQLNLP.resolveLanguages
127 , nodes = GQLNode.resolveNodes
128 , nodes_corpus = GQLNode.resolveNodesCorpus
129 , node_parent = GQLNode.resolveNodeParent
130 , user_infos = GQLUserInfo.resolveUserInfos
131 , users = GQLUser.resolveUsers
132 , tree = GQLTree.resolveTree
133 , team = GQLTeam.resolveTeam }
134 , mutationResolver = Mutation { update_user_info = GQLUserInfo.updateUserInfo
135 , update_user_pubmed_api_key = GQLUser.updateUserPubmedAPIKey
136 , delete_team_membership = GQLTeam.deleteTeamMembership
137 , update_node_context_category = GQLCTX.updateNodeContextCategory }
140 -- | Main GraphQL "app".
142 :: (Typeable env, CmdCommon env, HasJobEnv' env, HasNLPServer env, HasSettings env)
143 => App (EVENT (GargM env GargError)) (GargM env GargError)
144 app = deriveApp rootResolver
146 ----------------------------------------------
148 -- Now for some boilerplate to integrate the above GraphQL app with
151 -- | Servant route for the app we defined above.
152 type GQAPI = ReqBody '[JSON] GQLRequest :> Post '[JSON] GQLResponse
153 -- type Schema = "schema" :> Get '[PlainText] Text
154 -- | Servant route for the playground.
155 type Playground = Get '[HTML] ByteString
156 -- type API' (name :: Symbol) = name :> (GQAPI :<|> Schema :<|> Playground)
157 -- | Our API consists of `GQAPI` and `Playground`.
158 type API = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser
159 :> "gql" :> (GQAPI :<|> Playground)
165 -- ( SubApp ServerApp e
171 -- serveEndpoint publish app' = (liftIO . httpPubApp publish app') :<|> withSchema app' :<|> pure httpPlayground
173 -- withSchema :: (Applicative f) => App e m -> f Text
174 -- withSchema = pure . LT.toStrict . decodeUtf8 . render
176 -- | Implementation of our API.
179 :: (Typeable env, CmdCommon env, HasJobEnv' env, HasSettings env)
180 => ServerT API (GargM env GargError)
181 api (SAS.Authenticated _auser) = httpPubApp [] app :<|> pure httpPlayground
182 api _ = panic "401 in graphql" -- SAS.throwAll (_ServerError # err401)