Skip to content

Commit

Permalink
Merge pull request #78 from solaoi/feature_api-component-handles-path…
Browse files Browse the repository at this point in the history
…-param

Feature api component handles path param
  • Loading branch information
solaoi authored Apr 16, 2022
2 parents 19c26ab + 6737612 commit 36496bb
Show file tree
Hide file tree
Showing 15 changed files with 345 additions and 36 deletions.
44 changes: 38 additions & 6 deletions command/cmd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func findNext(node map[string]interface{}) (name string, content interface{}, ne
data := node["data"].(map[string]interface{})

if name == "API" {
content = map[string]interface{}{"method": data["method"], "url": data["url"], "cached": data["cached"], "cacheTime": data["cacheTime"]}
content = map[string]interface{}{"method": data["method"], "headers": data["headers"], "cached": data["cached"], "cacheTime": data["cacheTime"]}
} else if name == "MySQL" || name == "PostgreSQL" {
content = map[string]interface{}{"host": data["host"], "port": data["port"], "user": data["user"], "db": data["db"], "cached": data["cached"], "cacheTime": data["cacheTime"]}
} else if name == "SQLite" {
Expand Down Expand Up @@ -210,20 +210,23 @@ func contentBuilder(contents map[int]map[string]map[string]interface{}) func(req
for k, v := range c[i] {
if v["name"] == "API" {
content := v["content"].(map[string]interface{})
url := fmt.Sprintf("%v", content["url"])
headers := fmt.Sprintf("%v", content["headers"])
cached := fmt.Sprintf("%v", content["cached"])
method := fmt.Sprintf("%v", content["method"])
url := ""
query := ""
for _, v1 := range c[i+1] {
if v1["parent"] == k {
if v1["name"] != "DummyJSON" {
if v1["name"] == "URL" || v1["name"] == "URLWithPathParam" {
url = v1["content"].(string)
} else if v1["name"] != "DummyJSON" {
query = v1["content"].(string)
}
}
}

if cached == "true" {
v, ok := gache.Get(url+query)
v, ok := gache.Get(url + query)
if ok {
apiResponses = append(apiResponses, apiResponse{method, url, "cached"})
c[i][k]["content"] = v
Expand All @@ -232,18 +235,28 @@ func contentBuilder(contents map[int]map[string]map[string]interface{}) func(req
}

req, _ := http.NewRequest(method, url, nil)
if(query != ""){
if query != "" {
params := request.URL.Query()
tmp := map[string]string{}
err := json.Unmarshal([]byte(query), &tmp)
if err != nil {
log.Fatal(err)
}
for k, v := range tmp {
params.Add(k,v)
params.Add(k, v)
}
req.URL.RawQuery = params.Encode()
}
if headers != "" {
tmp := map[string]string{}
err := json.Unmarshal([]byte(headers), &tmp)
if err != nil {
log.Fatal(err)
}
for k, v := range tmp {
req.Header.Set(k, v)
}
}
resp, err := client.Do(req)
if err == nil && resp.StatusCode >= 400 {
apiResponses = append(apiResponses, apiResponse{method, url, strconv.Itoa(resp.StatusCode)})
Expand Down Expand Up @@ -278,6 +291,25 @@ func contentBuilder(contents map[int]map[string]map[string]interface{}) func(req
}
}
c[i][k]["content"] = res
} else if v["name"] == "URLWithPathParam" {
unformattedURL := v["content"].(string)
pathParams := ""
for _, v1 := range c[i+1] {
if v1["parent"] == k {
pathParams = v1["content"].(string)
}
}
if pathParams != "" {
tmp := map[string]string{}
err := json.Unmarshal([]byte(pathParams), &tmp)
if err != nil {
log.Fatal(err)
}
for k, v := range tmp {
unformattedURL = strings.ReplaceAll(unformattedURL, ":"+k, v)
}
}
c[i][k]["content"] = unformattedURL
} else if v["name"] == "Request" {
content := v["content"].(map[string]interface{})
requestType := fmt.Sprintf("%v", content["type"])
Expand Down
10 changes: 8 additions & 2 deletions ui/src/rete.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import HistoryPlugin from "rete-history-plugin";

import { JsonComponent } from "./rete/components/input/JsonComponent";
import { DummyJsonComponent } from "./rete/components/input/DummyJsonComponent";
import { UrlComponent } from "./rete/components/input/UrlComponent";
import { UrlWithPathParamComponent } from "./rete/components/input/UrlWithPathParamComponent";
import { HtmlComponent } from "./rete/components/input/HtmlComponent";
import { SqlComponent } from "./rete/components/input/SqlComponent";
import { TemplateComponent } from "./rete/components/template/TemplateComponent";
Expand Down Expand Up @@ -58,6 +60,8 @@ export async function createEditor(container) {
rawHtmlSocket.combineWith(stringSocket);
// sql
const sqlSocket = new Rete.Socket("SQL value");
// url
const urlSocket = new Rete.Socket("URL value");

// 利用可能なコンポーネント一覧
const components = [
Expand All @@ -66,16 +70,18 @@ export async function createEditor(container) {
new JsonManagerComponent(jsonSocket),
new JsonComponent(rawJsonSocket),
new DummyJsonComponent(dummyJsonSocket),
new UrlComponent(urlSocket),
new UrlWithPathParamComponent(urlSocket, jsonSocket),
new HtmlComponent(rawHtmlSocket),
new TemplateComponent(jsonSocket, templateSocket, htmlSocket),
new HandlebarsComponent(handlebarsSocket),
new PugComponent(pugSocket),
new SqlComponent(sqlSocket),
new ApiComponent(jsonSocket, dummyJsonSocket),
new ApiComponent(jsonSocket, dummyJsonSocket, urlSocket),
new MySQLComponent(jsonSocket, dummyJsonSocket, sqlSocket),
new PostgreSQLComponent(jsonSocket, dummyJsonSocket, sqlSocket),
new SQLiteComponent(jsonSocket, dummyJsonSocket, sqlSocket),
new RequestComponent(jsonSocket),
new RequestComponent(jsonSocket, dummyJsonSocket),
new RedirectEndpointComponent(),
];

Expand Down
20 changes: 12 additions & 8 deletions ui/src/rete/components/ApiComponent.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Rete from "rete";
import { TextControl } from "../controls/TextControl";
import { TextAreaControl } from "../controls/TextAreaControl";
import { BooleanControl } from "../controls/BooleanControl";
import { NumControl } from "../controls/NumControl";
import { DefaultNode } from "../nodes/DefaultNode";
Expand All @@ -8,23 +8,26 @@ import { SelectControl } from "../controls/SelectControl";
export class ApiComponent extends Rete.Component {
path = ["New"];

constructor(jsonSocket, dummyJsonSocket) {
constructor(jsonSocket, dummyJsonSocket, urlSocket) {
super("API");
this.data.component = DefaultNode; // optional
this.jsonSocket = jsonSocket;
this.dummyJsonSocket = dummyJsonSocket;
this.urlSocket = urlSocket;
}

builder(node) {
const queryInput = new Rete.Input("query", "Query (JSON)", this.jsonSocket);
const dummyJsonInput = new Rete.Input(
"json",
"Output (DummyJSON)",
"Expected (DummyJSON)",
this.dummyJsonSocket
);
const urlInput = new Rete.Input("url", "URL", this.urlSocket);
const out = new Rete.Output("json", "JSON", this.jsonSocket);

return node
.addInput(urlInput)
.addInput(queryInput)
.addInput(dummyJsonInput)
.addControl(
Expand All @@ -38,13 +41,13 @@ export class ApiComponent extends Rete.Component {
])
)
.addControl(
new TextControl(
new TextAreaControl(
this.editor,
"url",
"headers",
node,
false,
"URL",
"https://example.com/bar"
"Headers",
'{"KEY":"VALUE"}'
)
)
.addControl(
Expand Down Expand Up @@ -72,7 +75,8 @@ export class ApiComponent extends Rete.Component {
worker(node, inputs, outputs) {
outputs.query = inputs.query.length ? inputs.query[0] : node.data.query;
outputs.json = inputs.json.length ? inputs.json[0] : node.data.json;
outputs.url = node.data.url;
outputs.url = inputs.url.length ? inputs.url[0] : node.data.url;
outputs.headers = node.data.headers;
outputs.cached = node.data.cached;

this.editor.nodes
Expand Down
2 changes: 1 addition & 1 deletion ui/src/rete/components/MySQLComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class MySQLComponent extends Rete.Component {
builder(node) {
const dummyJsonInput = new Rete.Input(
"json",
"Output (DummyJSON)",
"Expected (DummyJSON)",
this.dummyJsonSocket
);
const out = new Rete.Output("json", "JSON", this.jsonSocket);
Expand Down
2 changes: 1 addition & 1 deletion ui/src/rete/components/PostgreSQLComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class PostgreSQLComponent extends Rete.Component {
builder(node) {
const dummyJsonInput = new Rete.Input(
"json",
"Output (DummyJSON)",
"Expected (DummyJSON)",
this.dummyJsonSocket
);
const out = new Rete.Output("json", "JSON", this.jsonSocket);
Expand Down
11 changes: 6 additions & 5 deletions ui/src/rete/components/RequestComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@ import { SelectControl } from "../controls/SelectControl";
export class RequestComponent extends Rete.Component {
path = ["New"];

constructor(jsonSocket) {
constructor(jsonSocket, dummyJsonSocket) {
super("Request");
this.data.component = DefaultNode; // optional
this.jsonSocket = jsonSocket;
this.dummyJsonSocket = dummyJsonSocket;
}

builder(node) {
const jsonInput = new Rete.Input(
const dummyJsonInput = new Rete.Input(
"json",
"Dummy Output (JSON)",
this.jsonSocket
"Expected (DummyJSON)",
this.dummyJsonSocket
);
const out = new Rete.Output("json", "JSON", this.jsonSocket);

return node
.addInput(jsonInput)
.addInput(dummyJsonInput)
.addControl(
new SelectControl(this.editor, "type", node, false, "Type", [
"QUERY",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/rete/components/SQLiteComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class SQLiteComponent extends Rete.Component {
builder(node) {
const dummyJsonInput = new Rete.Input(
"json",
"Output (DummyJSON)",
"Expected (DummyJSON)",
this.dummyJsonSocket
);
const out = new Rete.Output("json", "JSON", this.jsonSocket);
Expand Down
2 changes: 1 addition & 1 deletion ui/src/rete/components/input/DummyJsonComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class DummyJsonComponent extends Rete.Component {
}

builder(node) {
const out = new Rete.Output("json", "JSON", this.socket);
const out = new Rete.Output("json", "DummyJSON", this.socket);

return node
.addControl(new JsonControl(this.editor, "json", node))
Expand Down
23 changes: 23 additions & 0 deletions ui/src/rete/components/input/UrlComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Rete from "rete";
import { UrlControl } from "../../controls/UrlControl";

export class UrlComponent extends Rete.Component {
path = ["New"];

constructor(socket) {
super("URL");
this.socket = socket;
}

builder(node) {
const out = new Rete.Output("url", "URL", this.socket);

return node
.addControl(new UrlControl(this.editor, "url", node))
.addOutput(out);
}

worker(node, _, outputs) {
outputs.url = node.data.url;
}
}
60 changes: 60 additions & 0 deletions ui/src/rete/components/input/UrlWithPathParamComponent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Rete from "rete";
import { UrlWithPathParamControl } from "../../controls/UrlWithPathParamControl";

export class UrlWithPathParamComponent extends Rete.Component {
path = ["New"];

constructor(socket, jsonSocket) {
super("URLWithPathParam");
this.socket = socket;
this.jsonSocket = jsonSocket;
}

builder(node) {
const input = new Rete.Input(
"pathParams",
"PathParams (JSON)",
this.jsonSocket
);
const out = new Rete.Output("url", "URL", this.socket);

return node
.addInput(input)
.addControl(
new UrlWithPathParamControl(this.editor, "unFormattedUrl", node)
)
.addOutput(out);
}

worker(node, inputs) {
const pathParams = inputs.pathParams.length
? inputs.pathParams[0]
: node.data.pathParams;
const { unFormattedUrl } = node.data;

if (
pathParams &&
(unFormattedUrl.startsWith("https://") ||
unFormattedUrl.startsWith("http://"))
) {
const urlElements = unFormattedUrl.split("/");
if (urlElements.length > 3) {
const formatterUrl = `${urlElements[0]}//${urlElements[2]}/${urlElements
.filter((_, i) => i > 2)
.map((v) => {
if (v.startsWith(":")) {
const key = v.slice(1);
return JSON.parse(pathParams)[key] || v;
}
return v;
})
.join("/")}`;

this.editor.nodes
.find((n) => n.id === node.id)
.controls.get("unFormattedUrl")
.setValue(unFormattedUrl, formatterUrl);
}
}
}
}
43 changes: 43 additions & 0 deletions ui/src/rete/controls/EditableUrlComponent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useState } from "react";
import Editor from "react-simple-code-editor";
import { highlight, languages } from "prismjs/components/prism-core";
import "prismjs/components/prism-uri";
import "prismjs/themes/prism.css";
import useInterval from "use-interval";

export const EditableUrlComponent = ({ value, onChange }) => {
const [code, setCode] = useState(value);
const [warn, setWarn] = useState(false);
const [stack, setStack] = useState(null);
useInterval(() => {
if (stack !== null) {
import("react-toastify").then(({ toast }) => toast.error(stack));
setStack(null);
}
}, 10000);

return (
<Editor
value={code}
onValueChange={(c) => {
if (c.startsWith("https://") || c.startsWith("http://")) {
setWarn(false);
setStack(null);
} else {
setStack("URL doesn't start with https:// or http://");
setWarn(true);
}
setCode(c);
onChange(c);
}}
highlight={(c) => highlight(c, languages.uri)}
padding={10}
style={{
fontFamily: '"Fira code", "Fira Mono", monospace',
fontSize: 12,
background: warn ? "rgba(255, 0, 80, 0.7)" : "#FFF",
maxWidth: "450px",
}}
/>
);
};
Loading

0 comments on commit 36496bb

Please sign in to comment.