[
  {
    "path": ".babelrc",
    "content": ""
  },
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n# dependencies\nnode_modules/\n/.pnp\n.pnp.js\n/sslcert\n# testing\n/coverage\n# production\nbuild\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlog.txt"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2019 Tammy Tan, Cedric Theofanous, German Rovati, Jamie Highsmith, Davey Yedid\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"./src/assets/logo_gif.gif\" />\n</p>\n\n<p align=\"center\">\n  <b>Yodelay.io </b> 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\n</p>\n\n## Core Features ✨\n\n- Unary Calls and Server Side Streaming Support\n- Client side and Bi-directional Streaming\n- Automatic gRPC Service & Method recognition\n- Request Cancellation\n\n## Planned Features 🚧\n\n- [ ] Web Version with gRPC-WEB\n- [ ] Persistent Workspace\n- [ ] Electron App\n- [ ] Search History\n\n## Getting Started 🚀\n\nFor 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.\n\n## Installation ⚙\n\nFork and clone this repo:\n\n```sh\ngit clone https://github.com/<yourgithubhandle>/Yodelay.git\n```\n\n```sh\ncd Yodelay\n```\n\n```sh\nnpm install\n```\n<p align=\"center\">\n  <img src=\"https://media.giphy.com/media/kBSlhxKc4xkSQcGk3x/giphy.gif\" />\n</p>\n\n### Test your endpoints locally ☄\n\nNavigate to the Yodelay folder in your terminal and run the following command:\n\n```sh\nnpm start\n```\n\nNPM 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\n<p align=\"center\">\n  <img src=\"https://media.giphy.com/media/hU4Vzx4IbuIo8ps6A8/giphy.gif\" />\n</p>\nGo to your browser and enter the URL:\n\n```sh\n0.0.0.0:8080\n```\n\nTo test our demo proto file, upload the demo.proto file in the /protos folder\n\nInput the server ip address:\n\n```sh\n0.0.0.0:8080\n```\n\nSelect Service from the drop down you want to test:\n\nSelect Request from the drop down menu you want to test:\n\nEdit your input message so it matches the gRPC server fields:\n\nClick on the Send Request button and see the results from your gRPC call!\n\n<p align=\"center\">\n  <img src=\"https://media.giphy.com/media/hW9ui8UcGlfVXI31hY/giphy.gif\" />\n</p>\n\n## Contributing ✏️👩‍💻👨‍💻📓\n\nWe have an open door policy - all ideas, feedback, and contributions are always welcome!\nNote - 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.\n\n## Built with 💛\n\n- Cedric Theofanous - <a href=\"https://github.com/CedricTheofanous\">@CedricTheofanous</a>\n- Davey Yedid - <a href=\"https://github.com/dYedid\">@dYedid</a>\n- Jamie Highsmith - <a href=\"https://github.com/JamesHighsmith\">@JamesHighsmith</a>\n- German Rovati - <a href=\"https://github.com/grovati\">@grovati</a>\n- Tammy Tan - <a href=\"https://github.com/tammytan95\">@tammytan95</a>\n\n## Developed using amazing technologies ⚛ 🐳🚢\n\n  <p float=\"left\">\n    <img src=\"./src/assets/technologies.png\" width=\"600\"/>\n  </p>\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE.md file for details.\n"
  },
  {
    "path": "grpc_server/demo.js",
    "content": "let grpc = require(\"grpc\");\nlet protoLoader = require(\"@grpc/proto-loader\");\n// this is our test grpc server:\nlet PROTO_PATH = __dirname + \"/../protos/demo.proto\";\nlet packageDefinition = protoLoader.loadSync(PROTO_PATH, {\n  keepCase: true,\n  longs: String,\n  enums: String,\n  defaults: true,\n  oneofs: true\n});\nconst packageName = \"demo\";\nlet demo_proto = grpc.loadPackageDefinition(packageDefinition)[packageName];\n// console.log(demo_proto)\n// first demo function:\nfunction YodelayWorld(call, callback) {\n  console.log(\"call: \", call);\n  const whenI = call.request.whenI;\n  callback(null, {\n    message: `When I yodel ${whenI} -->  you yodel IiiOoo!!!! YODELAY!!! --> ________________`\n  });\n}\n// second demo:\nfunction toLowerCase(call, callback) {\n  // console.log(call.request)\n  const value = call.request.uppercase;\n  const lower = value.toLowerCase();\n  callback(null, {\n    message: `When you input this uppercase string: ${value} the gRPC server runs the function and responds with this output: ${lower} <--`\n  });\n}\n// run innerRps function n times\nfunction gRPCPermutations(call, callback) {\n  let n = call.request.n;\n  let arr = [\"\"];\n  while (n > 0) {\n    arr = innerGRPC(arr);\n    n -= 1;\n  }\n  console.log(arr);\n  const str = JSON.stringify(arr);\n  console.log(str);\n  callback(null, {\n    message: str\n  });\n  function innerGRPC(arr) {\n    const g = arr.map(letter => `g${letter}`);\n    const r = arr.map(letter => `R${letter}`);\n    const p = arr.map(letter => `P${letter}`);\n    const c = arr.map(letter => `C${letter}`);\n    return [...g, ...r, ...p, ...c];\n  }\n}\n// server streaming example\nfunction greetManyTimes(call, callback) {\n  // console.log(call);\n  let first_name = call.request.greeting.first_name;\n  // console.log(call.request)\n  let count = 0,\n    intervalID = setInterval(function() {\n      // var greetManyTimesResponse = new demo_proto.GreetManyTimesResponse();\n      let greetManyTimesResponse = {};\n      greetManyTimesResponse.result = first_name;\n      // console.log(greetManyTimesResponse.result);\n      // setup streaming\n      call.write(greetManyTimesResponse);\n      if (++count > 9) {\n        clearInterval(intervalID);\n        call.end(); // we have sent all messages!\n      }\n    }, 1000);\n}\n\n//Client streaming example\n//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\n//Paulo's server just listens for call.on(end)\n\n//For us --> on client side, message should be sent added to responseStream everytime sendReq button is clicked\n//Upon user clicking end stream button, call.end happens and server sends back response\n//long greet response = \"whew that was a long one - you yodeled xxx number of times!\"\n\nfunction longGreet(call, callback) {\n  let greetArr = [];\n  let greet = call.request.greet;\n  //on receiving data, push greeting into array\n  call.on(\"data\", greet => {\n    greetArr.push(greet);\n  });\n\n  //upon ending, return response\n  call.on(\"end\", greet => {\n    let numOfYodel = greetArr.length - 1;\n    let LongGreetResponse = `You Yodeled ${numOfYodel} of times!`;\n    console.log(\"client streaming has ended\");\n    //or should this be ws.send? it needs to go to front end\n    call.write(LongGreetResponse);\n  });\n}\n\n// bidi streaming example\n// async function sleep(interval) {\n//   return new Promise(resolve => {\n//     setTimeout(() => resolve(), interval);\n//   });\n// }\n// async function greetEveryone(call, callback) {\n//   call.on(\"data\", response => {\n//     // let firstName = call.request.greeting.first_name\n//     // let lastName = call.request.greeting.last_name\n//     // let fullName = firstName + ' ' + lastName\n//     console.log('here is the data stupid ', response)\n//     // console.log(\"Hello \" + fullName);\n//   });\n//   call.on(\"error\", error => {\n//     console.error(error);\n//   });\n//   call.on(\"end\", () => {\n//     console.log(\"Server The End...\");\n//   });\n//   for (let i = 0; i < 10; i++) {\n//     call.write({ result: 'Tammy Tan' });\n//     await sleep(1000);\n//   }\n//   call.end();\n// }\nfunction main() {\n  let server = new grpc.Server();\n  server.addService(demo_proto.itIsDemoTimeYodelay.service, {\n    YodelayWorld,\n    toLowerCase,\n    gRPCPermutations,\n    greetManyTimes,\n    longGreet\n    // greetEveryone\n  });\n  server.bind(\"0.0.0.0:8080\", grpc.ServerCredentials.createInsecure());\n  server.start();\n}\nmain();\nconsole.log(`gRPC💥 'n on port: 0.0.0.0:8080`);\n"
  },
  {
    "path": "grpc_server/grpc_server.js",
    "content": "let grpc = require('grpc');\nlet protoLoader = require('@grpc/proto-loader');\n\n// this is our test grpc server:\nlet PROTO_PATH = __dirname + '/../protos/helloworld.proto';\n// const port = '0.0.0.0:50051';\n\nlet packageDefinition = protoLoader.loadSync(\n    PROTO_PATH,\n    {keepCase: true,\n     longs: String,\n     enums: String,\n     defaults: true,\n     oneofs: true\n    });\n\n//\n\nconst packageName = 'helloaworld'\n\nlet hello_proto = grpc.loadPackageDefinition(packageDefinition)[packageName];\n\n/**\n * Implements the SayHello RPC method.\n */\nlet url;\n\nfunction sayHello(call, callback) {\n  console.log('------rpc function call------')\n  console.log(`Hi! I'm the gRPC server`)\n  // items coning in from the express server:\n  console.log('gRPC incoming call request: ', call.request)\n  url = call.request.url;\n  let package = call.request.package;\n  let serviceInput = call.request.serviceInput;\n  let requestInput = call.request.requestInput;\n  let messageInput = call.request.messageInput;\n  let protoFile = call.request.protoFile;\n  let protoDescriptor = call.request.protoDescriptor;\n  \n  \n  // callback(null, {message: 'Hello ' + package + `! This was a call to port ${url} requesting the ${serviceInput} in ${protoFile} with the message of: ${messageInput}`});\n  callback(null, {\n    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}.`\n  });\n  // console.log('after grpc server')\n}\n\n/**\n * Starts an RPC server that receives requests for the Greeter service at the\n * sample server port\n */\nfunction main() {\n  let server = new grpc.Server();\n  server.addService(hello_proto.YodelayAPI.service, \n    { sayHello });\n    console.log('grpc main url: ', url);\n  server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());\n  server.start();\n}\n\nmain();\n\nconsole.log(`gRPC💥 'n on port: 0.0.0.0:50051 (${url})`)"
  },
  {
    "path": "grpc_server/uServerStream.js",
    "content": "const fs = require(\"fs\");\nconst grpc = require(\"grpc\");\nconst protoLoader = require('@grpc/proto-loader');\n\n\nlet PROTO_PATH = __dirname + '/../protos/uGreet.proto';\n\nlet packageDefinition = protoLoader.loadSync(\n  PROTO_PATH,\n  {\n    keepCase: true,\n    longs: String,\n    enums: String,\n    defaults: true,\n    oneofs: true\n  });\n\nconst packageName = 'greet'\n\nlet greets = grpc.loadPackageDefinition(packageDefinition)[packageName];\n\n\nfunction greetManyTimes(call, callback) {\n  let firstName = call.request.getGreeting().getFirstName();\n\n  let count = 0,\n    intervalID = setInterval(function () {\n      let greetManyTimesResponse = new greets.GreetManyTimesResponse();\n      greetManyTimesResponse.setResult(firstName);\n\n      // setup streaming\n      call.write(greetManyTimesResponse);\n      if (++count > 9) {\n        clearInterval(intervalID);\n        call.end(); // we have sent all messages!\n      }\n    }, 1000);\n}\n\n\nfunction main() {\n  // let credentials = grpc.ServerCredentials.createSsl(\n  //   fs.readFileSync(\"../certs/ca.crt\"),\n  //   [\n  //     {\n  //       cert_chain: fs.readFileSync(\"../certs/server.crt\"),\n  //       private_key: fs.readFileSync(\"../certs/server.key\")\n  //     }\n  //   ],\n  //   true\n  // );\n\n  let server = new grpc.Server();\n\n\n  server.addService(greets.service, {\n    greetManyTimes: greetManyTimes,\n  });\n  server.bind(\"127.0.0.1:50051\", grpc.ServerCredentials.createInsecure());\n  server.start();\n\n  console.log(\"Server running on port 127.0.0.1:50051\");\n}\n\nmain();"
  },
  {
    "path": "helloworld.proto",
    "content": "syntax = \"proto3\";\n\n// option java_multiple_files = true;\n// option java_package = \"io.grpc.examples.helloworld\";\n// option java_outer_classname = \"HelloWorldProto\";\n// option objc_class_prefix = \"HLW\";\n\npackage helloaworld;\n\n// The greeting service definition.\nservice YodelayAPI {\n  // Sends a greeting\n  rpc SayHello (HelloRequest) returns (HelloReply) {}\n}\n\n// The request message containing the user's name.\nmessage HelloRequest {\n  string port = 1;\n  string packageName = 2;\n  string service = 3;\n  string message = 4;\n  string protoObject = 5;\n\n}\n\n// The response message containing the greetings\nmessage HelloReply {\n  string message = 1;\n}\n\n"
  },
  {
    "path": "index.js",
    "content": ""
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"yodelay\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Yodelay source code.\",\n  \"repository\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"concurrently --kill-others \\\"npm run src-dev\\\" \\\"npm run start-client\\\" \\\"npm run grpc\\\"\",\n    \"start-client\": \"INSECURE_PORT=4000 nodemon server_client/server_client.js\",\n    \"start-client-noenv\": \"nodemon server_client/server_client.js\",\n    \"grpc\": \"nodemon grpc_server/demo.js\",\n    \"src-dev\": \"webpack-dev-server --config webpack.dev.ts --env.API_PORT=4000 --env.API_HOST=localhost --env.API_PROTOCOL=http\",\n    \"src-build\": \"webpack --config webpack.prod.ts\",\n    \"server-dev\": \"ts-node-dev --respawn --transpileOnly ./server/index.ts | ./node_modules/.bin/pino-pretty -t SYS:standard -c\",\n    \"server-local\": \"MODE=DEVELOPMENT PORT=8443 INSECURE_PORT=8000 CORS_URL=http://localhost:3000 HOST=http://localhost:3000 npm run server-dev\",\n    \"server-test\": \"MODE=TEST PORT=8443 INSECURE_PORT=8000 CORS_URL=http://localhost:3000 HOST=http://localhost:3000 npm run server-dev\",\n    \"server\": \"ts-node-dev --respawn --transpileOnly ./server/index.ts | ./node_modules/.bin/pino-pretty -t SYS:standard -c > log.txt 2>&1\",\n    \"test\": \"npm run jest\",\n    \"jest\": \"jest test/ --coverage --runInBand\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@grpc/proto-loader\": \"^0.5.3\",\n    \"@testing-library/react\": \"^9.3.3\",\n    \"@types/classnames\": \"^2.2.9\",\n    \"@types/enzyme\": \"^3.10.3\",\n    \"@types/express\": \"^4.17.0\",\n    \"@types/express-pino-logger\": \"^4.0.2\",\n    \"@types/jest\": \"^24.0.23\",\n    \"@types/numeral\": \"0.0.26\",\n    \"@types/react-redux\": \"^7.1.1\",\n    \"@types/react-router-dom\": \"^5.1.0\",\n    \"@types/uuid\": \"^3.4.6\",\n    \"@types/uuidv4\": \"^5.0.0\",\n    \"ace-builds\": \"^1.4.7\",\n    \"ag-grid-community\": \"^22.1.0\",\n    \"ag-grid-react\": \"^22.1.0\",\n    \"antd\": \"^3.26.5\",\n    \"babel-plugin-transform-es2015-modules-commonjs\": \"^6.26.2\",\n    \"body-parser\": \"^1.19.0\",\n    \"concurrently\": \"^5.0.2\",\n    \"cookie-parser\": \"^1.4.4\",\n    \"cors\": \"^2.8.5\",\n    \"css-loader\": \"^3.0.0\",\n    \"enzyme\": \"^3.10.0\",\n    \"enzyme-adapter-react-16\": \"^1.15.1\",\n    \"esm\": \"^3.2.25\",\n    \"express\": \"^4.17.1\",\n    \"express-http-to-https\": \"^1.1.4\",\n    \"express-pino-logger\": \"^4.0.0\",\n    \"express-ws\": \"^4.0.0\",\n    \"file-loader\": \"^5.0.2\",\n    \"google-protobuf\": \"^3.11.2\",\n    \"grpc\": \"^1.24.2\",\n    \"grpc-promise\": \"^1.4.0\",\n    \"grpc-tools\": \"^1.8.1\",\n    \"immutable\": \"^4.0.0-rc.12\",\n    \"isomorphic-fetch\": \"^2.2.1\",\n    \"jest\": \"^24.9.0\",\n    \"jsonwebtoken\": \"^8.5.1\",\n    \"lodash\": \"^4.17.15\",\n    \"node-fetch\": \"^2.6.0\",\n    \"node-sass\": \"^4.13.0\",\n    \"nodemon\": \"^2.0.2\",\n    \"popper\": \"^1.0.1\",\n    \"protoc-gen-grpc\": \"^1.3.8\",\n    \"react\": \"^16.8.6\",\n    \"react-ace\": \"^8.0.0\",\n    \"react-dom\": \"^16.8.6\",\n    \"react-hot-loader\": \"^4.12.18\",\n    \"react-pivot\": \"^4.1.0\",\n    \"react-redux\": \"^7.1.0\",\n    \"react-router-dom\": \"^5.1.2\",\n    \"react-vis\": \"^1.11.7\",\n    \"redux\": \"^4.0.1\",\n    \"redux-devtools-extension\": \"^2.13.8\",\n    \"redux-saga\": \"^0.16.0\",\n    \"reselect\": \"^4.0.0\",\n    \"sass-loader\": \"^8.0.0\",\n    \"style-loader\": \"^0.23.1\",\n    \"timm\": \"^1.6.1\",\n    \"ts-jest\": \"^24.2.0\",\n    \"ts-node-dev\": \"^1.0.0-pre.40\",\n    \"uuidv4\": \"^4.0.0\",\n    \"ws\": \"^7.2.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.7.5\",\n    \"@babel/preset-env\": \"^7.7.6\",\n    \"@babel/preset-react\": \"^7.7.4\",\n    \"@types/html-webpack-plugin\": \"^3.2.0\",\n    \"@types/lodash\": \"^4.14.136\",\n    \"@types/react\": \"^16.8.22\",\n    \"@types/react-dom\": \"^16.8.4\",\n    \"@types/react-plaid-link\": \"^1.3.0\",\n    \"@types/webpack\": \"^4.4.34\",\n    \"awesome-typescript-loader\": \"^5.2.1\",\n    \"babel-loader\": \"^8.0.6\",\n    \"clean-webpack-plugin\": \"^3.0.0\",\n    \"html-webpack-plugin\": \"^3.2.0\",\n    \"ts-node\": \"^8.3.0\",\n    \"typescript\": \"^3.6.2\",\n    \"url-loader\": \"^3.0.0\",\n    \"webpack\": \"^4.35.0\",\n    \"webpack-cli\": \"^3.3.5\",\n    \"webpack-dev-server\": \"^3.7.2\"\n  }\n}\n"
  },
  {
    "path": "protos/demo.proto",
    "content": "syntax = \"proto3\";\npackage demo;\n// This service implements a simple guestbook\nservice itIsDemoTimeYodelay {\n    // first hello world test\n    rpc YodelayWorld (Yodelay) returns (IiiOoo) {\n    }\n    // second calls a function that reponsed\n    rpc toLowerCase (UpperCaseRequest) returns (LowerCaseResponse) {\n    }\n    // List existing posts\n    rpc gRPCPermutations (PermutationRequest) returns (PermutationResponse) {\n    }\n    //unary API\n    rpc Greet (GreetRequest) returns (GreetResponse) {};\n    //Server streaming API\n    rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};\n    // Client Streaming\n    rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};\n    // BiDi Streaming\n    rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};\n}\n// ! first test for the hello world demo:\nmessage Yodelay {\n    string whenI = 1;\n}\nmessage IiiOoo {\n    string message = 1;\n}\n// ! second test for unique array:\nmessage UpperCaseRequest {\n  string uppercase = 1;\n}\nmessage LowerCaseResponse {\n  string message = 1;\n}\n// third test:\nmessage PermutationRequest {\n    int32 n = 1;\n}\nmessage PermutationResponse {\n    string message = 1;\n}\n//Greet Mesages\nmessage GreetEveryoneRequest {\n    Greeting greet = 1;\n}\nmessage GreetEveryoneResponse { \n    string result = 1;\n}\nmessage LongGreetRequest {\n    Greeting greet = 1;\n}\nmessage LongGreetResponse {\n    string result = 1;\n}\nmessage GreetManyTimesRequest {\n    Greeting greeting = 1;\n}\nmessage GreetManyTimesResponse {\n     string result = 1;\n}\nmessage Greeting {\n    string first_name = 1;\n    string last_name = 2;\n}\nmessage GreetRequest {\n    Greeting greeting = 1;\n}\nmessage GreetResponse {\n    string result = 1;\n}\n"
  },
  {
    "path": "protos/helloworld-copy.proto",
    "content": "syntax = \"proto3\";\n\n// option java_multiple_files = true;\n// option java_package = \"io.grpc.examples.helloworld\";\n// option java_outer_classname = \"HelloWorldProto\";\n// option objc_class_prefix = \"HLW\";\n\npackage helloaworld;\n\n// The greeting service definition.\nservice YodelayAPI {\n  // Sends a greeting\n  rpc SayHello (HelloRequest) returns (HelloReply) {}\n  rpc SayHelloAgain (HelloRequestAGAIN) returns (HelloReplyAGAIN) {}\n  // rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}\n}\n\n// The SECOND greeting service definition.\nservice servTWO {\n  // Sends a greeting\n  rpc SayHelloTWO (HelloRequestTWO) returns (HelloReplyTWO) {}\n  rpc SayHelloAgainTWO (HelloRequestTWOagain) returns (HelloReplyTWOagain) {}\n  // rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}\n}\n\n// The request message containing the user's name.\nmessage HelloRequest {\n  string port = 1;\n  string packageName = 2;\n  string service = 3;\n  string message = 4;\n  string protoObject = 5;\n  int32 integer = 6;\n\n}\n\n// The response message containing the greetings\nmessage HelloReply {\n  string message = 1;\n  int32 integer = 2;\n  \n}\n\n// The AGAIN request message containing the user's name.\nmessage HelloRequestAGAIN {\n  string portAGAIN = 1;\n  bytes bytes = 2;\n  int64 int64 = 3;\n  float float = 4;\n  bool bool = 5;\n  int32 integerAGAIN = 6;\n\n}\n\n// The AGAIN response message containing the greetings\nmessage HelloReplyAGAIN {\n  string messageAGAIN = 1;\n  int32 integerAGAIN = 2;\n  \n}\n\n\n// The SECOND request message containing the user's name.\nmessage HelloRequestTWO {\n  string portTWO = 1;\n  double double = 2;\n  uint32 uint32 = 3;\n  uint64 uint64 = 4;\n  sint32 sint32 = 5;\n  sint64 sint64 = 6;\n\n}\n\n// The SECOND response message containing the greetings\nmessage HelloReplyTWO {\n  string messageTWO = 1;\n  int32 integerTWO = 2;\n\n}\n\n// The SECOND AGAIN request message containing the user's name.\nmessage HelloRequestTWOagain {\n  fixed32 fixed32 = 1;\n  fixed64 fixed64 = 2;\n  sfixed32 sfixed32 = 3;\n  sfixed64 sfixed64 = 4;\n  string protoObjectTWOagain = 5;\n  int32 integerTWOagain = 6;\n\n}\n\n// The SECOND AGAIN response message containing the greetings\nmessage HelloReplyTWOagain {\n  string messageTWOagain = 1;\n  int32 integerTWOagain = 2;\n\n}\n\n\n\n"
  },
  {
    "path": "protos/helloworld.proto",
    "content": "syntax = \"proto3\";\n\n// option java_multiple_files = true;\n// option java_package = \"io.grpc.examples.helloworld\";\n// option java_outer_classname = \"HelloWorldProto\";\n// option objc_class_prefix = \"HLW\";\n\npackage helloaworld;\n\n// The greeting service definition.\nservice YodelayAPI {\n  // Sends a greeting\n  rpc SayHello (HelloRequest) returns (HelloReply) {}\n  // rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}\n  // rpc SayHelloAgainAgain (HelloRequest) returns (HelloReply) {}\n}\n\n// The request message containing the user's name.\nmessage HelloRequest {\n  string url = 1;\n  string packageName = 2;\n  string serviceInput = 3;\n  string requestInput = 4;\n  string messageInput = 5;\n  string protoFile = 6;\n  string protoDescriptor = 7;\n}\n\n// The response message containing the greetings\nmessage HelloReply {\n  string message = 1;\n}\n\n"
  },
  {
    "path": "protos/output.proto",
    "content": "syntax = \"proto3\";\npackage demo;\n// This service implements a simple guestbook\nservice itIsDemoTimeYodelay {\n    // first hello world test\n    rpc YodelayWorld (Yodelay) returns (IiiOoo) {\n    }\n    // second calls a function that reponsed\n    rpc toLowerCase (UpperCaseRequest) returns (LowerCaseResponse) {\n    }\n    // List existing posts\n    rpc gRPCPermutations (PermutationRequest) returns (PermutationResponse) {\n    }\n    //unary API\n    rpc Greet (GreetRequest) returns (GreetResponse) {};\n    //Server streaming API\n    rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};\n    // Client Streaming\n    rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};\n    // BiDi Streaming\n    rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};\n}\n// ! first test for the hello world demo:\nmessage Yodelay {\n    string whenI = 1;\n}\nmessage IiiOoo {\n    string message = 1;\n}\n// ! second test for unique array:\nmessage UpperCaseRequest {\n  string uppercase = 1;\n}\nmessage LowerCaseResponse {\n  string message = 1;\n}\n// third test:\nmessage PermutationRequest {\n    int32 n = 1;\n}\nmessage PermutationResponse {\n    string message = 1;\n}\n//Greet Mesages\nmessage GreetEveryoneRequest {\n    Greeting greet = 1;\n}\nmessage GreetEveryoneResponse { \n    string result = 1;\n}\nmessage LongGreetRequest {\n    Greeting greet = 1;\n}\nmessage LongGreetResponse {\n    string result = 1;\n}\nmessage GreetManyTimesRequest {\n    Greeting greeting = 1;\n}\nmessage GreetManyTimesResponse {\n     string result = 1;\n}\nmessage Greeting {\n    string first_name = 1;\n    string last_name = 2;\n}\nmessage GreetRequest {\n    Greeting greeting = 1;\n}\nmessage GreetResponse {\n    string result = 1;\n}\n"
  },
  {
    "path": "protos/route_guide.proto",
    "content": "// Copyright 2015 gRPC authors.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nsyntax = \"proto3\";\n\noption java_multiple_files = true;\noption java_package = \"io.grpc.examples.routeguide\";\noption java_outer_classname = \"RouteGuideProto\";\noption objc_class_prefix = \"RTG\";\n\npackage routeguide;\n\n\n// Interface exported by the server.\nservice RouteGuide {\n  // A simple RPC.\n  //\n  // Obtains the feature at a given position.\n  //\n  // A feature with an empty name is returned if there's no feature at the given\n  // position.\n  rpc GetFeature(Point) returns (Feature) {}\n\n  // A server-to-client streaming RPC.\n  //\n  // Obtains the Features available within the given Rectangle.  Results are\n  // streamed rather than returned at once (e.g. in a response message with a\n  // repeated field), as the rectangle may cover a large area and contain a\n  // huge number of features.\n  rpc ListFeatures(Rectangle) returns (stream Feature) {}\n\n  // A client-to-server streaming RPC.\n  //\n  // Accepts a stream of Points on a route being traversed, returning a\n  // RouteSummary when traversal is completed.\n  rpc RecordRoute(stream Point) returns (RouteSummary) {}\n\n  // A Bidirectional streaming RPC.\n  //\n  // Accepts a stream of RouteNotes sent while a route is being traversed,\n  // while receiving other RouteNotes (e.g. from other users).\n  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}\n}\n\n// Points are represented as latitude-longitude pairs in the E7 representation\n// (degrees multiplied by 10**7 and rounded to the nearest integer).\n// Latitudes should be in the range +/- 90 degrees and longitude should be in\n// the range +/- 180 degrees (inclusive).\nmessage Point {\n  int32 latitude = 1;\n  int32 longitude = 2;\n}\n\n// A latitude-longitude rectangle, represented as two diagonally opposite\n// points \"lo\" and \"hi\".\nmessage Rectangle {\n  // One corner of the rectangle.\n  Point lo = 1;\n\n  // The other corner of the rectangle.\n  Point hi = 2;\n}\n\n// A feature names something at a given point.\n//\n// If a feature could not be named, the name is empty.\nmessage Feature {\n  // The name of the feature.\n  string name = 1;\n\n  // The point where the feature is detected.\n  Point location = 2;\n}\n\n// A RouteNote is a message sent while at a given point.\nmessage RouteNote {\n  // The location from which the message is sent.\n  Point location = 1;\n\n  // The message to be sent.\n  string message = 2;\n}\n\n// A RouteSummary is received in response to a RecordRoute rpc.\n//\n// It contains the number of individual points received, the number of\n// detected features, and the total distance covered as the cumulative sum of\n// the distance between each point.\nmessage RouteSummary {\n  // The number of points received.\n  int32 point_count = 1;\n\n  // The number of known features passed while traversing the route.\n  int32 feature_count = 2;\n\n  // The distance covered in metres.\n  int32 distance = 3;\n\n  // The duration of the traversal in seconds.\n  int32 elapsed_time = 4;\n}\n"
  },
  {
    "path": "protos/uGreet.proto",
    "content": "syntax = \"proto3\";\n\npackage greet;\n\n\nservice GreetService {\n\n    //unary API\n    rpc Greet (GreetRequest) returns (GreetResponse) {};\n    \n    //Server streaming API\n    rpc GreetManyTimes (GreetManyTimesRequest) returns ( stream GreetManyTimesResponse) {};\n\n    // Client Streaming\n    rpc LongGreet (stream LongGreetRequest) returns (LongGreetResponse) {};\n\n    // BiDi Streaming\n    rpc GreetEveryone (stream GreetEveryoneRequest) returns ( stream GreetEveryoneResponse) {};\n\n\n}\n\n\nmessage GreetEveryoneRequest {\n    Greeting greet = 1;\n}\n\nmessage GreetEveryoneResponse { \n    string result = 1;\n}\nmessage LongGreetRequest {\n    Greeting greet = 1;\n}\n\nmessage LongGreetResponse {\n    string result = 1;\n}\n\nmessage GreetManyTimesRequest {\n    Greeting greeting = 1;\n}\n\nmessage GreetManyTimesResponse {\n     string result = 1;\n}\n\n\nmessage Greeting {\n    string first_name = 1;\n    string last_name = 2;\n}\n\nmessage GreetRequest {\n    Greeting greeting = 1;\n}\n\nmessage GreetResponse {\n    string result = 1;\n}"
  },
  {
    "path": "server_client/helper_request_func.js",
    "content": "const grpc = require(\"grpc\");\nconst protoLoader = require(\"@grpc/proto-loader\");\nconst grpc_promise = require(\"grpc-promise\");\nconst fs = require(\"fs\");\nconst { EventEmitter } = require(\"events\");\n// input: .proto file\n// output: {protoFile: \"the text of the proto file\", definition: {}, package: '', protoDescriptor: {}, services: [{}, {}, {}]}\nasync function parseProto(uploadParsedReqBody) {\n  // MESSAGE FIELDS:\n  console.log(\"-----Start Parsing Proto-----\");\n  // the proto object is where we are passed in the .proto file from the server_client\n  // we then take this object and write it to the temp output.proto file in the proto folder:\n  let output = {};\n  const protoFile = uploadParsedReqBody;\n  output.protoFile = protoFile;\n  // WRITE TO TEMP .PROTO\n  // now let's write our protoObject string to the output.proto file:\n  fs.writeFileSync(\"./protos/output.proto\", protoFile, \"utf8\", function (err) {\n    if (err) {\n      console.log(\"An error occurred while writing JSON Object to File.\");\n      return console.log(err);\n    }\n    console.log(\"JSON file has been saved.\");\n  });\n  // BUILD DEFINITION AND DESCRIPTOR:\n  // now we have a path for our proto:\n  const PROTO_PATH = __dirname + \"/../protos/output.proto\";\n  // and a config object:\n  const CONFIG_OBJECT = {\n    keepCase: true,\n    longs: String,\n    enums: String,\n    defaults: true,\n    oneofs: true\n  };\n  // now that the file is written we want to create our package definition:\n  const packageDefinition = protoLoader.loadSync(PROTO_PATH, CONFIG_OBJECT);\n  output.definition = packageDefinition;\n\n  \n  // let's use the package definintion to create our descriptor:\n  \n  const descriptorPre = grpc.loadPackageDefinition(packageDefinition);\n  // this is how you grab the .proto file package name:\n  const protoPackageName = Object.keys(descriptorPre)[0];\n  const descriptor = descriptorPre[protoPackageName];\n  output.package = protoPackageName;\n  output.protoDescriptor = descriptor;\n  // Creating the services object, which includes the various services, methods, messages, and message fields/types\n  const servicesObj = {};\n\n  for (let [service, serviceValue] of Object.entries(descriptor)) {\n    if (typeof serviceValue === \"function\") {\n      servicesObj[service] = {};\n      for (let [serviceMethodName, serviceMethodValue] of Object.entries(\n        serviceValue.service\n      )) {\n        const isMethodRequestStreaming = serviceMethodValue.requestStream;\n        const isMethodResponseStreaming = serviceMethodValue.responseStream;\n        \n        let streamingType = \"unary\";\n        if (isMethodResponseStreaming) {\n          streamingType = \"serverStreaming\";\n        }\n        if (isMethodRequestStreaming) {\n          streamingType = \"clientStreaming\";\n        }\n        if (isMethodRequestStreaming && isMethodResponseStreaming) {\n          streamingType = \"bidiStreaming\";\n        }\n        \n        const messageName = serviceMethodValue.requestType.type.name;\n        const messageFieldsRawData = serviceMethodValue.requestType.type.field;\n        servicesObj[service][serviceMethodName] = {};\n        servicesObj[service][serviceMethodName][messageName] = {};\n        servicesObj[service][serviceMethodName][\"type\"] = streamingType;\n\n        for (let messageInfo of messageFieldsRawData) {\n          console.log('messageInfo:: ', messageInfo)\n          const messageField = messageInfo.name;\n          let messageFieldType;\n          if (messageInfo.typeName !== '') {\n            messageFieldType = messageInfo.typeName;\n          } else {\n            messageFieldType = messageInfo.type;\n          }\n          servicesObj[service][serviceMethodName][messageName][\n            messageField\n          ] = messageFieldType;\n        }\n      }\n    }\n  }\n  output.services = servicesObj;\n  \n  return output;\n}\n\nclass GrpcRequestClass extends EventEmitter {\n  constructor(websocket) {\n    super();\n    this.ws = websocket;\n    this.url = undefined\n    this.serviceInput =  undefined;\n    this.messageInput = undefined;\n    this.requestInput = undefined;\n    this.package = undefined;\n    this.protoFile = undefined;\n    this.streamType = undefined;\n    this._call = undefined;\n  }\n\n  \n\n  sendInit (reqbody) {\n    this.url = reqbody.url;\n    this.serviceInput =  reqbody.serviceInput;\n    this.messageInput = reqbody.messageInput;\n    this.requestInput = reqbody.requestInput;\n    this.package = reqbody.package;\n    this.protoFile = reqbody.protoFile;\n    this.streamType = reqbody.requestInput.streamType;\n    this._call = undefined;\n\n    fs.writeFileSync(\"./protos/output.proto\", this.protoFile, \"utf8\", function (err) {\n      if (err) {\n        console.log(\"An error occurred while writing JSON Object to File.\");\n        return console.log(err);\n      }\n      console.log(\"JSON file has been saved.\");\n    });\n\n    const PROTO_PATH = __dirname + \"/../protos/output.proto\";\n    const CONFIG_OBJECT = {\n      keepCase: true,\n      longs: String,\n      enums: String,\n      defaults: true,\n      oneofs: true\n    };\n\n    const packageDefinition = protoLoader.loadSync(PROTO_PATH, CONFIG_OBJECT);\n    let protoPackageName2 = Object.keys(packageDefinition)[0].split(\".\")[0];\n    let packageDefinitionName = Object.keys(packageDefinition)[0];\n    const descriptor = grpc.loadPackageDefinition(packageDefinition)[\n      protoPackageName2\n    ];\n    let servicePackage;\n\n    try {\n      servicePackage = new descriptor[this.serviceInput](\n        this.url,\n        grpc.credentials.createInsecure()\n      );\n    } catch {\n      console.log('error creating servicePackage (descriptor) in sendInit func.')\n    }\n\n    function round(value, precision) {\n      var multiplier = Math.pow(10, precision || 0);\n      return Math.round(value * multiplier) / multiplier;\n    }\n\n    let ws = this.ws;\n    let messageInput;\n    try {\n      messageInput = JSON.parse(this.messageInput)\n    } catch {\n      console.log('error JSON parsing messageInput in sendInit')\n    }\n    let requestInput = this.requestInput;\n    let streamType = this.streamType;\n\n    if (streamType === \"unary\") {\n      // UNARY\n      let reqTime = process.hrtime();\n\n      try {\n        servicePackage[requestInput.methodName](messageInput, function (\n          err,\n          feature\n        ) {\n          if (err) {\n            let unaryError = JSON.stringify(err)\n            console.log(unaryError)\n            ws.send(unaryError);\n          } else {\n            let resTime = process.hrtime();\n            let resTimeSec = resTime[0] - reqTime[0];\n            let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);\n            let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;\n            let message = '';\n            try {\n              message = JSON.stringify(feature);\n              ws.send(message);\n            } catch {\n              console.log('error JSON parsing unary gRPC response');\n              ws.send('error JSON parsing unary gRPC response');\n            }\n          }\n        });\n      } catch {\n        console.log('error in streamType === \"unary\"')\n      }\n      return this;\n    } else if (requestInput.streamType === \"serverStreaming\") {\n          // STREAMING\n          \n          let reqTime = process.hrtime();\n          let call; \n          try {\n            call = servicePackage[requestInput.methodName](messageInput);\n          } catch {\n            console.log('error creating call - servicePackage')\n          }\n          this._call = call;\n          try {\n            call.on(\"data\", function (feature) {\n              let resTime = process.hrtime();\n              let resTimeSec = resTime[0] - reqTime[0];\n              let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);\n              let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;\n              let message = JSON.stringify(feature);\n              ws.send(message);\n            });\n  \n            call.on(\"end\", function () {\n              ws.send('server streaming has ended')\n            });\n            call.on(\"error\", function (e) {\n              () => {\n                ws.send('server streaming ending')\n              }\n            });\n          } catch {\n            console.log('server streaming ERROR')\n            ws.send('server streaming ERROR')\n          }\n      } else if (requestInput.streamType === \"clientStreaming\") {\n            //////// CLIENT STREAMING //////////\n        //receive data from gRPC demo server (resulting from call.write)\n        //link to the connection of the grpc server, must remain on clientStreaming\n        let reqTime = process.hrtime();\n        const call = servicePackage[requestInput.methodName](function (error, feature) {\n          if(error) {\n            let clientStreamingError = JSON.stringify(error)\n            console.log(clientStreamingError)\n            ws.send(clientStreamingError);\n          } \n          ws.send(JSON.stringify(feature))\n        });\n\n        try {\n\n          call.write(messageInput)\n          this._call = call;\n  \n          call.on(\"data\", function(feature) {\n            let resTime = process.hrtime();\n            let resTimeSec = resTime[0] - reqTime[0];\n            let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);\n            let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;\n            let message = JSON.stringify(feature);\n            ws.send(message);\n          });\n          call.on(\"end\", function() {\n            ws.send('server has ended the client streaming')\n          });\n          call.on(\"error\", function(e) {\n            // An error has occurred and the stream has been closed.\n            let clientStreamError = JSON.stringify(e)\n            ws.send('the following error occurred in the gRPC server: ', clientStreamError)\n          });\n        } catch {\n          console.log('Error in client-streaming')\n          ws.send('Error in client-streaming')\n        }\n\n      } else if (requestInput.streamType === 'bidiStreaming'){\n        let reqTime = process.hrtime();\n        let call = servicePackage[requestInput.methodName]();\n        this._call = call;\n\n        call.on(\"data\", function (feature) {\n          let resTime = process.hrtime();\n          let resTimeSec = resTime[0] - reqTime[0];\n          let resTimeMs = round(resTime[1] / 1000000 - reqTime[1] / 1000000, 2);\n          let resTimeStr = `Response Time: ${resTimeSec}s ${resTimeMs}ms`;\n          let message = JSON.stringify(feature);\n          ws.send(message);\n        });\n\n        call.on(\"end\", function () {\n          ws.send('server has ended the bidirectional streaming')\n        });\n\n        call.on(\"error\", function (e) {\n          let bidiError = JSON.stringify(e)\n          ws.send('the following error occurred in the gRPC server: ', bidiError)\n        });\n      }\n  } \n}\n\nmodule.exports = {\n  GrpcRequestClass,\n  parseProto\n};\n"
  },
  {
    "path": "server_client/server_client.js",
    "content": "const express = require(\"express\");\nconst cookieParser = require(\"cookie-parser\");\nconst bodyParser = require(\"body-parser\");\nconst cors = require(\"cors\");\nconst { parseProto, GrpcRequestClass } = require(\"./helper_request_func\");\nconst app = express();\nconst expressWs = require(\"express-ws\")(app);\n\nconst PORT = process.env.PORT || 443;\nconst INSECURE_PORT = process.env.INSECURE_PORT || 80;\nconst MODE = process.env.MODE || \"PRODUCTION\";\n\n// export const HOST = process.env.HOST || 'https://mypilea.com'\n\nconst port = INSECURE_PORT;\n\napp.use(cors());\napp.use(bodyParser.text());\napp.use(cookieParser());\n\napp.use(express.static(\"build\"));\n\n// app.get(\"/\", (req, res) => res.send(\"🍻  Yodelay World  🍻\"));\n// * UPLOAD:\napp.post(\"/upload\", async (req, res) => {\n  const parsedReqBody = JSON.parse(req.body);\n  let output = await parseProto(parsedReqBody);\n  res.json(output);\n});\n\n//Listens for messages\napp.ws(\"/websocket\", function(ws, req) {\n  const grpcRequestClass = new GrpcRequestClass(ws);\n  try {\n    ws.on(\"message\", function(msg) {\n      let parsedReqBody;\n      try {\n        parsedReqBody = JSON.parse(msg);\n      } catch {\n        ws.send(\"message\", \"error parsing JSON in ws.on message\");\n      }\n      if (parsedReqBody.wsCommand === \"sendInit\") {\n        console.log(\"sendInit\");\n        grpcRequestClass.sendInit(parsedReqBody);\n      } else if (parsedReqBody.wsCommand === \"push\") {\n        console.log(\"push\");\n        let messageInput;\n        try {\n          messageInput = JSON.parse(parsedReqBody.messageInput);\n        } catch {\n          console.log('error parsing messageInput in ws-router - \"push\"');\n        }\n        console.log(\"||||||||||||||||PUSH\", messageInput);\n        grpcRequestClass._call.write(messageInput);\n      } else if (parsedReqBody.wsCommand === \"end\") {\n        if (parsedReqBody.requestInput.streamType === \"serverStreaming\") {\n          grpcRequestClass._call.cancel();\n          console.log(\"Cancel\");\n        } else {\n          grpcRequestClass._call.end();\n          console.log(\"end\");\n        }\n      }\n    });\n  } catch {\n    console.log(\"error in ws\");\n  }\n});\n\napp.use((req, res) => {\n  res.status(404).send(\"Page Not Found\");\n});\n// Global error handling:\napp.use(function(err, req, res, next) {\n  const defaultError = {\n    log: \"Express error handler caught unknown middleware error\",\n    status: 400,\n    message: { err: \"An error occurred\" }\n  };\n  const newErrObj = Object.assign(defaultError, err);\n  console.log(newErrObj);\n  res.status(newErrObj.status).json(newErrObj.message);\n});\napp.listen(port, () =>\n  console.log(`  👽  invasion happening on port: ${port} `)\n);\n"
  },
  {
    "path": "src/actions/changeTheme.ts",
    "content": "//Define action type\n\nexport const CHANGE_THEME = \"CHANGE_THEME\";\n\n//Define shape of action type\nexport interface changeTheme {\n  type: typeof CHANGE_THEME;\n  payload: string;\n}\n\n//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\nexport type changeThemeAction = changeTheme;\n\nexport const changeThemeActionCreator = (payloadObj: string): changeTheme => {\n  return {\n    type: CHANGE_THEME,\n    payload: payloadObj\n  };\n};\n"
  },
  {
    "path": "src/actions/index.ts",
    "content": "/****************************************single source of all creators and action types***************************** */\n\nexport * from \"./test\";\nexport * from \"./uploadProto\";\nexport * from \"./updateMenu\";\nexport * from \"./changeTheme\";\n\n// export * from './actionTypes'\n"
  },
  {
    "path": "src/actions/test.ts",
    "content": "// 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\n// import {INCREMENT} from './actionTypes'\n\n/****************************create action type*************************** */\nexport const INCREMENT = 'INCREMENT'\nexport const DECREMENT = 'DECREMENT'\n\n\n/*****************************************define types for action obj************** */\n\n// defines \nexport interface incrementAction {\n  type: typeof INCREMENT\n  payload: number\n}\n\nexport interface decrementAction {\n  type: typeof DECREMENT\n  payload: number\n}\n\n// we combine the increment and decrement interface types into one type so that this one type can be used elsewhere, like in /reducers/increment\nexport type incrementActions = incrementAction | decrementAction \n\n/**********************************makes available outside of file ********** */\n//we can get rid of export type by just exporting the interface. Remove below line\n// export type incrementActionType = incrementAction\n\nexport const incrementActionCreator = (incrementNum: number): incrementAction => {\n  return {\n    type: INCREMENT,\n    payload: incrementNum\n  }\n}\n\nexport const decrementActionCreator = (decrementNum: number): decrementAction => {\n  return {\n    type: DECREMENT,\n    payload: decrementNum\n  }\n}\n\n"
  },
  {
    "path": "src/actions/updateMenu.ts",
    "content": "\n//Define action type\nexport const LOAD_SERVICE_OPTIONS = 'LOAD_SERVICE_OPTIONS '\nexport const LOAD_REQUEST_OPTIONS = 'LOAD_REQUEST_OPTIONS '\n\n\n\n//Define shape of action type\nexport interface loadServiceOptions {\n  type: typeof LOAD_SERVICE_OPTIONS;\n  payload: object\n}\n\nexport interface loadRequestOptions {\n  type: typeof LOAD_REQUEST_OPTIONS;\n  payload: object\n}\n\n//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\nexport type loadMenuAction = loadServiceOptions | loadRequestOptions\n\nexport const loadServiceActionCreator = (\n  payloadObj: object\n): loadServiceOptions => {\n  return {\n    type: LOAD_SERVICE_OPTIONS,\n    payload: payloadObj\n  };\n};\n\nexport const loadRequestActionCreator = (\n  payloadObj: object\n): loadRequestOptions => {\n  return {\n    type: LOAD_REQUEST_OPTIONS,\n    payload: payloadObj\n  };\n};\n\n"
  },
  {
    "path": "src/actions/uploadProto.ts",
    "content": "import { typeResponse } from \"../reducers/uploadProto\";\n\n//Define action type\nexport const UPLOAD_PROTO = \"UPLOAD_PROTO\";\nexport const SEND_PROTO = \"SEND_PROTO\";\nexport const UPLOAD_PROTO_SUCCESSFUL = \"UPLOAD_PROTO_SUCCESSFUL\";\nexport const UPLOAD_PROTO_FAILED = \"UPLOAD_PROTO_FAILED\";\nexport const SEND_UNARY_REQUEST = \"SEND_UNARY_REQUEST\";\nexport const SET_MESSAGE = \"SET_MESSAGE\";\nexport const SET_SERVICE = \"SET_SERVICE\";\nexport const SET_URL = \"SET_URL\";\nexport const SET_REQUEST = \"SET_REQUEST\";\nexport const DISPLAY_UNARY_RESPONSE = \"DISPLAY_UNARY_RESPONSE\";\nexport const CLEAR_RESPONSE_EDITOR = \"CLEAR_RESPONSE_EDITOR\";\nexport const SHOW_POPUP = \"SHOW_POPUP\";\nexport const SET_WS_COMMAND = \"SET_WS_COMMAND\";\nexport const START_WEBSOCKET = \"START_WEBSOCKET\";\n\n//Define shape of action type\n//Arraybuffer is an array of bytes, representing a generic, fixed-length raw binary data buffer\nexport interface uploadProto {\n  type: typeof UPLOAD_PROTO;\n  payload: string | ArrayBuffer;\n}\n\nexport interface sendProto {\n  type: typeof SEND_PROTO;\n  payload: string | ArrayBuffer;\n}\n\nexport interface uploadProtoSuccessful {\n  type: typeof UPLOAD_PROTO_SUCCESSFUL;\n  payload: object;\n}\n\nexport interface sendUnaryRequest {\n  type: typeof SEND_UNARY_REQUEST;\n  payload: any;\n}\n\nexport interface displayUnaryResponse {\n  type: typeof DISPLAY_UNARY_RESPONSE;\n  payload: typeResponse;\n}\n\nexport interface setMessage {\n  type: typeof SET_MESSAGE;\n  payload: string;\n}\n\nexport interface setService {\n  type: typeof SET_SERVICE;\n  payload: string;\n}\n\nexport interface setUrl {\n  type: typeof SET_URL;\n  payload: string;\n}\n\nexport interface setRequest {\n  type: typeof SET_REQUEST;\n  payload: object;\n}\n\nexport interface uploadProtoFailed {\n  type: typeof UPLOAD_PROTO_FAILED;\n  payload: string;\n}\n\nexport interface clearResponseEditor {\n  type: typeof CLEAR_RESPONSE_EDITOR;\n  payload: typeResponse[];\n}\n\nexport interface showPopup {\n  type: typeof SHOW_POPUP;\n  payload: boolean;\n}\n\nexport interface setWsCommand {\n  type: typeof SET_WS_COMMAND;\n  payload: string;\n}\n\nexport interface startWebsocket {\n  type: typeof START_WEBSOCKET;\n  payload: string;\n}\n\n//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\nexport type uploadProtoAction =\n  | uploadProto\n  | sendProto\n  | uploadProtoSuccessful\n  | uploadProtoFailed\n  | setMessage\n  | setService\n  | setUrl\n  | setRequest\n  | sendUnaryRequest\n  | displayUnaryResponse\n  | clearResponseEditor\n  | showPopup\n  | setWsCommand\n  | startWebsocket\n\n\nexport const uploadProtoActionCreator = (\n  payloadObj: string | ArrayBuffer\n): uploadProto => {\n  return {\n    type: UPLOAD_PROTO,\n    payload: payloadObj\n  };\n};\n\n// Do we ever use sendProtoActionCreator?\nexport const sendProtoActionCreator = (\n  payloadObj: string | ArrayBuffer\n): sendProto => {\n  return {\n    type: SEND_PROTO,\n    payload: payloadObj\n  };\n};\n\nexport const uploadProtoSuccessfulActionCreator = (\n  payloadObj: object\n): uploadProtoSuccessful => {\n  return {\n    type: UPLOAD_PROTO_SUCCESSFUL,\n    payload: payloadObj\n  };\n};\n\nexport const uploadProtoFailedActionCreator = (\n  payloadObj: string\n): uploadProtoFailed => {\n  return {\n    type: UPLOAD_PROTO_FAILED,\n    payload: payloadObj\n  };\n};\n\nexport const sendUnaryRequestActionCreator = (\n  payloadObj: any\n): sendUnaryRequest => {\n  return {\n    type: SEND_UNARY_REQUEST,\n    payload: payloadObj\n  };\n};\n\nexport const displayUnaryResponseActionCreator = (\n  payloadObj: any\n): displayUnaryResponse => {\n  return {\n    type: DISPLAY_UNARY_RESPONSE,\n    payload: payloadObj\n  };\n};\n\nexport const setMessageActionCreator = (payloadObj: string): setMessage => {\n  return {\n    type: SET_MESSAGE,\n    payload: payloadObj\n  };\n};\n\nexport const setServiceActionCreator = (payloadObj: string): setService => {\n  return {\n    type: SET_SERVICE,\n    payload: payloadObj\n  };\n};\n\nexport const setUrlActionCreator = (payloadObj: string): setUrl => {\n  return {\n    type: SET_URL,\n    payload: payloadObj\n  };\n};\n\nexport const setRequestActionCreator = (payloadObj: object): setRequest => {\n  return {\n    type: SET_REQUEST,\n    payload: payloadObj\n  };\n};\n\nexport const clearResponseEditorActionCreator = (\n  payloadObj: typeResponse[]\n): clearResponseEditor => {\n  return {\n    type: CLEAR_RESPONSE_EDITOR,\n    payload: payloadObj\n  };\n};\n\nexport const showPopupActionCreator = (payloadObj: boolean): showPopup => {\n  return {\n    type: SHOW_POPUP,\n    payload: payloadObj\n  };\n};\n\nexport const setWsCommandActionCreator = (\n  payloadObj: string\n): setWsCommand => {\n  return {\n    type: SET_WS_COMMAND,\n    payload: payloadObj\n  };\n};\n\nexport const startWebsocketActionCreator = (\n  payloadObj: string\n): startWebsocket => {\n  return {\n    type: START_WEBSOCKET,\n    payload: payloadObj\n  }\n}\n"
  },
  {
    "path": "src/components/DropdownRequest.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\nimport { setRequestActionCreator, \n  setMessageActionCreator, \n  clearResponseEditorActionCreator,\n  setWsCommandActionCreator\n} from \"../actions\";\nimport { typeRequest } from \"../reducers/uploadProto\";\n\ninterface DropdownRequestProps {\n  parsedProtoObj: any;\n  className: string;\n  menuOptions: any;\n  service: string;\n  value: typeRequest;\n  setRequest: typeof setRequestActionCreator;\n  setMessageAction?: typeof setMessageActionCreator;\n  setWsCommandAction: typeof setWsCommandActionCreator;\n  clearResponseEditor: typeof clearResponseEditorActionCreator;\n}\nexport const DropdownRequest: FunctionComponent<DropdownRequestProps> = props => {\n  {\n    const {\n      parsedProtoObj,\n      className,\n      menuOptions,\n      service,\n      setRequest,\n      value,\n      setMessageAction,\n      setWsCommandAction,\n      clearResponseEditor\n    } = props;\n\n    //create array of requests\n    let servicesArr: string[] = [];\n    let servicesObj: {\n      [index: string]: {\n        message: { [nestedIndex: string]: { message: string } };\n      };\n    } = {};\n\n    if (service) {\n      servicesArr = Object.keys(menuOptions[service]);\n      servicesObj = menuOptions[service];\n    } else {\n\n    }\n\n    return (\n      <div>\n        <select\n          onChange={e => {\n            if (e.target.value === \"Select Request\") {\n              setRequest({ methodName: \"\", streamType: \"\" });\n              setMessageAction(\"\");\n            } else {\n              //user selects request method\n              let requestSelected = e.target.value;\n\n              //Need to update state w/ requestSelected and streamType\n              let streamType =\n                parsedProtoObj[\"services\"][`${service}`][`${requestSelected}`]\n                  .type;\n\n              clearResponseEditor([])\n              setWsCommandAction('');\n              \n              setRequest({\n                methodName: requestSelected,\n                streamType: streamType\n              });\n\n              //Need to auto populate editor with types\n              const messageFieldsObj: object = Object.values(\n                servicesObj[e.target.value]\n              )[0];\n              const messageFieldsArrayOfTuples: string[][] = Object.entries(\n                messageFieldsObj\n              );\n              let editorDisplay: string = \"\";\n              for (let [field, type] of messageFieldsArrayOfTuples) {\n                // if (Array.isArray(type)) {\n                //   let [definedMessageType, definedMessageName] = type;\n                //   let definedMessageString =  \n\n                // } else {\n\n                // }\n                let typeDisplay: any = type;\n                switch (type) {\n                  case \"TYPE_STRING\": {\n                    typeDisplay = '\"Hello\"';\n                    break;\n                  }\n                  case \"TYPE_INT32\": {\n                    typeDisplay = 10;\n                    break;\n                  }\n                  case \"TYPE_INT32\": {\n                    typeDisplay = 10;\n                    break;\n                  }\n                }\n                const currentStr: string = `\"${field}\": ${typeDisplay},\\n  `;\n                editorDisplay += currentStr;\n              }\n              editorDisplay =\n                \"{\\n  \" +\n                editorDisplay.slice(0, editorDisplay.length - 4) +\n                \"\\n}\";\n              setMessageAction(editorDisplay);\n            }\n          }}\n        >\n          <option>Select Request</option>\n          {servicesArr.map((menuOptions, i) => (\n            <option key={i}>{menuOptions}</option>\n          ))}\n        </select>\n      </div>\n    );\n  }\n};\n"
  },
  {
    "path": "src/components/DropdownService.tsx",
    "content": "import React, { FunctionComponent } from 'react';\nimport { setServiceActionCreator, \n  startWebsocketActionCreator, \n  clearResponseEditorActionCreator, \n  setWsCommandActionCreator } \n  from '../actions';\ninterface DropdownServiceProps {\n  className?: string;\n  menuOptions?: object;\n  value: string;\n  setService: typeof setServiceActionCreator;\n  startWebsocket: typeof startWebsocketActionCreator;\n  clearResponseEditor: typeof clearResponseEditorActionCreator;\n  setWsCommandAction: typeof setWsCommandActionCreator;\n}\nexport const DropdownService: FunctionComponent< DropdownServiceProps> = props => {\n  {\n    const { \n      className, \n      menuOptions, \n      setService, \n      startWebsocket, \n      value,\n      setWsCommandAction,\n      clearResponseEditor\n    } = props;\n\n    //create array of services\n    const servicesArr = Object.keys(menuOptions);\n\n    return (\n      <div>\n        <select\n          onChange={e => {\n            if (e.target.value === 'Select Service') {\n              setService('');\n            } else {\n              setService(e.target.value);\n              startWebsocket('string');\n              setWsCommandAction('');\n              clearResponseEditor([])\n            }\n          }}\n        >\n          <option>Select Service</option>\n          {servicesArr.map((menuOptions, i) => (\n            <option key={i}>{menuOptions}</option>\n          ))}\n        </select>\n      </div>\n    );\n  }\n};\n"
  },
  {
    "path": "src/components/Editor.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\nimport { EditorRequest } from \"./EditorRequest\";\nimport { EditorResponse } from \"./EditorResponse\";\nimport { statement } from \"@babel/template\";\nimport { setMessageActionCreator } from \"../actions\";\nimport { useDispatch } from \"react-redux\";\nimport { typeResponse } from \"../reducers/uploadProto\";\n\ninterface editorProps {\n  setMessageAction?: typeof setMessageActionCreator;\n  data: string;\n  response: typeResponse[];\n  changeTheme: string;\n}\n\nexport const Editor: FunctionComponent<editorProps> = props => {\n  {\n    const { setMessageAction, data, response, changeTheme } = props;\n\n    return (\n      <>\n        <EditorRequest\n          data={data}\n          newRequest={value => {\n            setMessageAction(value);\n          }}\n          changeTheme={changeTheme}\n        />\n\n        <EditorResponse response={response} changeTheme={changeTheme} />\n      </>\n    );\n  }\n};\n"
  },
  {
    "path": "src/components/EditorRequest.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\n// import AceEditor, {Command} from 'react-ace'\nimport AceEditor from \"react-ace\";\nimport { Tabs } from \"antd\";\n\nimport \"ace-builds/src-noconflict/theme-monokai\";\nimport \"ace-builds/src-noconflict/theme-cobalt\";\nimport \"ace-builds/src-noconflict/theme-pastel_on_dark\";\nimport \"ace-builds/src-noconflict/mode-json\";\nimport \"ace-builds/src-noconflict/theme-clouds\";\nimport \"ace-builds/src-noconflict/theme-crimson_editor\";\nimport \"ace-builds/src-noconflict/theme-sqlserver\";\n\ninterface RequestProps {\n  data?: string;\n  newRequest: (value: string) => void;\n  changeTheme: string;\n}\n\nexport const EditorRequest: FunctionComponent<RequestProps> = props => {\n  {\n    const { data, newRequest, changeTheme } = props;\n\n    const editorTabKey = `editor Tab`;\n\n    //CHANGE THEME\n    let toggleTheme =\n      changeTheme === \"dark-yellow\" ||\n      changeTheme === \"dark-green\" ||\n      changeTheme === \"dark-blue\"\n        ? \"monokai\"\n        : \"SQL Server\";\n\n    return (\n      <>\n       <div>Editor\n            <AceEditor\n              mode=\"json\"\n              name=\"requestInput\"\n              value={data}\n              onChange={newRequest}\n              theme={toggleTheme}\n              height={\"250px\"}\n              width={\"100%\"}\n              wrapEnabled\n              showGutter\n              fontSize={12}\n              cursorStart={2}\n              showPrintMargin={false}\n              highlightActiveLine={false}\n              tabSize={2}\n              setOptions={{\n                useWorker: true,\n                displayIndentGuides: true\n              }}\n            />\n         </div>\n      </>\n    );\n  }\n};\n"
  },
  {
    "path": "src/components/EditorResponse.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\n// import AceEditor, {Command} from 'react-ace'\nimport AceEditor from \"react-ace\";\nimport { Tabs } from \"antd\";\nimport { typeResponse } from \"../reducers/uploadProto\";\n\nimport \"ace-builds/src-noconflict/theme-monokai\";\nimport \"ace-builds/src-noconflict/theme-cobalt\";\nimport \"ace-builds/src-noconflict/theme-pastel_on_dark\";\nimport \"ace-builds/src-noconflict/mode-json\";\nimport \"ace-builds/src-noconflict/theme-clouds\";\nimport \"ace-builds/src-noconflict/theme-crimson_editor\";\nimport \"ace-builds/src-noconflict/theme-sqlserver\";\n\ninterface ResponseProps {\n  response: typeResponse[];\n  changeTheme: string;\n}\n\nexport const EditorResponse: FunctionComponent<ResponseProps> = props => {\n  {\n    const defaultKey = `responseTab`;\n    const { response, changeTheme } = props;\n\n    let stringResponse = \"\";\n    let requestCount = 0;\n    let responseCount = 0;\n    response.forEach((element, i) => {\n      if( i === 0) {\n        responseCount = 0;\n        requestCount = 0;\n      }\n      if (typeof element === 'object') {\n        responseCount += 1;\n        stringResponse += `\\nResponse:\\n${element.message}\\n`;\n      } else {\n        requestCount += 1;\n        stringResponse += `\\nRequest:\\n${element}\\n`;\n      }\n    });\n\n    let responseTime = 1;\n\n    //CHANGE THEME\n    let toggleTheme =\n      changeTheme === \"dark-yellow\" ||\n      changeTheme === \"dark-green\" ||\n      changeTheme === \"dark-blue\"\n        ? \"monokai\"\n        : \"SQL Server\";\n\n    return (\n      <>\n         <div> Log\n            <AceEditor\n              mode=\"json\"\n              name=\"requestInput\"\n              value={stringResponse}\n              width={\"100%\"}\n              height={\"250px\"}\n              theme={toggleTheme}\n              fontSize={12}\n              cursorStart={2}\n              showGutter\n              wrapEnabled\n              showPrintMargin={false}\n              highlightActiveLine={false}\n              tabSize={2}\n              readOnly={true}\n              setOptions={{\n                useWorker: true,\n                displayIndentGuides: true,\n                highlightGutterLine: false\n              }}\n            />\n          </div>\n      </>\n    );\n  }\n};\n"
  },
  {
    "path": "src/components/Popup.tsx",
    "content": "import React, { FunctionComponent } from 'react';\nimport { Button } from './common/Button';\nimport { showPopupActionCreator } from '../actions';\n\ninterface PopupProps {\n  popup: boolean;\n  toggle: typeof showPopupActionCreator;\n  proto: string | ArrayBuffer;\n}\n\nexport const Popup: FunctionComponent<PopupProps> = (props) => {\n  {\n    const {\n      popup,\n      toggle,\n      proto\n    } = props;\n\n    const popupClass: string = popup ? 'popup-on' : 'popup-off';\n    // const popupClass: string = \"modal popup-off\";\n\n    const handleToggle = () => {\n      toggle(!popup);\n    }\n\n    return(\n      <div className={popupClass}>\n        <div className=\"modal-main\">\n          <pre>{proto}</pre>\n          <Button onClick={handleToggle} text={'Close'}></Button>\n        </div>\n      </div>\n    )\n  }\n}"
  },
  {
    "path": "src/components/Settings.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\nimport { connect } from \"react-redux\";\nimport { BrowserRouter as Router, Route, Link } from \"react-router-dom\";\nimport { Button } from \"./common/Button\";\nimport { changeTheme, themeSelector } from \"../reducers/changeTheme\";\nimport { RootState } from \"../reducers\";\nimport { changeThemeActionCreator } from \"../actions\";\n\n// sets type for props\ninterface SettingsProps {\n  changeThemeAction: typeof changeThemeActionCreator;\n  changeTheme: string;\n}\n\nexport const Settings: FunctionComponent<SettingsProps> = props => {\n  {\n    const { changeThemeAction, changeTheme } = props;\n\n    const toggleDarkYellow = () => {\n      changeThemeAction(\"dark-yellow\");\n    };\n    const toggleLightYellow = () => {\n      changeThemeAction(\"light-yellow\");\n    };\n    const toggleDarkGreen = () => {\n      changeThemeAction(\"dark-green\");\n    };\n    const toggleDarkBlue = () => {\n      changeThemeAction(\"dark-blue\");\n    };\n\n    return (\n      <div>\n        <div>⚡⚙ Select A Theme ⚙⚡</div>\n\n        {/* Dark Yellow Theme */}\n        <Button\n          className=\"button-dark-yellow\"\n          onClick={toggleDarkYellow}\n        ></Button>\n        {/* Light Yellow Theme */}\n        <Button\n          className=\"button-light-yellow\"\n          onClick={toggleLightYellow}\n        ></Button>\n        {/* Dark Green Theme */}\n        <Button\n          className=\"button-dark-green\"\n          onClick={toggleDarkGreen}\n        ></Button>\n        {/* Dark Blue Theme */}\n        <Button className=\"button-dark-blue\" onClick={toggleDarkBlue}></Button>\n      </div>\n    );\n  }\n};\n\nexport default connect(\n  (state: RootState) => ({\n    changeTheme: themeSelector(state)\n  }),\n  {\n    changeThemeAction: changeThemeActionCreator\n  }\n)(Settings);\n"
  },
  {
    "path": "src/components/TestProto.tsx",
    "content": "import React, { FunctionComponent } from 'react';\nimport { connect } from 'react-redux';\nimport { BrowserRouter as Router, Route, Link } from 'react-router-dom';\nimport {\n  setMessageActionCreator,\n  setServiceActionCreator,\n  setUrlActionCreator,\n  setRequestActionCreator,\n  sendUnaryRequestActionCreator,\n  clearResponseEditorActionCreator,\n  showPopupActionCreator,\n  setWsCommandActionCreator,\n  startWebsocketActionCreator\n} from '../actions';\nimport { Editor } from './Editor';\nimport {\n  typeResponse,\n  typeRequest,\n  popupSelector\n} from '../reducers/uploadProto';\nimport { DropdownService } from './DropdownService';\nimport { DropdownRequest } from './DropdownRequest';\nimport { Button } from './common/Button';\n\n// sets type for props\ninterface TestProtoProps {\n  parsedProtoObj: object;\n  serviceOptions: object;\n  data: string;\n  service: string;\n  url: string;\n  response: typeResponse[];\n  request: typeRequest;\n  wsCommand: string;\n  setMessageAction: typeof setMessageActionCreator;\n  setServiceAction: typeof setServiceActionCreator;\n  setUrlAction: typeof setUrlActionCreator;\n  setRequestAction: typeof setRequestActionCreator;\n  setWsCommandAction: typeof setWsCommandActionCreator;\n  sendUnaryRequestAction: any;\n  clearResponseEditor: typeof clearResponseEditorActionCreator;\n  proto: string | ArrayBuffer;\n  togglePopup: typeof showPopupActionCreator;\n  startWebsocketAction: typeof startWebsocketActionCreator;\n  popupStatus: boolean;\n  changeTheme: string;\n}\n\nexport const TestProto: FunctionComponent<TestProtoProps> = props => {\n  {\n    const {\n      parsedProtoObj,\n      serviceOptions,\n      data,\n      response,\n      service,\n      request,\n      url,\n      proto,\n      wsCommand,\n      togglePopup,\n      popupStatus,\n      changeTheme,\n      setWsCommandAction,\n      setMessageAction,\n      setServiceAction,\n      setUrlAction,\n      setRequestAction,\n      sendUnaryRequestAction,\n      startWebsocketAction,\n      clearResponseEditor\n    } = props;\n\n    const handleUrlChange = (e: any) => {\n      setUrlAction(e.target.value);\n    };\n    // function that inovokes the action creator to clear response editor, sends grpc request information, and starts websocket connection\n    const handleRequestClick = (e: any) => {\n      if(url.length === 0) {\n        let value = prompt('Please enter IP address');\n\n        if(!value) {\n          setUrlAction('');\n        } else {\n          setUrlAction(value);\n        }\n      } else {\n        clearResponseEditor([]);\n        setWsCommandAction('sendInit');\n        sendUnaryRequestAction(data);\n      }\n    };\n\n    // function that invokes action creator to push messages\n    const handlePushClick = (e: any) => {\n      setWsCommandAction('push');\n      sendUnaryRequestAction(data);\n    };\n    // function that invokes action creator to end websocket connection\n    const handleEndClick = (e: any) => {\n      setWsCommandAction('end');\n      sendUnaryRequestAction('End stream');\n    };\n\n    const handleViewClick = (e: any) => {\n      if (proto === '') {\n        alert('upload proto file');\n      } else {\n        togglePopup(!popupStatus);\n      }\n    };\n    //based on state (e.g. \"yellow\"), pass down\n    const toggle = 'yellow';\n\n    //CHANGE THEME\n    let toggleThemeTestProto = `testProto-${changeTheme}`;\n    let toggleThemeInputBox = `url-input-${changeTheme}`;\n    let toggleThemeViewProto = `button viewProto-button-${changeTheme}`;\n    let pushButton;\n    let endButton;\n    let requestButton;\n    let showStreamingType;\n    let changeThemeBackground;\n\n    if (request.streamType === '' || request.streamType === 'unary') {\n      requestButton =  (<Button className='send-button' onClick={handleRequestClick}/>);\n\n    } else if (request.streamType === 'clientStreaming' || request.streamType === 'bidiStreaming') {\n      if(wsCommand === '' || wsCommand === 'end') {\n        requestButton =  (<Button className='send-button'  onClick={handleRequestClick}/>);\n      } else {\n        pushButton = (<Button className='push-button' onClick={handlePushClick} />);\n        endButton = (<Button className='pause-button' onClick={handleEndClick} />); \n      }\n    } else if (request.streamType === 'serverStreaming') {\n      if(wsCommand === '' || wsCommand === 'end') {\n        requestButton =  (<Button className='send-button'  onClick={handleRequestClick}/>);\n      } else {\n        endButton = (<Button className='pause-button' onClick={handleEndClick}/>);\n        }\n      }\n    \n\n    if (changeTheme === 'dark-yellow' || changeTheme === 'light-yellow') {\n      changeThemeBackground = '#f9c132';\n    } else if (changeTheme === 'dark-green') {\n      changeThemeBackground = '#50fa7b';\n    } else if (changeTheme === 'dark-blue') {\n      changeThemeBackground = '#57b5f9';\n    }\n    if (request.streamType) {\n      showStreamingType = (\n        <em\n          style={{ backgroundColor: changeThemeBackground, color: 'black' }}\n        >\n          {' '}\n          {`Type: ${request.streamType}`}\n        </em>\n      );\n    }\n\n    return (\n      <div id={toggleThemeTestProto}>\n        Test Your Proto File:\n        <div id='menu-and-view-section'>\n          <div className='menu-options'>\n            <input\n              className={toggleThemeInputBox}\n              placeholder=' IP address'\n              onChange={handleUrlChange}\n              value={url}\n            ></input>\n\n            <DropdownService\n              className='service-dropdown-menu'\n              menuOptions={serviceOptions}\n              setService={setServiceAction}\n              startWebsocket={startWebsocketAction}\n              setWsCommandAction={setWsCommandAction}\n              clearResponseEditor={clearResponseEditor}\n              value={service}\n            ></DropdownService>\n\n            <DropdownRequest\n              className='request-dropdown-menu'\n              menuOptions={serviceOptions}\n              service={service}\n              setRequest={setRequestAction}\n              setWsCommandAction={setWsCommandAction}\n              clearResponseEditor={clearResponseEditor}\n              value={request}\n              parsedProtoObj={parsedProtoObj}\n              setMessageAction={setMessageAction}\n            ></DropdownRequest>\n            {requestButton}\n            {pushButton}\n            {endButton}\n          </div>\n          <div id=\"handleViewClick\">\n            {showStreamingType}\n            <Button\n              className={toggleThemeViewProto}\n              text=\"View Proto File\"\n              onClick={handleViewClick}\n            />\n          </div>\n        </div>\n        <div>\n          <Editor\n            setMessageAction={setMessageAction}\n            data={data}\n            response={response}\n            changeTheme={changeTheme}\n          />\n        </div>\n      </div>\n    );\n  }\n};\n\nexport default TestProto;\n"
  },
  {
    "path": "src/components/common/Button.tsx",
    "content": "import React, { FunctionComponent } from 'react'\nimport { urlencoded } from 'body-parser'\n\ninterface ButtonProps {\n  className?: string\n  onClick?: (...arg: any[]) => any\n  text?: string\n  value?: number\n  icon?: string\n}\n\nexport const Button:\nFunctionComponent<ButtonProps> = props => {\n  {\n    const {\n      className, \n      onClick,\n      text,\n      value, \n      icon\n    } = props\n  \n  return (\n    <button className={className} onClick={onClick} value={value}>{text}</button>\n    ) \n  }\n}\n\n// style = { {backgroundImage: `url(${icon})`}}\n"
  },
  {
    "path": "src/components/common/DropdownMenu.tsx",
    "content": "import React, { FunctionComponent } from 'react';\ninterface DropdownMenuProps {\n  id?: string;\n  menuOptions?: object;\n}\nexport const DropdownMenu: FunctionComponent<DropdownMenuProps> = props => {\n  {\n    const { id, menuOptions } = props;\n\n    //menuOptions object holds the following content:\n    //services: {\n    //service1: {request1: {message1Options}}\n    //service2: {request2: {message2Options}}\n    //}\n    //get array of services\n    const servicesArr = Object.keys(menuOptions);\n    let selectValue;\n    return (\n      <div>\n        <select\n          onChange={e => {\n            selectValue = e.target.value;\n          }}\n        >\n          {servicesArr.map((menuOptions, i) => (\n            <option key={i}>{menuOptions}</option>\n          ))}\n        </select>\n      </div>\n    );\n  }\n};\n"
  },
  {
    "path": "src/containers/App.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\nimport { connect } from \"react-redux\";\nimport { RootState } from \"../reducers\";\nimport HeaderContainer, { Header } from \"./Header\";\nimport BodyContainer from \"./Body\";\nimport FooterContainer from \"./Footer\";\nimport NavbarContainer from \"./Navbar\";\nimport { Popup } from \"../components/Popup\";\nimport { Button } from \"../components/common/Button\";\nimport {\n  incrementActionCreator,\n  uploadProtoActionCreator,\n  uploadProtoSuccessfulActionCreator,\n  loadServiceActionCreator,\n  showPopupActionCreator,\n  changeThemeActionCreator\n} from \"../actions\";\nimport { countSelector } from \"../reducers/test\";\nimport {\n  protoSelector,\n  parsedProtoObjSelector,\n  popupSelector\n} from \"../reducers/uploadProto\";\nimport { BrowserRouter as Router, Route, Link } from \"react-router-dom\";\nimport \"../scss/index.scss\";\nimport { serviceMenuSelector } from \"../reducers/updateMenu\";\nimport { themeSelector } from \"../reducers/changeTheme\";\n\n// import { loggedInSelector } from '../reducers/login'\n\n// sets type for props\ninterface AppProps {\n  incrementAction: typeof incrementActionCreator;\n  uploadProtoSuccessful: typeof uploadProtoSuccessfulActionCreator;\n  serviceOptions: object;\n  protoObjContents: object;\n  togglePopup: typeof showPopupActionCreator;\n  proto: string | ArrayBuffer;\n  popupStatus: boolean;\n  changeThemeAction: typeof changeThemeActionCreator;\n  changeTheme: string;\n}\nexport const App: FunctionComponent<AppProps> = props => {\n  {\n    const {\n      incrementAction,\n      serviceOptions,\n      protoObjContents,\n      togglePopup,\n      proto,\n      popupStatus,\n      changeTheme\n    } = props;\n\n    //CHANGE THEME\n    let toggleThemeMainView = `main-view-${changeTheme}`;\n    let toggleThemeNavBar = `navbar-${changeTheme}`;\n\n    return (\n      //Wrap everything in Router so that nested containers/components have access to router\n      <Router>\n        {/* main-view */}\n        <div id={toggleThemeMainView}>\n          <div id={toggleThemeNavBar}>\n            <NavbarContainer></NavbarContainer>\n          </div>\n\n          <div id=\"app-container\">\n            <HeaderContainer></HeaderContainer>\n            <BodyContainer serviceOptions={serviceOptions}></BodyContainer>\n            <FooterContainer></FooterContainer>\n          </div>\n          <div>\n            <Popup\n              popup={popupStatus}\n              toggle={togglePopup}\n              proto={proto}\n            ></Popup>\n          </div>\n          {/* <Button text='enter' onClick={ () => {incrementAction(1)}} >\n            </Button> */}\n        </div>\n      </Router>\n    );\n  }\n};\n\n// gives the app component access to state and actions from the store\nexport default connect(\n  //if using selector\n  (state: RootState) => ({\n    test: countSelector(state),\n    protoContents: protoSelector(state),\n    serviceOptions: serviceMenuSelector(state),\n    protoObjContents: parsedProtoObjSelector(state),\n    proto: protoSelector(state),\n    popupStatus: popupSelector(state),\n    changeTheme: themeSelector(state)\n  }),\n  {\n    incrementAction: incrementActionCreator,\n    uploadProto: uploadProtoActionCreator,\n    uploadProtoSuccessful: uploadProtoSuccessfulActionCreator,\n    loadServiceOptions: loadServiceActionCreator,\n    togglePopup: showPopupActionCreator,\n    changeThemeAction: changeThemeActionCreator\n  }\n)(App);\n\n//if not using selector\n// (state: RootState) => ({\n//   test: state.test\n// }),\n"
  },
  {
    "path": "src/containers/Body.tsx",
    "content": "import React, { FunctionComponent, useState } from \"react\";\nimport { connect } from \"react-redux\";\nimport TestProto from \"../components/TestProto\";\nimport Settings from \"../components/Settings\";\nimport { Route } from \"react-router\";\nimport {\n  setMessageActionCreator,\n  setServiceActionCreator,\n  setUrlActionCreator,\n  setRequestActionCreator,\n  sendUnaryRequestActionCreator,\n  clearResponseEditorActionCreator,\n  showPopupActionCreator,\n  changeThemeActionCreator,\n  setWsCommandActionCreator,\n  startWebsocketActionCreator\n} from \"../actions\";\nimport {\n  messageSelector,\n  serviceSelector,\n  urlSelector,\n  requestSelector,\n  responseSelector,\n  typeResponse,\n  typeRequest,\n  parsedProtoObjSelector,\n  protoSelector,\n  popupSelector,\n  setWsSelector\n} from \"../reducers/uploadProto\";\nimport { RootState } from \"../reducers\";\nimport { themeSelector } from \"../reducers/changeTheme\";\nimport { start } from \"repl\";\n\n// sets type for props\ninterface BodyProps {\n  parsedProtoObj: object;\n  serviceOptions: object;\n  setMessageAction: typeof setMessageActionCreator;\n  setUrlAction: typeof setUrlActionCreator;\n  setRequestAction: typeof setRequestActionCreator;\n  setServiceAction: typeof setServiceActionCreator;\n  sendUnaryRequestAction?: typeof sendUnaryRequestActionCreator;\n  clearResponseEditorAction: typeof clearResponseEditorActionCreator;\n  setWsCommandAction: typeof setWsCommandActionCreator;\n  startWebsocketAction: typeof startWebsocketActionCreator;\n  selectMessage: string;\n  selectService: string;\n  selectUrl: string;\n  selectRequest: typeRequest;\n  selectResponse: typeResponse[];\n  selectWsCommand: string;\n  proto: string | ArrayBuffer;\n  togglePopup?: typeof showPopupActionCreator;\n  popupStatus?: boolean;\n  changeThemeAction: typeof changeThemeActionCreator;\n  changeTheme: string;\n\n}\n\nexport const Body: FunctionComponent<BodyProps> = props => {\n  {\n    const {\n      parsedProtoObj,\n      serviceOptions,\n      setMessageAction,\n      setServiceAction,\n      setUrlAction,\n      setRequestAction,\n      setWsCommandAction,\n      sendUnaryRequestAction,\n      clearResponseEditorAction,\n      startWebsocketAction,\n      selectWsCommand,\n      selectMessage,\n      selectService,\n      selectUrl,\n      selectRequest,\n      selectResponse,\n      togglePopup,\n      popupStatus,\n      proto,\n      changeTheme\n    } = props;\n\n    return (\n      <div>\n        <Route exact path=\"/\">\n          <TestProto\n            parsedProtoObj={parsedProtoObj}\n            serviceOptions={serviceOptions}\n            setMessageAction={setMessageAction}\n            setRequestAction={setRequestAction}\n            setServiceAction={setServiceAction}\n            setUrlAction={setUrlAction}\n            setWsCommandAction={setWsCommandAction}\n            sendUnaryRequestAction={sendUnaryRequestAction}\n            clearResponseEditor={clearResponseEditorAction}\n            startWebsocketAction={startWebsocketAction}\n            url={selectUrl}\n            data={selectMessage}\n            request={selectRequest}\n            response={selectResponse}\n            togglePopup={togglePopup}\n            popupStatus={popupStatus}\n            proto={proto}\n            service={selectService}\n            changeTheme={changeTheme}\n            wsCommand={selectWsCommand}\n          ></TestProto>\n        </Route>\n        <Route path=\"/settings\">\n          <Settings>Settings</Settings>\n        </Route>\n      </div>\n    );\n  }\n};\n\nexport default connect(\n  // gives the app component access to state and actions from the store\n  //   export default connect(\n\n  //     //using selector\n\n  (state: RootState) => ({\n    parsedProtoObj: parsedProtoObjSelector(state),\n    selectMessage: messageSelector(state),\n    selectService: serviceSelector(state),\n    selectUrl: urlSelector(state),\n    selectRequest: requestSelector(state),\n    selectResponse: responseSelector(state),\n    proto: protoSelector(state),\n    popupStatus: popupSelector(state),\n    changeTheme: themeSelector(state),\n    selectWsCommand: setWsSelector(state)\n  }),\n  {\n    setMessageAction: setMessageActionCreator,\n    setServiceAction: setServiceActionCreator,\n    setUrlAction: setUrlActionCreator,\n    setRequestAction: setRequestActionCreator,\n    sendUnaryRequestAction: sendUnaryRequestActionCreator,\n    clearResponseEditorAction: clearResponseEditorActionCreator,\n    togglePopup: showPopupActionCreator,\n    changeThemeAction: changeThemeActionCreator,\n    setWsCommandAction: setWsCommandActionCreator,\n    startWebsocketAction: startWebsocketActionCreator\n  }\n)(Body);\n"
  },
  {
    "path": "src/containers/Footer.tsx",
    "content": "import React, {FunctionComponent } from 'react'\nimport { connect } from 'react-redux'\nimport { Link, RouteComponentProps, withRouter } from 'react-router-dom'\n\n// sets type for props\ninterface FooterProps {\n\n  }\n  export const Footer: FunctionComponent<FooterProps> = props => {\n    {\n    //   const {\n    //     incrementAction\n    //   } = props\n      return (\n        <div id = \"footer\">\n        Built with 💛 by the Yodelays (v1.0 beta)\n\n        </div>\n      )\n    }\n  }\n\nexport default Footer\n\n  // gives the app component access to state and actions from the store\n//   export default connect(\n  \n//     //using selector\n//     (state: RootState) => ({\n//         test: countSelector(state)\n//       })\n//       ,\n    \n//     {\n//       incrementAction: incrementActionCreator,\n//     }\n//   )(App)"
  },
  {
    "path": "src/containers/Header.tsx",
    "content": "import React, { FunctionComponent } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Link, RouteComponentProps, withRouter } from \"react-router-dom\";\nimport { Button } from \"../components/common/Button\";\nimport { RootState } from \"../reducers\";\nimport { themeSelector } from \"../reducers/changeTheme\";\nimport { changeThemeActionCreator } from \"../actions\";\n\n// sets type for props\ninterface HeaderProps {\n  changeThemeAction: typeof changeThemeActionCreator;\n  changeTheme: string;\n}\nexport const Header: FunctionComponent<HeaderProps> = props => {\n  {\n    const { changeTheme } = props;\n\n    // //should evaluate to button-dark-yellow\n    let toggleThemeName = `header-button-${changeTheme}`;\n\n    const navToGithub = () => {\n      window.location.href = \"https://github.com/oslabs-beta/Yodelay\";\n    };\n\n    const navToTwitter = () => {\n      window.location.href = \"https://twitter.com/yodelay_io\";\n    };\n\n    return (\n      <div>\n        {/* On click, sends user back to home page */}\n        <div style={{ display: \"block\", height: \"15px\" }}></div>\n        <div id=\"header-container\">\n          <Link to=\"/\">\n            <Button className={toggleThemeName} text=\"Yodelay.io\"></Button>\n          </Link>\n          <div id=\"social-media\">\n            <Button className=\"github-button\" onClick={navToGithub}></Button>\n            <Button className=\"twitter-button\" onClick={navToTwitter}></Button>\n            <div style={{ display: \"block\", width: \"15px\" }}></div>\n          </div>\n        </div>\n      </div>\n    );\n  }\n};\n\nexport default connect(\n  (state: RootState) => ({\n    changeTheme: themeSelector(state)\n  }),\n  {\n    changeThemeAction: changeThemeActionCreator\n  }\n)(Header);\n"
  },
  {
    "path": "src/containers/Navbar.tsx",
    "content": "import React, { FunctionComponent, RefObject, useRef, createRef } from \"react\";\nimport { connect } from \"react-redux\";\nimport { Link, Route } from \"react-router-dom\";\nimport { Button } from \"../components/common/Button\";\nimport { uploadProtoActionCreator } from \"../actions\";\nimport { protoSelector } from \"../reducers/uploadProto\";\nimport { RootState } from \"../reducers\";\nimport { themeSelector } from \"../reducers/changeTheme\";\n\n// sets type for props\ninterface NavbarProps {\n  inputOpenFileRef?: RefObject<HTMLInputElement>;\n  showOpenFileDlg?: () => any;\n  uploadProto?: typeof uploadProtoActionCreator;\n  protoFile?: File;\n  changeTheme: string;\n}\n\n//Upon user clicking upload proto button in navbar, folder dialog window opens. User-selected file is read and its contents are passed as a payload\n\nexport const Navbar: FunctionComponent<NavbarProps> = props => {\n  {\n    const { uploadProto, changeTheme } = props;\n\n    //Refs allow us to access DOM nodes or React elements created in the render method\n    //Both createRef and useRef hook returns the same result. createRef  returns a new ref on every render while useRef will return the same ref obj each time\n    //\n\n    const inputOpenFileRef = useRef<HTMLInputElement>();\n\n    const showOpenFileDlg = () => {\n      inputOpenFileRef.current.click();\n    };\n    const onFileSubmit = () => {\n      const protoFile = inputOpenFileRef.current.files[0];\n\n      const reader = new FileReader();\n\n      reader.onloadend = e => {\n        uploadProto(e.target.result);\n      };\n\n      reader.readAsText(protoFile);\n    };\n\n    let toggleThemeUploadProto =\n      changeTheme === \"dark-yellow\" ||\n      changeTheme === \"dark-green\" ||\n      changeTheme === \"dark-blue\"\n        ? \"upload-proto-button-grey\"\n        : \"upload-proto-button-light\";\n\n    let toggleThemeSettings =\n      changeTheme === \"dark-yellow\" ||\n      changeTheme === \"dark-green\" ||\n      changeTheme === \"dark-blue\"\n        ? \"settings-button-grey\"\n        : \"settings-button-light\";\n\n    return (\n      <div>\n        <Link to=\"/\">\n          <Button className=\"home-button\"></Button>\n        </Link>\n\n        {/* Upload Proto Button */}\n        <input\n          ref={inputOpenFileRef}\n          type=\"file\"\n          style={{ display: \"none\" }}\n          onChange={onFileSubmit}\n        />\n\n        <Button\n          className={toggleThemeUploadProto}\n          onClick={showOpenFileDlg}\n        ></Button>\n\n        <Link to=\"/settings\">\n          <Button className={toggleThemeSettings}></Button>\n        </Link>\n      </div>\n    );\n  }\n};\n\nexport default connect(\n  // gives the navbar component access to specific state and actions from the store\n  (state: RootState) => ({\n    protoContents: protoSelector(state),\n    changeTheme: themeSelector(state)\n  }),\n  {\n    uploadProto: uploadProtoActionCreator\n  }\n)(Navbar);\n"
  },
  {
    "path": "src/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\" />\n    <title>Yodelay</title>\n  </head>\n  <body>\n    <div id='root'>\n\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "src/index.tsx",
    "content": "import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport { Provider } from \"react-redux\";\nimport { createStore, applyMiddleware } from \"redux\";\nimport { composeWithDevTools } from \"redux-devtools-extension\";\nimport saga from \"./sagas/sagas\";\nimport createSagaMiddleware from \"redux-saga\";\nimport App from \"./containers/App\";\nimport rootReducer from \"./reducers\";\n\nconst sagaMiddleware = createSagaMiddleware();\n\nconst store = createStore(\n  rootReducer,\n  composeWithDevTools(applyMiddleware(sagaMiddleware))\n);\n\nsagaMiddleware.run(saga);\n\nReactDOM.render(\n  <Provider store={store}>\n    <App />\n  </Provider>,\n  document.getElementById(\"root\")\n);\n"
  },
  {
    "path": "src/reducers/changeTheme.ts",
    "content": "import { changeThemeAction, CHANGE_THEME } from \"../actions\";\nimport { setIn } from \"timm\";\nimport { RootState } from \".\";\n\nexport interface initialThemeStateType {\n  theme: string;\n}\n\nconst initialState: initialThemeStateType = {\n  theme: \"dark-yellow\"\n  //payload will change based on theme: dark-yellow | light-yellow | dark-green | dark-blue\n};\n\nexport const changeTheme: (\n  state: initialThemeStateType,\n  action: changeThemeAction\n) => initialThemeStateType = (state = initialState, action) => {\n  // console.log(action.type)\n  switch (action.type) {\n    case CHANGE_THEME: {\n      //setIn takes in param1) state object, param2) the key in state that is what we want to update, and param3) the value we want to change\n      return setIn(state, [\"theme\"], action.payload);\n    }\n  }\n  return state;\n};\n\nexport const themeSelector: (state: RootState) => string = state =>\n  state.changeTheme.theme;\n"
  },
  {
    "path": "src/reducers/index.ts",
    "content": "import { combineReducers } from \"redux\";\n// needs clarifying -- how does it recognizes increment and why does it need an alias\nimport { test, testState } from \"./test\";\nimport { uploadProto, initialProtoStateType } from \"./uploadProto\";\nimport { updateMenu, initialMenuStateType } from \"./updateMenu\";\nimport { changeTheme, initialThemeStateType } from \"./changeTheme\";\n\nexport interface RootState {\n  test: testState;\n  uploadProto: initialProtoStateType;\n  updateMenu: initialMenuStateType;\n  changeTheme: initialThemeStateType;\n}\n\n// Turns an object whose values are different reducing functions into a single reducing function you can pass to createStore\nconst rootReducer = combineReducers({\n  test,\n  uploadProto,\n  updateMenu,\n  changeTheme\n});\n\nexport default rootReducer;\n"
  },
  {
    "path": "src/reducers/test.ts",
    "content": "import { INCREMENT, incrementActions, DECREMENT } from '../actions'\nimport {updateIn, setIn} from 'timm'\nimport { RootState } from '.'\n\nexport interface testState {\n  count: number\n}\n\nconst initialState: testState = {\n  count: 0\n}\n\n//this reducer can only take in actions of type increment actions\nexport const test: (state: testState, action: incrementActions) => testState = (\n  state = initialState, action) => {\n    switch (action.type) {\n      case INCREMENT:{\n        //setIn takes in param1) state object, param2) the key in state that is what we want to update, and param3) the value we want to change \n        return setIn(state, [\"count\"], state.count+1)\n        // {\n        //   count: state.count + action.payload\n        // }\n      }\n\n      case DECREMENT: {\n        //updateIn -- the only thing that changes is that param3 is a function\n        return updateIn(state, [\"count\"], (prevCount) => prevCount-1)\n      }\n      \n    }\n    return state\n  }\n\n\n// selectors\nexport const countSelector: (state: RootState)=> number = (state) => state.test.count \n\n//// OLD\n// function incrementReducer (\n//   state = initialState,\n//   action: incrementActionType\n// ): incrementState {\n//   switch (action.type) {\n//     case INCREMENT:\n//       return {\n//         count: state.count + action.payload\n//       }\n//   }\n// }\n"
  },
  {
    "path": "src/reducers/updateMenu.ts",
    "content": "import { setIn } from 'timm'\nimport { RootState } from '.'\nimport { loadMenuAction, LOAD_SERVICE_OPTIONS, LOAD_REQUEST_OPTIONS } from '../actions'\n\nexport interface initialMenuStateType {\n    serviceOptions: object;\n    requestOptions: object\n}\n\nconst initialState: initialMenuStateType = {\n    serviceOptions: {},\n    requestOptions: {}\n}\n\nexport const updateMenu: (state: initialMenuStateType, action: loadMenuAction) => initialMenuStateType = (state = initialState, action) =>{\n    switch(action.type){\n        case LOAD_SERVICE_OPTIONS:{\n            return setIn(state, [\"serviceOptions\"], action.payload)\n        }\n        case LOAD_REQUEST_OPTIONS:{\n            return setIn(state, [\"requestOptions\"], action.payload)\n        }\n    }\n    return state\n}\n\nexport const serviceMenuSelector: (state: RootState) => object = (state) => state.updateMenu.serviceOptions\n\n\nexport const requestMenuSelector: (state: RootState) => object = (state) => state.updateMenu.requestOptions"
  },
  {
    "path": "src/reducers/uploadProto.ts",
    "content": "import {\n  uploadProtoAction,\n  UPLOAD_PROTO,\n  SET_MESSAGE,\n  UPLOAD_PROTO_SUCCESSFUL,\n  SEND_PROTO,\n  SET_SERVICE,\n  SET_URL,\n  SET_REQUEST,\n  SEND_UNARY_REQUEST,\n  DISPLAY_UNARY_RESPONSE,\n  CLEAR_RESPONSE_EDITOR,\n  SHOW_POPUP,\n  SET_WS_COMMAND,\n} from \"../actions\";\nimport { setIn } from \"timm\";\nimport { RootState } from \".\";\n\nexport interface typeResponse {\n  message: string; //change to [], could impact editor\n  responseTime?: number;\n}\n\nexport interface typeRequest {\n  methodName: string;\n  streamType: string;\n}\n\n\n\nexport interface initialProtoStateType {\n  //obj containing pased proto file, incl. services, request methods, etc.\n  parsedProtosObj: object;\n  //from here onwards, we capture the user's selections\n  urlInput: string;\n  serviceInput: string;\n  // requestInput: string;\n  requestInput: typeRequest;\n  //request message\n  messageInput: string;\n  //response obj\n  response: typeResponse;\n  //array of response stream\n  responseStream: typeResponse[];\n  //ignore this\n  proto: string | ArrayBuffer;\n  showPopup: boolean;\n  wsCommand: string;\n}\n\nconst initialState: initialProtoStateType = {\n  parsedProtosObj: {},\n  urlInput: \"\",\n  serviceInput: \"\",\n  // requestInput: \"\",\n  requestInput: {\n    methodName: \"\",\n    streamType: \"\"\n  },\n  messageInput: \"Input message here...\",\n  response: {\n    message: \"View response here!\",\n    responseTime: undefined\n  },\n  responseStream: [],\n  proto: \"\",\n  showPopup: false,\n  wsCommand: ''\n};\n\n//uploadProto is a function that takes in state and action as params; it returns an updated state object of type initialProtoStateType\n//state type is initialProtoStateType; action type is uploadProtoAction\nexport const uploadProto: (\n  state: initialProtoStateType,\n  action: uploadProtoAction\n) => initialProtoStateType = (state = initialState, action) => {\n  // console.log(action.type)\n  switch (action.type) {\n    case UPLOAD_PROTO: {\n      //setIn takes in param1) state object, param2) the key in state that is what we want to update, and param3) the value we want to change\n      return setIn(state, [\"proto\"], action.payload);\n    }\n    case SET_MESSAGE: {\n      return { ...state, messageInput: action.payload };\n    }\n    case SET_SERVICE: {\n      return { ...state, serviceInput: action.payload };\n    }\n    case SET_URL: {\n      return { ...state, urlInput: action.payload };\n    }\n    case SET_REQUEST: {\n      return setIn(state, [\"requestInput\"], action.payload);\n    }\n    case UPLOAD_PROTO_SUCCESSFUL: {\n      //need to add in functionality to push multiple protoobj to state\n      return setIn(state, [\"parsedProtosObj\"], action.payload);\n    }\n    case SEND_UNARY_REQUEST: {\n      return { ...state, responseStream: [...state.responseStream, action.payload] };\n    }\n    case DISPLAY_UNARY_RESPONSE: {\n      return {\n        ...state,\n        responseStream: [...state.responseStream, action.payload]\n      };\n    }\n    case CLEAR_RESPONSE_EDITOR: {\n      return { ...state, responseStream: action.payload };\n    }\n    case SHOW_POPUP: {\n      // return setIn(state, ['showPopup'], action.payload);\n      return { ...state, showPopup: action.payload };\n    }\n    case SET_WS_COMMAND: {\n      return { ...state, wsCommand: action.payload };\n    }\n  }\n\n  return state;\n};\n\n//makes the proto state and parsedProtosObj state available to connected components\nexport const protoSelector: (\n  state: RootState\n) => string | ArrayBuffer = state => state.uploadProto.proto;\nexport const messageSelector: (state: RootState) => string = state =>\n  state.uploadProto.messageInput;\nexport const serviceSelector: (state: RootState) => string = state =>\n  state.uploadProto.serviceInput;\nexport const urlSelector: (state: RootState) => string = state =>\n  state.uploadProto.urlInput;\nexport const requestSelector: (state: RootState) => object = state =>\n  state.uploadProto.requestInput;\nexport const parsedProtoObjSelector: (state: RootState) => object = state =>\n  state.uploadProto.parsedProtosObj;\nexport const responseSelector: (state: RootState) => object = state =>\n  state.uploadProto.responseStream;\nexport const popupSelector: (state: RootState) => boolean = state =>\n  state.uploadProto.showPopup;\nexport const setWsSelector: (state: RootState) => string = state => \n  state.uploadProto.wsCommand;\n\n// selecting all of state for the request saga\nexport const stateSelector: (state: RootState) => object = state =>\n  state.uploadProto;\n"
  },
  {
    "path": "src/sagas/sagas.ts",
    "content": "import { call, put, takeLatest, select, take, fork } from \"redux-saga/effects\";\nimport { takeEvery, eventChannel } from \"redux-saga\";\n// import moment from 'moment'\nimport {\n  UPLOAD_PROTO,\n  uploadProto,\n  uploadProtoSuccessfulActionCreator,\n  uploadProtoFailedActionCreator,\n  loadServiceActionCreator,\n  SEND_UNARY_REQUEST,\n  sendUnaryRequest,\n  setMessageActionCreator,\n  displayUnaryResponseActionCreator,\n  START_WEBSOCKET\n} from \"../actions/index\";\nimport { json } from \"body-parser\";\nimport { stateSelector } from \"../reducers/uploadProto\";\n//Used payload from uploadProto action as an input for the sendProto saga middleware, enabling us to POST the file string to the express server\n\n// @ts-ignore\nconst API_PORT = env.API_PORT;\n// @ts-ignore\nconst API_HOST = env.API_HOST;\n// @ts-ignore\nconst API_PROTOCOL = env.API_PROTOCOL;\n// @ts-ignore\nconst NODE_ENV = env.NODE_ENV;\nconsole.log(API_PORT, API_HOST, API_PROTOCOL, NODE_ENV);\n\nfunction* sendProto({ payload }: uploadProto) {\n  try {\n    const jsonProtoFile = JSON.stringify(payload);\n    const data = yield fetch(\n      `${API_PROTOCOL}://${API_HOST}:${API_PORT}/upload`,\n      {\n        method: \"POST\",\n        headers: {\n          Accept: \"text/plain\",\n          \"Content-Type\": \"text/plain\"\n        },\n        body: jsonProtoFile\n      }\n    );\n    const response = yield data.json();\n    //No need to connect() to store; yield put apparently does it for us; that's how we could access the uploadProtoSuccessful action creator -- CHECK\n    yield put(uploadProtoSuccessfulActionCreator(response));\n    yield put(loadServiceActionCreator(response.services));\n  } catch ({ error, status }) {\n    const errorMessage = \"error in upload saga\";\n    yield put(uploadProtoFailedActionCreator(errorMessage));\n  }\n}\n\nfunction* startWebsocket() {\n  const socket = yield call(connect);\n  yield fork(read, socket);\n  yield fork(write, socket);\n  console.log(socket);\n}\n\nfunction* connect() {\n  const mySocket = yield new WebSocket(\n    `ws://${API_HOST}:${API_PORT}/websocket`,\n    \"protocol\"\n  );\n\n  return mySocket;\n}\n\nfunction* subscribe(socket?: any) {\n  const message = yield take(SEND_UNARY_REQUEST);\n  const state = yield select(stateSelector);\n  const jsonRequestObj = JSON.stringify({\n    url: state.urlInput,\n    serviceInput: state.serviceInput,\n    messageInput: state.messageInput,\n    requestInput: state.requestInput,\n    package: state.parsedProtosObj.package,\n    protoFile: state.parsedProtosObj.protoFile\n  });\n\n  return eventChannel(emit => {\n    socket.onmessage = (message: any) => {\n      emit(message);\n    };\n\n    return () => {\n      socket.close();\n    };\n  });\n}\n\nfunction* read(socket?: any) {\n  const channel = yield call(subscribe, socket);\n\n  while (true) {\n    let message = yield take(channel);\n    // dispatch actions with messages recieved from ws connection with server here\n    yield put(\n      displayUnaryResponseActionCreator({\n        message: message.data,\n        responseTime: message.timeStamp\n      })\n    );\n  }\n}\n\nfunction* write(socket?: any) {\n  while (true) {\n    const message = yield take(SEND_UNARY_REQUEST);\n    const state = yield select(stateSelector);\n    const jsonRequestObj = JSON.stringify({\n      url: state.urlInput,\n      serviceInput: state.serviceInput,\n      messageInput: state.messageInput,\n      requestInput: state.requestInput,\n      package: state.parsedProtosObj.package,\n      protoFile: state.parsedProtosObj.protoFile,\n      wsCommand: state.wsCommand\n    });\n\n    socket.send(jsonRequestObj);\n  }\n}\n\nfunction* saga() {\n  console.log(\"hello saga\");\n  yield takeLatest(UPLOAD_PROTO, sendProto);\n  yield takeLatest(START_WEBSOCKET, startWebsocket);\n  // const socket = yield call(connect)\n  // yield fork(read, socket)\n  // yield fork(write, socket)\n}\nexport default saga;\n"
  },
  {
    "path": "src/scss/colours.scss",
    "content": "// dark mode\n\n//yodelay default - yellow - dark- theme\n$black-background: #202123;\n$grey-navbar: #242527;\n$yellow: #f9c132;\n$grey-font: #e8e8e9;\n$disabled: #969696;\n$black-field: #1a1b1c;\n\n//yellow - light mode\n$white-background: #fafafa;\n$yellow: #f9c132; //navbar & font\n$grey-font: #e8e8e9;\n$disabled: #969696;\n$white-field: #fafafa;\n\n//green - dark theme\n$black-background: #202123;\n$grey-navbar: #242527;\n$green: #50fa7b;\n$grey-font: #e8e8e9;\n$disabled: #969696;\n$black-field: #1a1b1c;\n\n//blue - dark theme\n$black-background: #202123;\n$grey-navbar: #242527;\n$blue: #57b5f9;\n$grey-font: #e8e8e9;\n$disabled: #969696;\n$black-field: #1a1b1c;\n\n//misc - not used yet\n$black-container: #1d1e1f;\n$Yblack-background: #181e23;\n$Ygrey-navbar: #232b33;\n$Yblue-font: #a6e0db;\n"
  },
  {
    "path": "src/scss/common.scss",
    "content": "@import 'colours';\n\n//NOT AFFECTED BY THEME\n.home-button {\n  height: 70px;\n  width: 70px;\n  background-image: url(\"dog_vector.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-bottom: 20px;\n}\n\n.upload-proto-button-grey {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"upload_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 20px;\n  margin-left: 5px;\n}\n\n.upload-proto-button-light {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"upload_light.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 20px;\n  margin-left: 5px;\n}\n\n.settings-button-grey {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"settings_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 20px;\n  margin-left: 5px;\n}\n\n.settings-button-light {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"settings_light.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 20px;\n  margin-left: 5px;\n}\n\n.github-button {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"github_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 10px;\n}\n\n.twitter-button {\n  height: 50px;\n  width: 50px;\n  background-image: url(\"twitter_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-top: 12px;\n}\n\n.send-button {\n  height: 24px;\n  width: 24px;\n  background-image: url(\"sendreq_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-left: 15px;\n}\n\n.push-button {\n  height: 25px;\n  width: 25px;\n  background-image: url(\"adddata2_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-left: 5px;\n}\n\n.pause-button {\n  height: 24px;\n  width: 24px;\n  background-image: url(\"endstream_grey.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n  margin-left: 5px;\n}\n\n\n.modal {\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  // background: rgba(0, 0, 0, 0.6);\n  // background-color: '#fff';\n  // z-index: 99;\n  padding: 50;\n}\n\n.modal-main {\n  position: fixed;\n  background: $black-background;\n  width: 50%;\n  height: 90%;\n  top: 50%;\n  left: 50%;\n  transform: translate(0%, -40%);\n  color: $white-field;\n  overflow-x: auto;\n  z-index: 99;\n  padding: 30;\n  margin: 0 auto;\n  border-radius: 5;\n  max-width: 500;\n  min-height: 300;\n}\n\n.popup-on {\n  display: block;\n}\n\n.popup-off {\n  display: none;\n}\n\n//AFFECTED BY THEME\n.viewProto-button-dark-yellow:hover {\n  color: $yellow;\n}\n\n.viewProto-button-light-yellow:hover {\n  color: $yellow;\n}\n\n.viewProto-button-dark-green:hover {\n  color: $green;\n}\n\n.viewProto-button-dark-blue:hover {\n  color: $blue;\n}\n\n.button-dark-yellow {\n  height: 40px;\n  width: 40px;\n  background-image: url(\"theme-dark-yellow.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.button-light-yellow {\n  height: 40px;\n  width: 40px;\n  background-image: url(\"theme-light-yellow.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.button-dark-green {\n  height: 40px;\n  width: 40px;\n  background-image: url(\"theme-dark-green.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.button-dark-blue {\n  height: 40px;\n  width: 40px;\n  background-image: url(\"theme-dark-blue.svg\");\n  background-repeat: no-repeat;\n  background-color: Transparent;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.button {\n  background-color: Transparent;\n  background-repeat: no-repeat;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  color: $disabled;\n  font-family: 'Roboto Mono', monospace;\n  font-weight: 500;\n  font-size: 14px;\n  cursor: pointer;\n}\n\n//NEEDS TO BE BELOW OTHER BUTTON TYPES\n.header-button-dark-yellow {\n  color: $grey-font;\n  font-weight: 700;\n  font-size: 30px;\n  font-family: 'Poppins', sans-serif;\n  background-color: Transparent;\n  background-repeat: no-repeat;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.header-button-dark-yellow:hover {\n  color: $yellow;\n}\n\n.header-button-light-yellow {\n  color: $disabled;\n  font-weight: 700;\n  font-size: 30px;\n  font-family: 'Poppins', sans-serif;\n  background-color: Transparent;\n  background-repeat: no-repeat;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.header-button-light-yellow:hover {\n  color: $yellow;\n}\n\n.header-button-dark-green {\n  color: $grey-font;\n  font-weight: 700;\n  font-size: 30px;\n  font-family: 'Poppins', sans-serif;\n  background-color: Transparent;\n  background-repeat: no-repeat;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.header-button-dark-green:hover {\n  color: $green;\n}\n\n.header-button-dark-blue {\n  color: $grey-font;\n  font-weight: 700;\n  font-size: 30px;\n  font-family: 'Poppins', sans-serif;\n  background-color: Transparent;\n  background-repeat: no-repeat;\n  border: none;\n  overflow: hidden;\n  outline: none;\n  cursor: pointer;\n}\n\n.header-button-dark-blue:hover {\n  color: $blue;\n}\n"
  },
  {
    "path": "src/scss/index.scss",
    "content": "@import \"colours\";\n@import \"common\";\n@import \"input\";\n@import \"layout\";\n"
  },
  {
    "path": "src/scss/input.scss",
    "content": "@import \"colours\";\n\n.menu-options {\n  display: flex;\n  flex-direction: row;\n  justify-content: flex-start;\n}\n\n.url-input-dark-yellow {\n  background-color: $black-field;\n  color: $grey-font;\n}\n\n.url-input-light-yellow {\n  background-color: $white-field;\n  color: $grey-font;\n}\n\n.url-input-dark-green {\n  background-color: $black-field;\n  color: $grey-font;\n}\n\n.url-input-dark-blue {\n  background-color: $black-field;\n  color: $grey-font;\n}\n"
  },
  {
    "path": "src/scss/layout.scss",
    "content": "@import 'colours';\n\n//NOT AFFECTED BY THEME\n#app-container {\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n  height: 100%;\n  margin-left: 15px;\n}\n\n#menu-and-view-section {\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n}\n\n#footer {\n  font-size: 12px;\n  display: flex;\n  align-items: flex-end;\n}\n\n#header-container {\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n}\n\n#social-media {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n}\n\n//AFFECTED BY THEME\n//DEFAULT - DARK-YELLOW MODE\nhtml,\nbody,\n#root,\n#main-view-dark-yellow {\n  margin: 0;\n  height: 100%;\n  width: 100%;\n  background-color: $black-background;\n  color: $grey-font;\n  font-weight: 500;\n  font-size: 14px;\n  font-family: 'Roboto Mono', monospace;\n  display: flex;\n  flex-direction: row;\n}\n\n#navbar-dark-yellow {\n  background-color: $grey-navbar;\n  display: flex;\n  flex-direction: column;\n  width: 50px;\n  height: 100%;\n  padding: 15px;\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n}\n\n#testProto-dark-yellow {\n  color: $yellow;\n}\n\n//LIGHT-YELLOW MODE\n#main-view-light-yellow {\n  margin: 0;\n  height: 100%;\n  width: 100%;\n  background-color: $white-background;\n  color: $disabled;\n  font-weight: 500;\n  font-size: 14px;\n  font-family: 'Roboto Mono', monospace;\n  display: flex;\n  flex-direction: row;\n}\n\n#navbar-light-yellow {\n  background-color: $yellow;\n  display: flex;\n  flex-direction: column;\n  width: 50px;\n  height: 100%;\n  padding: 15px;\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n}\n\n#testProto-light-yellow {\n  color: $yellow;\n}\n\n//DARK-GREEN MODE\n#main-view-dark-green {\n  margin: 0;\n  height: 100%;\n  width: 100%;\n  background-color: $black-background;\n  color: $grey-font;\n  font-weight: 500;\n  font-size: 14px;\n  font-family: 'Roboto Mono', monospace;\n  display: flex;\n  flex-direction: row;\n}\n\n#navbar-dark-green {\n  background-color: $grey-navbar;\n  display: flex;\n  flex-direction: column;\n  width: 50px;\n  height: 100%;\n  padding: 15px;\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n}\n\n#testProto-dark-green {\n  color: $green;\n}\n\n//DARK-BLUE MODE\n#main-view-dark-blue {\n  margin: 0;\n  height: 100%;\n  width: 100%;\n  background-color: $black-background;\n  color: $grey-font;\n  font-weight: 500;\n  font-size: 14px;\n  font-family: 'Roboto Mono', monospace;\n  display: flex;\n  flex-direction: row;\n}\n\n#navbar-dark-blue {\n  background-color: $grey-navbar;\n  display: flex;\n  flex-direction: column;\n  width: 50px;\n  height: 100%;\n  padding: 15px;\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n}\n\n#testProto-dark-blue {\n  color: $blue;\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"exclude\": [\"node_modules\", \"**/*.spec.ts\", \"server\"],\n  \"compilerOptions\": {\n    \"outDir\": \"./dist/\",\n    \"noImplicitAny\": true,\n    \"target\": \"es5\",\n    \"lib\": [\"es5\", \"es6\", \"dom\"],\n    \"jsx\": \"react\",\n    \"allowJs\": true,\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"downlevelIteration\": true,\n    \"traceResolution\": true\n  }\n}\n"
  },
  {
    "path": "webpack.dev.ts",
    "content": "import * as webpack from \"webpack\";\nimport HtmlWebPackPlugin from \"html-webpack-plugin\";\nimport { CleanWebpackPlugin } from \"clean-webpack-plugin\";\n\nconst config = (env: any): webpack.Configuration => {\n  const API_PORT = env ? env.API_PORT : undefined;\n  const API_HOST = env ? env.API_HOST : undefined;\n  const API_PROTOCOL = env ? env.API_PROTOCOL : undefined;\n  const NODE_ENV = env ? env.NODE_ENV : \"development\";\n  return {\n    mode: \"development\",\n    entry: \"./src/index.tsx\",\n    output: {\n      filename: \"bundle.js\",\n      publicPath: \"/\"\n    },\n    resolve: {\n      extensions: [\".ts\", \".tsx\", \".jsx\", \".js\", \".json\", \".css\", \".scss\"]\n    },\n    devtool: \"source-map\",\n    module: {\n      rules: [\n        {\n          test: /\\.tsx?$/,\n          exclude: /node_modules/,\n          loader: \"awesome-typescript-loader\"\n        },\n        {\n          test: /\\.(s*)css$/i,\n          use: [\"style-loader\", \"css-loader\", \"sass-loader\"]\n        },\n        {\n          test: /\\.(png|svg|jpg|gif)$/,\n          use: [\n            {\n              loader: \"url-loader\",\n              options: {\n                limit: 8000,\n                name: \"./src/scss/[hash]-[name].[ext]\"\n              }\n            }\n          ]\n        }\n      ]\n    },\n    // @ts-ignore\n    devServer: {\n      port: 3000,\n      historyApiFallback: true,\n      open: false,\n      hot: true\n    },\n    plugins: [\n      new CleanWebpackPlugin(),\n\n      new HtmlWebPackPlugin({\n        template: \"./src/index.html\"\n      }),\n      new webpack.DefinePlugin({\n        \"env.API_PORT\": API_PORT\n          ? JSON.stringify(API_PORT)\n          : JSON.stringify(\"8000\"),\n        \"env.API_HOST\": API_HOST\n          ? JSON.stringify(API_HOST)\n          : JSON.stringify(\"localhost\"),\n        \"env.API_PROTOCOL\": API_PROTOCOL\n          ? JSON.stringify(API_PROTOCOL)\n          : JSON.stringify(\"http\"),\n        \"env.NODE_ENV\": NODE_ENV\n          ? JSON.stringify(NODE_ENV)\n          : JSON.stringify(\"development\")\n      }),\n      new webpack.HotModuleReplacementPlugin()\n    ]\n  };\n};\nexport default config;\n"
  },
  {
    "path": "webpack.prod.ts",
    "content": "import * as path from 'path';\nimport * as webpack from 'webpack';\nimport HtmlWebPackPlugin from 'html-webpack-plugin';\nimport {CleanWebpackPlugin} from 'clean-webpack-plugin';\n\n\n\nconst config = (env: any): webpack.Configuration => {\n  const API_PORT = env ? env.API_PORT : undefined;\n  const API_HOST = env ? env.API_HOST : undefined;\n  const API_PROTOCOL = env ? env.API_PROTOCOL : undefined;\n  return {\n    mode: 'production',\n    entry: './src/index.tsx',\n    output: {\n      path: path.resolve(__dirname, 'build'),\n      filename: 'bundle.js',\n      publicPath: '/'\n    },\n    resolve: {\n      extensions: ['.ts', '.tsx', '.jsx', '.js', '.json', '.css', '.scss']\n    },\n    module: {\n      rules: [\n        { test: /\\.tsx?$/, loader: 'awesome-typescript-loader' },\n        {\n          test: /\\.(js|jsx)$/,\n          exclude: /node_modules/,\n          use: {\n            loader: 'babel-loader'\n          }\n        },\n        {\n          test: /\\.(sc|c)ss$/i,\n          use: ['style-loader', 'css-loader', 'sass-loader']\n        },\n        {\n          test: /\\.(png|svg|jpg|gif)$/,\n          use: { loader: 'file-loader'}\n        },\n      ]\n    },\n    plugins: [\n      new CleanWebpackPlugin(),\n      new HtmlWebPackPlugin({\n        template: './src/index.html'\n      }),\n      new webpack.DefinePlugin({\n        'env.API_PORT': API_PORT\n          ? JSON.stringify(API_PORT)\n          : JSON.stringify('8000'),\n        'env.API_HOST': API_HOST\n          ? JSON.stringify(API_HOST)\n          : JSON.stringify('localhost'),\n        'env.API_PROTOCOL': API_PROTOCOL\n          ? JSON.stringify(API_PROTOCOL)\n          : JSON.stringify('http'),\n        'env.NODE_ENV': JSON.stringify('production')\n      })\n    ]\n  };\n};\nexport default config;\n"
  }
]