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

pbts-grpc-transcoder-tmp

v0.1.1

Published

pbts-grpc-transcoder is a [TypeScript](https://www.typescriptlang.org) library that provides [gRPC](https://grpc.io) to HTTP/1 & JSON transcoding for the [protobuf.js library](https://github.com/protobufjs/protobuf.js).

Downloads

1

Readme

pbts-grpc-transcoder

pbts-grpc-transcoder is a TypeScript library that provides gRPC to HTTP/1 & JSON transcoding for the protobuf.js library.

The library is published via npm. Get it via:

npm i @wisetime/pbts-grpc-transcoder

Transcoding

gRPC uses HTTP/2 as its transfer protocol and typically sends messages as binary payloads. However, when we define a gRPC service, we can optionally specify HTTP Options for the RPCs, so that REST clients can interact with our service using HTTP/1 and JSON.

We can implement our service as usual in gRPC, and then pass client requests through a transcoding proxy to our service. The following applications can transcode HTTP/1 + JSON to gRPC:

Transcoding is useful if the client does not support gRPC and is not able to use gRPC-Web.

Example Service

Let's look at an example Todo service, defined using Protocol Buffers as:

package todo;

service TodoService {
  rpc CreateTodo(CreateTodoRequest) returns (Todo);
  rpc DeleteTodo(DeleteTodoRequest) returns (google.protobuf.Empty);
}

message CreateTodoRequest {
  string title = 1;
}

message Todo {
  string id = 1;
  string title = 2;
  bool completed = 3;
}

message DeleteTodoRequest {
  string id = 1;
}

If we define the following HTTP options for the RPCs:

service TodoService {
  rpc CreateTodo(CreateTodoRequest) returns (Todo) {
    option (google.api.http) = {
      post: "/v1/todos"
      body: "*"
    };
  }
  rpc DeleteTodo(DeleteTodoRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/todos/{id}"
    };
  }
}

We can then create a new Todo item by making a POST HTTP request to /v1/todos with the following JSON payload:

{
  "title": "Book flight to Mauritius"
}

We can delete a Todo item by making a HTTP request such as:

DELETE /v1/todos/123

Reverse Transcoding

That's great, we can now communicate with a gRPC service through plain HTTP/1 and JSON. However, we have lost our strongly typed calls and messages and are now dealing with ad hoc HTTP requests and hand-crafted JSON.

What if we could still make fully-typed RPC calls to the server while still going over HTTP/1 with JSON payloads? We would like to use protobuf.js with TypeScript to call our service like this:

todoService
  .createTodo(CreateTodoRequest.create({
    title: "Book flight to Mauritius"  // Type-checked by TypeScript.
  }))
  .then(response => {
    console.log(`id: ${response.id}`)
    console.log(`title: ${response.title}`)
    console.log(`completed: ${response.completed}`)
  })

This is what pbts-grpc-transcoder allows us to do. We call our service as if we were making a normal gRPC call using protobuf.js. pbts-grpc-transcoder transcodes the call to HTTP/1 and JSON using the HTTP options specified for the RPC. The proxy receives the HTTP/1 and JSON request and transcodes that to a gRPC call to the underlying service.

Setup

Install pbts-grpc-transcoder via npm:

npm i @wisetime/pbts-grpc-transcoder

protobuf.js will be installed as a dependency and the pbjs and pbts utilities will be available in your node_modules/.bin directory.

Generate the JSON protobuf descriptor. This will be used by the transcoder. For example:

node_modules/.bin/pbjs -t json \
  -o src/generated/protobuf-descriptor.json \
  src/protobuf/todo.proto \

Next, generate the JavaScript client library as a static module that you can import:

node_modules/.bin/pbjs -t static-module \
  -o src/generated/protobuf.js \
  src/protobuf/todo.proto \

Finally, generate the TypeScript types:

node_modules/.bin/pbts \
  -o src/generated/protobuf.d.ts \
  src/generated/protobuf.js

Usage

pbts-grpc-transcoder provides a HTTP executor for protobuf.js. The executor supports automatic call retries via a RetryPolicy. Here's an example showing how to create an executor and provide it to protobuf.js.

import { todo as TodoApi } from "generated/protobuf"
const descriptor = require("generated/protobuf-descriptor.json")

// Request decorator to add the user's ID token for authentication.
const configureRequest = (): RequestInit => ({
  headers: {
    "Authorization": "Bearer ID_TOKEN_HERE",
  },
})

const willRetry = () => {
  // Here we could attempt to exchange user's refresh token for an ID token...
  // Call will be retried when the promise resolves.
  return Promise.resolve()
}

const onGiveUp = () => {
  // For example, force user logout...
}

// Set up a retry policy that will cause the RPC executor to automatically
// retry calls if they fail with status 401 Unauthorized. The executor will
// run willRetry() before retrying the call. It will retry up to 2 times with
// exponential backoff. If the call still fails after 2 retries, the executor
// calls the onGiveUp() callback.
const retryPolicy = responseNotOk(
  (response: Response) => response.status === 401,
  2,
  willRetry,
  onGiveUp,
)

// Create the RPC executor. The createHttpExecutor function is auto-curried.
// You can preconfigure various versions as needed.
const executor = createHttpExecutor(
  window.fetch, retryPolicy, "http://localhost", descriptor, configureRequest
)

const todoService = ReportApi.ReportService.create(
  executor(TodoApi.TodoService)
)

// An RPC message is type checked.
const deleteRequest = TodoApi.DeleteTodoRequest.create({ id: "123" })

// Call the service.
todoService
  .deleteTodo(deleteRequest)
  .then(response => {
    // ...
  })

Limitations

This library implements HTTP Options transcoding. It only supports unary RPCs.