From 3448a73d9a275a2252bf2947d665c50a6284048c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D8=A7=D9=85=DB=8C=D8=B1=D8=AD=D8=B3=DB=8C=D9=86=20=D9=85?= =?UTF-8?q?=D9=82=DB=8C=D8=B3=D9=87?= Date: Sun, 21 Feb 2021 13:16:24 +0330 Subject: [PATCH] Initial Commit --- .gitignore | 2 + client/client.js | 17 ++ client/index.js | 70 ++++++++ client/views/users.hbs | 176 ++++++++++++++++++ lib/proto/users_pb2.py | 271 ++++++++++++++++++++++++++++ lib/proto/users_pb2_grpc.py | 198 +++++++++++++++++++++ package-lock.json | 344 ++++++++++++++++++++++++++++++++++++ package.json | 19 ++ requirement.txt | 2 + server/server.js | 93 ++++++++++ server/server.py | 69 ++++++++ users.proto | 26 +++ 12 files changed, 1287 insertions(+) create mode 100644 .gitignore create mode 100644 client/client.js create mode 100644 client/index.js create mode 100644 client/views/users.hbs create mode 100644 lib/proto/users_pb2.py create mode 100644 lib/proto/users_pb2_grpc.py create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 requirement.txt create mode 100644 server/server.js create mode 100644 server/server.py create mode 100644 users.proto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7fe771a --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +__pycache__ \ No newline at end of file diff --git a/client/client.js b/client/client.js new file mode 100644 index 0000000..1777e26 --- /dev/null +++ b/client/client.js @@ -0,0 +1,17 @@ +var PROTO_PATH = __dirname + "/../users.proto"; + +var grpc = require("@grpc/grpc-js"); +var protoLoader = require("@grpc/proto-loader"); +var packageDefinition = protoLoader.loadSync(PROTO_PATH, { + keepCase: true, + longs: String, + enums: String, + arrays: true, +}); +var UserService = grpc.loadPackageDefinition(packageDefinition).UserService; + +const client = new UserService( + "127.0.0.1:50051", + grpc.credentials.createInsecure() +); +module.exports = client; diff --git a/client/index.js b/client/index.js new file mode 100644 index 0000000..d337be4 --- /dev/null +++ b/client/index.js @@ -0,0 +1,70 @@ +const client = require("./client"); + +const path = require("path"); +const express = require("express"); +const bodyParser = require("body-parser"); + +const app = express(); + +app.set("views", path.join(__dirname, "views")); +app.set("view engine", "hbs"); + +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); + +app.get("/", (req, res) => { + client.getAll(null, (err, data) => { + console.log(data); + if (!err) { + res.render("users", { + results: data.users, + }); + } + }); +}); + +app.post("/save", (req, res) => { + let newUser = { + name: req.body.name, + age: req.body.age, + address: req.body.address, + }; + + client.insert(newUser, (err, data) => { + if (err) throw err; + + console.log("User created successfully", data); + res.redirect("/"); + }); +}); + +app.post("/update", (req, res) => { + const updateUser = { + id: req.body.id, + name: req.body.name, + age: req.body.age, + address: req.body.address, + }; + + client.update(updateUser, (err, data) => { + if (err) throw err; + + console.log("User updated successfully", data); + res.redirect("/"); + }); +}); + +app.post("/remove", (req, res) => { + console.log(req.body); + client.remove({ id: req.body.user_id }, (err, _) => { + if (err) throw err; + + console.log("User removed successfully"); + res.redirect("/"); + }); +}); + +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log("Server running at port %d", PORT); +}); diff --git a/client/views/users.hbs b/client/views/users.hbs new file mode 100644 index 0000000..1ab9550 --- /dev/null +++ b/client/views/users.hbs @@ -0,0 +1,176 @@ + + + + + LogRocket CRUD with gRPC and Node + + + + + +
+
+ +

Users's List

+

Example of CRUD made with Node.js, Express, Handlebars and gRPC

+
+ + + + + + + + + + + + + {{#each results}} + + + + + + + + {{else}} + + + + {{/each}} + +
Customer IDCustomer NameAgeAddressAction
{{ id }}{{ name }}{{ age }} years old{{ address }} + Edit + Remove +
No data to display.
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + + + + \ No newline at end of file diff --git a/lib/proto/users_pb2.py b/lib/proto/users_pb2.py new file mode 100644 index 0000000..64a62b4 --- /dev/null +++ b/lib/proto/users_pb2.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: users.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='users.proto', + package='', + syntax='proto3', + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_pb=b'\n\x0busers.proto\"\x07\n\x05\x45mpty\">\n\x04User\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0b\n\x03\x61ge\x18\x03 \x01(\x05\x12\x0f\n\x07\x61\x64\x64ress\x18\x04 \x01(\t\" \n\x08UserList\x12\x14\n\x05users\x18\x01 \x03(\x0b\x32\x05.User\"\x1b\n\rUserRequestId\x12\n\n\x02id\x18\x01 \x01(\t2\xa4\x01\n\x0bUserService\x12\x1d\n\x06GetAll\x12\x06.Empty\x1a\t.UserList\"\x00\x12\x1e\n\x03Get\x12\x0e.UserRequestId\x1a\x05.User\"\x00\x12\x18\n\x06Insert\x12\x05.User\x1a\x05.User\"\x00\x12\x18\n\x06Update\x12\x05.User\x1a\x05.User\"\x00\x12\"\n\x06Remove\x12\x0e.UserRequestId\x1a\x06.Empty\"\x00\x62\x06proto3' +) + + + + +_EMPTY = _descriptor.Descriptor( + name='Empty', + full_name='Empty', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=15, + serialized_end=22, +) + + +_USER = _descriptor.Descriptor( + name='User', + full_name='User', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='User.id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', full_name='User.name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='age', full_name='User.age', index=2, + number=3, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='address', full_name='User.address', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=24, + serialized_end=86, +) + + +_USERLIST = _descriptor.Descriptor( + name='UserList', + full_name='UserList', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='users', full_name='UserList.users', index=0, + number=1, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=88, + serialized_end=120, +) + + +_USERREQUESTID = _descriptor.Descriptor( + name='UserRequestId', + full_name='UserRequestId', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='id', full_name='UserRequestId.id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=b"".decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=122, + serialized_end=149, +) + +_USERLIST.fields_by_name['users'].message_type = _USER +DESCRIPTOR.message_types_by_name['Empty'] = _EMPTY +DESCRIPTOR.message_types_by_name['User'] = _USER +DESCRIPTOR.message_types_by_name['UserList'] = _USERLIST +DESCRIPTOR.message_types_by_name['UserRequestId'] = _USERREQUESTID +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Empty = _reflection.GeneratedProtocolMessageType('Empty', (_message.Message,), { + 'DESCRIPTOR' : _EMPTY, + '__module__' : 'users_pb2' + # @@protoc_insertion_point(class_scope:Empty) + }) +_sym_db.RegisterMessage(Empty) + +User = _reflection.GeneratedProtocolMessageType('User', (_message.Message,), { + 'DESCRIPTOR' : _USER, + '__module__' : 'users_pb2' + # @@protoc_insertion_point(class_scope:User) + }) +_sym_db.RegisterMessage(User) + +UserList = _reflection.GeneratedProtocolMessageType('UserList', (_message.Message,), { + 'DESCRIPTOR' : _USERLIST, + '__module__' : 'users_pb2' + # @@protoc_insertion_point(class_scope:UserList) + }) +_sym_db.RegisterMessage(UserList) + +UserRequestId = _reflection.GeneratedProtocolMessageType('UserRequestId', (_message.Message,), { + 'DESCRIPTOR' : _USERREQUESTID, + '__module__' : 'users_pb2' + # @@protoc_insertion_point(class_scope:UserRequestId) + }) +_sym_db.RegisterMessage(UserRequestId) + + + +_USERSERVICE = _descriptor.ServiceDescriptor( + name='UserService', + full_name='UserService', + file=DESCRIPTOR, + index=0, + serialized_options=None, + create_key=_descriptor._internal_create_key, + serialized_start=152, + serialized_end=316, + methods=[ + _descriptor.MethodDescriptor( + name='GetAll', + full_name='UserService.GetAll', + index=0, + containing_service=None, + input_type=_EMPTY, + output_type=_USERLIST, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='Get', + full_name='UserService.Get', + index=1, + containing_service=None, + input_type=_USERREQUESTID, + output_type=_USER, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='Insert', + full_name='UserService.Insert', + index=2, + containing_service=None, + input_type=_USER, + output_type=_USER, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='Update', + full_name='UserService.Update', + index=3, + containing_service=None, + input_type=_USER, + output_type=_USER, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.MethodDescriptor( + name='Remove', + full_name='UserService.Remove', + index=4, + containing_service=None, + input_type=_USERREQUESTID, + output_type=_EMPTY, + serialized_options=None, + create_key=_descriptor._internal_create_key, + ), +]) +_sym_db.RegisterServiceDescriptor(_USERSERVICE) + +DESCRIPTOR.services_by_name['UserService'] = _USERSERVICE + +# @@protoc_insertion_point(module_scope) diff --git a/lib/proto/users_pb2_grpc.py b/lib/proto/users_pb2_grpc.py new file mode 100644 index 0000000..bae2e10 --- /dev/null +++ b/lib/proto/users_pb2_grpc.py @@ -0,0 +1,198 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +"""Client and server classes corresponding to protobuf-defined services.""" +import grpc + +import users_pb2 as users__pb2 + + +class UserServiceStub(object): + """Missing associated documentation comment in .proto file.""" + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.GetAll = channel.unary_unary( + '/UserService/GetAll', + request_serializer=users__pb2.Empty.SerializeToString, + response_deserializer=users__pb2.UserList.FromString, + ) + self.Get = channel.unary_unary( + '/UserService/Get', + request_serializer=users__pb2.UserRequestId.SerializeToString, + response_deserializer=users__pb2.User.FromString, + ) + self.Insert = channel.unary_unary( + '/UserService/Insert', + request_serializer=users__pb2.User.SerializeToString, + response_deserializer=users__pb2.User.FromString, + ) + self.Update = channel.unary_unary( + '/UserService/Update', + request_serializer=users__pb2.User.SerializeToString, + response_deserializer=users__pb2.User.FromString, + ) + self.Remove = channel.unary_unary( + '/UserService/Remove', + request_serializer=users__pb2.UserRequestId.SerializeToString, + response_deserializer=users__pb2.Empty.FromString, + ) + + +class UserServiceServicer(object): + """Missing associated documentation comment in .proto file.""" + + def GetAll(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Get(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Insert(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Update(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Remove(self, request, context): + """Missing associated documentation comment in .proto file.""" + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_UserServiceServicer_to_server(servicer, server): + rpc_method_handlers = { + 'GetAll': grpc.unary_unary_rpc_method_handler( + servicer.GetAll, + request_deserializer=users__pb2.Empty.FromString, + response_serializer=users__pb2.UserList.SerializeToString, + ), + 'Get': grpc.unary_unary_rpc_method_handler( + servicer.Get, + request_deserializer=users__pb2.UserRequestId.FromString, + response_serializer=users__pb2.User.SerializeToString, + ), + 'Insert': grpc.unary_unary_rpc_method_handler( + servicer.Insert, + request_deserializer=users__pb2.User.FromString, + response_serializer=users__pb2.User.SerializeToString, + ), + 'Update': grpc.unary_unary_rpc_method_handler( + servicer.Update, + request_deserializer=users__pb2.User.FromString, + response_serializer=users__pb2.User.SerializeToString, + ), + 'Remove': grpc.unary_unary_rpc_method_handler( + servicer.Remove, + request_deserializer=users__pb2.UserRequestId.FromString, + response_serializer=users__pb2.Empty.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'UserService', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + # This class is part of an EXPERIMENTAL API. +class UserService(object): + """Missing associated documentation comment in .proto file.""" + + @staticmethod + def GetAll(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/UserService/GetAll', + users__pb2.Empty.SerializeToString, + users__pb2.UserList.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Get(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/UserService/Get', + users__pb2.UserRequestId.SerializeToString, + users__pb2.User.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Insert(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/UserService/Insert', + users__pb2.User.SerializeToString, + users__pb2.User.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Update(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/UserService/Update', + users__pb2.User.SerializeToString, + users__pb2.User.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) + + @staticmethod + def Remove(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary(request, target, '/UserService/Remove', + users__pb2.UserRequestId.SerializeToString, + users__pb2.Empty.FromString, + options, channel_credentials, + insecure, call_credentials, compression, wait_for_ready, timeout, metadata) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..af4a5e9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,344 @@ +{ + "name": "nodetest", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@grpc/grpc-js": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.8.tgz", + "integrity": "sha512-9C1xiCbnYe/3OFpSuRqz2JgFSOxv6+SlqFhXgRC1nHfXYbLnXvtmsI/NpaMs6k9ZNyV4gyaOOh5Z4McfegQGew==", + "requires": { + "@types/node": ">=12.12.47", + "google-auth-library": "^6.1.1", + "semver": "^6.2.0" + } + }, + "@grpc/proto-loader": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.6.tgz", + "integrity": "sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==", + "requires": { + "lodash.camelcase": "^4.3.0", + "protobufjs": "^6.8.6" + } + }, + "@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=" + }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "@types/node": { + "version": "14.14.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.31.tgz", + "integrity": "sha512-vFHy/ezP5qI0rFgJ7aQnjDXwAMrG0KqqIH7tQG5PPv3BWBayOPIQNBjVc/P6hhdZfMx51REc6tfDNXHUio893g==" + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "agent-base": { + "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" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + }, + "gaxios": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", + "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.3.0" + } + }, + "gcp-metadata": { + "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": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "google-auth-library": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", + "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-p12-pem": { + "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.10.0" + } + }, + "google-protobuf": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.15.1.tgz", + "integrity": "sha512-Ss2fADC0TpZXn6bqGgPJMUWoD1y9J7BTtJRVvf+quNxXRtQnrpubiFCdgoown+OetNsU4H3YbJgnpxYY/3kH6g==" + }, + "gtoken": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", + "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.0.3", + "jws": "^4.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, + "protobufjs": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.2.tgz", + "integrity": "sha512-27yj+04uF6ya9l+qfpH187aqEzfCF4+Uit0I9ZBQVqK09hk/SQzKa2MUqUpXaVa7LOFRg1TSSr3lVxGOk6c0SQ==", + "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.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.45.tgz", + "integrity": "sha512-703YTEp8AwQeapI0PTXDOj+Bs/mtdV/k9VcTP7z/de+lx6XjFMKdB+JhKnK+6PZ5za7omgZ3V6qm/dNkMj/Zow==" + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e507068 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "nodetest", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "dependencies": { + "@grpc/grpc-js": "^1.1.0", + "@grpc/proto-loader": "^0.5.0", + "async": "^1.5.2", + "google-protobuf": "^3.0.0", + "minimist": "^1.2.5" + }, + "author": "", + "license": "ISC" +} diff --git a/requirement.txt b/requirement.txt new file mode 100644 index 0000000..fbfdd09 --- /dev/null +++ b/requirement.txt @@ -0,0 +1,2 @@ +grpcio==1.35.0 +grpcio-tools==1.35.0 \ No newline at end of file diff --git a/server/server.js b/server/server.js new file mode 100644 index 0000000..7797b7e --- /dev/null +++ b/server/server.js @@ -0,0 +1,93 @@ +var PROTO_PATH = __dirname + "/../users.proto"; + +var grpc = require("@grpc/grpc-js"); +var protoLoader = require("@grpc/proto-loader"); +var packageDefinition = protoLoader.loadSync(PROTO_PATH, { + keepCase: true, + longs: String, + enums: String, + arrays: true, +}); +var users_proto = grpc.loadPackageDefinition(packageDefinition); +const { v4: uuidv4 } = require("uuid"); +const server = new grpc.Server(); +const users = [ + { + id: "a68b823c-7ca6-44bc-b721-fb4d5312cafc", + name: "John Brad", + age: 23, + address: "Address 1", + }, + { + id: "34415c7c-f82d-4e44-88ca-ae2a1aaa92b7", + name: "Mary Anne", + age: 45, + address: "Address 2", + }, +]; + +server.addService(users_proto.UserService.service, { + getAll: (_, callback) => { + callback(null, { users }); + }, + + get: (call, callback) => { + let user = users.find((n) => n.id == call.request.id); + + if (user) { + callback(null, user); + } else { + callback({ + code: grpc.status.NOT_FOUND, + details: "Not found", + }); + } + }, + + insert: (call, callback) => { + let user = call.request; + + user.id = uuidv4(); + users.push(user); + callback(null, user); + }, + + update: (call, callback) => { + let existinguser = users.find((n) => n.id == call.request.id); + + if (existinguser) { + existinguser.name = call.request.name; + existinguser.age = call.request.age; + existinguser.address = call.request.address; + callback(null, existinguser); + } else { + callback({ + code: grpc.status.NOT_FOUND, + details: "Not found", + }); + } + }, + + remove: (call, callback) => { + let existinguserIndex = users.findIndex((n) => n.id == call.request.id); + + if (existinguserIndex != -1) { + users.splice(existinguserIndex, 1); + callback(null, {}); + } else { + callback({ + code: grpc.status.NOT_FOUND, + details: "Not found", + }); + } + }, +}); + +server.bindAsync( + "127.0.0.1:50051", + grpc.ServerCredentials.createInsecure(), + () => { + console.log("Server running at http://127.0.0.1:50051"); + server.start(); + } +); diff --git a/server/server.py b/server/server.py new file mode 100644 index 0000000..fa6f709 --- /dev/null +++ b/server/server.py @@ -0,0 +1,69 @@ +from concurrent import futures +import logging +import uuid +import grpc +import sys +sys.path.append('C:/Users/user/Documents/Develop Land/grpc/NodeTest/lib/proto') +import users_pb2_grpc as pb2_grpc +import users_pb2 as pb2 + +users = [ + { + "id": "a68b823c-7ca6-44bc-b721-fb4d5312cafc", + "name": "John Brad", + "age": 23, + "address": "Address 1", + }, + { + "id": "34415c7c-f82d-4e44-88ca-ae2a1aaa92b7", + "name": "Mary Anne", + "age": 45, + "address": "Address 2", + }, +] + +class UserController(pb2_grpc.UserServiceServicer): + + def GetAll(self,request,context): + return pb2.UserList(users=users) + def Get(self, request, context): + pass + # user.id = str(uuid.uuid4()) + + + def Insert(self, request, context): + user = request + user.id = str(uuid.uuid4()) + users.append(user) + return pb2.User( + id=user.id, + name=user.name, + age=user.age, + address=user.address + ) + def Update(self, request, context): + user = [user for user in users if user['id'] == request.id][0] + user['id'] = request.id + user['name'] = request.name + user['address'] = request.address + user['age'] = request.age + return pb2.User(**user) + def Remove(self, request, context): + print(request) + index = next((i for i, user in enumerate(users) if user['id'] == request.id), -1) + del users[index] + return pb2.Empty() + + +def serve(): + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + pb2_grpc.add_UserServiceServicer_to_server(UserController(), server) + server.add_insecure_port('[::]:50051') + server.start() + print("Server running at http://127.0.0.1:50051") + server.wait_for_termination() + + +if __name__ == '__main__': + logging.basicConfig() + serve() diff --git a/users.proto b/users.proto new file mode 100644 index 0000000..ffd2b8e --- /dev/null +++ b/users.proto @@ -0,0 +1,26 @@ +syntax = "proto3"; + +service UserService { + rpc GetAll (Empty) returns (UserList) {} + rpc Get (UserRequestId) returns (User) {} + rpc Insert (User) returns (User) {} + rpc Update (User) returns (User) {} + rpc Remove (UserRequestId) returns (Empty) {} +} + +message Empty {} + +message User { + string id = 1; + string name = 2; + int32 age = 3; + string address = 4; +} + +message UserList { + repeated User users = 1; +} + +message UserRequestId { + string id = 1; +} \ No newline at end of file