1
1
import React , { useState , useEffect , ChangeEvent , Dispatch } from "react" ;
2
2
import SplitPane from "react-split-pane" ;
3
3
import JSONRPCRequestEditor from "./JSONRPCRequestEditor" ;
4
+ import * as monaco from "monaco-editor" ;
4
5
import PlayCircle from "@material-ui/icons/PlayCircleFilled" ;
5
6
import CloseIcon from "@material-ui/icons/Close" ;
6
7
import History from "@material-ui/icons/History" ;
@@ -27,13 +28,15 @@ import { Client, RequestManager, HTTPTransport, WebSocketTransport } from "@open
27
28
import Brightness3Icon from "@material-ui/icons/Brightness3" ;
28
29
import WbSunnyIcon from "@material-ui/icons/WbSunny" ;
29
30
import { JSONRPCError } from "@open-rpc/client-js/build/Error" ;
30
- import { MethodObject } from "@open-rpc/meta-schema" ;
31
+ import { OpenrpcDocument } from "@open-rpc/meta-schema" ;
31
32
import MonacoEditor from "@etclabscore/react-monaco-editor" ;
32
33
import useTabs from "../hooks/useTabs" ;
33
34
import { useDebounce } from "use-debounce" ;
34
35
import { green } from "@material-ui/core/colors" ;
35
36
import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js" ;
36
37
import useMonacoVimMode from "../hooks/useMonacoVimMode" ;
38
+ import { addDiagnostics } from "@etclabscore/monaco-add-json-schema-diagnostics" ;
39
+ import openrpcDocumentToJSONRPCSchemaResult from "../helpers/openrpcDocumentToJSONRPCSchemaResult" ;
37
40
38
41
const errorToJSON = ( error : JSONRPCError | any ) : any => {
39
42
const isError = error instanceof Error ;
@@ -55,7 +58,7 @@ interface IProps {
55
58
request ?: any ;
56
59
darkMode ?: boolean ;
57
60
hideToggleTheme ?: boolean ;
58
- openrpcMethodObject ?: MethodObject ;
61
+ openrpcDocument ?: OpenrpcDocument ;
59
62
onToggleDarkMode ?: ( ) => void ;
60
63
}
61
64
@@ -64,6 +67,10 @@ const useClient = (url: string): [Client, JSONRPCError | undefined, Dispatch<JSO
64
67
const [ error , setError ] = useState ( ) ;
65
68
useEffect ( ( ) => {
66
69
let transport ;
70
+ if ( url === "" || url === undefined ) {
71
+ setClient ( undefined ) ;
72
+ return ;
73
+ }
67
74
if ( url . includes ( "http://" ) || url . includes ( "https://" ) ) {
68
75
transport = HTTPTransport ;
69
76
}
@@ -79,6 +86,7 @@ const useClient = (url: string): [Client, JSONRPCError | undefined, Dispatch<JSO
79
86
console . log ( "onError" , e ) ; //tslint:disable-line
80
87
} ) ;
81
88
} catch ( e ) {
89
+ setClient ( undefined ) ;
82
90
setError ( e ) ;
83
91
}
84
92
} , [ url ] ) ;
@@ -118,7 +126,7 @@ const Inspector: React.FC<IProps> = (props) => {
118
126
} = useTabs (
119
127
[
120
128
{
121
- name : "New Tab" ,
129
+ name : props . request ? props . request . method : "New Tab" ,
122
130
content : props . request || { ...emptyJSONRPC } ,
123
131
url : props . url || "" ,
124
132
} ,
@@ -127,7 +135,7 @@ const Inspector: React.FC<IProps> = (props) => {
127
135
const [ id , incrementId ] = useCounter ( 0 ) ;
128
136
const [ responseEditor , setResponseEditor ] = useState ( ) ;
129
137
useMonacoVimMode ( responseEditor ) ;
130
- const [ openrpcDocument , setOpenRpcDocument ] = useState ( ) ;
138
+ const [ openrpcDocument , setOpenRpcDocument ] = useState ( props . openrpcDocument ) ;
131
139
const [ json , setJson ] = useState ( props . request || {
132
140
jsonrpc : "2.0" ,
133
141
method : "" ,
@@ -142,16 +150,16 @@ const Inspector: React.FC<IProps> = (props) => {
142
150
const [ requestHistory , setRequestHistory ] : [ any [ ] , Dispatch < any > ] = useState ( [ ] ) ;
143
151
const [ historySelectedIndex , setHistorySelectedIndex ] = useState ( 0 ) ;
144
152
useEffect ( ( ) => {
145
- if ( props . openrpcMethodObject ) {
146
- setJson ( {
147
- jsonrpc : "2.0" ,
148
- method : props . openrpcMethodObject . name ,
149
- params : json . params ,
150
- id : id . toString ( ) ,
151
- } ) ;
152
- }
153
- // eslint-disable-next-line react-hooks/exhaustive-deps
154
- } , [ ] ) ;
153
+ setTabs ( [
154
+ ... tabs ,
155
+ {
156
+ name : props . request ? props . request . method || "New Tab" : "New Tab" ,
157
+ content : props . request ,
158
+ url : props . url ,
159
+ } ,
160
+ ] ) ;
161
+ setTabIndex ( tabs . length ) ;
162
+ } , [ props . request ] ) ;
155
163
useEffect ( ( ) => {
156
164
if ( json ) {
157
165
const jsonResult = {
@@ -164,6 +172,25 @@ const Inspector: React.FC<IProps> = (props) => {
164
172
// eslint-disable-next-line react-hooks/exhaustive-deps
165
173
} , [ id ] ) ;
166
174
175
+ useEffect ( ( ) => {
176
+ if ( ! openrpcDocument ) {
177
+ return ;
178
+ }
179
+ if ( ! responseEditor ) {
180
+ return ;
181
+ }
182
+ if ( ! results ) {
183
+ return ;
184
+ }
185
+ const schema = openrpcDocumentToJSONRPCSchemaResult ( openrpcDocument , json . method ) ;
186
+ const modelName = "inspector-results" ;
187
+ const modelUriString = `inmemory://${ modelName } -${ Math . random ( ) } .json` ;
188
+ const modelUri = monaco . Uri . parse ( modelUriString ) ;
189
+ const model = monaco . editor . createModel ( results ? JSON . stringify ( results , null , 4 ) : "" , "json" , modelUri ) ;
190
+ responseEditor . setModel ( model ) ;
191
+ addDiagnostics ( modelUri . toString ( ) , schema , monaco ) ;
192
+ } , [ results , responseEditor , openrpcDocument ] ) ;
193
+
167
194
useEffect ( ( ) => {
168
195
if ( json ) {
169
196
setTabContent ( tabIndex , json ) ;
@@ -217,13 +244,13 @@ const Inspector: React.FC<IProps> = (props) => {
217
244
}
218
245
} ;
219
246
const refreshOpenRpcDocument = async ( ) => {
220
- if ( url ) {
221
- try {
222
- const d = await client . request ( "rpc.discover" , [ ] ) ;
223
- const doc = await parseOpenRPCDocument ( d ) ;
224
- setOpenRpcDocument ( doc ) ;
225
- setTabOpenRPCDocument ( tabIndex , doc ) ;
226
- } catch ( e ) {
247
+ try {
248
+ const d = await client . request ( "rpc.discover" , [ ] ) ;
249
+ const doc = await parseOpenRPCDocument ( d ) ;
250
+ setOpenRpcDocument ( doc ) ;
251
+ setTabOpenRPCDocument ( tabIndex , doc ) ;
252
+ } catch ( e ) {
253
+ if ( ! props . openrpcDocument ) {
227
254
setOpenRpcDocument ( undefined ) ;
228
255
setTabOpenRPCDocument ( tabIndex , undefined ) ;
229
256
}
@@ -232,18 +259,22 @@ const Inspector: React.FC<IProps> = (props) => {
232
259
useEffect ( ( ) => {
233
260
refreshOpenRpcDocument ( ) ;
234
261
// eslint-disable-next-line react-hooks/exhaustive-deps
235
- } , [ client ] ) ;
262
+ } , [ client , tabIndex ] ) ;
236
263
237
264
useEffect ( ( ) => {
238
265
if ( tabs [ tabIndex ] ) {
239
266
setJson ( tabs [ tabIndex ] . content ) ;
240
267
setUrl ( tabs [ tabIndex ] . url || "" ) ;
241
- setOpenRpcDocument ( tabs [ tabIndex ] . openrpcDocument ) ;
242
268
setResults ( tabs [ tabIndex ] . results ) ;
243
269
}
244
270
// eslint-disable-next-line react-hooks/exhaustive-deps
245
271
} , [ tabIndex ] ) ;
246
272
273
+ useEffect ( ( ) => {
274
+ setOpenRpcDocument ( props . openrpcDocument ) ;
275
+ setTabOpenRPCDocument ( tabIndex , undefined ) ;
276
+ } , [ props . openrpcDocument ] ) ;
277
+
247
278
const handleTabIndexChange = ( event : React . ChangeEvent < { } > , newValue : number ) => {
248
279
setTabIndex ( newValue ) ;
249
280
} ;
@@ -358,6 +389,7 @@ const Inspector: React.FC<IProps> = (props) => {
358
389
{
359
390
name : "New Tab" ,
360
391
content : { ...emptyJSONRPC } ,
392
+ openrpcDocument : undefined ,
361
393
url : "" ,
362
394
} ,
363
395
] ,
@@ -388,9 +420,10 @@ const Inspector: React.FC<IProps> = (props) => {
388
420
?
389
421
< Tooltip title = {
390
422
< div style = { { textAlign : "center" } } >
391
- < Typography > Valid OpenRPC Endpoint. </ Typography >
423
+ < Typography > OpenRPC Document Detected </ Typography >
392
424
< Typography variant = "caption" >
393
- The JSON-RPC endpoint responds to the rpc.discover method.
425
+ A JSON-RPC endpoint may respond to the rpc.discover method
426
+ or a provide a static document.
394
427
This adds features like auto completion to the inspector.
395
428
</ Typography >
396
429
</ div >
@@ -452,7 +485,6 @@ const Inspector: React.FC<IProps> = (props) => {
452
485
}
453
486
} }
454
487
openrpcDocument = { openrpcDocument }
455
- openrpcMethodObject = { props . openrpcMethodObject }
456
488
value = { JSON . stringify ( json , null , 4 ) }
457
489
/>
458
490
< >
@@ -484,7 +516,7 @@ const Inspector: React.FC<IProps> = (props) => {
484
516
value = { JSON . stringify ( errorToJSON ( results ) || results , null , 4 ) || "" }
485
517
/>
486
518
: < Grid container justify = "center" style = { { paddingTop : "20px" } } direction = "column" alignItems = "center" >
487
- < Typography variant = "body1" gutterBottom color = "textSecondary" style = { { paddingBottom : "15px" } } >
519
+ < Typography variant = "body1" gutterBottom color = "textSecondary" style = { { paddingBottom : "15px" } } >
488
520
Press the Play button to see the results here.
489
521
</ Typography >
490
522
< Typography variant = "body1" color = "textSecondary" >
0 commit comments