npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rn-grpc-bridge

v0.0.12

Published

Generate grpc Swift/Android bridge for React Native

Downloads

7

Readme

npm version

React Native gRPC Swift/Java bridge generator

If 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. React Native accepts only Dictionaries and Arrays with primitive types.

Features

  • [x] Generate Swift Unary calls code for JS mappings
  • [x] Generate iOS Swift bridge header
  • [x] Generate Typescript interfaces for JS/TS
  • [ ] Generate Swift Streaming calls code for JS mappings
  • [ ] Generate Android Unary code for JS mappings
  • [ ] Generate Android Streaming code for JS mappings

Example Use case

  1. Lets say we have proto
message Book {
    int64 isbn = 1;
    string title = 2;
    string author = 3;
    int32 pages = 4;
    bool isActivate = 5;
    BookDetails details = 6;
}

message GetTypesRequest {
    double dbl = 1;
    float flt = 2;
    int32 intr32 = 3;
    int64 intr64 = 4;
    uint32 uintr32 = 5;
    uint64 uintr64 = 6;
    sint32 suint32 = 7;
    sint64 suint64 = 8;
    fixed32	fxd32 = 9;
    fixed64	fxd64 = 10;
    sfixed32 sfxd32 = 11;
    sfixed64 sfxd64 = 12;
    bool bln = 13;
    string str = 14;
    bytes bytx = 15;
    repeated Book books = 16;
    Book book = 17;
}

message GetTypesResponse {
    double dbl = 1;
    float flt = 2;
    int32 intr32 = 3;
    int64 intr64 = 4;
    uint32 uintr32 = 5;
    uint64 uintr64 = 6;
    sint32 suint32 = 7;
    sint64 suint64 = 8;
    fixed32	fxd32 = 9;
    fixed64	fxd64 = 10;
    sfixed32 sfxd32 = 11;
    sfixed64 sfxd64 = 12;
    bool bln = 13;
    string str = 14;
    bytes bytx = 15;
    repeated Book books = 16;
    Book book = 17;
}

service BookService {
    rpc GetTypes (GetTypesRequest) returns (GetTypesResponse) {}
}
  1. Now if you want to call GetTypes method from javascript you need to write all these mappings
@objc(BookService)
class BookService: NSObject, GrpcService {

  @objc func GetTypes(_ req$: [String: Any], resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
    let svc = BookServiceClient()
    var req = Book_GetTypesRequest()

    // request mapping
    req.dbl = req$["dbl"] as? Double ?? 0
    req.flt = req$["flt"] as? Float ?? 0
    req.intr32 = Int32(req$["intr32"] as? Int ?? 0)
    req.intr64 = Int64(req$["intr64"] as? Int ?? 0)
    req.uintr32 = UInt32(req$["uintr32"] as? Int ?? 0)
    req.uintr64 = UInt64(req$["uintr64"] as? Int ?? 0)
    req.suint32 = Int32(req$["suint32"] as? Int ?? 0)
    req.suint64 = Int64(req$["suint64"] as? Int ?? 0)
    req.fxd32 = UInt32(req$["fxd32"] as? Int ?? 0)
    req.fxd64 = UInt64(req$["fxd64"] as? Int ?? 0)
    req.sfxd32 = Int32(req$["sfxd32"] as? Int ?? 0)
    req.sfxd64 = Int64(req$["sfxd64"] as? Int ?? 0)
    req.bln = req$["bln"] as? Bool ?? false
    req.str = req$["str"] as? String ?? ""
    req.bytx = req$["bytx"] as? Data ?? Data()
    if let arr = req$["books"] as? [[String: Any]] {
      for item in arr {
        if let books_Book$ = item as? [String: Any] {
          var books_Book = Book()
          books_Book.isbn = Int64(books_Book$["isbn"] as? Int ?? 0)
          books_Book.title = books_Book$["title"] as? String ?? ""
          books_Book.author = books_Book$["author"] as? String ?? ""
          books_Book.pages = Int32(books_Book$["pages"] as? Int ?? 0)
          books_Book.isActivate = books_Book$["isActivate"] as? Bool ?? false
          if let details_BookDetails$ = books_Book$["details"] as? [String: Any] {
            var details_BookDetails = BookDetails()
            details_BookDetails.pages = Int32(details_BookDetails$["pages"] as? Int ?? 0)
            books_Book.details = details_BookDetails
          }
          req.books.append(books_Book)
        }
      }
    }
    if let book_Book$ = item["book"] as? [String: Any] {
      var book_Book = Book()
      book_Book.isbn = Int64(book_Book$["isbn"] as? Int ?? 0)
      book_Book.title = book_Book$["title"] as? String ?? ""
      book_Book.author = book_Book$["author"] as? String ?? ""
      book_Book.pages = Int32(book_Book$["pages"] as? Int ?? 0)
      book_Book.isActivate = book_Book$["isActivate"] as? Bool ?? false
      if let details_BookDetails$ = book_Book$["details"] as? [String: Any] {
        var details_BookDetails = BookDetails()
        details_BookDetails.pages = Int32(details_BookDetails$["pages"] as? Int ?? 0)
        book_Book.details = details_BookDetails
      }
      req.book = book_Book
    }
    // end request mapping

    do {
      let res = try svc.GetTypes(req)
      var res$: [String: Any] = [:]

      // response mapping
      res$["dbl"] = res.dbl
      res$["flt"] = res.flt
      res$["intr32"] = res.intr32
      res$["intr64"] = res.intr64
      res$["uintr32"] = res.uintr32
      res$["uintr64"] = res.uintr64
      res$["suint32"] = res.suint32
      res$["suint64"] = res.suint64
      res$["fxd32"] = res.fxd32
      res$["fxd64"] = res.fxd64
      res$["sfxd32"] = res.sfxd32
      res$["sfxd64"] = res.sfxd64
      res$["bln"] = res.bln
      res$["str"] = res.str
      res$["bytx"] = res.bytx
      var books$: [[String: Any]] = []
      for item in res.books {
        var _books_Book = item
        var _books_Book$: [String: Any] = [:]
        _books_Book$["isbn"] = _books_Book.isbn
        _books_Book$["title"] = _books_Book.title
        _books_Book$["author"] = _books_Book.author
        _books_Book$["pages"] = _books_Book.pages
        _books_Book$["isActivate"] = _books_Book.isActivate
        var _details_BookDetails = _books_Book.details
        var _details_BookDetails$: [String: Any] = [:]
        _details_BookDetails$["pages"] = _details_BookDetails.pages
        _books_Book$["details"] = _details_BookDetails$
        books$.append(_books_Book$)
      }
      res$["books"] = books$
      var _book_Book = res.book
      var _book_Book$: [String: Any] = [:]
      _book_Book$["isbn"] = _book_Book.isbn
      _book_Book$["title"] = _book_Book.title
      _book_Book$["author"] = _book_Book.author
      _book_Book$["pages"] = _book_Book.pages
      _book_Book$["isActivate"] = _book_Book.isActivate
      var _details_BookDetails = _book_Book.details
      var _details_BookDetails$: [String: Any] = [:]
      _details_BookDetails$["pages"] = _details_BookDetails.pages
      _book_Book$["details"] = _details_BookDetails$
      res$["book"] = _book_Book$
      // end response mapping

      resolve(res$)
    } catch {
      reject("ERROR", error.localizedDescription, error)
    }
  }
}
  1. rn-grpc-bridge generator can do it for you

Usage

  1. Install
yarn add rn-grpc-bridge --dev
  1. Compile using protoc compiler
protoc \
--rn_out=${OUTDIR} \
--plugin=protoc-gen-rn=./node_modules/.bin/rn-grpc-bridge \
-I ./proto \
proto/*.proto
  1. Initialize services from react native. See generate grpc_config.swift for call arguments.
import { NativeModules, DebugService } from 'react-native';
import { DebugService, PingRequest } from './pb/debug_grpc_pb_types';

// inside some initial component
class InitialScreen {
  async componentDidMount() {
    const grpcConfig = NativeModules.GrpcConfig;

    // init for local dev
    await grpcConfig.initServices('localhost:9000', false, '');
    // or for secure with TLS cert to staging/prod
    // await grpcConfig.initServices('corp.staging.com', true, 'certname');

    // it is also possible to set global for all services metadata
    await grpcConfig.setMetadata({
      'x-key': 'x-value',
      'api-key': 'abc1'
    });

    // now we are ready to call grpc
    const debugService: DebugService = NativeModules.DebugService;
    const req: PingRequest = {
      message: `ping from react native ${new Date().getTime()}`
    };
    const rsp = await debugService.ping(req);
    console.log(rsp);
  }
}

Docker

See example which uses Docker image to run rn-grpc-bridge without any external library.