Skip to content

Commit

Permalink
feat: add http transport options configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejonas committed Oct 30, 2020
1 parent e662f5f commit 585ebe8
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 32 deletions.
35 changes: 28 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@material-ui/icons": "3.0.2",
"@material-ui/lab": "4.0.0-alpha.47",
"@monaco-editor/react": "^2.3.0",
"@open-rpc/client-js": "^1.3.1",
"@open-rpc/client-js": "^1.6.0",
"@open-rpc/logs-react": "^1.1.13",
"@open-rpc/meta-schema": "^1.7.0",
"@open-rpc/schema-utils-js": "^1.12.0",
Expand Down
96 changes: 78 additions & 18 deletions src/containers/Inspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,40 @@ import { useDebounce } from "use-debounce";
import { green } from "@material-ui/core/colors";
import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js";
import TransportDropdown from "../components/TransportDropdown";
import useTransport, { ITransport, TTransport } from "../hooks/useTransport";
import useTransport, { ITransport, IWebTransport, TTransport } from "../hooks/useTransport";
import JSONRPCLogger, { JSONRPCLog } from "@open-rpc/logs-react";
import OptionsEditor from "./OptionsEditor";

const defaultTransports: ITransport[] = [
{
type: "http",
name: "HTTP",
schema: {
type: "object",
properties: {
headers: {
patternProperties: {
"": {
type: "string",
},
},
},
credentials: {
type: "string",
enum: [
"omit",
"same-origin",
"include",
],
},
},
examples: [
{
headers: {
},
},
],
},
},
{
type: "websocket",
Expand Down Expand Up @@ -143,7 +170,14 @@ const Inspector: React.FC<IProps> = (props) => {
const [url, setUrl] = useState(props.url || "");
const [debouncedUrl] = useDebounce(url, 1000);
const [selectedTransport, setSelectedTransport] = useState(defaultTransports[0]);
const [transport, setTransport, , connected] = useTransport(transportList, debouncedUrl, defaultTransports[0]);
const [transportOptions, setTransportOptions] = useState();
const [debouncedtransportOptions] = useDebounce(transportOptions, 1000);
const [transport, setTransport, , connected] = useTransport(
transportList,
debouncedUrl,
defaultTransports[0],
debouncedtransportOptions,
);
const [historyOpen, setHistoryOpen] = useState(false);
const [requestHistory, setRequestHistory]: [any[], Dispatch<any>] = useState([]);
const [historySelectedIndex, setHistorySelectedIndex] = useState(0);
Expand All @@ -165,6 +199,10 @@ const Inspector: React.FC<IProps> = (props) => {
useEffect(() => {
if (selectedTransport !== undefined) {
setTransport(selectedTransport!);
const s: IWebTransport = selectedTransport as IWebTransport;
if (s.schema && s.schema?.examples) {
setTransportOptions(s.schema.examples[0]);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedTransport]);
Expand Down Expand Up @@ -323,6 +361,14 @@ const Inspector: React.FC<IProps> = (props) => {
}
};

const handleTransportOptionsChange = (optionsString: string) => {
try {
setTransportOptions(JSON.parse(optionsString));
} catch (e) {
// cannot parse transport options
}
};

return (
<>
<Dialog onClose={() => setHistoryOpen(false)} aria-labelledby="simple-dialog-title" open={historyOpen} >
Expand Down Expand Up @@ -527,22 +573,36 @@ const Inspector: React.FC<IProps> = (props) => {
defaultSize={"50%"}
pane2Style={{ height: "100%", width: "100%", overflow: "auto" }}
style={{ flexGrow: 1, height: "calc(100% - 128px)" }}>
<JSONRPCRequestEditor
onChange={(val) => {
let jsonResult;
try {
jsonResult = JSON.parse(val);
} catch (e) {
console.error(e);
}
if (jsonResult) {
setJson(jsonResult);
setTabContent(tabIndex, jsonResult);
}
}}
openrpcDocument={openrpcDocument}
value={JSON.stringify(json, null, 4)}
/>
<SplitPane
split="horizontal"
minSize={100}
maxSize={-100}
defaultSize={(selectedTransport as IWebTransport).schema ? "85%" : "100%"}
pane2Style={{ height: "100%", width: "100%", overflow: "auto" }}
style={{ flexGrow: 1, height: "calc(100% - 128px)" }}>
<JSONRPCRequestEditor
onChange={(val) => {
let jsonResult;
try {
jsonResult = JSON.parse(val);
} catch (e) {
console.error(e);
}
if (jsonResult) {
setJson(jsonResult);
setTabContent(tabIndex, jsonResult);
}
}}
openrpcDocument={openrpcDocument}
value={JSON.stringify(json, null, 4)}
/>
{(selectedTransport as IWebTransport).schema && <OptionsEditor
schema={(selectedTransport as IWebTransport).schema}
value={JSON.stringify(transportOptions, null, 4)}
onChange={handleTransportOptionsChange}>
</OptionsEditor>
}
</SplitPane>
<>
{logs.length > 0 &&
<Button
Expand Down
1 change: 1 addition & 0 deletions src/containers/JSONRPCRequestEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const JSONRPCRequestEditor: React.FC<IProps> = (props) => {
return (
<MonacoEditor
height="100%"
width="100%"
value={props.value}
editorDidMount={handleEditorDidMount}
editorOptions={{
Expand Down
76 changes: 76 additions & 0 deletions src/containers/OptionsEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useEffect, useState } from "react";
import MonacoEditor from "@etclabscore/react-monaco-editor";
import * as monaco from "monaco-editor";
import { JSONSchema, MethodObject } from "@open-rpc/meta-schema";
import useWindowSize from "@rehooks/window-size";
import { addDiagnostics } from "@etclabscore/monaco-add-json-schema-diagnostics";
import useMonacoVimMode from "../hooks/useMonacoVimMode";

interface IProps {
onChange?: (newValue: any) => void;
openrpcMethodObject?: MethodObject;
schema?: JSONSchema;
value: any;
}

const OptionsEditor: React.FC<IProps> = (props) => {
const [editor, setEditor] = useState();
useMonacoVimMode(editor);
const windowSize = useWindowSize();
useEffect(() => {
if (editor) {
editor.layout();
}
}, [windowSize, editor]);

useEffect(() => {
if (!editor) {
return;
}
const modelName = "inspector-transport-options";
const modelUriString = `inmemory://${modelName}-${Math.random()}.json`;
const modelUri = monaco.Uri.parse(modelUriString);
const model = monaco.editor.createModel(props.value || "", "json", modelUri);
editor.setModel(model);

addDiagnostics(modelUri.toString(), props.schema, monaco);

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [props.schema, editor]);

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

const handleChange = (ev: any, value: any) => {
if (props.onChange) {
props.onChange(value);
}
};

return (
<>
<div style={{ marginTop: "5px", background: "black" }}></div>
<MonacoEditor
height="95%"
width="100%"
value={props.value}
editorDidMount={handleEditorDidMount}
editorOptions={{
minimap: {
enabled: false,
},
lineNumbers: "off",
glyphMargin: false,
folding: false,
automaticLayout: true,
fixedOverflowWidgets: true,
}}
language="json"
onChange={handleChange}
/>
</>
);
};

export default OptionsEditor;
19 changes: 13 additions & 6 deletions src/hooks/useTransport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { Dispatch, useEffect, useState } from "react";
import { HTTPTransport, WebSocketTransport, PostMessageWindowTransport, PostMessageIframeTransport } from "@open-rpc/client-js";
import { Transport } from "@open-rpc/client-js/build/transports/Transport";
import { IJSONRPCData } from "@open-rpc/client-js/build/Request";
import { JSONSchema } from "@open-rpc/meta-schema";

export type TTransport = "http" | "websocket" | "postmessagewindow" | "postmessageiframe";

export interface IWebTransport {
type: TTransport;
name?: string;
schema?: JSONSchema;
}

export interface IPluginTransport {
Expand All @@ -22,6 +24,7 @@ const getTransportFromType = async (
uri: string,
transports: ITransport[],
transport: ITransport,
transportOptions?: any,
): Promise<Transport> => {
let localTransport: any;
const localTransportType = transports.find((value) => {
Expand All @@ -30,7 +33,7 @@ const getTransportFromType = async (
if (localTransportType?.type === "websocket") {
localTransport = new WebSocketTransport(uri);
} else if (localTransportType?.type === "http") {
localTransport = new HTTPTransport(uri);
localTransport = new HTTPTransport(uri, transportOptions);
} else if (localTransportType?.type === "postmessageiframe") {
localTransport = new PostMessageIframeTransport(uri);
} else if (localTransportType?.type === "postmessagewindow") {
Expand Down Expand Up @@ -86,10 +89,14 @@ const getTransportFromType = async (

export type ITransport = IWebTransport | IPluginTransport;

type TUseTransport = (transports: ITransport[], url: string, defaultTransportType: ITransport) =>
[Transport | undefined, (t: ITransport) => void, JSONRPCError | undefined, boolean];
type TUseTransport = (
transports: ITransport[],
url: string,
defaultTransportType: ITransport,
transportOptions?: any,
) => [Transport | undefined, (t: ITransport) => void, JSONRPCError | undefined, boolean];

const useTransport: TUseTransport = (transports, url, defaultTransportType) => {
const useTransport: TUseTransport = (transports, url, defaultTransportType, transportOptions) => {
const [transport, setTransport] = useState<Transport>();
const [transportConnected, setTransportConnected] = useState<boolean>(false);
const [transportType, setTransportType]:
Expand All @@ -104,7 +111,7 @@ const useTransport: TUseTransport = (transports, url, defaultTransportType) => {
return;
}
const doSetTransport = async () => {
const localTransport = await getTransportFromType(url, transports, transportType);
const localTransport = await getTransportFromType(url, transports, transportType, transportOptions);
return localTransport.connect().then(() => {
setTransportConnected(true);
setTransport(localTransport);
Expand All @@ -117,7 +124,7 @@ const useTransport: TUseTransport = (transports, url, defaultTransportType) => {
setTransport(undefined);
setError(e);
});
}, [transportType, url, transports]);
}, [transportType, url, transports, transportOptions]);
const setSelectedTransportType = async (t: ITransport) => {
setTransportConnected(false);
setTransportType(t);
Expand Down

0 comments on commit 585ebe8

Please sign in to comment.