From 7505aded5f124fd49e493d495d809307fcbcb4ee Mon Sep 17 00:00:00 2001
From: Jan Zak <zj@zakjan.cz>
Date: Tue, 24 Nov 2020 12:18:26 +0100
Subject: [PATCH] Add build script for proto files

---
 backend/gateway/package-lock.json             | 262 +------
 backend/gateway/package.json                  |   4 +-
 .../src/generated/projector_grpc_pb.js        | 104 +++
 backend/gateway/src/generated/projector_pb.js | 653 ++++++++++++++++++
 backend/gateway/src/index.js                  |  34 +-
 frontend/package-lock.json                    | 236 +++----
 frontend/package.json                         |   4 +-
 frontend/src/generated/projector_pb.js        |  12 +-
 protos/README.md                              |  11 +
 protos/build.sh                               |  18 +
 {frontend/src => protos}/projector.proto      |   0
 11 files changed, 922 insertions(+), 416 deletions(-)
 create mode 100644 backend/gateway/src/generated/projector_grpc_pb.js
 create mode 100644 backend/gateway/src/generated/projector_pb.js
 create mode 100644 protos/README.md
 create mode 100755 protos/build.sh
 rename {frontend/src => protos}/projector.proto (100%)

diff --git a/backend/gateway/package-lock.json b/backend/gateway/package-lock.json
index c6bf089..d00c621 100644
--- a/backend/gateway/package-lock.json
+++ b/backend/gateway/package-lock.json
@@ -66,87 +66,20 @@
       }
     },
     "@grpc/grpc-js": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.5.tgz",
-      "integrity": "sha512-2huf5z85TdZI4nLmJQ9Zdfd+6vmIyBDs7B4L71bTaHKA9pRsGKAH24XaktMk/xneKJIqAgeIZtg1cyivVZtvrg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.1.tgz",
+      "integrity": "sha512-JpGh2CgqnwVII0S9TMEX3HY+PkLJnb7HSAar3Md1Y3aWxTZqAGb7gTrNyBWn/zueaGFsMYRm2u/oYufWFYVoIQ==",
       "requires": {
-        "@grpc/proto-loader": "^0.6.0-pre14",
         "@types/node": "^12.12.47",
-        "google-auth-library": "^6.0.0",
+        "google-auth-library": "^6.1.1",
         "semver": "^6.2.0"
       }
     },
-    "@grpc/proto-loader": {
-      "version": "0.6.0-pre9",
-      "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz",
-      "integrity": "sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww==",
-      "requires": {
-        "@types/long": "^4.0.1",
-        "lodash.camelcase": "^4.3.0",
-        "long": "^4.0.0",
-        "protobufjs": "^6.9.0",
-        "yargs": "^15.3.1"
-      }
-    },
     "@js-joda/core": {
       "version": "3.2.0",
       "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-3.2.0.tgz",
       "integrity": "sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg=="
     },
-    "@protobufjs/aspromise": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
-      "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
-    },
-    "@protobufjs/base64": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
-      "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
-    },
-    "@protobufjs/codegen": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
-      "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
-    },
-    "@protobufjs/eventemitter": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
-      "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
-    },
-    "@protobufjs/fetch": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
-      "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
-      "requires": {
-        "@protobufjs/aspromise": "^1.1.1",
-        "@protobufjs/inquire": "^1.1.0"
-      }
-    },
-    "@protobufjs/float": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
-      "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
-    },
-    "@protobufjs/inquire": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
-      "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
-    },
-    "@protobufjs/path": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
-      "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
-    },
-    "@protobufjs/pool": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
-      "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
-    },
-    "@protobufjs/utf8": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
-      "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
-    },
     "@sindresorhus/is": {
       "version": "0.14.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
@@ -174,7 +107,8 @@
     "@types/color-name": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
-      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
     },
     "@types/long": {
       "version": "4.0.1",
@@ -329,12 +263,14 @@
     "ansi-regex": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+      "dev": true
     },
     "ansi-styles": {
       "version": "4.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
       "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+      "dev": true,
       "requires": {
         "@types/color-name": "^1.1.1",
         "color-convert": "^2.0.1"
@@ -425,9 +361,9 @@
       "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
     },
     "base64-js": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
-      "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
     },
     "bcrypt-pbkdf": {
       "version": "1.0.2",
@@ -557,7 +493,8 @@
     "camelcase": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "dev": true
     },
     "caseless": {
       "version": "0.12.0",
@@ -624,16 +561,6 @@
       "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
       "dev": true
     },
-    "cliui": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
-      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
-      "requires": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.0",
-        "wrap-ansi": "^6.2.0"
-      }
-    },
     "clone-response": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
@@ -652,6 +579,7 @@
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
       "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
       "requires": {
         "color-name": "~1.1.4"
       }
@@ -659,7 +587,8 @@
     "color-name": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
     },
     "colour": {
       "version": "0.7.1",
@@ -815,7 +744,8 @@
     "emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
     },
     "end-of-stream": {
       "version": "1.4.4",
@@ -871,15 +801,6 @@
         "to-regex-range": "^5.0.1"
       }
     },
-    "find-up": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-      "requires": {
-        "locate-path": "^5.0.0",
-        "path-exists": "^4.0.0"
-      }
-    },
     "follow-redirects": {
       "version": "1.13.0",
       "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
@@ -989,11 +910,6 @@
         "json-bigint": "^1.0.0"
       }
     },
-    "get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
-    },
     "get-stream": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
@@ -1067,9 +983,9 @@
       }
     },
     "google-protobuf": {
-      "version": "3.13.0",
-      "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.13.0.tgz",
-      "integrity": "sha512-ZIf3qfLFayVrPvAjeKKxO5FRF1/NwRxt6Dko+fWEMuHwHbZx8/fcaAao9b0wCM6kr8qeg2te8XTpyuvKuD9aKw=="
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.14.0.tgz",
+      "integrity": "sha512-bwa8dBuMpOxg7COyqkW6muQuvNnWgVN8TX/epDRGW5m0jcrmq2QJyCyiV8ZE2/6LaIIqJtiv9bYokFhfpy/o6w=="
     },
     "got": {
       "version": "9.6.0",
@@ -1202,9 +1118,9 @@
       "integrity": "sha512-ibBaJPzfMVuLPgaST9w0kZl60s+SnkPBQp6QKdpEr85tpc1gXW2QDqSne9xiyiym0logDfdUSm4aX5h9YBA2mw=="
     },
     "gtoken": {
-      "version": "5.0.5",
-      "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.5.tgz",
-      "integrity": "sha512-wvjkecutFh8kVfbcdBdUWqDRrXb+WrgD79DBDEYf1Om8S1FluhylhtFjrL7Tx69vNhh259qA3Q1P4sPtb+kUYw==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.1.0.tgz",
+      "integrity": "sha512-4d8N6Lk8TEAHl9vVoRVMh9BNOKWVgl2DdNtr3428O75r3QFrF/a5MMu851VmK0AA8+iSvbwRv69k5XnMLURGhg==",
       "requires": {
         "gaxios": "^4.0.0",
         "google-p12-pem": "^3.0.3",
@@ -1353,7 +1269,8 @@
     "is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
     },
     "is-glob": {
       "version": "4.0.1",
@@ -1519,14 +1436,6 @@
         "invert-kv": "^1.0.0"
       }
     },
-    "locate-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-      "requires": {
-        "p-locate": "^4.1.0"
-      }
-    },
     "lodash": {
       "version": "4.17.20",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
@@ -1542,11 +1451,6 @@
       "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz",
       "integrity": "sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y="
     },
-    "long": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
-      "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
-    },
     "lowercase-keys": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
@@ -1925,27 +1829,6 @@
       "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
       "dev": true
     },
-    "p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-      "requires": {
-        "p-try": "^2.0.0"
-      }
-    },
-    "p-locate": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-      "requires": {
-        "p-limit": "^2.2.0"
-      }
-    },
-    "p-try": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
-    },
     "package-json": {
       "version": "6.5.0",
       "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz",
@@ -1958,11 +1841,6 @@
         "semver": "^6.2.0"
       }
     },
-    "path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
-    },
     "path-is-absolute": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -1990,33 +1868,6 @@
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
       "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
     },
-    "protobufjs": {
-      "version": "6.10.1",
-      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz",
-      "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==",
-      "requires": {
-        "@protobufjs/aspromise": "^1.1.2",
-        "@protobufjs/base64": "^1.1.2",
-        "@protobufjs/codegen": "^2.0.4",
-        "@protobufjs/eventemitter": "^1.1.0",
-        "@protobufjs/fetch": "^1.1.0",
-        "@protobufjs/float": "^1.0.2",
-        "@protobufjs/inquire": "^1.1.0",
-        "@protobufjs/path": "^1.1.2",
-        "@protobufjs/pool": "^1.1.0",
-        "@protobufjs/utf8": "^1.1.0",
-        "@types/long": "^4.0.1",
-        "@types/node": "^13.7.0",
-        "long": "^4.0.0"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "13.13.15",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.15.tgz",
-          "integrity": "sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw=="
-        }
-      }
-    },
     "psl": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
@@ -2155,16 +2006,6 @@
         }
       }
     },
-    "require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
-    },
-    "require-main-filename": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
-    },
     "responselike": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
@@ -2256,6 +2097,7 @@
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
       "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+      "dev": true,
       "requires": {
         "emoji-regex": "^8.0.0",
         "is-fullwidth-code-point": "^3.0.0",
@@ -2281,6 +2123,7 @@
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
       "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+      "dev": true,
       "requires": {
         "ansi-regex": "^5.0.0"
       }
@@ -2548,11 +2391,6 @@
         "extsprintf": "^1.2.0"
       }
     },
-    "which-module": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
-    },
     "wide-align": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -2604,16 +2442,6 @@
       "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz",
       "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY="
     },
-    "wrap-ansi": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
-      "requires": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      }
-    },
     "wrappy": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -2661,42 +2489,10 @@
       "resolved": "https://registry.npmjs.org/xpath.js/-/xpath.js-1.1.0.tgz",
       "integrity": "sha512-jg+qkfS4K8E7965sqaUl8mRngXiKb3WZGfONgE18pr03FUQiuSV6G+Ej4tS55B+rIQSFEIw3phdVAQ4pPqNWfQ=="
     },
-    "y18n": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
-    },
     "yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
       "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
-    },
-    "yargs": {
-      "version": "15.4.1",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
-      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
-      "requires": {
-        "cliui": "^6.0.0",
-        "decamelize": "^1.2.0",
-        "find-up": "^4.1.0",
-        "get-caller-file": "^2.0.1",
-        "require-directory": "^2.1.1",
-        "require-main-filename": "^2.0.0",
-        "set-blocking": "^2.0.0",
-        "string-width": "^4.2.0",
-        "which-module": "^2.0.0",
-        "y18n": "^4.0.0",
-        "yargs-parser": "^18.1.2"
-      }
-    },
-    "yargs-parser": {
-      "version": "18.1.3",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
-      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
-      "requires": {
-        "camelcase": "^5.0.0",
-        "decamelize": "^1.2.0"
-      }
     }
   }
 }
diff --git a/backend/gateway/package.json b/backend/gateway/package.json
index 0990cdc..9d9440f 100644
--- a/backend/gateway/package.json
+++ b/backend/gateway/package.json
@@ -9,11 +9,11 @@
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "dependencies": {
-    "@grpc/grpc-js": "^1.1.5",
+    "@grpc/grpc-js": "^1.2.1",
     "async": "3.2.0",
     "axios": "^0.20.0",
     "core-js": "^3.6.5",
-    "google-protobuf": "^3.6.1",
+    "google-protobuf": "^3.14.0",
     "grpc": "^1.24.3",
     "grpc-web": "^1.0.0",
     "lodash": "4.17.20",
diff --git a/backend/gateway/src/generated/projector_grpc_pb.js b/backend/gateway/src/generated/projector_grpc_pb.js
new file mode 100644
index 0000000..67f4fa1
--- /dev/null
+++ b/backend/gateway/src/generated/projector_grpc_pb.js
@@ -0,0 +1,104 @@
+// GENERATED CODE -- DO NOT EDIT!
+
+'use strict';
+var grpc = require('@grpc/grpc-js');
+var projector_pb = require('./projector_pb.js');
+var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js');
+
+function serialize_google_protobuf_Empty(arg) {
+  if (!(arg instanceof google_protobuf_empty_pb.Empty)) {
+    throw new Error('Expected argument of type google.protobuf.Empty');
+  }
+  return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_google_protobuf_Empty(buffer_arg) {
+  return google_protobuf_empty_pb.Empty.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_provee_Point(arg) {
+  if (!(arg instanceof projector_pb.Point)) {
+    throw new Error('Expected argument of type provee.Point');
+  }
+  return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_provee_Point(buffer_arg) {
+  return projector_pb.Point.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+function serialize_provee_TrainingSet(arg) {
+  if (!(arg instanceof projector_pb.TrainingSet)) {
+    throw new Error('Expected argument of type provee.TrainingSet');
+  }
+  return Buffer.from(arg.serializeBinary());
+}
+
+function deserialize_provee_TrainingSet(buffer_arg) {
+  return projector_pb.TrainingSet.deserializeBinary(new Uint8Array(buffer_arg));
+}
+
+
+// Interface exported by the server.
+var ProjectorService = exports.ProjectorService = {
+  // A simple RPC.
+//
+// Start the Projector calculation
+start: {
+    path: '/provee.Projector/start',
+    requestStream: false,
+    responseStream: false,
+    requestType: google_protobuf_empty_pb.Empty,
+    responseType: google_protobuf_empty_pb.Empty,
+    requestSerialize: serialize_google_protobuf_Empty,
+    requestDeserialize: deserialize_google_protobuf_Empty,
+    responseSerialize: serialize_google_protobuf_Empty,
+    responseDeserialize: deserialize_google_protobuf_Empty,
+  },
+  // Stop the Projector calculation
+stop: {
+    path: '/provee.Projector/stop',
+    requestStream: false,
+    responseStream: false,
+    requestType: google_protobuf_empty_pb.Empty,
+    responseType: google_protobuf_empty_pb.Empty,
+    requestSerialize: serialize_google_protobuf_Empty,
+    requestDeserialize: deserialize_google_protobuf_Empty,
+    responseSerialize: serialize_google_protobuf_Empty,
+    responseDeserialize: deserialize_google_protobuf_Empty,
+  },
+  // A server-to-client streaming RPC.
+//
+// Obtains the Projection Points in 2D given the trainings values stored in a row format.  Results are
+// streamed rather than returned at once (e.g. in a response message with a
+// repeated field).
+getProjectionPoints: {
+    path: '/provee.Projector/getProjectionPoints',
+    requestStream: false,
+    responseStream: true,
+    requestType: projector_pb.TrainingSet,
+    responseType: projector_pb.Point,
+    requestSerialize: serialize_provee_TrainingSet,
+    requestDeserialize: deserialize_provee_TrainingSet,
+    responseSerialize: serialize_provee_Point,
+    responseDeserialize: deserialize_provee_Point,
+  },
+  // A server-to-client streaming RPC.
+//
+// Obtains the Projection Points in 2D given the trainings values stored in a row format.  Results are
+// streamed rather than returned at once (e.g. in a response message with a
+// repeated field).
+getUpdates: {
+    path: '/provee.Projector/getUpdates',
+    requestStream: false,
+    responseStream: true,
+    requestType: google_protobuf_empty_pb.Empty,
+    responseType: projector_pb.Point,
+    requestSerialize: serialize_google_protobuf_Empty,
+    requestDeserialize: deserialize_google_protobuf_Empty,
+    responseSerialize: serialize_provee_Point,
+    responseDeserialize: deserialize_provee_Point,
+  },
+};
+
+exports.ProjectorClient = grpc.makeGenericClientConstructor(ProjectorService);
diff --git a/backend/gateway/src/generated/projector_pb.js b/backend/gateway/src/generated/projector_pb.js
new file mode 100644
index 0000000..e88b0f4
--- /dev/null
+++ b/backend/gateway/src/generated/projector_pb.js
@@ -0,0 +1,653 @@
+// source: projector.proto
+/**
+ * @fileoverview
+ * @enhanceable
+ * @suppress {messageConventions} JS Compiler reports an error if a variable or
+ *     field starts with 'MSG_' and isn't a translatable message.
+ * @public
+ */
+// GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
+
+var jspb = require('google-protobuf');
+var goog = jspb;
+var global = Function('return this')();
+
+var google_protobuf_empty_pb = require('google-protobuf/google/protobuf/empty_pb.js');
+goog.object.extend(proto, google_protobuf_empty_pb);
+goog.exportSymbol('proto.provee.Point', null, global);
+goog.exportSymbol('proto.provee.TrainingSet', null, global);
+goog.exportSymbol('proto.provee.TrainingSetRow', null, global);
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.provee.Point = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, null, null);
+};
+goog.inherits(proto.provee.Point, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.provee.Point.displayName = 'proto.provee.Point';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.provee.TrainingSet = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.provee.TrainingSet.repeatedFields_, null);
+};
+goog.inherits(proto.provee.TrainingSet, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.provee.TrainingSet.displayName = 'proto.provee.TrainingSet';
+}
+/**
+ * Generated by JsPbCodeGenerator.
+ * @param {Array=} opt_data Optional initial data array, typically from a
+ * server response, or constructed directly in Javascript. The array is used
+ * in place and becomes part of the constructed object. It is not cloned.
+ * If no data is provided, the constructed object will be empty, but still
+ * valid.
+ * @extends {jspb.Message}
+ * @constructor
+ */
+proto.provee.TrainingSetRow = function(opt_data) {
+  jspb.Message.initialize(this, opt_data, 0, -1, proto.provee.TrainingSetRow.repeatedFields_, null);
+};
+goog.inherits(proto.provee.TrainingSetRow, jspb.Message);
+if (goog.DEBUG && !COMPILED) {
+  /**
+   * @public
+   * @override
+   */
+  proto.provee.TrainingSetRow.displayName = 'proto.provee.TrainingSetRow';
+}
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.provee.Point.prototype.toObject = function(opt_includeInstance) {
+  return proto.provee.Point.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.provee.Point} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.Point.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    id: jspb.Message.getFieldWithDefault(msg, 1, 0),
+    x: jspb.Message.getFieldWithDefault(msg, 2, 0),
+    y: jspb.Message.getFieldWithDefault(msg, 3, 0)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.provee.Point}
+ */
+proto.provee.Point.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.provee.Point;
+  return proto.provee.Point.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.provee.Point} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.provee.Point}
+ */
+proto.provee.Point.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setId(value);
+      break;
+    case 2:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setX(value);
+      break;
+    case 3:
+      var value = /** @type {number} */ (reader.readInt32());
+      msg.setY(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.provee.Point.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.provee.Point.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.provee.Point} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.Point.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getId();
+  if (f !== 0) {
+    writer.writeInt32(
+      1,
+      f
+    );
+  }
+  f = message.getX();
+  if (f !== 0) {
+    writer.writeInt32(
+      2,
+      f
+    );
+  }
+  f = message.getY();
+  if (f !== 0) {
+    writer.writeInt32(
+      3,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional int32 id = 1;
+ * @return {number}
+ */
+proto.provee.Point.prototype.getId = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 1, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.provee.Point} returns this
+ */
+proto.provee.Point.prototype.setId = function(value) {
+  return jspb.Message.setProto3IntField(this, 1, value);
+};
+
+
+/**
+ * optional int32 x = 2;
+ * @return {number}
+ */
+proto.provee.Point.prototype.getX = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 2, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.provee.Point} returns this
+ */
+proto.provee.Point.prototype.setX = function(value) {
+  return jspb.Message.setProto3IntField(this, 2, value);
+};
+
+
+/**
+ * optional int32 y = 3;
+ * @return {number}
+ */
+proto.provee.Point.prototype.getY = function() {
+  return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 3, 0));
+};
+
+
+/**
+ * @param {number} value
+ * @return {!proto.provee.Point} returns this
+ */
+proto.provee.Point.prototype.setY = function(value) {
+  return jspb.Message.setProto3IntField(this, 3, value);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.provee.TrainingSet.repeatedFields_ = [2];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.provee.TrainingSet.prototype.toObject = function(opt_includeInstance) {
+  return proto.provee.TrainingSet.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.provee.TrainingSet} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.TrainingSet.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    modelid: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    rowsList: jspb.Message.toObjectList(msg.getRowsList(),
+    proto.provee.TrainingSetRow.toObject, includeInstance)
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.provee.TrainingSet}
+ */
+proto.provee.TrainingSet.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.provee.TrainingSet;
+  return proto.provee.TrainingSet.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.provee.TrainingSet} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.provee.TrainingSet}
+ */
+proto.provee.TrainingSet.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setModelid(value);
+      break;
+    case 2:
+      var value = new proto.provee.TrainingSetRow;
+      reader.readMessage(value,proto.provee.TrainingSetRow.deserializeBinaryFromReader);
+      msg.addRows(value);
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.provee.TrainingSet.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.provee.TrainingSet.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.provee.TrainingSet} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.TrainingSet.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getModelid();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getRowsList();
+  if (f.length > 0) {
+    writer.writeRepeatedMessage(
+      2,
+      f,
+      proto.provee.TrainingSetRow.serializeBinaryToWriter
+    );
+  }
+};
+
+
+/**
+ * optional string modelid = 1;
+ * @return {string}
+ */
+proto.provee.TrainingSet.prototype.getModelid = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.provee.TrainingSet} returns this
+ */
+proto.provee.TrainingSet.prototype.setModelid = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+/**
+ * repeated TrainingSetRow rows = 2;
+ * @return {!Array<!proto.provee.TrainingSetRow>}
+ */
+proto.provee.TrainingSet.prototype.getRowsList = function() {
+  return /** @type{!Array<!proto.provee.TrainingSetRow>} */ (
+    jspb.Message.getRepeatedWrapperField(this, proto.provee.TrainingSetRow, 2));
+};
+
+
+/**
+ * @param {!Array<!proto.provee.TrainingSetRow>} value
+ * @return {!proto.provee.TrainingSet} returns this
+*/
+proto.provee.TrainingSet.prototype.setRowsList = function(value) {
+  return jspb.Message.setRepeatedWrapperField(this, 2, value);
+};
+
+
+/**
+ * @param {!proto.provee.TrainingSetRow=} opt_value
+ * @param {number=} opt_index
+ * @return {!proto.provee.TrainingSetRow}
+ */
+proto.provee.TrainingSet.prototype.addRows = function(opt_value, opt_index) {
+  return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.provee.TrainingSetRow, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.provee.TrainingSet} returns this
+ */
+proto.provee.TrainingSet.prototype.clearRowsList = function() {
+  return this.setRowsList([]);
+};
+
+
+
+/**
+ * List of repeated fields within this message type.
+ * @private {!Array<number>}
+ * @const
+ */
+proto.provee.TrainingSetRow.repeatedFields_ = [2];
+
+
+
+if (jspb.Message.GENERATE_TO_OBJECT) {
+/**
+ * Creates an object representation of this proto.
+ * Field names that are reserved in JavaScript and will be renamed to pb_name.
+ * Optional fields that are not set will be set to undefined.
+ * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
+ * For the list of reserved names please see:
+ *     net/proto2/compiler/js/internal/generator.cc#kKeyword.
+ * @param {boolean=} opt_includeInstance Deprecated. whether to include the
+ *     JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @return {!Object}
+ */
+proto.provee.TrainingSetRow.prototype.toObject = function(opt_includeInstance) {
+  return proto.provee.TrainingSetRow.toObject(opt_includeInstance, this);
+};
+
+
+/**
+ * Static version of the {@see toObject} method.
+ * @param {boolean|undefined} includeInstance Deprecated. Whether to include
+ *     the JSPB instance for transitional soy proto support:
+ *     http://goto/soy-param-migration
+ * @param {!proto.provee.TrainingSetRow} msg The msg instance to transform.
+ * @return {!Object}
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.TrainingSetRow.toObject = function(includeInstance, msg) {
+  var f, obj = {
+    id: jspb.Message.getFieldWithDefault(msg, 1, ""),
+    hdvectorList: (f = jspb.Message.getRepeatedFloatingPointField(msg, 2)) == null ? undefined : f
+  };
+
+  if (includeInstance) {
+    obj.$jspbMessageInstance = msg;
+  }
+  return obj;
+};
+}
+
+
+/**
+ * Deserializes binary data (in protobuf wire format).
+ * @param {jspb.ByteSource} bytes The bytes to deserialize.
+ * @return {!proto.provee.TrainingSetRow}
+ */
+proto.provee.TrainingSetRow.deserializeBinary = function(bytes) {
+  var reader = new jspb.BinaryReader(bytes);
+  var msg = new proto.provee.TrainingSetRow;
+  return proto.provee.TrainingSetRow.deserializeBinaryFromReader(msg, reader);
+};
+
+
+/**
+ * Deserializes binary data (in protobuf wire format) from the
+ * given reader into the given message object.
+ * @param {!proto.provee.TrainingSetRow} msg The message object to deserialize into.
+ * @param {!jspb.BinaryReader} reader The BinaryReader to use.
+ * @return {!proto.provee.TrainingSetRow}
+ */
+proto.provee.TrainingSetRow.deserializeBinaryFromReader = function(msg, reader) {
+  while (reader.nextField()) {
+    if (reader.isEndGroup()) {
+      break;
+    }
+    var field = reader.getFieldNumber();
+    switch (field) {
+    case 1:
+      var value = /** @type {string} */ (reader.readString());
+      msg.setId(value);
+      break;
+    case 2:
+      var values = /** @type {!Array<number>} */ (reader.isDelimited() ? reader.readPackedDouble() : [reader.readDouble()]);
+      for (var i = 0; i < values.length; i++) {
+        msg.addHdvector(values[i]);
+      }
+      break;
+    default:
+      reader.skipField();
+      break;
+    }
+  }
+  return msg;
+};
+
+
+/**
+ * Serializes the message to binary data (in protobuf wire format).
+ * @return {!Uint8Array}
+ */
+proto.provee.TrainingSetRow.prototype.serializeBinary = function() {
+  var writer = new jspb.BinaryWriter();
+  proto.provee.TrainingSetRow.serializeBinaryToWriter(this, writer);
+  return writer.getResultBuffer();
+};
+
+
+/**
+ * Serializes the given message to binary data (in protobuf wire
+ * format), writing to the given BinaryWriter.
+ * @param {!proto.provee.TrainingSetRow} message
+ * @param {!jspb.BinaryWriter} writer
+ * @suppress {unusedLocalVariables} f is only used for nested messages
+ */
+proto.provee.TrainingSetRow.serializeBinaryToWriter = function(message, writer) {
+  var f = undefined;
+  f = message.getId();
+  if (f.length > 0) {
+    writer.writeString(
+      1,
+      f
+    );
+  }
+  f = message.getHdvectorList();
+  if (f.length > 0) {
+    writer.writePackedDouble(
+      2,
+      f
+    );
+  }
+};
+
+
+/**
+ * optional string id = 1;
+ * @return {string}
+ */
+proto.provee.TrainingSetRow.prototype.getId = function() {
+  return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, ""));
+};
+
+
+/**
+ * @param {string} value
+ * @return {!proto.provee.TrainingSetRow} returns this
+ */
+proto.provee.TrainingSetRow.prototype.setId = function(value) {
+  return jspb.Message.setProto3StringField(this, 1, value);
+};
+
+
+/**
+ * repeated double hdvector = 2;
+ * @return {!Array<number>}
+ */
+proto.provee.TrainingSetRow.prototype.getHdvectorList = function() {
+  return /** @type {!Array<number>} */ (jspb.Message.getRepeatedFloatingPointField(this, 2));
+};
+
+
+/**
+ * @param {!Array<number>} value
+ * @return {!proto.provee.TrainingSetRow} returns this
+ */
+proto.provee.TrainingSetRow.prototype.setHdvectorList = function(value) {
+  return jspb.Message.setField(this, 2, value || []);
+};
+
+
+/**
+ * @param {number} value
+ * @param {number=} opt_index
+ * @return {!proto.provee.TrainingSetRow} returns this
+ */
+proto.provee.TrainingSetRow.prototype.addHdvector = function(value, opt_index) {
+  return jspb.Message.addToRepeatedField(this, 2, value, opt_index);
+};
+
+
+/**
+ * Clears the list making it empty but non-null.
+ * @return {!proto.provee.TrainingSetRow} returns this
+ */
+proto.provee.TrainingSetRow.prototype.clearHdvectorList = function() {
+  return this.setHdvectorList([]);
+};
+
+
+goog.object.extend(exports, proto.provee);
diff --git a/backend/gateway/src/index.js b/backend/gateway/src/index.js
index 4b5302a..1d19e35 100644
--- a/backend/gateway/src/index.js
+++ b/backend/gateway/src/index.js
@@ -1,31 +1,15 @@
-//SETUP
-var PROTO_PATH = __dirname + '/../protos/v3/projector.proto';
-var assert = require('assert');
-var async = require('async');
+const assert = require('assert');
 const axios = require('axios');
-var _ = require('lodash');
-var grpc = require('@grpc/grpc-js');
-var protoLoader = require('@grpc/proto-loader');
-const http = require("http");
+const grpc = require('@grpc/grpc-js');
+const http = require('http');
 
+const { ProjectorService } = require('./generated/projector_grpc_pb');
+const { Point } = require('./generated/projector_pb');
 const database = require('./database');
-const { callErrorFromStatus } = require('@grpc/grpc-js/build/src/call');
-//let connection = mysql.createConnection(config);
 
 const port = process.env.PORT || 9090;
 const projectorUrl = process.env.PROJECTOR_URL || 'http://localhost:8090';
 
-var packageDefinition = protoLoader.loadSync(
-    PROTO_PATH,
-    {keepCase: true,
-     longs: String,
-     enums: String,
-     defaults: true,
-     oneofs: true
-    });
-var protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
-var projectorPackage = protoDescriptor.provee;
-
 //OLD
 function sendPoint(call, callback) {
   axios.get(`${projectorUrl}/generatePoint`).then(resp=>{
@@ -85,7 +69,11 @@ function sendDataStream(data,call){
   for(var i =0; i <list.length;i++){
     try {
       var response = JSON.parse(list[i]);
-      call.write(response["point"]);
+      var point = new Point();
+      point.setId(response["point"]["id"]);
+      point.setX(response["point"]["x"]);
+      point.setY(response["point"]["y"]);
+      call.write(point);
     } catch (e) {}
   }
 }
@@ -94,7 +82,7 @@ function sendDataStream(data,call){
 function getServer() {
 
   var server = new grpc.Server();
-  server.addService(projectorPackage.Projector.service, {
+  server.addService(ProjectorService, {
     getProjectionPoints: sendPointStream,
   });
   console.log("started");
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index cd12bf2..da04ae0 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1077,20 +1077,19 @@
       }
     },
     "@grpc/grpc-js": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.1.5.tgz",
-      "integrity": "sha512-2huf5z85TdZI4nLmJQ9Zdfd+6vmIyBDs7B4L71bTaHKA9pRsGKAH24XaktMk/xneKJIqAgeIZtg1cyivVZtvrg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.1.tgz",
+      "integrity": "sha512-JpGh2CgqnwVII0S9TMEX3HY+PkLJnb7HSAar3Md1Y3aWxTZqAGb7gTrNyBWn/zueaGFsMYRm2u/oYufWFYVoIQ==",
       "requires": {
-        "@grpc/proto-loader": "^0.6.0-pre14",
         "@types/node": "^12.12.47",
-        "google-auth-library": "^6.0.0",
+        "google-auth-library": "^6.1.1",
         "semver": "^6.2.0"
       },
       "dependencies": {
         "@types/node": {
-          "version": "12.12.54",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.54.tgz",
-          "integrity": "sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w=="
+          "version": "12.19.6",
+          "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.6.tgz",
+          "integrity": "sha512-U2VopDdmBoYBmtm8Rz340mvvSz34VgX/K9+XCuckvcLGMkt3rbMX8soqFOikIPlPBc5lmw8By9NUK7bEFSBFlQ=="
         },
         "semver": {
           "version": "6.3.0",
@@ -1099,50 +1098,6 @@
         }
       }
     },
-    "@grpc/proto-loader": {
-      "version": "0.6.0-pre9",
-      "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz",
-      "integrity": "sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww==",
-      "requires": {
-        "@types/long": "^4.0.1",
-        "lodash.camelcase": "^4.3.0",
-        "long": "^4.0.0",
-        "protobufjs": "^6.9.0",
-        "yargs": "^15.3.1"
-      },
-      "dependencies": {
-        "@types/node": {
-          "version": "13.13.15",
-          "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.15.tgz",
-          "integrity": "sha512-kwbcs0jySLxzLsa2nWUAGOd/s21WU1jebrEdtzhsj1D4Yps1EOuyI1Qcu+FD56dL7NRNIJtDDjcqIG22NwkgLw=="
-        },
-        "long": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
-          "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
-        },
-        "protobufjs": {
-          "version": "6.10.1",
-          "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz",
-          "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==",
-          "requires": {
-            "@protobufjs/aspromise": "^1.1.2",
-            "@protobufjs/base64": "^1.1.2",
-            "@protobufjs/codegen": "^2.0.4",
-            "@protobufjs/eventemitter": "^1.1.0",
-            "@protobufjs/fetch": "^1.1.0",
-            "@protobufjs/float": "^1.0.2",
-            "@protobufjs/inquire": "^1.1.0",
-            "@protobufjs/path": "^1.1.2",
-            "@protobufjs/pool": "^1.1.0",
-            "@protobufjs/utf8": "^1.1.0",
-            "@types/long": "^4.0.1",
-            "@types/node": "^13.7.0",
-            "long": "^4.0.0"
-          }
-        }
-      }
-    },
     "@hapi/address": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -1209,60 +1164,6 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
-    "@protobufjs/aspromise": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
-      "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
-    },
-    "@protobufjs/base64": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
-      "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
-    },
-    "@protobufjs/codegen": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
-      "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
-    },
-    "@protobufjs/eventemitter": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
-      "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
-    },
-    "@protobufjs/fetch": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
-      "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
-      "requires": {
-        "@protobufjs/aspromise": "^1.1.1",
-        "@protobufjs/inquire": "^1.1.0"
-      }
-    },
-    "@protobufjs/float": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
-      "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
-    },
-    "@protobufjs/inquire": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
-      "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
-    },
-    "@protobufjs/path": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
-      "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
-    },
-    "@protobufjs/pool": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
-      "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
-    },
-    "@protobufjs/utf8": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
-      "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
-    },
     "@sindresorhus/is": {
       "version": "0.7.0",
       "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
@@ -1388,7 +1289,8 @@
     "@types/color-name": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
-      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==",
+      "dev": true
     },
     "@types/connect": {
       "version": "3.4.33",
@@ -2324,9 +2226,9 @@
       "dev": true
     },
     "agent-base": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz",
-      "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==",
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
       "requires": {
         "debug": "4"
       }
@@ -2796,9 +2698,9 @@
       "dev": true
     },
     "bignumber.js": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
-      "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A=="
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
+      "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA=="
     },
     "binary-extensions": {
       "version": "2.1.0",
@@ -3636,6 +3538,7 @@
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
       "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dev": true,
       "requires": {
         "string-width": "^4.2.0",
         "strip-ansi": "^6.0.0",
@@ -5177,7 +5080,8 @@
     "emoji-regex": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
     },
     "emojis-list": {
       "version": "3.0.0",
@@ -6193,9 +6097,9 @@
       }
     },
     "gaxios": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.1.0.tgz",
-      "integrity": "sha512-DDTn3KXVJJigtz+g0J3vhcfbDbKtAroSTxauWsdnP57sM5KZ3d2c/3D9RKFJ86s43hfw6WULg6TXYw/AYiBlpA==",
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.0.1.tgz",
+      "integrity": "sha512-jOin8xRZ/UytQeBpSXFqIzqU7Fi5TqgPNLlUsSB8kjJ76+FiGBfImF8KJu++c6J4jOldfJUtt0YmkRj2ZpSHTQ==",
       "requires": {
         "abort-controller": "^3.0.0",
         "extend": "^3.0.2",
@@ -6212,11 +6116,11 @@
       }
     },
     "gcp-metadata": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.1.4.tgz",
-      "integrity": "sha512-5J/GIH0yWt/56R3dNaNWPGQ/zXsZOddYECfJaqxFWgrZ9HC2Kvc5vl9upOgUUHKzURjAVf2N+f6tEJiojqXUuA==",
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz",
+      "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==",
       "requires": {
-        "gaxios": "^3.0.0",
+        "gaxios": "^4.0.0",
         "json-bigint": "^1.0.0"
       }
     },
@@ -6229,7 +6133,8 @@
     "get-caller-file": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true
     },
     "get-stream": {
       "version": "4.1.0",
@@ -6306,17 +6211,17 @@
       }
     },
     "google-auth-library": {
-      "version": "6.0.6",
-      "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.0.6.tgz",
-      "integrity": "sha512-fWYdRdg55HSJoRq9k568jJA1lrhg9i2xgfhVIMJbskUmbDpJGHsbv9l41DGhCDXM21F9Kn4kUwdysgxSYBYJUw==",
+      "version": "6.1.3",
+      "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.3.tgz",
+      "integrity": "sha512-m9mwvY3GWbr7ZYEbl61isWmk+fvTmOt0YNUfPOUY2VH8K5pZlAIWJjxEi0PqR3OjMretyiQLI6GURMrPSwHQ2g==",
       "requires": {
         "arrify": "^2.0.0",
         "base64-js": "^1.3.0",
         "ecdsa-sig-formatter": "^1.0.11",
         "fast-text-encoding": "^1.0.0",
-        "gaxios": "^3.0.0",
-        "gcp-metadata": "^4.1.0",
-        "gtoken": "^5.0.0",
+        "gaxios": "^4.0.0",
+        "gcp-metadata": "^4.2.0",
+        "gtoken": "^5.0.4",
         "jws": "^4.0.0",
         "lru-cache": "^6.0.0"
       },
@@ -6337,17 +6242,24 @@
       }
     },
     "google-p12-pem": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz",
-      "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz",
+      "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==",
       "requires": {
-        "node-forge": "^0.9.0"
+        "node-forge": "^0.10.0"
+      },
+      "dependencies": {
+        "node-forge": {
+          "version": "0.10.0",
+          "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
+          "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
+        }
       }
     },
     "google-protobuf": {
-      "version": "3.13.0",
-      "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.13.0.tgz",
-      "integrity": "sha512-ZIf3qfLFayVrPvAjeKKxO5FRF1/NwRxt6Dko+fWEMuHwHbZx8/fcaAao9b0wCM6kr8qeg2te8XTpyuvKuD9aKw=="
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.14.0.tgz",
+      "integrity": "sha512-bwa8dBuMpOxg7COyqkW6muQuvNnWgVN8TX/epDRGW5m0jcrmq2QJyCyiV8ZE2/6LaIIqJtiv9bYokFhfpy/o6w=="
     },
     "got": {
       "version": "8.3.2",
@@ -6410,12 +6322,12 @@
       "integrity": "sha512-ibBaJPzfMVuLPgaST9w0kZl60s+SnkPBQp6QKdpEr85tpc1gXW2QDqSne9xiyiym0logDfdUSm4aX5h9YBA2mw=="
     },
     "gtoken": {
-      "version": "5.0.3",
-      "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.3.tgz",
-      "integrity": "sha512-Nyd1wZCMRc2dj/mAD0LlfQLcAO06uKdpKJXvK85SGrF5+5+Bpfil9u/2aw35ltvEHjvl0h5FMKN5knEU+9JrOg==",
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.1.0.tgz",
+      "integrity": "sha512-4d8N6Lk8TEAHl9vVoRVMh9BNOKWVgl2DdNtr3428O75r3QFrF/a5MMu851VmK0AA8+iSvbwRv69k5XnMLURGhg==",
       "requires": {
-        "gaxios": "^3.0.0",
-        "google-p12-pem": "^3.0.0",
+        "gaxios": "^4.0.0",
+        "google-p12-pem": "^3.0.3",
         "jws": "^4.0.0",
         "mime": "^2.2.0"
       }
@@ -7323,7 +7235,8 @@
     "is-fullwidth-code-point": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
     },
     "is-glob": {
       "version": "4.0.1",
@@ -8423,7 +8336,8 @@
     "node-forge": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
-      "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ=="
+      "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
+      "dev": true
     },
     "node-ipc": {
       "version": "9.1.1",
@@ -8912,6 +8826,7 @@
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
       "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dev": true,
       "requires": {
         "p-try": "^2.0.0"
       }
@@ -8954,7 +8869,8 @@
     "p-try": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "dev": true
     },
     "pako": {
       "version": "1.0.11",
@@ -10369,12 +10285,14 @@
     "require-directory": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
+      "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+      "dev": true
     },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
-      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+      "dev": true
     },
     "requires-port": {
       "version": "1.0.0",
@@ -11277,6 +11195,7 @@
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
       "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
+      "dev": true,
       "requires": {
         "emoji-regex": "^8.0.0",
         "is-fullwidth-code-point": "^3.0.0",
@@ -11315,6 +11234,7 @@
       "version": "6.0.0",
       "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
       "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
+      "dev": true,
       "requires": {
         "ansi-regex": "^5.0.0"
       },
@@ -11322,7 +11242,8 @@
         "ansi-regex": {
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
-          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
+          "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
+          "dev": true
         }
       }
     },
@@ -12970,7 +12891,8 @@
     "which-module": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
-      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
+      "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+      "dev": true
     },
     "wide-align": {
       "version": "1.1.3",
@@ -13033,6 +12955,7 @@
       "version": "6.2.0",
       "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
       "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
       "requires": {
         "ansi-styles": "^4.0.0",
         "string-width": "^4.1.0",
@@ -13043,6 +12966,7 @@
           "version": "4.2.1",
           "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
           "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
+          "dev": true,
           "requires": {
             "@types/color-name": "^1.1.1",
             "color-convert": "^2.0.1"
@@ -13052,6 +12976,7 @@
           "version": "2.0.1",
           "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
           "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
           "requires": {
             "color-name": "~1.1.4"
           }
@@ -13059,7 +12984,8 @@
         "color-name": {
           "version": "1.1.4",
           "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true
         }
       }
     },
@@ -13095,7 +13021,8 @@
     "y18n": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+      "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+      "dev": true
     },
     "yallist": {
       "version": "3.1.1",
@@ -13106,6 +13033,7 @@
       "version": "15.4.1",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
       "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "dev": true,
       "requires": {
         "cliui": "^6.0.0",
         "decamelize": "^1.2.0",
@@ -13124,6 +13052,7 @@
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
           "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "dev": true,
           "requires": {
             "locate-path": "^5.0.0",
             "path-exists": "^4.0.0"
@@ -13133,6 +13062,7 @@
           "version": "5.0.0",
           "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
           "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "dev": true,
           "requires": {
             "p-locate": "^4.1.0"
           }
@@ -13141,6 +13071,7 @@
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
           "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "dev": true,
           "requires": {
             "p-limit": "^2.2.0"
           }
@@ -13148,7 +13079,8 @@
         "path-exists": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+          "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+          "dev": true
         }
       }
     },
@@ -13156,6 +13088,7 @@
       "version": "18.1.3",
       "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
       "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dev": true,
       "requires": {
         "camelcase": "^5.0.0",
         "decamelize": "^1.2.0"
@@ -13164,7 +13097,8 @@
         "camelcase": {
           "version": "5.3.1",
           "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+          "dev": true
         }
       }
     },
diff --git a/frontend/package.json b/frontend/package.json
index 4324a3c..fcbc52e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,11 +9,11 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
-    "@grpc/grpc-js": "^1.1.5",
+    "@grpc/grpc-js": "^1.2.1",
     "axios": "^0.20.0",
     "core-js": "^3.6.5",
     "d3": "^5.16.0",
-    "google-protobuf": "^3.6.1",
+    "google-protobuf": "^3.14.0",
     "grpc": "^1.24.3",
     "grpc-web": "^1.0.0",
     "readline": "^1.3.0",
diff --git a/frontend/src/generated/projector_pb.js b/frontend/src/generated/projector_pb.js
index 91a4309..e88b0f4 100644
--- a/frontend/src/generated/projector_pb.js
+++ b/frontend/src/generated/projector_pb.js
@@ -1,6 +1,4 @@
-/* eslint-disable */
-
-// source: src/projector.proto
+// source: projector.proto
 /**
  * @fileoverview
  * @enhanceable
@@ -9,6 +7,8 @@
  * @public
  */
 // GENERATED CODE -- DO NOT EDIT!
+/* eslint-disable */
+// @ts-nocheck
 
 var jspb = require('google-protobuf');
 var goog = jspb;
@@ -544,8 +544,10 @@ proto.provee.TrainingSetRow.deserializeBinaryFromReader = function(msg, reader)
       msg.setId(value);
       break;
     case 2:
-      var value = /** @type {!Array<number>} */ (reader.readPackedDouble());
-      msg.setHdvectorList(value);
+      var values = /** @type {!Array<number>} */ (reader.isDelimited() ? reader.readPackedDouble() : [reader.readDouble()]);
+      for (var i = 0; i < values.length; i++) {
+        msg.addHdvector(values[i]);
+      }
       break;
     default:
       reader.skipField();
diff --git a/protos/README.md b/protos/README.md
new file mode 100644
index 0000000..4cd0c30
--- /dev/null
+++ b/protos/README.md
@@ -0,0 +1,11 @@
+# protos
+
+Contains all Protos (gRCP) files that are used to communicate between services in Provee
+
+## Dependencies
+
+```
+brew install protoc
+brew install protoc-gen-grpc-node
+npm install -g grpc-tools
+```
\ No newline at end of file
diff --git a/protos/build.sh b/protos/build.sh
new file mode 100755
index 0000000..cd978c8
--- /dev/null
+++ b/protos/build.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+DIR="$(dirname "$0")"
+
+PROJECTOR_PROTO_FILE="$DIR/projector.proto"
+
+FRONTEND_GENERATED_DIR="$DIR/../frontend/src/generated"
+BACKEND_GATEWAY_GENERATED_DIR="$DIR/../backend/gateway/src/generated"
+
+protoc \
+    "$PROJECTOR_PROTO_FILE" \
+    --js_out=import_style=commonjs:"$FRONTEND_GENERATED_DIR" \
+    --grpc-web_out=import_style=commonjs,mode=grpcwebtext:"$FRONTEND_GENERATED_DIR"
+
+grpc_tools_node_protoc \
+    "$PROJECTOR_PROTO_FILE" \
+    --js_out=import_style=commonjs:"$BACKEND_GATEWAY_GENERATED_DIR" \
+    --grpc_out=grpc_js:"$BACKEND_GATEWAY_GENERATED_DIR"
\ No newline at end of file
diff --git a/frontend/src/projector.proto b/protos/projector.proto
similarity index 100%
rename from frontend/src/projector.proto
rename to protos/projector.proto
-- 
GitLab