Repository: oslabs-beta/Yodelay
Branch: dev
Commit: 0a9b84d2c7ad
Files: 54
Total size: 108.8 KB
Directory structure:
gitextract_ayrg5r4x/
├── .babelrc
├── .gitignore
├── LICENSE.md
├── README.md
├── grpc_server/
│ ├── demo.js
│ ├── grpc_server.js
│ └── uServerStream.js
├── helloworld.proto
├── index.js
├── package.json
├── protos/
│ ├── demo.proto
│ ├── helloworld-copy.proto
│ ├── helloworld.proto
│ ├── output.proto
│ ├── route_guide.proto
│ └── uGreet.proto
├── server_client/
│ ├── helper_request_func.js
│ └── server_client.js
├── src/
│ ├── actions/
│ │ ├── changeTheme.ts
│ │ ├── index.ts
│ │ ├── test.ts
│ │ ├── updateMenu.ts
│ │ └── uploadProto.ts
│ ├── components/
│ │ ├── DropdownRequest.tsx
│ │ ├── DropdownService.tsx
│ │ ├── Editor.tsx
│ │ ├── EditorRequest.tsx
│ │ ├── EditorResponse.tsx
│ │ ├── Popup.tsx
│ │ ├── Settings.tsx
│ │ ├── TestProto.tsx
│ │ └── common/
│ │ ├── Button.tsx
│ │ └── DropdownMenu.tsx
│ ├── containers/
│ │ ├── App.tsx
│ │ ├── Body.tsx
│ │ ├── Footer.tsx
│ │ ├── Header.tsx
│ │ └── Navbar.tsx
│ ├── index.html
│ ├── index.tsx
│ ├── reducers/
│ │ ├── changeTheme.ts
│ │ ├── index.ts
│ │ ├── test.ts
│ │ ├── updateMenu.ts
│ │ └── uploadProto.ts
│ ├── sagas/
│ │ └── sagas.ts
│ └── scss/
│ ├── colours.scss
│ ├── common.scss
│ ├── index.scss
│ ├── input.scss
│ └── layout.scss
├── tsconfig.json
├── webpack.dev.ts
└── webpack.prod.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
node_modules/
/.pnp
.pnp.js
/sslcert
# testing
/coverage
# production
build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
log.txt
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2019 Tammy Tan, Cedric Theofanous, German Rovati, Jamie Highsmith, Davey Yedid
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
Yodelay.io is a browser-based testing tool that supports all types of gRPC calls: unary, server streaming, client streaming and bi-directional streaming, and aims to provide a beautiful interface and intuitive developer experience
## Core Features ✨
- Unary Calls and Server Side Streaming Support
- Client side and Bi-directional Streaming
- Automatic gRPC Service & Method recognition
- Request Cancellation
## Planned Features 🚧
- [ ] Web Version with gRPC-WEB
- [ ] Persistent Workspace
- [ ] Electron App
- [ ] Search History
## Getting Started 🚀
For an overview of gRPC in general, checkout the official [DOCS](https://grpc.io/docs/) here. There are clear and simple walkthroughs for each of the 12 programming languages supported by gRPC. Butter, Yodelay’s furry mascot, recommends choosing your preferred language, uploading the .proto file into yodelay and then using those examples to walk through this readme.
## Installation ⚙
Fork and clone this repo:
```sh
git clone https://github.com//Yodelay.git
```
```sh
cd Yodelay
```
```sh
npm install
```
### Test your endpoints locally ☄
Navigate to the Yodelay folder in your terminal and run the following command:
```sh
npm start
```
NPM start will build the bundle, make it available in your browser at localhost:3000, start the client server on port 4000, and start a demo grpc server at localhost:8080
Go to your browser and enter the URL:
```sh
0.0.0.0:8080
```
To test our demo proto file, upload the demo.proto file in the /protos folder
Input the server ip address:
```sh
0.0.0.0:8080
```
Select Service from the drop down you want to test:
Select Request from the drop down menu you want to test:
Edit your input message so it matches the gRPC server fields:
Click on the Send Request button and see the results from your gRPC call!
## Contributing ✏️👩💻👨💻📓
We have an open door policy - all ideas, feedback, and contributions are always welcome!
Note - When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change.
## Built with 💛
- Cedric Theofanous - @CedricTheofanous
- Davey Yedid - @dYedid
- Jamie Highsmith - @JamesHighsmith
- German Rovati - @grovati
- Tammy Tan - @tammytan95
## Developed using amazing technologies ⚛ 🐳🚢
## License
This project is licensed under the MIT License - see the LICENSE.md file for details.
================================================
FILE: grpc_server/demo.js
================================================
let grpc = require("grpc");
let protoLoader = require("@grpc/proto-loader");
// this is our test grpc server:
let PROTO_PATH = __dirname + "/../protos/demo.proto";
let packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const packageName = "demo";
let demo_proto = grpc.loadPackageDefinition(packageDefinition)[packageName];
// console.log(demo_proto)
// first demo function:
function YodelayWorld(call, callback) {
console.log("call: ", call);
const whenI = call.request.whenI;
callback(null, {
message: `When I yodel ${whenI} --> you yodel IiiOoo!!!! YODELAY!!! --> ________________`
});
}
// second demo:
function toLowerCase(call, callback) {
// console.log(call.request)
const value = call.request.uppercase;
const lower = value.toLowerCase();
callback(null, {
message: `When you input this uppercase string: ${value} the gRPC server runs the function and responds with this output: ${lower} <--`
});
}
// run innerRps function n times
function gRPCPermutations(call, callback) {
let n = call.request.n;
let arr = [""];
while (n > 0) {
arr = innerGRPC(arr);
n -= 1;
}
console.log(arr);
const str = JSON.stringify(arr);
console.log(str);
callback(null, {
message: str
});
function innerGRPC(arr) {
const g = arr.map(letter => `g${letter}`);
const r = arr.map(letter => `R${letter}`);
const p = arr.map(letter => `P${letter}`);
const c = arr.map(letter => `C${letter}`);
return [...g, ...r, ...p, ...c];
}
}
// server streaming example
function greetManyTimes(call, callback) {
// console.log(call);
let first_name = call.request.greeting.first_name;
// console.log(call.request)
let count = 0,
intervalID = setInterval(function() {
// var greetManyTimesResponse = new demo_proto.GreetManyTimesResponse();
let greetManyTimesResponse = {};
greetManyTimesResponse.result = first_name;
// console.log(greetManyTimesResponse.result);
// setup streaming
call.write(greetManyTimesResponse);
if (++count > 9) {
clearInterval(intervalID);
call.end(); // we have sent all messages!
}
}, 1000);
}
//Client streaming example
//In Paulo's example - he uses setInterval to make the client programmatically send requests using setInterval. After all requests are sent, on.end is called which indicates all messages are sent
//Paulo's server just listens for call.on(end)
//For us --> on client side, message should be sent added to responseStream everytime sendReq button is clicked
//Upon user clicking end stream button, call.end happens and server sends back response
//long greet response = "whew that was a long one - you yodeled xxx number of times!"
function longGreet(call, callback) {
let greetArr = [];
let greet = call.request.greet;
//on receiving data, push greeting into array
call.on("data", greet => {
greetArr.push(greet);
});
//upon ending, return response
call.on("end", greet => {
let numOfYodel = greetArr.length - 1;
let LongGreetResponse = `You Yodeled ${numOfYodel} of times!`;
console.log("client streaming has ended");
//or should this be ws.send? it needs to go to front end
call.write(LongGreetResponse);
});
}
// bidi streaming example
// async function sleep(interval) {
// return new Promise(resolve => {
// setTimeout(() => resolve(), interval);
// });
// }
// async function greetEveryone(call, callback) {
// call.on("data", response => {
// // let firstName = call.request.greeting.first_name
// // let lastName = call.request.greeting.last_name
// // let fullName = firstName + ' ' + lastName
// console.log('here is the data stupid ', response)
// // console.log("Hello " + fullName);
// });
// call.on("error", error => {
// console.error(error);
// });
// call.on("end", () => {
// console.log("Server The End...");
// });
// for (let i = 0; i < 10; i++) {
// call.write({ result: 'Tammy Tan' });
// await sleep(1000);
// }
// call.end();
// }
function main() {
let server = new grpc.Server();
server.addService(demo_proto.itIsDemoTimeYodelay.service, {
YodelayWorld,
toLowerCase,
gRPCPermutations,
greetManyTimes,
longGreet
// greetEveryone
});
server.bind("0.0.0.0:8080", grpc.ServerCredentials.createInsecure());
server.start();
}
main();
console.log(`gRPC💥 'n on port: 0.0.0.0:8080`);
================================================
FILE: grpc_server/grpc_server.js
================================================
let grpc = require('grpc');
let protoLoader = require('@grpc/proto-loader');
// this is our test grpc server:
let PROTO_PATH = __dirname + '/../protos/helloworld.proto';
// const port = '0.0.0.0:50051';
let packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
//
const packageName = 'helloaworld'
let hello_proto = grpc.loadPackageDefinition(packageDefinition)[packageName];
/**
* Implements the SayHello RPC method.
*/
let url;
function sayHello(call, callback) {
console.log('------rpc function call------')
console.log(`Hi! I'm the gRPC server`)
// items coning in from the express server:
console.log('gRPC incoming call request: ', call.request)
url = call.request.url;
let package = call.request.package;
let serviceInput = call.request.serviceInput;
let requestInput = call.request.requestInput;
let messageInput = call.request.messageInput;
let protoFile = call.request.protoFile;
let protoDescriptor = call.request.protoDescriptor;
// callback(null, {message: 'Hello ' + package + `! This was a call to port ${url} requesting the ${serviceInput} in ${protoFile} with the message of: ${messageInput}`});
callback(null, {
message: `This was a call to ${url} using the ${packageName} package with the ${serviceInput} that contains the ${requestInput} method with the message of: ${messageInput}. We were able to get this from parsing ${protoFile} with the built in ${protoDescriptor}.`
});
// console.log('after grpc server')
}
/**
* Starts an RPC server that receives requests for the Greeter service at the
* sample server port
*/
function main() {
let server = new grpc.Server();
server.addService(hello_proto.YodelayAPI.service,
{ sayHello });
console.log('grpc main url: ', url);
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
server.start();
}
main();
console.log(`gRPC💥 'n on port: 0.0.0.0:50051 (${url})`)
================================================
FILE: grpc_server/uServerStream.js
================================================
const fs = require("fs");
const grpc = require("grpc");
const protoLoader = require('@grpc/proto-loader');
let PROTO_PATH = __dirname + '/../protos/uGreet.proto';
let packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const packageName = 'greet'
let greets = grpc.loadPackageDefinition(packageDefinition)[packageName];
function greetManyTimes(call, callback) {
let firstName = call.request.getGreeting().getFirstName();
let count = 0,
intervalID = setInterval(function () {
let greetManyTimesResponse = new greets.GreetManyTimesResponse();
greetManyTimesResponse.setResult(firstName);
// setup streaming
call.write(greetManyTimesResponse);
if (++count > 9) {
clearInterval(intervalID);
call.end(); // we have sent all messages!
}
}, 1000);
}
function main() {
// let credentials = grpc.ServerCredentials.createSsl(
// fs.readFileSync("../certs/ca.crt"),
// [
// {
// cert_chain: fs.readFileSync("../certs/server.crt"),
// private_key: fs.readFileSync("../certs/server.key")
// }
// ],
// true
// );
let server = new grpc.Server();
server.addService(greets.service, {
greetManyTimes: greetManyTimes,
});
server.bind("127.0.0.1:50051", grpc.ServerCredentials.createInsecure());
server.start();
console.log("Server running on port 127.0.0.1:50051");
}
main();
================================================
FILE: helloworld.proto
================================================
syntax = "proto3";
// option java_multiple_files = true;
// option java_package = "io.grpc.examples.helloworld";
// option java_outer_classname = "HelloWorldProto";
// option objc_class_prefix = "HLW";
package helloaworld;
// The greeting service definition.
service YodelayAPI {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string port = 1;
string packageName = 2;
string service = 3;
string message = 4;
string protoObject = 5;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
================================================
FILE: index.js
================================================
================================================
FILE: package.json
================================================
{
"name": "yodelay",
"version": "1.0.0",
"description": "Yodelay source code.",
"repository": "",
"main": "index.js",
"scripts": {
"start": "concurrently --kill-others \"npm run src-dev\" \"npm run start-client\" \"npm run grpc\"",
"start-client": "INSECURE_PORT=4000 nodemon server_client/server_client.js",
"start-client-noenv": "nodemon server_client/server_client.js",
"grpc": "nodemon grpc_server/demo.js",
"src-dev": "webpack-dev-server --config webpack.dev.ts --env.API_PORT=4000 --env.API_HOST=localhost --env.API_PROTOCOL=http",
"src-build": "webpack --config webpack.prod.ts",
"server-dev": "ts-node-dev --respawn --transpileOnly ./server/index.ts | ./node_modules/.bin/pino-pretty -t SYS:standard -c",
"server-local": "MODE=DEVELOPMENT PORT=8443 INSECURE_PORT=8000 CORS_URL=http://localhost:3000 HOST=http://localhost:3000 npm run server-dev",
"server-test": "MODE=TEST PORT=8443 INSECURE_PORT=8000 CORS_URL=http://localhost:3000 HOST=http://localhost:3000 npm run server-dev",
"server": "ts-node-dev --respawn --transpileOnly ./server/index.ts | ./node_modules/.bin/pino-pretty -t SYS:standard -c > log.txt 2>&1",
"test": "npm run jest",
"jest": "jest test/ --coverage --runInBand"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@grpc/proto-loader": "^0.5.3",
"@testing-library/react": "^9.3.3",
"@types/classnames": "^2.2.9",
"@types/enzyme": "^3.10.3",
"@types/express": "^4.17.0",
"@types/express-pino-logger": "^4.0.2",
"@types/jest": "^24.0.23",
"@types/numeral": "0.0.26",
"@types/react-redux": "^7.1.1",
"@types/react-router-dom": "^5.1.0",
"@types/uuid": "^3.4.6",
"@types/uuidv4": "^5.0.0",
"ace-builds": "^1.4.7",
"ag-grid-community": "^22.1.0",
"ag-grid-react": "^22.1.0",
"antd": "^3.26.5",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"body-parser": "^1.19.0",
"concurrently": "^5.0.2",
"cookie-parser": "^1.4.4",
"cors": "^2.8.5",
"css-loader": "^3.0.0",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"esm": "^3.2.25",
"express": "^4.17.1",
"express-http-to-https": "^1.1.4",
"express-pino-logger": "^4.0.0",
"express-ws": "^4.0.0",
"file-loader": "^5.0.2",
"google-protobuf": "^3.11.2",
"grpc": "^1.24.2",
"grpc-promise": "^1.4.0",
"grpc-tools": "^1.8.1",
"immutable": "^4.0.0-rc.12",
"isomorphic-fetch": "^2.2.1",
"jest": "^24.9.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.15",
"node-fetch": "^2.6.0",
"node-sass": "^4.13.0",
"nodemon": "^2.0.2",
"popper": "^1.0.1",
"protoc-gen-grpc": "^1.3.8",
"react": "^16.8.6",
"react-ace": "^8.0.0",
"react-dom": "^16.8.6",
"react-hot-loader": "^4.12.18",
"react-pivot": "^4.1.0",
"react-redux": "^7.1.0",
"react-router-dom": "^5.1.2",
"react-vis": "^1.11.7",
"redux": "^4.0.1",
"redux-devtools-extension": "^2.13.8",
"redux-saga": "^0.16.0",
"reselect": "^4.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^0.23.1",
"timm": "^1.6.1",
"ts-jest": "^24.2.0",
"ts-node-dev": "^1.0.0-pre.40",
"uuidv4": "^4.0.0",
"ws": "^7.2.1"
},
"devDependencies": {
"@babel/core": "^7.7.5",
"@babel/preset-env": "^7.7.6",
"@babel/preset-react": "^7.7.4",
"@types/html-webpack-plugin": "^3.2.0",
"@types/lodash": "^4.14.136",
"@types/react": "^16.8.22",
"@types/react-dom": "^16.8.4",
"@types/react-plaid-link": "^1.3.0",
"@types/webpack": "^4.4.34",
"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"html-webpack-plugin": "^3.2.0",
"ts-node": "^8.3.0",
"typescript": "^3.6.2",
"url-loader": "^3.0.0",
"webpack": "^4.35.0",
"webpack-cli": "^3.3.5",
"webpack-dev-server": "^3.7.2"
}
}
================================================
FILE: protos/demo.proto
================================================
syntax = "proto3";
package demo;
// This service implements a simple guestbook
service itIsDemoTimeYodelay {
// first hello world test
rpc YodelayWorld (Yodelay) returns (IiiOoo) {
}
// second calls a function that reponsed
rpc toLowerCase (UpperCaseRequest) returns (LowerCaseResponse) {
}
// List existing posts
rpc gRPCPermutations (PermutationRequest) returns (PermutationResponse) {
}
//unary API
rpc Greet (GreetRequest) returns (GreetResponse) {};
//Server streaming API
rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};
// Client Streaming
rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};
// BiDi Streaming
rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};
}
// ! first test for the hello world demo:
message Yodelay {
string whenI = 1;
}
message IiiOoo {
string message = 1;
}
// ! second test for unique array:
message UpperCaseRequest {
string uppercase = 1;
}
message LowerCaseResponse {
string message = 1;
}
// third test:
message PermutationRequest {
int32 n = 1;
}
message PermutationResponse {
string message = 1;
}
//Greet Mesages
message GreetEveryoneRequest {
Greeting greet = 1;
}
message GreetEveryoneResponse {
string result = 1;
}
message LongGreetRequest {
Greeting greet = 1;
}
message LongGreetResponse {
string result = 1;
}
message GreetManyTimesRequest {
Greeting greeting = 1;
}
message GreetManyTimesResponse {
string result = 1;
}
message Greeting {
string first_name = 1;
string last_name = 2;
}
message GreetRequest {
Greeting greeting = 1;
}
message GreetResponse {
string result = 1;
}
================================================
FILE: protos/helloworld-copy.proto
================================================
syntax = "proto3";
// option java_multiple_files = true;
// option java_package = "io.grpc.examples.helloworld";
// option java_outer_classname = "HelloWorldProto";
// option objc_class_prefix = "HLW";
package helloaworld;
// The greeting service definition.
service YodelayAPI {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequestAGAIN) returns (HelloReplyAGAIN) {}
// rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}
}
// The SECOND greeting service definition.
service servTWO {
// Sends a greeting
rpc SayHelloTWO (HelloRequestTWO) returns (HelloReplyTWO) {}
rpc SayHelloAgainTWO (HelloRequestTWOagain) returns (HelloReplyTWOagain) {}
// rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string port = 1;
string packageName = 2;
string service = 3;
string message = 4;
string protoObject = 5;
int32 integer = 6;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
int32 integer = 2;
}
// The AGAIN request message containing the user's name.
message HelloRequestAGAIN {
string portAGAIN = 1;
bytes bytes = 2;
int64 int64 = 3;
float float = 4;
bool bool = 5;
int32 integerAGAIN = 6;
}
// The AGAIN response message containing the greetings
message HelloReplyAGAIN {
string messageAGAIN = 1;
int32 integerAGAIN = 2;
}
// The SECOND request message containing the user's name.
message HelloRequestTWO {
string portTWO = 1;
double double = 2;
uint32 uint32 = 3;
uint64 uint64 = 4;
sint32 sint32 = 5;
sint64 sint64 = 6;
}
// The SECOND response message containing the greetings
message HelloReplyTWO {
string messageTWO = 1;
int32 integerTWO = 2;
}
// The SECOND AGAIN request message containing the user's name.
message HelloRequestTWOagain {
fixed32 fixed32 = 1;
fixed64 fixed64 = 2;
sfixed32 sfixed32 = 3;
sfixed64 sfixed64 = 4;
string protoObjectTWOagain = 5;
int32 integerTWOagain = 6;
}
// The SECOND AGAIN response message containing the greetings
message HelloReplyTWOagain {
string messageTWOagain = 1;
int32 integerTWOagain = 2;
}
================================================
FILE: protos/helloworld.proto
================================================
syntax = "proto3";
// option java_multiple_files = true;
// option java_package = "io.grpc.examples.helloworld";
// option java_outer_classname = "HelloWorldProto";
// option objc_class_prefix = "HLW";
package helloaworld;
// The greeting service definition.
service YodelayAPI {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
// rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string url = 1;
string packageName = 2;
string serviceInput = 3;
string requestInput = 4;
string messageInput = 5;
string protoFile = 6;
string protoDescriptor = 7;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
================================================
FILE: protos/output.proto
================================================
syntax = "proto3";
package demo;
// This service implements a simple guestbook
service itIsDemoTimeYodelay {
// first hello world test
rpc YodelayWorld (Yodelay) returns (IiiOoo) {
}
// second calls a function that reponsed
rpc toLowerCase (UpperCaseRequest) returns (LowerCaseResponse) {
}
// List existing posts
rpc gRPCPermutations (PermutationRequest) returns (PermutationResponse) {
}
//unary API
rpc Greet (GreetRequest) returns (GreetResponse) {};
//Server streaming API
rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};
// Client Streaming
rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};
// BiDi Streaming
rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};
}
// ! first test for the hello world demo:
message Yodelay {
string whenI = 1;
}
message IiiOoo {
string message = 1;
}
// ! second test for unique array:
message UpperCaseRequest {
string uppercase = 1;
}
message LowerCaseResponse {
string message = 1;
}
// third test:
message PermutationRequest {
int32 n = 1;
}
message PermutationResponse {
string message = 1;
}
//Greet Mesages
message GreetEveryoneRequest {
Greeting greet = 1;
}
message GreetEveryoneResponse {
string result = 1;
}
message LongGreetRequest {
Greeting greet = 1;
}
message LongGreetResponse {
string result = 1;
}
message GreetManyTimesRequest {
Greeting greeting = 1;
}
message GreetManyTimesResponse {
string result = 1;
}
message Greeting {
string first_name = 1;
string last_name = 2;
}
message GreetRequest {
Greeting greeting = 1;
}
message GreetResponse {
string result = 1;
}
================================================
FILE: protos/route_guide.proto
================================================
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples.routeguide";
option java_outer_classname = "RouteGuideProto";
option objc_class_prefix = "RTG";
package routeguide;
// Interface exported by the server.
service RouteGuide {
// A simple RPC.
//
// Obtains the feature at a given position.
//
// A feature with an empty name is returned if there's no feature at the given
// position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC.
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC.
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
// A latitude-longitude rectangle, represented as two diagonally opposite
// points "lo" and "hi".
message Rectangle {
// One corner of the rectangle.
Point lo = 1;
// The other corner of the rectangle.
Point hi = 2;
}
// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
message Feature {
// The name of the feature.
string name = 1;
// The point where the feature is detected.
Point location = 2;
}
// A RouteNote is a message sent while at a given point.
message RouteNote {
// The location from which the message is sent.
Point location = 1;
// The message to be sent.
string message = 2;
}
// A RouteSummary is received in response to a RecordRoute rpc.
//
// It contains the number of individual points received, the number of
// detected features, and the total distance covered as the cumulative sum of
// the distance between each point.
message RouteSummary {
// The number of points received.
int32 point_count = 1;
// The number of known features passed while traversing the route.
int32 feature_count = 2;
// The distance covered in metres.
int32 distance = 3;
// The duration of the traversal in seconds.
int32 elapsed_time = 4;
}
================================================
FILE: protos/uGreet.proto
================================================
syntax = "proto3";
package greet;
service GreetService {
//unary API
rpc Greet (GreetRequest) returns (GreetResponse) {};
//Server streaming API
rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};
// Client Streaming
rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};
// BiDi Streaming
rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};
}
message GreetEveryoneRequest {
Greeting greet = 1;
}
message GreetEveryoneResponse {
string result = 1;
}
message LongGreetRequest {
Greeting greet = 1;
}
message LongGreetResponse {
string result = 1;
}
message GreetManyTimesRequest {
Greeting greeting = 1;
}
message GreetManyTimesResponse {
string result = 1;
}
message Greeting {
string first_name = 1;
string last_name = 2;
}
message GreetRequest {
Greeting greeting = 1;
}
message GreetResponse {
string result = 1;
}
================================================
FILE: server_client/helper_request_func.js
================================================
const grpc = require("grpc");
const protoLoader = require("@grpc/proto-loader");
const grpc_promise = require("grpc-promise");
const fs = require("fs");
const { EventEmitter } = require("events");
// input: .proto file
// output: {protoFile: "the text of the proto file", definition: {}, package: '', protoDescriptor: {}, services: [{}, {}, {}]}
async function parseProto(uploadParsedReqBody) {
// MESSAGE FIELDS:
console.log("-----Start Parsing Proto-----");
// the proto object is where we are passed in the .proto file from the server_client
// we then take this object and write it to the temp output.proto file in the proto folder:
let output = {};
const protoFile = uploadParsedReqBody;
output.protoFile = protoFile;
// WRITE TO TEMP .PROTO
// now let's write our protoObject string to the output.proto file:
fs.writeFileSync("./protos/output.proto", protoFile, "utf8", function (err) {
if (err) {
console.log("An error occurred while writing JSON Object to File.");
return console.log(err);
}
console.log("JSON file has been saved.");
});
// BUILD DEFINITION AND DESCRIPTOR:
// now we have a path for our proto:
const PROTO_PATH = __dirname + "/../protos/output.proto";
// and a config object:
const CONFIG_OBJECT = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
};
// now that the file is written we want to create our package definition:
const packageDefinition = protoLoader.loadSync(PROTO_PATH, CONFIG_OBJECT);
output.definition = packageDefinition;
// let's use the package definintion to create our descriptor:
const descriptorPre = grpc.loadPackageDefinition(packageDefinition);
// this is how you grab the .proto file package name:
const protoPackageName = Object.keys(descriptorPre)[0];
const descriptor = descriptorPre[protoPackageName];
output.package = protoPackageName;
output.protoDescriptor = descriptor;
// Creating the services object, which includes the various services, methods, messages, and message fields/types
const servicesObj = {};
for (let [service, serviceValue] of Object.entries(descriptor)) {
if (typeof serviceValue === "function") {
servicesObj[service] = {};
for (let [serviceMethodName, serviceMethodValue] of Object.entries(
serviceValue.service
)) {
const isMethodRequestStreaming = serviceMethodValue.requestStream;
const isMethodResponseStreaming = serviceMethodValue.responseStream;
let streamingType = "unary";
if (isMethodResponseStreaming) {
streamingType = "serverStreaming";
}
if (isMethodRequestStreaming) {
streamingType = "clientStreaming";
}
if (isMethodRequestStreaming && isMethodResponseStreaming) {
streamingType = "bidiStreaming";
}
const messageName = serviceMethodValue.requestType.type.name;
const messageFieldsRawData = serviceMethodValue.requestType.type.field;
servicesObj[service][serviceMethodName] = {};
servicesObj[service][serviceMethodName][messageName] = {};
servicesObj[service][serviceMethodName]["type"] = streamingType;
for (let messageInfo of messageFieldsRawData) {
console.log('messageInfo:: ', messageInfo)
const messageField = messageInfo.name;
let messageFieldType;
if (messageInfo.typeName !== '') {
messageFieldType = messageInfo.typeName;
} else {
messageFieldType = messageInfo.type;
}
servicesObj[service][serviceMethodName][messageName][
messageField
] = messageFieldType;
}
}
}
}
output.services = servicesObj;
return output;
}
class GrpcRequestClass extends EventEmitter {
constructor(websocket) {
super();
this.ws = websocket;
this.url = undefined
this.serviceInput = undefined;
this.messageInput = undefined;
this.requestInput = undefined;
this.package = undefined;
this.protoFile = undefined;
this.streamType = undefined;
this._call = undefined;
}
sendInit (reqbody) {
this.url = reqbody.url;
this.serviceInput = reqbody.serviceInput;
this.messageInput = reqbody.messageInput;
this.requestInput = reqbody.requestInput;
this.package = reqbody.package;
this.protoFile = reqbody.protoFile;
this.streamType = reqbody.requestInput.streamType;
this._call = undefined;
fs.writeFileSync("./protos/output.proto", this.protoFile, "utf8", function (err) {
if (err) {
console.log("An error occurred while writing JSON Object to File.");
return console.log(err);
}
console.log("JSON file has been saved.");
});
const PROTO_PATH = __dirname + "/../protos/output.proto";
const CONFIG_OBJECT = {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
};
const packageDefinition = protoLoader.loadSync(PROTO_PATH, CONFIG_OBJECT);
let protoPackageName2 = Object.keys(packageDefinition)[0].split(".")[0];
let packageDefinitionName = Object.keys(packageDefinition)[0];
const descriptor = grpc.loadPackageDefinition(packageDefinition)[
protoPackageName2
];
let servicePackage;
try {
servicePackage = new descriptor[this.serviceInput](
this.url,
grpc.credentials.createInsecure()
);
} catch {
console.log('error creating servicePackage (descriptor) in sendInit func.')
}
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
let ws = this.ws;
let messageInput;
try {
messageInput = JSON.parse(this.messageInput)
} catch {
console.log('error JSON parsing messageInput in sendInit')
}
let requestInput = this.requestInput;
let streamType = this.streamType;
if (streamType === "unary") {
// UNARY
let reqTime = process.hrtime();
try {
servicePackage[requestInput.methodName](messageInput, function (
err,
feature
) {
if (err) {
let unaryError = JSON.stringify(err)
console.log(unaryError)
ws.send(unaryError);
} else {
let resTime = process.hrtime();
let resTimeSec = resTime[0] - reqTime[0];
let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);
let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;
let message = '';
try {
message = JSON.stringify(feature);
ws.send(message);
} catch {
console.log('error JSON parsing unary gRPC response');
ws.send('error JSON parsing unary gRPC response');
}
}
});
} catch {
console.log('error in streamType === "unary"')
}
return this;
} else if (requestInput.streamType === "serverStreaming") {
// STREAMING
let reqTime = process.hrtime();
let call;
try {
call = servicePackage[requestInput.methodName](messageInput);
} catch {
console.log('error creating call - servicePackage')
}
this._call = call;
try {
call.on("data", function (feature) {
let resTime = process.hrtime();
let resTimeSec = resTime[0] - reqTime[0];
let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);
let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;
let message = JSON.stringify(feature);
ws.send(message);
});
call.on("end", function () {
ws.send('server streaming has ended')
});
call.on("error", function (e) {
() => {
ws.send('server streaming ending')
}
});
} catch {
console.log('server streaming ERROR')
ws.send('server streaming ERROR')
}
} else if (requestInput.streamType === "clientStreaming") {
//////// CLIENT STREAMING //////////
//receive data from gRPC demo server (resulting from call.write)
//link to the connection of the grpc server, must remain on clientStreaming
let reqTime = process.hrtime();
const call = servicePackage[requestInput.methodName](function (error, feature) {
if(error) {
let clientStreamingError = JSON.stringify(error)
console.log(clientStreamingError)
ws.send(clientStreamingError);
}
ws.send(JSON.stringify(feature))
});
try {
call.write(messageInput)
this._call = call;
call.on("data", function(feature) {
let resTime = process.hrtime();
let resTimeSec = resTime[0] - reqTime[0];
let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);
let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;
let message = JSON.stringify(feature);
ws.send(message);
});
call.on("end", function() {
ws.send('server has ended the client streaming')
});
call.on("error", function(e) {
// An error has occurred and the stream has been closed.
let clientStreamError = JSON.stringify(e)
ws.send('the following error occurred in the gRPC server: ', clientStreamError)
});
} catch {
console.log('Error in client-streaming')
ws.send('Error in client-streaming')
}
} else if (requestInput.streamType === 'bidiStreaming'){
let reqTime = process.hrtime();
let call = servicePackage[requestInput.methodName]();
this._call = call;
call.on("data", function (feature) {
let resTime = process.hrtime();
let resTimeSec = resTime[0] - reqTime[0];
let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);
let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;
let message = JSON.stringify(feature);
ws.send(message);
});
call.on("end", function () {
ws.send('server has ended the bidirectional streaming')
});
call.on("error", function (e) {
let bidiError = JSON.stringify(e)
ws.send('the following error occurred in the gRPC server: ', bidiError)
});
}
}
}
module.exports = {
GrpcRequestClass,
parseProto
};
================================================
FILE: server_client/server_client.js
================================================
const express = require("express");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const cors = require("cors");
const { parseProto, GrpcRequestClass } = require("./helper_request_func");
const app = express();
const expressWs = require("express-ws")(app);
const PORT = process.env.PORT || 443;
const INSECURE_PORT = process.env.INSECURE_PORT || 80;
const MODE = process.env.MODE || "PRODUCTION";
// export const HOST = process.env.HOST || 'https://mypilea.com'
const port = INSECURE_PORT;
app.use(cors());
app.use(bodyParser.text());
app.use(cookieParser());
app.use(express.static("build"));
// app.get("/", (req, res) => res.send("🍻 Yodelay World 🍻"));
// * UPLOAD:
app.post("/upload", async (req, res) => {
const parsedReqBody = JSON.parse(req.body);
let output = await parseProto(parsedReqBody);
res.json(output);
});
//Listens for messages
app.ws("/websocket", function(ws, req) {
const grpcRequestClass = new GrpcRequestClass(ws);
try {
ws.on("message", function(msg) {
let parsedReqBody;
try {
parsedReqBody = JSON.parse(msg);
} catch {
ws.send("message", "error parsing JSON in ws.on message");
}
if (parsedReqBody.wsCommand === "sendInit") {
console.log("sendInit");
grpcRequestClass.sendInit(parsedReqBody);
} else if (parsedReqBody.wsCommand === "push") {
console.log("push");
let messageInput;
try {
messageInput = JSON.parse(parsedReqBody.messageInput);
} catch {
console.log('error parsing messageInput in ws-router - "push"');
}
console.log("||||||||||||||||PUSH", messageInput);
grpcRequestClass._call.write(messageInput);
} else if (parsedReqBody.wsCommand === "end") {
if (parsedReqBody.requestInput.streamType === "serverStreaming") {
grpcRequestClass._call.cancel();
console.log("Cancel");
} else {
grpcRequestClass._call.end();
console.log("end");
}
}
});
} catch {
console.log("error in ws");
}
});
app.use((req, res) => {
res.status(404).send("Page Not Found");
});
// Global error handling:
app.use(function(err, req, res, next) {
const defaultError = {
log: "Express error handler caught unknown middleware error",
status: 400,
message: { err: "An error occurred" }
};
const newErrObj = Object.assign(defaultError, err);
console.log(newErrObj);
res.status(newErrObj.status).json(newErrObj.message);
});
app.listen(port, () =>
console.log(` 👽 invasion happening on port: ${port} `)
);
================================================
FILE: src/actions/changeTheme.ts
================================================
//Define action type
export const CHANGE_THEME = "CHANGE_THEME";
//Define shape of action type
export interface changeTheme {
type: typeof CHANGE_THEME;
payload: string;
}
//Groups all action types so that they can be referenced in the reducer files via one umbrella type -- basically, we're trying to make sure that any given reducer can only accept certain action types in the switch/case statement
export type changeThemeAction = changeTheme;
export const changeThemeActionCreator = (payloadObj: string): changeTheme => {
return {
type: CHANGE_THEME,
payload: payloadObj
};
};
================================================
FILE: src/actions/index.ts
================================================
/****************************************single source of all creators and action types***************************** */
export * from "./test";
export * from "./uploadProto";
export * from "./updateMenu";
export * from "./changeTheme";
// export * from './actionTypes'
================================================
FILE: src/actions/test.ts
================================================
// Consolidate actionTypes with this file. Rename this file from actionCreators to increment.ts (we should mirror increment.ts in the reducers file). Remove below line
// import {INCREMENT} from './actionTypes'
/****************************create action type*************************** */
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'
/*****************************************define types for action obj************** */
// defines
export interface incrementAction {
type: typeof INCREMENT
payload: number
}
export interface decrementAction {
type: typeof DECREMENT
payload: number
}
// we combine the increment and decrement interface types into one type so that this one type can be used elsewhere, like in /reducers/increment
export type incrementActions = incrementAction | decrementAction
/**********************************makes available outside of file ********** */
//we can get rid of export type by just exporting the interface. Remove below line
// export type incrementActionType = incrementAction
export const incrementActionCreator = (incrementNum: number): incrementAction => {
return {
type: INCREMENT,
payload: incrementNum
}
}
export const decrementActionCreator = (decrementNum: number): decrementAction => {
return {
type: DECREMENT,
payload: decrementNum
}
}
================================================
FILE: src/actions/updateMenu.ts
================================================
//Define action type
export const LOAD_SERVICE_OPTIONS = 'LOAD_SERVICE_OPTIONS '
export const LOAD_REQUEST_OPTIONS = 'LOAD_REQUEST_OPTIONS '
//Define shape of action type
export interface loadServiceOptions {
type: typeof LOAD_SERVICE_OPTIONS;
payload: object
}
export interface loadRequestOptions {
type: typeof LOAD_REQUEST_OPTIONS;
payload: object
}
//Groups all action types so that they can be referenced in the reducer files via one umbrella type -- basically, we're trying to make sure that any given reducer can only accept certain action types in the switch/case statement
export type loadMenuAction = loadServiceOptions | loadRequestOptions
export const loadServiceActionCreator = (
payloadObj: object
): loadServiceOptions => {
return {
type: LOAD_SERVICE_OPTIONS,
payload: payloadObj
};
};
export const loadRequestActionCreator = (
payloadObj: object
): loadRequestOptions => {
return {
type: LOAD_REQUEST_OPTIONS,
payload: payloadObj
};
};
================================================
FILE: src/actions/uploadProto.ts
================================================
import { typeResponse } from "../reducers/uploadProto";
//Define action type
export const UPLOAD_PROTO = "UPLOAD_PROTO";
export const SEND_PROTO = "SEND_PROTO";
export const UPLOAD_PROTO_SUCCESSFUL = "UPLOAD_PROTO_SUCCESSFUL";
export const UPLOAD_PROTO_FAILED = "UPLOAD_PROTO_FAILED";
export const SEND_UNARY_REQUEST = "SEND_UNARY_REQUEST";
export const SET_MESSAGE = "SET_MESSAGE";
export const SET_SERVICE = "SET_SERVICE";
export const SET_URL = "SET_URL";
export const SET_REQUEST = "SET_REQUEST";
export const DISPLAY_UNARY_RESPONSE = "DISPLAY_UNARY_RESPONSE";
export const CLEAR_RESPONSE_EDITOR = "CLEAR_RESPONSE_EDITOR";
export const SHOW_POPUP = "SHOW_POPUP";
export const SET_WS_COMMAND = "SET_WS_COMMAND";
export const START_WEBSOCKET = "START_WEBSOCKET";
//Define shape of action type
//Arraybuffer is an array of bytes, representing a generic, fixed-length raw binary data buffer
export interface uploadProto {
type: typeof UPLOAD_PROTO;
payload: string | ArrayBuffer;
}
export interface sendProto {
type: typeof SEND_PROTO;
payload: string | ArrayBuffer;
}
export interface uploadProtoSuccessful {
type: typeof UPLOAD_PROTO_SUCCESSFUL;
payload: object;
}
export interface sendUnaryRequest {
type: typeof SEND_UNARY_REQUEST;
payload: any;
}
export interface displayUnaryResponse {
type: typeof DISPLAY_UNARY_RESPONSE;
payload: typeResponse;
}
export interface setMessage {
type: typeof SET_MESSAGE;
payload: string;
}
export interface setService {
type: typeof SET_SERVICE;
payload: string;
}
export interface setUrl {
type: typeof SET_URL;
payload: string;
}
export interface setRequest {
type: typeof SET_REQUEST;
payload: object;
}
export interface uploadProtoFailed {
type: typeof UPLOAD_PROTO_FAILED;
payload: string;
}
export interface clearResponseEditor {
type: typeof CLEAR_RESPONSE_EDITOR;
payload: typeResponse[];
}
export interface showPopup {
type: typeof SHOW_POPUP;
payload: boolean;
}
export interface setWsCommand {
type: typeof SET_WS_COMMAND;
payload: string;
}
export interface startWebsocket {
type: typeof START_WEBSOCKET;
payload: string;
}
//Groups all action types so that they can be referenced in the reducer files via one umbrella type -- basically, we're trying to make sure that any given reducer can only accept certain action types in the switch/case statement
export type uploadProtoAction =
| uploadProto
| sendProto
| uploadProtoSuccessful
| uploadProtoFailed
| setMessage
| setService
| setUrl
| setRequest
| sendUnaryRequest
| displayUnaryResponse
| clearResponseEditor
| showPopup
| setWsCommand
| startWebsocket
export const uploadProtoActionCreator = (
payloadObj: string | ArrayBuffer
): uploadProto => {
return {
type: UPLOAD_PROTO,
payload: payloadObj
};
};
// Do we ever use sendProtoActionCreator?
export const sendProtoActionCreator = (
payloadObj: string | ArrayBuffer
): sendProto => {
return {
type: SEND_PROTO,
payload: payloadObj
};
};
export const uploadProtoSuccessfulActionCreator = (
payloadObj: object
): uploadProtoSuccessful => {
return {
type: UPLOAD_PROTO_SUCCESSFUL,
payload: payloadObj
};
};
export const uploadProtoFailedActionCreator = (
payloadObj: string
): uploadProtoFailed => {
return {
type: UPLOAD_PROTO_FAILED,
payload: payloadObj
};
};
export const sendUnaryRequestActionCreator = (
payloadObj: any
): sendUnaryRequest => {
return {
type: SEND_UNARY_REQUEST,
payload: payloadObj
};
};
export const displayUnaryResponseActionCreator = (
payloadObj: any
): displayUnaryResponse => {
return {
type: DISPLAY_UNARY_RESPONSE,
payload: payloadObj
};
};
export const setMessageActionCreator = (payloadObj: string): setMessage => {
return {
type: SET_MESSAGE,
payload: payloadObj
};
};
export const setServiceActionCreator = (payloadObj: string): setService => {
return {
type: SET_SERVICE,
payload: payloadObj
};
};
export const setUrlActionCreator = (payloadObj: string): setUrl => {
return {
type: SET_URL,
payload: payloadObj
};
};
export const setRequestActionCreator = (payloadObj: object): setRequest => {
return {
type: SET_REQUEST,
payload: payloadObj
};
};
export const clearResponseEditorActionCreator = (
payloadObj: typeResponse[]
): clearResponseEditor => {
return {
type: CLEAR_RESPONSE_EDITOR,
payload: payloadObj
};
};
export const showPopupActionCreator = (payloadObj: boolean): showPopup => {
return {
type: SHOW_POPUP,
payload: payloadObj
};
};
export const setWsCommandActionCreator = (
payloadObj: string
): setWsCommand => {
return {
type: SET_WS_COMMAND,
payload: payloadObj
};
};
export const startWebsocketActionCreator = (
payloadObj: string
): startWebsocket => {
return {
type: START_WEBSOCKET,
payload: payloadObj
}
}
================================================
FILE: src/components/DropdownRequest.tsx
================================================
import React, { FunctionComponent } from "react";
import { setRequestActionCreator,
setMessageActionCreator,
clearResponseEditorActionCreator,
setWsCommandActionCreator
} from "../actions";
import { typeRequest } from "../reducers/uploadProto";
interface DropdownRequestProps {
parsedProtoObj: any;
className: string;
menuOptions: any;
service: string;
value: typeRequest;
setRequest: typeof setRequestActionCreator;
setMessageAction?: typeof setMessageActionCreator;
setWsCommandAction: typeof setWsCommandActionCreator;
clearResponseEditor: typeof clearResponseEditorActionCreator;
}
export const DropdownRequest: FunctionComponent = props => {
{
const {
parsedProtoObj,
className,
menuOptions,
service,
setRequest,
value,
setMessageAction,
setWsCommandAction,
clearResponseEditor
} = props;
//create array of requests
let servicesArr: string[] = [];
let servicesObj: {
[index: string]: {
message: { [nestedIndex: string]: { message: string } };
};
} = {};
if (service) {
servicesArr = Object.keys(menuOptions[service]);
servicesObj = menuOptions[service];
} else {
}
return (