1
1
import {
2
2
buildASTSchema ,
3
- DefinitionNode ,
4
3
DocumentNode ,
5
4
GraphQLSchema ,
6
5
isTypeSystemDefinitionNode ,
7
6
isTypeSystemExtensionNode ,
8
7
parse ,
8
+ SchemaDefinitionNode ,
9
+ SchemaExtensionNode ,
10
+ TypeDefinitionNode ,
11
+ TypeSystemDefinitionNode ,
9
12
} from 'graphql' ;
10
13
import { 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' ;
12
22
import { TypeResolver } from './typeResolver' ;
13
23
import { ParserUtils } from './ParserUtils' ;
14
- import { createParserField , generateNodeId } from '@/shared' ;
24
+ import { createParserField , createSchemaDefinition , generateNodeId } from '@/shared' ;
15
25
export class Parser {
16
26
static findComments ( schema : string ) : string [ ] {
17
27
const stripDocs = schema
@@ -29,35 +39,97 @@ export class Parser {
29
39
* @param schema
30
40
*/
31
41
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 => {
33
45
if ( isTypeSystemDefinitionNode ( d ) || isTypeSystemExtensionNode ( d ) ) {
34
46
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' ) {
39
50
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 ,
49
62
} ,
63
+ } ,
64
+ } ) ,
65
+ ) ,
50
66
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
+ } ,
52
77
} ,
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 ) ,
59
78
} ;
60
79
}
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
+ } ;
61
133
}
62
134
} ;
63
135
/**
@@ -84,25 +156,19 @@ export class Parser {
84
156
if ( ! parsedSchema ) {
85
157
throw new Error ( 'Cannot parse the schema' ) ;
86
158
}
87
- const operations : { Query ?: string ; Mutation ?: string ; Subscription ?: string } = { } ;
88
159
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
- }
103
160
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
+ )
106
172
. filter ( ( d ) => ! ! d ) as ParserField [ ] ;
107
173
const comments : ParserField [ ] = Parser . findComments ( schema ) . map ( ( description ) =>
108
174
createParserField ( {
@@ -124,17 +190,6 @@ export class Parser {
124
190
} ;
125
191
const allInterfaceNodes = nodeTree . nodes . filter ( ( n ) => n . data . type === TypeDefinition . InterfaceTypeDefinition ) ;
126
192
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
- }
138
193
if (
139
194
n . data . type === TypeDefinition . ObjectTypeDefinition ||
140
195
n . data . type === TypeDefinition . InterfaceTypeDefinition
@@ -160,6 +215,23 @@ export class Parser {
160
215
}
161
216
}
162
217
} ) ;
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
+ }
163
235
return nodeTree ;
164
236
} ;
165
237
static parseAddExtensions = ( schema : string , excludeRoots : string [ ] = [ ] ) : ParserTree => {
0 commit comments