@@ -4,6 +4,9 @@ import './viewport.css';
4
4
import Button from '@mui/material/Button' ;
5
5
import Stack from '@mui/material/Stack' ;
6
6
import { ThemeProvider } from '@mui/material/styles' ;
7
+ import { ExecutionResult } from 'graphql/execution' ;
8
+ import { GraphQLSchema } from 'graphql/type' ;
9
+ import { buildClientSchema , IntrospectionQuery } from 'graphql/utilities' ;
7
10
import {
8
11
Children ,
9
12
type ReactElement ,
@@ -15,7 +18,7 @@ import {
15
18
} from 'react' ;
16
19
17
20
import { getTypeGraph } from '../graph/' ;
18
- import { extractTypeId , getSchema } from '../introspection' ;
21
+ import { extractTypeName , getSchema , typeNameToId } from '../introspection' ;
19
22
import DocExplorer from './doc-explorer/DocExplorer' ;
20
23
import GraphViewport from './GraphViewport' ;
21
24
import { IntrospectionModal } from './IntrospectionModal' ;
@@ -33,17 +36,8 @@ export interface VoyagerDisplayOptions {
33
36
hideRoot ?: boolean ;
34
37
}
35
38
36
- const defaultDisplayOptions = {
37
- rootType : undefined ,
38
- skipRelay : true ,
39
- skipDeprecated : true ,
40
- sortByAlphabet : false ,
41
- showLeafFields : true ,
42
- hideRoot : false ,
43
- } ;
44
-
45
39
export interface VoyagerProps {
46
- introspection : unknown ;
40
+ introspection : Promise < ExecutionResult < IntrospectionQuery > | GraphQLSchema > ;
47
41
displayOptions ?: VoyagerDisplayOptions ;
48
42
introspectionPresets ?: { [ name : string ] : any } ;
49
43
allowToChangeSchema ?: boolean ;
@@ -55,43 +49,59 @@ export interface VoyagerProps {
55
49
}
56
50
57
51
export default function Voyager ( props : VoyagerProps ) {
52
+ const initialDisplayOptions : VoyagerDisplayOptions = useMemo (
53
+ ( ) => ( {
54
+ rootType : undefined ,
55
+ skipRelay : true ,
56
+ skipDeprecated : true ,
57
+ sortByAlphabet : false ,
58
+ showLeafFields : true ,
59
+ hideRoot : false ,
60
+ ...props . displayOptions ,
61
+ } ) ,
62
+ [ props . displayOptions ] ,
63
+ ) ;
64
+
58
65
const [ introspectionModalOpen , setIntrospectionModalOpen ] = useState ( false ) ;
59
- const [ introspectionData , setIntrospectionData ] = useState ( null ) ;
60
- const [ displayOptions , setDisplayOptions ] = useState ( {
61
- ...defaultDisplayOptions ,
62
- ...props . displayOptions ,
63
- } ) ;
66
+ const [ introspectionResult , setIntrospectionResult ] = useState ( null ) ;
67
+ const [ displayOptions , setDisplayOptions ] = useState ( initialDisplayOptions ) ;
64
68
65
69
useEffect ( ( ) => {
66
70
// FIXME: handle rejection and also handle errors inside introspection
67
71
// eslint-disable-next-line @typescript-eslint/no-floating-promises
68
- Promise . resolve ( props . introspection ) . then ( ( { data } ) => {
69
- setIntrospectionData ( data ) ;
70
- setSelected ( { typeID : null , edgeID : null } ) ;
71
- } ) ;
72
+ Promise . resolve ( props . introspection ) . then ( setIntrospectionResult ) ;
72
73
} , [ props . introspection ] ) ;
73
74
74
- const schema = useMemo (
75
- ( ) =>
76
- getSchema (
77
- introspectionData ,
78
- displayOptions . sortByAlphabet ,
79
- displayOptions . skipRelay ,
80
- displayOptions . skipDeprecated ,
81
- ) ,
82
- [
83
- introspectionData ,
75
+ useEffect ( ( ) => {
76
+ setDisplayOptions ( initialDisplayOptions ) ;
77
+ } , [ introspectionResult , initialDisplayOptions ] ) ;
78
+
79
+ const typeGraph = useMemo ( ( ) => {
80
+ if ( introspectionResult == null ) {
81
+ return null ;
82
+ }
83
+
84
+ const introspectionSchema =
85
+ introspectionResult instanceof GraphQLSchema
86
+ ? introspectionResult
87
+ : buildClientSchema ( introspectionResult . data ) ;
88
+
89
+ const schema = getSchema (
90
+ introspectionSchema ,
84
91
displayOptions . sortByAlphabet ,
85
92
displayOptions . skipRelay ,
86
93
displayOptions . skipDeprecated ,
87
- ] ,
88
- ) ;
94
+ ) ;
95
+ return getTypeGraph (
96
+ schema ,
97
+ displayOptions . rootType ,
98
+ displayOptions . hideRoot ,
99
+ ) ;
100
+ } , [ introspectionResult , displayOptions ] ) ;
89
101
90
- const typeGraph = useMemo (
91
- ( ) =>
92
- getTypeGraph ( schema , displayOptions . rootType , displayOptions . hideRoot ) ,
93
- [ schema , displayOptions . rootType , displayOptions . hideRoot ] ,
94
- ) ;
102
+ useEffect ( ( ) => {
103
+ setSelected ( { typeID : null , edgeID : null } ) ;
104
+ } , [ typeGraph ] ) ;
95
105
96
106
const [ selected , setSelected ] = useState ( { typeID : null , edgeID : null } ) ;
97
107
@@ -123,7 +133,7 @@ export default function Voyager(props: VoyagerProps) {
123
133
open = { introspectionModalOpen }
124
134
presets = { props . introspectionPresets }
125
135
onClose = { ( ) => setIntrospectionModalOpen ( false ) }
126
- onChange = { setIntrospectionData }
136
+ onChange = { setIntrospectionResult }
127
137
/>
128
138
) ;
129
139
}
@@ -171,12 +181,12 @@ export default function Voyager(props: VoyagerProps) {
171
181
}
172
182
173
183
function renderSettings ( ) {
174
- if ( schema == null ) return null ;
184
+ if ( typeGraph == null ) return null ;
175
185
176
186
return (
177
187
< Settings
178
- schema = { schema }
179
188
options = { displayOptions }
189
+ typeGraph = { typeGraph }
180
190
onChange = { ( options ) =>
181
191
setDisplayOptions ( ( oldOptions ) => ( { ...oldOptions , ...options } ) )
182
192
}
@@ -213,7 +223,7 @@ export default function Voyager(props: VoyagerProps) {
213
223
// deselect if click again
214
224
return { ...oldSelected , edgeID : null } ;
215
225
} else {
216
- return { typeID : extractTypeId ( edgeID ) , edgeID } ;
226
+ return { typeID : typeNameToId ( extractTypeName ( edgeID ) ) , edgeID } ;
217
227
}
218
228
} ) ;
219
229
}
0 commit comments