{"id":18585158,"url":"https://github.com/anjmao/rn-grpc-bridge","last_synced_at":"2025-10-29T13:02:51.982Z","repository":{"id":97348790,"uuid":"138732139","full_name":"anjmao/rn-grpc-bridge","owner":"anjmao","description":"React native gRPC Swift/Android bridge generator","archived":false,"fork":false,"pushed_at":"2018-10-01T13:59:25.000Z","size":132,"stargazers_count":18,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T21:23:01.897Z","etag":null,"topics":["android","grpc","protocol-buffers","react","react-native","swift"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anjmao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-26T12:04:21.000Z","updated_at":"2024-04-15T21:48:51.000Z","dependencies_parsed_at":null,"dependency_job_id":"3d958049-c4ae-41b9-bf38-792db3b0a1e9","html_url":"https://github.com/anjmao/rn-grpc-bridge","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anjmao%2Frn-grpc-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anjmao%2Frn-grpc-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anjmao%2Frn-grpc-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anjmao%2Frn-grpc-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anjmao","download_url":"https://codeload.github.com/anjmao/rn-grpc-bridge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248225707,"owners_count":21068078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","grpc","protocol-buffers","react","react-native","swift"],"created_at":"2024-11-07T00:31:26.844Z","updated_at":"2025-10-29T13:02:46.935Z","avatar_url":"https://github.com/anjmao.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://badge.fury.io/js/rn-grpc-bridge.svg)](https://badge.fury.io/js/rn-grpc-bridge)\n\n# Obsolete!\nAs I prototyped better implementation using low level native grpc API, I was able to use Protobuf.js directly. See https://github.com/trackforce/react-native-grpc-starter\n\n# React Native gRPC Swift/Java bridge generator\nIf you are developing React Native app and using gRPC for backend communication when you need to bind native gRPC Swift/Android packages and communicate between native and javascript.\nReact Native accepts only Dictionaries and Arrays with primitive types.\n\n## Features\n\n- [x] Generate Swift Unary calls code for JS mappings\n- [x] Generate iOS Swift bridge header\n- [x] Generate Typescript interfaces for JS/TS\n- [ ] Generate Swift Streaming calls code for JS mappings\n- [ ] Generate Android Unary code for JS mappings\n- [ ] Generate Android Streaming code for JS mappings\n\n### Example Use case\n\n1. Lets say we have proto\n```\nmessage Book {\n    int64 isbn = 1;\n    string title = 2;\n    string author = 3;\n    int32 pages = 4;\n    bool isActivate = 5;\n    BookDetails details = 6;\n}\n\nmessage GetTypesRequest {\n    double dbl = 1;\n    float flt = 2;\n    int32 intr32 = 3;\n    int64 intr64 = 4;\n    uint32 uintr32 = 5;\n    uint64 uintr64 = 6;\n    sint32 suint32 = 7;\n    sint64 suint64 = 8;\n    fixed32\tfxd32 = 9;\n    fixed64\tfxd64 = 10;\n    sfixed32 sfxd32 = 11;\n    sfixed64 sfxd64 = 12;\n    bool bln = 13;\n    string str = 14;\n    bytes bytx = 15;\n    repeated Book books = 16;\n    Book book = 17;\n}\n\nmessage GetTypesResponse {\n    double dbl = 1;\n    float flt = 2;\n    int32 intr32 = 3;\n    int64 intr64 = 4;\n    uint32 uintr32 = 5;\n    uint64 uintr64 = 6;\n    sint32 suint32 = 7;\n    sint64 suint64 = 8;\n    fixed32\tfxd32 = 9;\n    fixed64\tfxd64 = 10;\n    sfixed32 sfxd32 = 11;\n    sfixed64 sfxd64 = 12;\n    bool bln = 13;\n    string str = 14;\n    bytes bytx = 15;\n    repeated Book books = 16;\n    Book book = 17;\n}\n\nservice BookService {\n    rpc GetTypes (GetTypesRequest) returns (GetTypesResponse) {}\n}\n\n```\n\n2. Now if you want to call GetTypes method from javascript you need to write all these mappings\n\n```swift\n@objc(BookService)\nclass BookService: NSObject, GrpcService {\n\n  @objc func GetTypes(_ req$: [String: Any], resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -\u003e Void {\n    let svc = BookServiceClient()\n    var req = Book_GetTypesRequest()\n\n    // request mapping\n    req.dbl = req$[\"dbl\"] as? Double ?? 0\n    req.flt = req$[\"flt\"] as? Float ?? 0\n    req.intr32 = Int32(req$[\"intr32\"] as? Int ?? 0)\n    req.intr64 = Int64(req$[\"intr64\"] as? Int ?? 0)\n    req.uintr32 = UInt32(req$[\"uintr32\"] as? Int ?? 0)\n    req.uintr64 = UInt64(req$[\"uintr64\"] as? Int ?? 0)\n    req.suint32 = Int32(req$[\"suint32\"] as? Int ?? 0)\n    req.suint64 = Int64(req$[\"suint64\"] as? Int ?? 0)\n    req.fxd32 = UInt32(req$[\"fxd32\"] as? Int ?? 0)\n    req.fxd64 = UInt64(req$[\"fxd64\"] as? Int ?? 0)\n    req.sfxd32 = Int32(req$[\"sfxd32\"] as? Int ?? 0)\n    req.sfxd64 = Int64(req$[\"sfxd64\"] as? Int ?? 0)\n    req.bln = req$[\"bln\"] as? Bool ?? false\n    req.str = req$[\"str\"] as? String ?? \"\"\n    req.bytx = req$[\"bytx\"] as? Data ?? Data()\n    if let arr = req$[\"books\"] as? [[String: Any]] {\n      for item in arr {\n        if let books_Book$ = item as? [String: Any] {\n          var books_Book = Book()\n          books_Book.isbn = Int64(books_Book$[\"isbn\"] as? Int ?? 0)\n          books_Book.title = books_Book$[\"title\"] as? String ?? \"\"\n          books_Book.author = books_Book$[\"author\"] as? String ?? \"\"\n          books_Book.pages = Int32(books_Book$[\"pages\"] as? Int ?? 0)\n          books_Book.isActivate = books_Book$[\"isActivate\"] as? Bool ?? false\n          if let details_BookDetails$ = books_Book$[\"details\"] as? [String: Any] {\n            var details_BookDetails = BookDetails()\n            details_BookDetails.pages = Int32(details_BookDetails$[\"pages\"] as? Int ?? 0)\n            books_Book.details = details_BookDetails\n          }\n          req.books.append(books_Book)\n        }\n      }\n    }\n    if let book_Book$ = item[\"book\"] as? [String: Any] {\n      var book_Book = Book()\n      book_Book.isbn = Int64(book_Book$[\"isbn\"] as? Int ?? 0)\n      book_Book.title = book_Book$[\"title\"] as? String ?? \"\"\n      book_Book.author = book_Book$[\"author\"] as? String ?? \"\"\n      book_Book.pages = Int32(book_Book$[\"pages\"] as? Int ?? 0)\n      book_Book.isActivate = book_Book$[\"isActivate\"] as? Bool ?? false\n      if let details_BookDetails$ = book_Book$[\"details\"] as? [String: Any] {\n        var details_BookDetails = BookDetails()\n        details_BookDetails.pages = Int32(details_BookDetails$[\"pages\"] as? Int ?? 0)\n        book_Book.details = details_BookDetails\n      }\n      req.book = book_Book\n    }\n    // end request mapping\n\n    do {\n      let res = try svc.GetTypes(req)\n      var res$: [String: Any] = [:]\n\n      // response mapping\n      res$[\"dbl\"] = res.dbl\n      res$[\"flt\"] = res.flt\n      res$[\"intr32\"] = res.intr32\n      res$[\"intr64\"] = res.intr64\n      res$[\"uintr32\"] = res.uintr32\n      res$[\"uintr64\"] = res.uintr64\n      res$[\"suint32\"] = res.suint32\n      res$[\"suint64\"] = res.suint64\n      res$[\"fxd32\"] = res.fxd32\n      res$[\"fxd64\"] = res.fxd64\n      res$[\"sfxd32\"] = res.sfxd32\n      res$[\"sfxd64\"] = res.sfxd64\n      res$[\"bln\"] = res.bln\n      res$[\"str\"] = res.str\n      res$[\"bytx\"] = res.bytx\n      var books$: [[String: Any]] = []\n      for item in res.books {\n        var _books_Book = item\n        var _books_Book$: [String: Any] = [:]\n        _books_Book$[\"isbn\"] = _books_Book.isbn\n        _books_Book$[\"title\"] = _books_Book.title\n        _books_Book$[\"author\"] = _books_Book.author\n        _books_Book$[\"pages\"] = _books_Book.pages\n        _books_Book$[\"isActivate\"] = _books_Book.isActivate\n        var _details_BookDetails = _books_Book.details\n        var _details_BookDetails$: [String: Any] = [:]\n        _details_BookDetails$[\"pages\"] = _details_BookDetails.pages\n        _books_Book$[\"details\"] = _details_BookDetails$\n        books$.append(_books_Book$)\n      }\n      res$[\"books\"] = books$\n      var _book_Book = res.book\n      var _book_Book$: [String: Any] = [:]\n      _book_Book$[\"isbn\"] = _book_Book.isbn\n      _book_Book$[\"title\"] = _book_Book.title\n      _book_Book$[\"author\"] = _book_Book.author\n      _book_Book$[\"pages\"] = _book_Book.pages\n      _book_Book$[\"isActivate\"] = _book_Book.isActivate\n      var _details_BookDetails = _book_Book.details\n      var _details_BookDetails$: [String: Any] = [:]\n      _details_BookDetails$[\"pages\"] = _details_BookDetails.pages\n      _book_Book$[\"details\"] = _details_BookDetails$\n      res$[\"book\"] = _book_Book$\n      // end response mapping\n\n      resolve(res$)\n    } catch {\n      reject(\"ERROR\", error.localizedDescription, error)\n    }\n  }\n}\n```\n\n3. rn-grpc-bridge generator can do it for you\n\n### Usage\n\n1. Install\n```\nyarn add rn-grpc-bridge --dev\n```\n\n2. Compile using protoc compiler\n```shell\nprotoc \\\n--rn_out=${OUTDIR} \\\n--plugin=protoc-gen-rn=./node_modules/.bin/rn-grpc-bridge \\\n-I ./proto \\\nproto/*.proto\n```\n\n3. Initialize services from react native. See generate grpc_config.swift for call arguments.\n\n\n```js\nimport { NativeModules, DebugService } from 'react-native';\nimport { DebugService, PingRequest } from './pb/debug_grpc_pb_types';\n\n// inside some initial component\nclass InitialScreen {\n  async componentDidMount() {\n    const grpcConfig = NativeModules.GrpcConfig;\n\n    // init for local dev\n    await grpcConfig.initServices('localhost:9000', false, '');\n    // or for secure with TLS cert to staging/prod\n    // await grpcConfig.initServices('corp.staging.com', true, 'certname');\n\n    // it is also possible to set global for all services metadata\n    await grpcConfig.setMetadata({\n      'x-key': 'x-value',\n      'api-key': 'abc1'\n    });\n\n    // now we are ready to call grpc\n    const debugService: DebugService = NativeModules.DebugService;\n    const req: PingRequest = {\n      message: `ping from react native ${new Date().getTime()}`\n    };\n    const rsp = await debugService.ping(req);\n    console.log(rsp);\n  }\n}\n```\n\n### Docker\n\nSee [example](https://github.com/anjmao/grpc-tools) which uses Docker image to run rn-grpc-bridge without any external library. \n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanjmao%2Frn-grpc-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanjmao%2Frn-grpc-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanjmao%2Frn-grpc-bridge/lists"}