Skip to content

Commit 0602c44

Browse files
authored
Merge pull request #132 from open-rpc/fix/inspector-props-updates
fix: add props updates
2 parents 765b899 + 5b8b058 commit 0602c44

6 files changed

+121
-71
lines changed

openrpc.json

Whitespace-only changes.

src/containers/App.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ const App: React.FC = () => {
2525
onToggleDarkMode={darkMode.toggle}
2626
darkMode={darkMode.value}
2727
url={query.url}
28-
openrpcMethodObject={query.openrpcMethodObject}
28+
openrpcDocument={query.openrpcDocument}
2929
request={query.request}
3030
/>
3131
</MuiThemeProvider>

src/containers/Inspector.tsx

+61-26
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useEffect, ChangeEvent, Dispatch } from "react";
22
import SplitPane from "react-split-pane";
33
import JSONRPCRequestEditor from "./JSONRPCRequestEditor";
4+
import * as monaco from "monaco-editor";
45
import PlayCircle from "@material-ui/icons/PlayCircleFilled";
56
import CloseIcon from "@material-ui/icons/Close";
67
import History from "@material-ui/icons/History";
@@ -27,13 +28,15 @@ import { Client, RequestManager, HTTPTransport, WebSocketTransport } from "@open
2728
import Brightness3Icon from "@material-ui/icons/Brightness3";
2829
import WbSunnyIcon from "@material-ui/icons/WbSunny";
2930
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";
3132
import MonacoEditor from "@etclabscore/react-monaco-editor";
3233
import useTabs from "../hooks/useTabs";
3334
import { useDebounce } from "use-debounce";
3435
import { green } from "@material-ui/core/colors";
3536
import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js";
3637
import useMonacoVimMode from "../hooks/useMonacoVimMode";
38+
import { addDiagnostics } from "@etclabscore/monaco-add-json-schema-diagnostics";
39+
import openrpcDocumentToJSONRPCSchemaResult from "../helpers/openrpcDocumentToJSONRPCSchemaResult";
3740

3841
const errorToJSON = (error: JSONRPCError | any): any => {
3942
const isError = error instanceof Error;
@@ -55,7 +58,7 @@ interface IProps {
5558
request?: any;
5659
darkMode?: boolean;
5760
hideToggleTheme?: boolean;
58-
openrpcMethodObject?: MethodObject;
61+
openrpcDocument?: OpenrpcDocument;
5962
onToggleDarkMode?: () => void;
6063
}
6164

@@ -64,6 +67,10 @@ const useClient = (url: string): [Client, JSONRPCError | undefined, Dispatch<JSO
6467
const [error, setError] = useState();
6568
useEffect(() => {
6669
let transport;
70+
if (url === "" || url === undefined) {
71+
setClient(undefined);
72+
return;
73+
}
6774
if (url.includes("http://") || url.includes("https://")) {
6875
transport = HTTPTransport;
6976
}
@@ -79,6 +86,7 @@ const useClient = (url: string): [Client, JSONRPCError | undefined, Dispatch<JSO
7986
console.log("onError", e); //tslint:disable-line
8087
});
8188
} catch (e) {
89+
setClient(undefined);
8290
setError(e);
8391
}
8492
}, [url]);
@@ -118,7 +126,7 @@ const Inspector: React.FC<IProps> = (props) => {
118126
} = useTabs(
119127
[
120128
{
121-
name: "New Tab",
129+
name: props.request ? props.request.method : "New Tab",
122130
content: props.request || { ...emptyJSONRPC },
123131
url: props.url || "",
124132
},
@@ -127,7 +135,7 @@ const Inspector: React.FC<IProps> = (props) => {
127135
const [id, incrementId] = useCounter(0);
128136
const [responseEditor, setResponseEditor] = useState();
129137
useMonacoVimMode(responseEditor);
130-
const [openrpcDocument, setOpenRpcDocument] = useState();
138+
const [openrpcDocument, setOpenRpcDocument] = useState(props.openrpcDocument);
131139
const [json, setJson] = useState(props.request || {
132140
jsonrpc: "2.0",
133141
method: "",
@@ -142,16 +150,17 @@ const Inspector: React.FC<IProps> = (props) => {
142150
const [requestHistory, setRequestHistory]: [any[], Dispatch<any>] = useState([]);
143151
const [historySelectedIndex, setHistorySelectedIndex] = useState(0);
144152
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);
153162
// eslint-disable-next-line react-hooks/exhaustive-deps
154-
}, []);
163+
}, [props.request]);
155164
useEffect(() => {
156165
if (json) {
157166
const jsonResult = {
@@ -164,6 +173,26 @@ const Inspector: React.FC<IProps> = (props) => {
164173
// eslint-disable-next-line react-hooks/exhaustive-deps
165174
}, [id]);
166175

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+
167196
useEffect(() => {
168197
if (json) {
169198
setTabContent(tabIndex, json);
@@ -217,13 +246,13 @@ const Inspector: React.FC<IProps> = (props) => {
217246
}
218247
};
219248
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) {
227256
setOpenRpcDocument(undefined);
228257
setTabOpenRPCDocument(tabIndex, undefined);
229258
}
@@ -232,18 +261,23 @@ const Inspector: React.FC<IProps> = (props) => {
232261
useEffect(() => {
233262
refreshOpenRpcDocument();
234263
// eslint-disable-next-line react-hooks/exhaustive-deps
235-
}, [client]);
264+
}, [client, tabIndex]);
236265

237266
useEffect(() => {
238267
if (tabs[tabIndex]) {
239268
setJson(tabs[tabIndex].content);
240269
setUrl(tabs[tabIndex].url || "");
241-
setOpenRpcDocument(tabs[tabIndex].openrpcDocument);
242270
setResults(tabs[tabIndex].results);
243271
}
244272
// eslint-disable-next-line react-hooks/exhaustive-deps
245273
}, [tabIndex]);
246274

275+
useEffect(() => {
276+
setOpenRpcDocument(props.openrpcDocument);
277+
setTabOpenRPCDocument(tabIndex, undefined);
278+
// eslint-disable-next-line react-hooks/exhaustive-deps
279+
}, [props.openrpcDocument]);
280+
247281
const handleTabIndexChange = (event: React.ChangeEvent<{}>, newValue: number) => {
248282
setTabIndex(newValue);
249283
};
@@ -358,6 +392,7 @@ const Inspector: React.FC<IProps> = (props) => {
358392
{
359393
name: "New Tab",
360394
content: { ...emptyJSONRPC },
395+
openrpcDocument: undefined,
361396
url: "",
362397
},
363398
],
@@ -388,9 +423,10 @@ const Inspector: React.FC<IProps> = (props) => {
388423
?
389424
<Tooltip title={
390425
<div style={{ textAlign: "center" }}>
391-
<Typography>Valid OpenRPC Endpoint.</Typography>
426+
<Typography>OpenRPC Document Detected</Typography>
392427
<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.
394430
This adds features like auto completion to the inspector.
395431
</Typography>
396432
</div>
@@ -452,7 +488,6 @@ const Inspector: React.FC<IProps> = (props) => {
452488
}
453489
}}
454490
openrpcDocument={openrpcDocument}
455-
openrpcMethodObject={props.openrpcMethodObject}
456491
value={JSON.stringify(json, null, 4)}
457492
/>
458493
<>
@@ -484,7 +519,7 @@ const Inspector: React.FC<IProps> = (props) => {
484519
value={JSON.stringify(errorToJSON(results) || results, null, 4) || ""}
485520
/>
486521
: <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" }}>
488523
Press the Play button to see the results here.
489524
</Typography>
490525
<Typography variant="body1" color="textSecondary">

src/containers/JSONRPCRequestEditor.tsx

+6-42
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useEffect, useState } from "react";
22
import MonacoEditor from "@etclabscore/react-monaco-editor";
33
import * as monaco from "monaco-editor";
4-
import { MethodObject, ContentDescriptorObject, OpenrpcDocument } from "@open-rpc/meta-schema";
4+
import { MethodObject, OpenrpcDocument } from "@open-rpc/meta-schema";
55
import useWindowSize from "@rehooks/window-size";
66
import { addDiagnostics } from "@etclabscore/monaco-add-json-schema-diagnostics";
77
import openrpcDocumentToJSONRPCSchema from "../helpers/openrpcDocumentToJSONRPCSchema";
@@ -28,7 +28,7 @@ const JSONRPCRequestEditor: React.FC<IProps> = (props) => {
2828
if (!editor) {
2929
return;
3030
}
31-
const modelName = props.openrpcMethodObject ? props.openrpcMethodObject.name : "inspector";
31+
const modelName = (props.openrpcDocument && props.openrpcDocument.info) ? props.openrpcDocument.info.title : "inspector";
3232
const modelUriString = `inmemory://${modelName}-${Math.random()}.json`;
3333
const modelUri = monaco.Uri.parse(modelUriString);
3434
const model = monaco.editor.createModel(props.value || "", "json", modelUri);
@@ -38,7 +38,7 @@ const JSONRPCRequestEditor: React.FC<IProps> = (props) => {
3838
properties: {
3939
jsonrpc: {
4040
type: "string",
41-
enum: ["2.0"],
41+
const: "2.0",
4242
},
4343
id: {
4444
oneOf: [
@@ -55,44 +55,8 @@ const JSONRPCRequestEditor: React.FC<IProps> = (props) => {
5555
},
5656
},
5757
};
58-
if (props.openrpcMethodObject) {
59-
schema = {
60-
...schema,
61-
additionalProperties: false,
62-
properties: {
63-
...schema.properties,
64-
method: {
65-
type: "string",
66-
enum: [props.openrpcMethodObject.name],
67-
},
68-
params: {
69-
oneOf: [
70-
{
71-
type: "array",
72-
...schema.properties.params,
73-
items: props.openrpcMethodObject.params.map((param: any) => {
74-
return {
75-
...param.schema,
76-
additionalProperties: false,
77-
};
78-
}),
79-
},
80-
{
81-
type: "object",
82-
properties: (props.openrpcMethodObject.params as ContentDescriptorObject[])
83-
.reduce((memo: any, param: ContentDescriptorObject) => {
84-
memo[param.name] = {
85-
...param.schema,
86-
additionalProperties: false,
87-
};
88-
return memo;
89-
}, {}),
90-
},
91-
],
92-
},
93-
},
94-
};
95-
} else if (props.openrpcDocument) {
58+
59+
if (props.openrpcDocument) {
9660
schema = openrpcDocumentToJSONRPCSchema(props.openrpcDocument);
9761
} else {
9862
schema = {
@@ -111,7 +75,7 @@ const JSONRPCRequestEditor: React.FC<IProps> = (props) => {
11175
addDiagnostics(modelUri.toString(), schema, monaco);
11276

11377
// eslint-disable-next-line react-hooks/exhaustive-deps
114-
}, [props.openrpcDocument, props.openrpcMethodObject]);
78+
}, [props.openrpcDocument]);
11579

11680
function handleEditorDidMount(_: any, ed: any) {
11781
setEditor(ed);

src/helpers/openrpcDocumentToJSONRPCSchema.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ const schema: any = {
66
jsonrpc: {
77
type: "string",
88
enum: ["2.0"],
9+
description: "JSON-RPC version string",
910
},
1011
id: {
12+
description: "unique identifier for the JSON-RPC request",
1113
oneOf: [
1214
{
1315
type: "string",
@@ -35,6 +37,7 @@ const openrpcDocumentToJSONRPCSchema = (openrpcDocument: OpenrpcDocument) => {
3537
},
3638
method: {
3739
type: "string",
40+
description: "Method Name",
3841
oneOf: openrpcDocument.methods.map((method) => {
3942
return {
4043
const: method.name,
@@ -72,7 +75,7 @@ const openrpcDocumentToJSONRPCSchema = (openrpcDocument: OpenrpcDocument) => {
7275
return {
7376
...param.schema,
7477
markdownDescription: param.description || param.summary,
75-
description: param.summary,
78+
description: param.description || param.summary,
7679
additionalProperties: false,
7780
};
7881
}),
@@ -84,7 +87,7 @@ const openrpcDocumentToJSONRPCSchema = (openrpcDocument: OpenrpcDocument) => {
8487
memo[param.name] = {
8588
...param.schema,
8689
markdownDescription: param.description || param.summary,
87-
description: param.summary,
90+
description: param.description || param.summary,
8891
additionalProperties: false,
8992
};
9093
return memo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { MethodObject, ContentDescriptorObject, OpenrpcDocument } from "@open-rpc/meta-schema";
2+
3+
const schema: any = {
4+
type: "object",
5+
properties: {
6+
jsonrpc: {
7+
type: "string",
8+
description: "JSON-RPC Version String",
9+
const: "2.0",
10+
},
11+
id: {
12+
oneOf: [
13+
{
14+
type: "string",
15+
},
16+
{
17+
type: "number",
18+
},
19+
],
20+
},
21+
},
22+
};
23+
24+
const openrpcDocumentToJSONRPCSchemaResult = (openrpcDocument: OpenrpcDocument, methodName: string) => {
25+
const methodObject: MethodObject | undefined = openrpcDocument.methods.find((method) => method.name === methodName);
26+
let methodSchema: any;
27+
if (methodObject !== undefined && methodObject.result !== undefined) {
28+
methodSchema = (methodObject.result as ContentDescriptorObject).schema;
29+
}
30+
return {
31+
type: "object",
32+
properties: {
33+
id: {
34+
...schema.properties.id,
35+
},
36+
jsonrpc: {
37+
...schema.properties.jsonrpc,
38+
},
39+
result: {
40+
...methodSchema,
41+
markdownDescription: methodObject?.description || methodObject?.summary,
42+
description: methodObject?.description || methodObject?.summary,
43+
},
44+
},
45+
};
46+
};
47+
48+
export default openrpcDocumentToJSONRPCSchemaResult;

0 commit comments

Comments
 (0)