11import {
22 buildASTSchema ,
3- DefinitionNode ,
43 DocumentNode ,
54 GraphQLSchema ,
65 isTypeSystemDefinitionNode ,
76 isTypeSystemExtensionNode ,
87 parse ,
8+ SchemaDefinitionNode ,
9+ SchemaExtensionNode ,
10+ TypeDefinitionNode ,
11+ TypeSystemDefinitionNode ,
912} from 'graphql' ;
1013import { ParserField , ParserTree , TypeDefinitionDisplayMap , Options , kindAsAllTypes } from '@/Models' ;
11- import { Directive , Helpers , OperationType , TypeDefinition , TypeExtension } from '@/Models/Spec' ;
14+ import {
15+ Directive ,
16+ Helpers ,
17+ TypeDefinition ,
18+ TypeExtension ,
19+ TypeSystemDefinition ,
20+ TypeSystemExtension ,
21+ } from '@/Models/Spec' ;
1222import { TypeResolver } from './typeResolver' ;
1323import { ParserUtils } from './ParserUtils' ;
14- import { createParserField , generateNodeId } from '@/shared' ;
24+ import { createParserField , createSchemaDefinition , generateNodeId } from '@/shared' ;
1525export class Parser {
1626 static findComments ( schema : string ) : string [ ] {
1727 const stripDocs = schema
@@ -29,35 +39,97 @@ export class Parser {
2939 * @param schema
3040 */
3141 static importSchema = ( schema : string ) : GraphQLSchema => buildASTSchema ( parse ( schema ) ) ;
32- static documentDefinitionToSerializedNodeTree = ( d : DefinitionNode ) : ParserField | undefined => {
42+ static documentDefinitionToSerializedNodeTree = (
43+ d : TypeSystemDefinitionNode | TypeDefinitionNode | SchemaDefinitionNode | SchemaExtensionNode ,
44+ ) : ParserField | undefined => {
3345 if ( isTypeSystemDefinitionNode ( d ) || isTypeSystemExtensionNode ( d ) ) {
3446 const args = TypeResolver . resolveFieldsFromDefinition ( d ) ;
35- if ( 'name' in d ) {
36- const interfaces = 'interfaces' in d && d . interfaces ? d . interfaces . map ( ( i ) => i . name . value ) : [ ] ;
37- const directives = 'directives' in d && d . directives ? TypeResolver . iterateDirectives ( d . directives ) : [ ] ;
38-
47+ const interfaces = 'interfaces' in d && d . interfaces ? d . interfaces . map ( ( i ) => i . name . value ) : [ ] ;
48+ const directives = 'directives' in d && d . directives ? TypeResolver . iterateDirectives ( d . directives ) : [ ] ;
49+ if ( d . kind === 'SchemaDefinition' ) {
3950 return {
40- name : d . name . value ,
41- type :
42- d . kind === 'DirectiveDefinition'
43- ? {
44- fieldType : { name : TypeDefinitionDisplayMap [ d . kind ] , type : Options . name } ,
45- directiveOptions : d . locations . map ( ( l ) => l . value as Directive ) ,
46- }
47- : {
48- fieldType : { name : TypeDefinitionDisplayMap [ d . kind ] , type : Options . name } ,
51+ name : 'schema' ,
52+ args : d . operationTypes . map ( ( ot ) =>
53+ createParserField ( {
54+ name : ot . operation ,
55+ data : {
56+ type : TypeSystemDefinition . FieldDefinition ,
57+ } ,
58+ type : {
59+ fieldType : {
60+ name : ot . type . name . value ,
61+ type : Options . name ,
4962 } ,
63+ } ,
64+ } ) ,
65+ ) ,
5066 data : {
51- type : kindAsAllTypes ( d . kind ) ,
67+ type : TypeSystemDefinition . SchemaDefinition ,
68+ } ,
69+ directives : d . directives ? TypeResolver . iterateDirectives ( d . directives ) : [ ] ,
70+ id : generateNodeId ( 'schema' , kindAsAllTypes ( d . kind ) , [ ] ) ,
71+ interfaces : [ ] ,
72+ type : {
73+ fieldType : {
74+ type : Options . name ,
75+ name : 'schema' ,
76+ } ,
5277 } ,
53-
54- ...( 'description' in d && d . description ?. value ? { description : d . description . value } : { } ) ,
55- interfaces,
56- directives,
57- args,
58- id : generateNodeId ( d . name . value , kindAsAllTypes ( d . kind ) , args ) ,
5978 } ;
6079 }
80+ if ( d . kind === 'SchemaExtension' ) {
81+ return {
82+ name : 'schema' ,
83+ data : {
84+ type : TypeSystemExtension . SchemaExtension ,
85+ } ,
86+ directives : d . directives ? TypeResolver . iterateDirectives ( d . directives ) : [ ] ,
87+ interfaces : [ ] ,
88+ type : {
89+ fieldType : {
90+ type : Options . name ,
91+ name : 'schema' ,
92+ } ,
93+ } ,
94+ args :
95+ d . operationTypes ?. map ( ( ot ) =>
96+ createParserField ( {
97+ name : ot . operation ,
98+ data : {
99+ type : TypeSystemDefinition . FieldDefinition ,
100+ } ,
101+ type : {
102+ fieldType : {
103+ name : ot . type . name . value ,
104+ type : Options . name ,
105+ } ,
106+ } ,
107+ } ) ,
108+ ) || [ ] ,
109+ id : generateNodeId ( 'schema' , kindAsAllTypes ( d . kind ) , [ ] ) ,
110+ } ;
111+ }
112+ return {
113+ name : d . name . value ,
114+ type :
115+ d . kind === 'DirectiveDefinition'
116+ ? {
117+ fieldType : { name : TypeDefinitionDisplayMap [ d . kind ] , type : Options . name } ,
118+ directiveOptions : d . locations . map ( ( l ) => l . value as Directive ) ,
119+ }
120+ : {
121+ fieldType : { name : TypeDefinitionDisplayMap [ d . kind ] , type : Options . name } ,
122+ } ,
123+ data : {
124+ type : kindAsAllTypes ( d . kind ) ,
125+ } ,
126+
127+ ...( 'description' in d && d . description ?. value ? { description : d . description . value } : { } ) ,
128+ interfaces,
129+ directives,
130+ args,
131+ id : generateNodeId ( d . name . value , kindAsAllTypes ( d . kind ) , args ) ,
132+ } ;
61133 }
62134 } ;
63135 /**
@@ -84,25 +156,19 @@ export class Parser {
84156 if ( ! parsedSchema ) {
85157 throw new Error ( 'Cannot parse the schema' ) ;
86158 }
87- const operations : { Query ?: string ; Mutation ?: string ; Subscription ?: string } = { } ;
88159
89- const schemaDefinition = parsedSchema . definitions . find ( ( d ) => d . kind === 'SchemaDefinition' ) ;
90- if ( schemaDefinition && 'operationTypes' in schemaDefinition ) {
91- schemaDefinition . operationTypes ?. forEach ( ( ot ) => {
92- if ( ot . operation === 'query' ) {
93- operations . Query = ot . type . name . value ;
94- }
95- if ( ot . operation === 'mutation' ) {
96- operations . Mutation = ot . type . name . value ;
97- }
98- if ( ot . operation === 'subscription' ) {
99- operations . Subscription = ot . type . name . value ;
100- }
101- } ) ;
102- }
103160 const nodes = parsedSchema . definitions
104- . filter ( ( t ) => 'name' in t && t . name && ! excludeRoots . includes ( t . name . value ) )
105- . map ( Parser . documentDefinitionToSerializedNodeTree )
161+ . filter ( ( t ) =>
162+ t . kind === 'SchemaExtension' || t . kind === 'SchemaDefinition'
163+ ? true
164+ : 'name' in t && t . name && ! excludeRoots . includes ( t . name . value ) ,
165+ )
166+ . filter ( ( t ) => t . kind !== 'FragmentDefinition' )
167+ . map ( ( t ) =>
168+ Parser . documentDefinitionToSerializedNodeTree (
169+ t as TypeDefinitionNode | SchemaDefinitionNode | TypeSystemDefinitionNode | SchemaExtensionNode ,
170+ ) ,
171+ )
106172 . filter ( ( d ) => ! ! d ) as ParserField [ ] ;
107173 const comments : ParserField [ ] = Parser . findComments ( schema ) . map ( ( description ) =>
108174 createParserField ( {
@@ -124,17 +190,6 @@ export class Parser {
124190 } ;
125191 const allInterfaceNodes = nodeTree . nodes . filter ( ( n ) => n . data . type === TypeDefinition . InterfaceTypeDefinition ) ;
126192 nodeTree . nodes . forEach ( ( n ) => {
127- if ( n . data . type === TypeDefinition . ObjectTypeDefinition ) {
128- if ( operations . Query ? operations . Query === n . name : n . name === 'Query' ) {
129- n . type . operations = [ OperationType . query ] ;
130- }
131- if ( operations . Mutation ? operations . Mutation === n . name : n . name === 'Mutation' ) {
132- n . type . operations = [ OperationType . mutation ] ;
133- }
134- if ( operations . Subscription ? operations . Subscription === n . name : n . name === 'Subscription' ) {
135- n . type . operations = [ OperationType . subscription ] ;
136- }
137- }
138193 if (
139194 n . data . type === TypeDefinition . ObjectTypeDefinition ||
140195 n . data . type === TypeDefinition . InterfaceTypeDefinition
@@ -160,6 +215,23 @@ export class Parser {
160215 }
161216 }
162217 } ) ;
218+ const schemaNode = nodeTree . nodes . find ( ( n ) => n . data . type === TypeSystemDefinition . SchemaDefinition ) ;
219+ if ( ! schemaNode ) {
220+ const query = nodeTree . nodes . find ( ( n ) => n . name === 'Query' ) ?. name ;
221+ const mutation = nodeTree . nodes . find ( ( n ) => n . name === 'Mutation' ) ?. name ;
222+ const subscription = nodeTree . nodes . find ( ( n ) => n . name === 'Subscription' ) ?. name ;
223+ if ( query || mutation || subscription ) {
224+ nodeTree . nodes . push (
225+ createSchemaDefinition ( {
226+ operations : {
227+ query,
228+ mutation,
229+ subscription,
230+ } ,
231+ } ) ,
232+ ) ;
233+ }
234+ }
163235 return nodeTree ;
164236 } ;
165237 static parseAddExtensions = ( schema : string , excludeRoots : string [ ] = [ ] ) : ParserTree => {
0 commit comments