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,17 @@ 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
+ 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 ) ;
153
162
// eslint-disable-next-line react-hooks/exhaustive-deps
154
- } , [ ] ) ;
163
+ } , [ props . request ] ) ;
155
164
useEffect ( ( ) => {
156
165
if ( json ) {
157
166
const jsonResult = {
@@ -164,6 +173,26 @@ const Inspector: React.FC<IProps> = (props) => {
164
173
// eslint-disable-next-line react-hooks/exhaustive-deps
165
174
} , [ id ] ) ;
166
175
176
+ useEffect ( ( ) => {
177
+ if ( ! openrpcDocument ) {
178
+ return ;
179
+ }
180
+ if ( ! responseEditor ) {
181
+ return ;
182
+ }
183
+ if ( ! results ) {
184
+ return ;
185
+ }
186
+ const schema = openrpcDocumentToJSONRPCSchemaResult ( openrpcDocument , json . method ) ;
187
+ const modelName = "inspector-results" ;
188
+ const modelUriString = `inmemory://${ modelName } -${ Math . random ( ) } .json` ;
189
+ const modelUri = monaco . Uri . parse ( modelUriString ) ;
190
+ const model = monaco . editor . createModel ( results ? JSON . stringify ( results , null , 4 ) : "" , "json" , modelUri ) ;
191
+ responseEditor . setModel ( model ) ;
192
+ addDiagnostics ( modelUri . toString ( ) , schema , monaco ) ;
193
+ // eslint-disable-next-line react-hooks/exhaustive-deps
194
+ } , [ results , responseEditor , openrpcDocument ] ) ;
195
+
167
196
useEffect ( ( ) => {
168
197
if ( json ) {
169
198
setTabContent ( tabIndex , json ) ;
@@ -217,13 +246,13 @@ const Inspector: React.FC<IProps> = (props) => {
217
246
}
218
247
} ;
219
248
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 ) {
249
+ try {
250
+ const d = await client . request ( "rpc.discover" , [ ] ) ;
251
+ const doc = await parseOpenRPCDocument ( d ) ;
252
+ setOpenRpcDocument ( doc ) ;
253
+ setTabOpenRPCDocument ( tabIndex , doc ) ;
254
+ } catch ( e ) {
255
+ if ( ! props . openrpcDocument ) {
227
256
setOpenRpcDocument ( undefined ) ;
228
257
setTabOpenRPCDocument ( tabIndex , undefined ) ;
229
258
}
@@ -232,18 +261,23 @@ const Inspector: React.FC<IProps> = (props) => {
232
261
useEffect ( ( ) => {
233
262
refreshOpenRpcDocument ( ) ;
234
263
// eslint-disable-next-line react-hooks/exhaustive-deps
235
- } , [ client ] ) ;
264
+ } , [ client , tabIndex ] ) ;
236
265
237
266
useEffect ( ( ) => {
238
267
if ( tabs [ tabIndex ] ) {
239
268
setJson ( tabs [ tabIndex ] . content ) ;
240
269
setUrl ( tabs [ tabIndex ] . url || "" ) ;
241
- setOpenRpcDocument ( tabs [ tabIndex ] . openrpcDocument ) ;
242
270
setResults ( tabs [ tabIndex ] . results ) ;
243
271
}
244
272
// eslint-disable-next-line react-hooks/exhaustive-deps
245
273
} , [ tabIndex ] ) ;
246
274
275
+ useEffect ( ( ) => {
276
+ setOpenRpcDocument ( props . openrpcDocument ) ;
277
+ setTabOpenRPCDocument ( tabIndex , undefined ) ;
278
+ // eslint-disable-next-line react-hooks/exhaustive-deps
279
+ } , [ props . openrpcDocument ] ) ;
280
+
247
281
const handleTabIndexChange = ( event : React . ChangeEvent < { } > , newValue : number ) => {
248
282
setTabIndex ( newValue ) ;
249
283
} ;
@@ -358,6 +392,7 @@ const Inspector: React.FC<IProps> = (props) => {
358
392
{
359
393
name : "New Tab" ,
360
394
content : { ...emptyJSONRPC } ,
395
+ openrpcDocument : undefined ,
361
396
url : "" ,
362
397
} ,
363
398
] ,
@@ -388,9 +423,10 @@ const Inspector: React.FC<IProps> = (props) => {
388
423
?
389
424
< Tooltip title = {
390
425
< div style = { { textAlign : "center" } } >
391
- < Typography > Valid OpenRPC Endpoint. </ Typography >
426
+ < Typography > OpenRPC Document Detected </ Typography >
392
427
< Typography variant = "caption" >
393
- The JSON-RPC endpoint responds to the rpc.discover method.
428
+ A JSON-RPC endpoint may respond to the rpc.discover method
429
+ or a provide a static document.
394
430
This adds features like auto completion to the inspector.
395
431
</ Typography >
396
432
</ div >
@@ -452,7 +488,6 @@ const Inspector: React.FC<IProps> = (props) => {
452
488
}
453
489
} }
454
490
openrpcDocument = { openrpcDocument }
455
- openrpcMethodObject = { props . openrpcMethodObject }
456
491
value = { JSON . stringify ( json , null , 4 ) }
457
492
/>
458
493
< >
@@ -484,7 +519,7 @@ const Inspector: React.FC<IProps> = (props) => {
484
519
value = { JSON . stringify ( errorToJSON ( results ) || results , null , 4 ) || "" }
485
520
/>
486
521
: < Grid container justify = "center" style = { { paddingTop : "20px" } } direction = "column" alignItems = "center" >
487
- < Typography variant = "body1" gutterBottom color = "textSecondary" style = { { paddingBottom : "15px" } } >
522
+ < Typography variant = "body1" gutterBottom color = "textSecondary" style = { { paddingBottom : "15px" } } >
488
523
Press the Play button to see the results here.
489
524
</ Typography >
490
525
< Typography variant = "body1" color = "textSecondary" >
0 commit comments