这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@
- add meta descriptions to actions docs (#4082)
- `HASURA_GRAPHQL_EVENTS_FETCH_INTERVAL` changes semantics slightly: we only sleep for the interval
when there were previously no events to process. Potential space leak fixed. (#3839)
- auto-include `__typename` field in custom types' objects (fix #4063)
38 changes: 2 additions & 36 deletions server/src-lib/Hasura/GraphQL/RemoteServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Hasura.Prelude
import qualified Data.Aeson as J
import qualified Data.ByteString.Lazy as BL
import qualified Data.HashMap.Strict as Map
import qualified Data.HashSet as Set
import qualified Data.Text as T
import qualified Language.GraphQL.Draft.Parser as G
import qualified Language.GraphQL.Draft.Syntax as G
Expand Down Expand Up @@ -159,43 +158,10 @@ mergeQueryRoot :: GS.GCtx -> GS.GCtx -> VT.ObjTyInfo
mergeQueryRoot a b = GS._gQueryRoot a <> GS._gQueryRoot b

mergeMutRoot :: GS.GCtx -> GS.GCtx -> Maybe VT.ObjTyInfo
mergeMutRoot a b =
let objA' = fromMaybe mempty $ GS._gMutRoot a
objB = fromMaybe mempty $ GS._gMutRoot b
objA = newRootOrEmpty objA' objB
merged = objA <> objB
in bool (Just merged) Nothing $ merged == mempty
where
newRootOrEmpty x y =
if x == mempty && y /= mempty
then mkNewEmptyMutRoot
else x

mkNewEmptyMutRoot :: VT.ObjTyInfo
mkNewEmptyMutRoot = VT.ObjTyInfo (Just "mutation root")
(G.NamedType "mutation_root") Set.empty Map.empty
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a has Semigroup instance. So, <> can be directly used to merge Maybe mutationRoots here. No need for mkNewEmptyMutRoot.


mkNewMutRoot :: VT.ObjFieldMap -> VT.ObjTyInfo
mkNewMutRoot flds = VT.ObjTyInfo (Just "mutation root")
(G.NamedType "mutation_root") Set.empty flds
mergeMutRoot a b = GS._gMutRoot a <> GS._gMutRoot b

mergeSubRoot :: GS.GCtx -> GS.GCtx -> Maybe VT.ObjTyInfo
mergeSubRoot a b =
let objA' = fromMaybe mempty $ GS._gSubRoot a
objB = fromMaybe mempty $ GS._gSubRoot b
objA = newRootOrEmpty objA' objB
merged = objA <> objB
in bool (Just merged) Nothing $ merged == mempty
where
newRootOrEmpty x y =
if x == mempty && y /= mempty
then mkNewEmptySubRoot
else x

mkNewEmptySubRoot :: VT.ObjTyInfo
mkNewEmptySubRoot = VT.ObjTyInfo (Just "subscription root")
(G.NamedType "subscription_root") Set.empty Map.empty
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explanation in above comment applicable here for subscription roots.


mergeSubRoot a b = GS._gSubRoot a <> GS._gSubRoot b

mergeTyMaps
:: VT.TypeMap
Expand Down
2 changes: 1 addition & 1 deletion server/src-lib/Hasura/GraphQL/Resolve/Action.hs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ resolveAsyncActionQuery userInfo selectOpCtx field = do

annotatedFields <- fmap (map (first FieldName)) $ withSelSet (_fSelSet field) $ \fld ->
case _fName fld of
"__typename" -> return $ RS.FExp $ G.unName $ G.unNamedType $ _fType fld
"__typename" -> return $ RS.FExp $ G.unName $ G.unNamedType $ _fType field
"output" -> do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using fld type here is a bug which always results in String for __typename field.

-- See Note [Resolving async action query/subscription]
let inputTableArgument = RS.AETableRow $ Just $ Iden "response_payload"
Expand Down
9 changes: 7 additions & 2 deletions server/src-lib/Hasura/GraphQL/Resolve/Introspect.hs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ objectTypeR
=> ObjTyInfo
-> Field
-> m J.Object
objectTypeR (ObjTyInfo descM n iFaces flds) fld =
objectTypeR objectType fld =
withSubFields (_fSelSet fld) $ \subFld ->
case _fName subFld of
"__typename" -> retJT "__Type"
Expand All @@ -87,6 +87,11 @@ objectTypeR (ObjTyInfo descM n iFaces flds) fld =
sortOn _fiName $
filter notBuiltinFld $ Map.elems flds
_ -> return J.Null
where
descM = _otiDesc objectType
n = _otiName objectType
iFaces = _otiImplIFaces objectType
flds = _otiFields objectType

notBuiltinFld :: ObjFldInfo -> Bool
notBuiltinFld f =
Expand Down Expand Up @@ -209,7 +214,7 @@ nonNullR gTyp fld =
"ofType" -> case gTyp of
G.TypeNamed (G.Nullability False) nt -> J.toJSON <$> namedTypeR nt subFld
G.TypeList (G.Nullability False) lt -> J.toJSON <$> listTypeR lt subFld
_ -> throw500 "nullable type passed to nonNullR"
_ -> throw500 "nullable type passed to nonNullR"
_ -> return J.Null

namedTypeR
Expand Down
11 changes: 5 additions & 6 deletions server/src-lib/Hasura/GraphQL/Schema/CustomTypes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ import qualified Hasura.GraphQL.Validate.Types as VT

buildObjectTypeInfo :: RoleName -> AnnotatedObjectType -> VT.ObjTyInfo
buildObjectTypeInfo roleName annotatedObjectType =
VT.ObjTyInfo
{ VT._otiDesc = _otdDescription objectDefinition
, VT._otiName = unObjectTypeName $ _otdName objectDefinition
, VT._otiImplIFaces = mempty
, VT._otiFields = mapFromL VT._fiName $ fields <> catMaybes relationships
}
let description = _otdDescription objectDefinition
namedType = unObjectTypeName $ _otdName objectDefinition
fieldMap = mapFromL VT._fiName $ fields <> catMaybes relationships
-- 'mkObjTyInfo' function takes care of inserting `__typename` field
in VT.mkObjTyInfo description namedType mempty fieldMap VT.TLCustom
where
objectDefinition = _aotDefinition annotatedObjectType

Expand Down
8 changes: 7 additions & 1 deletion server/src-lib/Hasura/GraphQL/Validate/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ module Hasura.GraphQL.Validate.Types
, mkHsraObjFldInfo
, ObjFieldMap

, ObjTyInfo(..)
-- Don't expose 'ObjTyInfo' constructor. Instead use 'mkObjTyInfo' or 'mkHsraObjTyInfo'
-- which will auto-insert the compulsory '__typename' field.
, ObjTyInfo
, _otiDesc
, _otiName
, _otiImplIFaces
, _otiFields
, mkObjTyInfo
, mkHsraObjTyInfo

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ query:
query: |
mutation {
create_user(email: "clarke@gmail.com", name: "Clarke"){
__typename
id
user {
__typename
name
email
is_admin
Expand All @@ -17,8 +19,10 @@ query:
response:
data:
create_user:
__typename: UserId
id: 1
user:
__typename: user
name: Clarke
email: clarke@gmail.com
is_admin: false
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ query:
mutation {
create_users(users: [{email: "blake@hasura.io", name: "Blake"}, {email: "random-email", name: "Elsa"}]){
id
__typename
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ query:
mutation {
create_users(users: [{email: "blake@hasura.io", name: "Blake"}, {email: "elsa@hasura.io", name: "Elsa"}]){
id
__typename
user {
__typename
name
email
is_admin
Expand All @@ -18,12 +20,16 @@ response:
data:
create_users:
- id: 1
__typename: UserId
user:
__typename: user
name: Blake
email: blake@hasura.io
is_admin: false
- id: 2
__typename: UserId
user:
__typename: user
name: Elsa
email: elsa@hasura.io
is_admin: false
6 changes: 6 additions & 0 deletions server/tests-py/test_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,13 @@ def test_create_user_success(self, hge_ctx):
query_async = '''
query ($action_id: uuid!){
create_user(id: $action_id){
__typename
id
output {
__typename
id
user {
__typename
name
email
is_admin
Expand All @@ -148,10 +151,13 @@ def test_create_user_success(self, hge_ctx):
response = {
'data': {
'create_user': {
'__typename': 'create_user',
'id': action_id,
'output': {
'__typename': 'UserId',
'id': 1,
'user': {
'__typename': 'user',
'name': 'Clarke',
'email': 'clarke@hasura.io',
'is_admin': False
Expand Down