Fixed GQL aliases not being respected in the OpenAPI schema

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/3484
GitOrigin-RevId: 0f49dd7f64e80dfe6940d673afa76f12f6599126
This commit is contained in:
Daniel Chambers 2022-01-27 16:54:51 +11:00 committed by hasura-bot
parent 9d2ac22365
commit bd6f7cd756
5 changed files with 102 additions and 19 deletions

View File

@ -32,6 +32,7 @@ count (
- server: fix support for joins in aggregates nodes in BigQuery
- server: fix for passing input objects in query variables to remote schemas with type name customization (#7977)
- server: fix REST endpoints with path segments not showing correctly in the OpenAPI spec
- server: fix aliases used in GraphQL queries in REST endpoints not being reflected in the OpenAPI spec
- console: action/event trigger transforms are now called REST connectors
- console: fix list of tables (and schemas) being unsorted when creating a new trigger event (fix #6391)
- cli: migrate and seed subcommands has an option in prompt to choose and apply operation on all available databases

View File

@ -13,10 +13,10 @@ import Hasura.RQL.Types.RemoteSchema
( RemoteSchemaInputValueDefinition (RemoteSchemaInputValueDefinition, _rsitdDefinition),
RemoteSchemaIntrospection (RemoteSchemaIntrospection),
)
import Language.GraphQL.Draft.Syntax (ExecutableDefinition, GType, Name, TypeDefinition)
import Language.GraphQL.Draft.Syntax (ExecutableDefinition, Field, GType, Name, TypeDefinition)
import Language.GraphQL.Draft.Syntax qualified as G
-- | Analyse and FieldAnalysis are almost similar, except, Analyse will have a bool field (in future)
-- | Analysis and FieldAnalysis are almost similar, except, Analysis will have a bool field (in future)
-- to indicate whether the GQL query is valid or not
data Analysis var = Analysis
{ -- | ordered hashmap from the fields to it's definition and analysis
@ -87,21 +87,23 @@ analyzeGraphqlQuery (G.ExecutableDefinitionOperation (G.OperationDefinitionTyped
pure Analysis {_aFields = fieldMap, _aVars = varMap, _aErrs = errs}
analyzeGraphqlQuery _ _ = Nothing
getFieldName :: Field frag var -> Name
getFieldName f = fromMaybe (G._fName f) (G._fAlias f)
getFieldsMap ::
RemoteSchemaIntrospection ->
[(G.OperationType, G.Selection frag var)] ->
(InsOrdHashMap Name (FieldDef, Maybe (FieldAnalysis var)), [Text])
(InsOrdHashMap FieldName (FieldDef, Maybe (FieldAnalysis var)), [Text])
getFieldsMap rs ss =
let fields = mapMaybe (\(o, s) -> (o,) <$> field s) ss
(ps, errs) =
foldl'
( \(m, e) (o, f) -> case lookupRoot rs (o, f) of
Left x0 -> (safeInsertInFieldMap m (G._fName f, x0), e)
Right txts -> (m, e <> txts)
)
(OMap.empty, [])
fields
in (ps, errs)
foldl'
( \(m, e) (o, f) -> case lookupRoot rs (o, f) of
Left x0 -> (safeInsertInFieldMap m (getFieldName f, x0), e)
Right txts -> (m, e <> txts)
)
(OMap.empty, [])
fields
where
fields = mapMaybe (\(o, s) -> (o,) <$> field s) ss
lookupRoot ::
RemoteSchemaIntrospection ->
@ -195,15 +197,15 @@ mkFieldAnalysis ::
-- TODO: Handle `SelectionFragmentSpread` and `SelectionInlineFragment` as well
mkFieldAnalysis _ (G.SelectionFragmentSpread _) _ = Nothing
mkFieldAnalysis _ (G.SelectionInlineFragment _) _ = Nothing
mkFieldAnalysis rs (G.SelectionField sel) fd = do
let ag = G._fArguments sel
mkFieldAnalysis rs (G.SelectionField f) fd = do
let ag = G._fArguments f
ft = G._fldType fd
fn = G._fldName fd
fn = getFieldName f
(fFds, fVrs, fErrs) = itrListWith ft \n ->
case lookupRS rs n of
Nothing -> (mempty, mempty, ["Couldn't find definition for type " <> G.unName n <> " in field " <> G.unName fn <> " selected by " <> G.unName (G._fName sel)])
Nothing -> (mempty, mempty, ["Couldn't find definition for type " <> G.unName n <> " in field " <> G.unName fn <> " selected by " <> G.unName (G._fName f)])
Just tDef ->
let (def, fAn) = getDefinition rs tDef (G._fSelectionSet sel)
let (def, fAn) = getDefinition rs tDef (G._fSelectionSet f)
in case ft of
G.TypeNamed n' _ ->
(OMap.singleton fn (FieldInfo n' def, fAn), Map.fromList (getFieldVars fd ag), [])

View File

@ -0,0 +1,75 @@
- description: Try to add a GET rest endpoint with no argument
url: /v1/query
status: 200
response:
message: success
query:
type: create_rest_endpoint
args:
url: simple_with_aliases
name: simple_with_aliases
methods:
- GET
definition:
query:
collection_name: test_collection
query_name: simple_query_with_aliases
- description: Call openapi json endpoint
url: /api/swagger/json
method: GET
status: 200
query:
response:
openapi: 3.0.0
info:
version: ''
title: Rest Endpoints
description: This OpenAPI specification is automatically generated by Hasura.
paths:
/api/rest/simple_with_aliases:
get:
summary: simple_with_aliases
description: "***\nThe GraphQl query for this endpoint is:\n``` graphql\n\
query { test: test_table { firstName: first_name lastName: last_name surname: last_name } }\n```"
parameters:
- schema:
type: string
in: header
name: x-hasura-admin-secret
description: Your x-hasura-admin-secret will be used for authentication
of the API request.
responses:
'200':
content:
application/json:
schema:
properties:
test:
items:
type: object
properties:
lastName:
title: String
type: string
firstName:
title: String
type: string
surname:
title: String
type: string
type: array
nullable: false
description: Responses for GET /api/rest/simple_with_aliases
components: {}
- description: Try to remove the endpoint
url: /v1/query
status: 200
response:
message: success
query:
type: drop_rest_endpoint
args:
name: simple_with_aliases

View File

@ -53,6 +53,8 @@ args:
queries:
- name: simple_query
query: "query { test_table { first_name last_name } }"
- name: simple_query_with_aliases
query: "query { test: test_table { firstName: first_name lastName: last_name surname: last_name } }"
- name: query_with_arg
query: "query ($first_name:String!) { test_table(where: {first_name: { _eq: $first_name } }) { first_name last_name } }"
- name: query_with_args
@ -70,4 +72,4 @@ args:
- name: mutation_recursive_arg
query: "mutation MyMutation($object: test_table_recurse_insert_input!) { insert_test_table_recurse_one(object: $object) { id } }"
- name: query_with_duplicate_field_name
query: "query { test_table { first_name } test_table { last_name } }"
query: "query { test_table { first_name } test_table { last_name } }"

View File

@ -17,6 +17,9 @@ class TestOpenAPISpec:
def test_endpoint_simple(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/openapi_get_endpoint_test_simple.yaml', transport)
def test_endpoint_with_aliases(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/openapi_endpoint_with_aliases.yaml', transport)
def test_endpoint_with_args(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/openapi_post_endpoint_test_with_args.yaml', transport)