protoc-gen-gopherjs

command module
v0.1.2-alpha Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 18, 2017 License: MIT Imports: 5 Imported by: 0

README

GopherJS support for Protocol Buffers and gRPC-Web

Generate GopherJS interfaces to ProtobufJS and gRPC Web from your proto files.

Attribution

Most of the code is based on a fork of Googles protoc-gen-go code generator, with heavy modifications to output GopherJS compatible structs.

Compatibility

Only proto files with syntax="proto3"; are supported.

Installation

To use this software, you must:

  • Install the protocol buffer compiler, protoc: https://developers.google.com/protocol-buffers/

  • Install the Go compiler and tools: https://golang.org/

  • Grab the code from the repository and install the proto package.

    $ go get -u github.com/johanbrandhorst/protoc-gen-gopherjs
    

    The compiler plugin, protoc-gen-gopherjs, will be installed in $GOBIN, defaulting to $GOPATH/bin. It must be in your $PATH for the protocol compiler, protoc, to find it.

This package generates files that import the GopherJS ProtobufJS bindings. The generated interface is designed to be as similar as possible to that of files generated with protoc-gen-go, with a few differences:

  1. Getters and Setters instead of properties on message structs. This is due to the design of ProtobufJS which similarly uses getters and setters instead of nested objects.
  2. "Factory functions" for initializing new message structs. This is mostly as a convenience to the user. Oneof fields still have to be set separately and will default to unset.
  3. Serialize and DeserializeX methods for each type. Instead of proto.Marshal and proto.Unmarshal, these are used to serialize to and from binary.

Usage

Once the software is installed, there are two steps to using it. First you must compile the protocol buffer definitions and then import them into your program.

To compile the protocol buffer definition, run protoc with the --gopherjs_out and --js_out parameters set to the directory you want to output the GopherJS code to. The ProtobufJS must be run with the following parameters: import_style=commonjs,binary

 $ protoc --gopherjs_out=. --js_out=import_style=commonjs,binary:. *.proto

The generated files will be suffixed .pb.gopherjs.go and pb.js. The generated JS file must be manually edited to be compatible;

  1. Each instance of require('google-protobuf') replaced with $global
  2. Each instance of require('google-protobuf/.*') replace with $global.proto.google.protobuf
  3. Any other require() instances must be modified to include correct objects. This will depend on the configuration of the proto files that were used when generating, but should be fairly straightforward given the examples here.
  4. The export statements at the end of the files must be removed.
  5. The generated JS file must be renamed *.inc.js to be properly included by GopherJS.

The reason for these modifications is because the $global object binds together all the definitions to one root object, without the need for require (this is subject to improval if someone with better JS knowledge than I knows a better way).

Here's a couple of handy sed snippets to accomplish this:

# Replace top level import with global reference
$ sed -i "s;require('google-protobuf');\$global;g" <generated_js_file_pb.js>
# Replace any well known type imports with correct namespace
$ sed -i -E "s;require\('google-protobuf/.*'\);\$global.proto.google.protobuf;g" <generated_js_file_pb.js>
# Remove export statement
$ sed -i -E "s/goog\.object\.extend\(exports, proto\..*\);$//g" <generated_js_file_pb.js>

An example

Consider file test.proto, containing

syntax="proto3";

package example;

message Test {
  string label = 1;
  int32 type = 2;
  int64 reps = 3;
}

Generate it:

$ protoc --gopherjs_out=. --js_out=import_style=commonjs,binary:. test.proto

This generates the following client code (abbreviated):

// Code generated by protoc-gen-gopherjs. DO NOT EDIT.
// source: test.proto
package example

import js "github.com/gopherjs/gopherjs/js"
import jspb "github.com/johanbrandhorst/jspb"

type Test struct {
	*js.Object
}

// New creates a new Test.
func (m *Test) New(label string, _type int32, reps int64) *Test {
	m := &Test{
		Object: js.Global.Get("proto").Get("example").Get("Test").New([]interface{}{
			label,
			_type,
			reps,
		}),
	}

	return m
}

// Setters and Getters
// ....

// Serialize marshals Test to a slice of bytes.
func (m *Test) Serialize() (rawBytes []byte, err error) {
	return jspb.Serialize(m)
}

// Deserialize unmarshals a Test from a slice of bytes.
func (m *Test) Deserialize(rawBytes []byte) (*Test, error) {
	obj, err := jspb.Deserialize(js.Global.Get("proto").Get("example").Get("Test"), rawBytes)
	if err != nil {
		return nil, err
	}

	return &Test{
		Object: obj,
	}, nil
}

In your client code, you can use the library like so:

package main

import "github.com/youruser/yourrepo/example"

func main() {
  t := new(example.Test).New("Label", 1234, 5678)
  rawBytes, err := t.Serialize()
  if err != nil {
    panic(err)
  }

  t1, err := new(example.Test).Deserialize(rawBytes)
  if err != nil {
    panic(err)
  }
}

Parameters

To pass extra parameters to the plugin, use a comma-separated parameter list separated from the output directory by a colon:

$ protoc --gopherjs_out=plugins=grpc,import_path=mypackage:. *.proto
  1. import_prefix=xxx - a prefix that is added onto the beginning of all imports. Useful for things like generating protos in a subdirectory, or regenerating vendored protobufs in-place.
  2. import_path=foo/bar - used as the package if no input files declare go_package. If it contains slashes, everything up to the rightmost slash is ignored.
  3. plugins=plugin1+plugin2 - specifies the list of sub-plugins to load. The only plugin in this repo is grpc.
  4. Mfoo/bar.proto=quux/shme - declares that foo/bar.proto is associated with Go package quux/shme. This is subject to the import_prefix parameter.

Generate gRPC-Web bindings

If a proto file specifies RPC services, protoc-gen-gopherjs can be instructed to generate code compatible with the GopherJS gRPC-Web bindings. To do this, pass the plugins parameter to protoc-gen-gopherjs:

$ protoc --gopherjs_out=plugins=grpc:. *.proto

Documentation

Overview

protoc-gen-gopherjs is a plugin for the Google protocol buffer compiler to generate GopherJS code. Run it by building this program and putting it in your path with the name

protoc-gen-gopherjs

That word 'gopherjs' at the end becomes part of the option string set for the protocol compiler, so once the protocol compiler (protoc) is installed you can run

protoc --gopherjs_out=output_directory input_directory/file.proto

to generate GopherJS bindings for the protocol defined by file.proto. With that input, the output will be written to

output_directory/file.pb.gopherjs.go

See the README and documentation for protocol buffers to learn more:

https://developers.google.com/protocol-buffers/

Directories

Path Synopsis
The code generator for the plugin for the Google protocol buffer compiler.
The code generator for the plugin for the Google protocol buffer compiler.
Package grpc outputs gRPC service descriptions in Go code.
Package grpc outputs gRPC service descriptions in Go code.
ptypes
any
Package any is a generated protocol buffer package.
Package any is a generated protocol buffer package.
duration
Package duration is a generated protocol buffer package.
Package duration is a generated protocol buffer package.
empty
Package empty is a generated protocol buffer package.
Package empty is a generated protocol buffer package.
struct
Package structpb is a generated protocol buffer package.
Package structpb is a generated protocol buffer package.
timestamp
Package timestamp is a generated protocol buffer package.
Package timestamp is a generated protocol buffer package.
wrappers
Package wrappers is a generated protocol buffer package.
Package wrappers is a generated protocol buffer package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL