graphql-engine/server/src-lib/Hasura/LogicalModelResolver/Schema.hs
Tom Harding e0c0043e76 Upgrade Ormolu to 0.7.0.0
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9284
GitOrigin-RevId: 2f2cf2ad01900a54e4bdb970205ac0ef313c7e00
2023-05-24 13:53:53 +00:00

70 lines
2.6 KiB
Haskell

{-# LANGUAGE QuasiQuotes #-}
-- | Schema parsers for common functionality of logical model resolvers.
module Hasura.LogicalModelResolver.Schema (argumentsSchema) where
import Data.HashMap.Strict qualified as HashMap
import Data.Monoid (Ap (Ap, getAp))
import Hasura.GraphQL.Schema.Backend
( BackendSchema (columnParser),
MonadBuildSchema,
)
import Hasura.GraphQL.Schema.Common
( SchemaT,
)
import Hasura.GraphQL.Schema.Parser qualified as P
import Hasura.Prelude
import Hasura.RQL.IR.Value (openValueOrigin)
import Hasura.RQL.Types.Column qualified as Column
import Hasura.StoredProcedure.Metadata (ArgumentName (..))
import Hasura.StoredProcedure.Types (NullableScalarType (..))
import Language.GraphQL.Draft.Syntax qualified as G
import Language.GraphQL.Draft.Syntax.QQ qualified as G
-- | Schema parser for native query or stored procedure arguments.
argumentsSchema ::
forall b r m n.
(MonadBuildSchema b r m n) =>
-- | The resolver description, such as "Stored Procedure" or "Native Query".
Text ->
-- | The resolver name.
G.Name ->
-- | Arguments
HashMap ArgumentName (NullableScalarType b) ->
MaybeT (SchemaT r m) (P.InputFieldsParser n (HashMap ArgumentName (Column.ColumnValue b)))
argumentsSchema resolverDesc resolverName argsSignature = do
-- Lift 'SchemaT r m (InputFieldsParser ..)' into a monoid using Applicative.
-- This lets us use 'foldMap' + monoid structure of hashmaps to avoid awkwardly
-- traversing the arguments and building the resulting parser.
argsParser <-
getAp
$ foldMap
( \(name, NullableScalarType {nstType, nstNullable, nstDescription}) -> Ap do
argValueParser <-
fmap (HashMap.singleton name . openValueOrigin)
<$> lift (columnParser (Column.ColumnScalar nstType) (G.Nullability nstNullable))
-- TODO: Naming conventions?
-- TODO: Custom fields? (Probably not)
argName <- hoistMaybe (G.mkName (getArgumentName name))
let description = case nstDescription of
Just desc -> G.Description desc
Nothing -> G.Description (resolverDesc <> " argument " <> getArgumentName name)
pure
$ P.field
argName
(Just description)
argValueParser
)
(HashMap.toList argsSignature)
let desc = Just $ G.Description $ G.unName resolverName <> resolverDesc <> " Arguments"
pure
$ if null argsSignature
then mempty
else
P.field
[G.name|args|]
desc
(P.object (resolverName <> [G.name|_arguments|]) desc argsParser)