mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-13 19:33:55 +03:00
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:
parent
9d2ac22365
commit
bd6f7cd756
@ -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
|
||||
|
@ -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), [])
|
||||
|
@ -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
|
@ -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 } }"
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user