From 79d0ba2cc71a156910a9d937683af164df694f08 Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Mon, 3 Apr 2017 20:56:50 +0200 Subject: [PATCH] Docs: Clarified that the service API targets clients consuming a service, see #742 --- README.md | 4 ++- cli/README.md | 55 +++++++++++++++++++++------------------ cli/package.json | 2 +- examples/streaming-rpc.js | 37 ++++++++++++++++---------- 4 files changed, 57 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index c3f8e97bf..450be2f13 100644 --- a/README.md +++ b/README.md @@ -381,7 +381,7 @@ AwesomeMessage.prototype.customInstanceMethod = function() { ... }; ### Using services -The library also supports services but it doesn't make any assumptions about the actual transport channel. Instead, a user must provide a suitable RPC implementation, which is an asynchronous function that takes the reflected service method, the binary request and a node-style callback as its parameters: +The library also supports consuming services but it doesn't make any assumptions about the actual transport channel. Instead, a user must provide a suitable RPC implementation, which is an asynchronous function that takes the reflected service method, the binary request and a node-style callback as its parameters: ```js function rpcImpl(method, requestData, callback) { @@ -432,6 +432,8 @@ greeter.sayHello({ name: 'you' }) There is also an [example for streaming RPC](https://github.com/dcodeIO/protobuf.js/blob/master/examples/streaming-rpc.js). +Note that the service API is meant for clients. Implementing a server-side endpoint pretty much always requires transport channel (i.e. http, websocket, etc.) specific code with the only common denominator being that it decodes and encodes messages. + ### Usage with TypeScript The library ships with its own [type definitions](https://github.com/dcodeIO/protobuf.js/blob/master/index.d.ts) and modern editors like [Visual Studio Code](https://code.visualstudio.com/) should automatically detect and use them for code completion when following this pattern: diff --git a/cli/README.md b/cli/README.md index 1cbd0c15b..e3b252232 100644 --- a/cli/README.md +++ b/cli/README.md @@ -43,50 +43,55 @@ Usage ``` Translates between file formats and generates static code. - -t, --target Specifies the target format. Also accepts a path to require a custom target. + -t, --target Specifies the target format. Also accepts a path to require a custom target. json JSON representation json-module JSON representation as a module proto2 Protocol Buffers, Version 2 proto3 Protocol Buffers, Version 3 - static Static code without reflection + static Static code without reflection (non-functional on its own) static-module Static code without reflection as a module - -p, --path Adds a directory to the include path. + -p, --path Adds a directory to the include path. - -o, --out Saves to a file instead of writing to stdout. + -o, --out Saves to a file instead of writing to stdout. - Module targets only: + --sparse Exports only those types referenced from a main file (experimental). - -w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper. + Module targets only: - default Default wrapper supporting both CommonJS and AMD - commonjs CommonJS wrapper - amd AMD wrapper - es6 ES6 wrapper (implies --es6) + -w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper. - -r, --root Specifies an alternative protobuf.roots name. + default Default wrapper supporting both CommonJS and AMD + commonjs CommonJS wrapper + amd AMD wrapper + es6 ES6 wrapper (implies --es6) - -l, --lint Linter configuration. Defaults to protobuf.js-compatible rules: + -r, --root Specifies an alternative protobuf.roots name. - eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins + -l, --lint Linter configuration. Defaults to protobuf.js-compatible rules: - --es6 Enables ES6 syntax (const/let instead of var) + eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins - Proto sources only: + --es6 Enables ES6 syntax (const/let instead of var) - --keep-case Keeps field casing instead of converting to camel case. + Proto sources only: - Static targets only: + --keep-case Keeps field casing instead of converting to camel case. - --no-create Does not generate create functions used for reflection compatibility. - --no-encode Does not generate encode functions. - --no-decode Does not generate decode functions. - --no-verify Does not generate verify functions. - --no-convert Does not generate convert functions like from/toObject - --no-delimited Does not generate delimited encode/decode functions. - --no-beautify Does not beautify generated code. - --no-comments Does not output any JSDoc comments. + Static targets only: + + --no-create Does not generate create functions used for reflection compatibility. + --no-encode Does not generate encode functions. + --no-decode Does not generate decode functions. + --no-verify Does not generate verify functions. + --no-convert Does not generate convert functions like from/toObject + --no-delimited Does not generate delimited encode/decode functions. + --no-beautify Does not beautify generated code. + --no-comments Does not output any JSDoc comments. + + --force-long Enfores the use of 'Long' for s-/u-/int64 and s-/fixed64 fields. + --force-message Enfores the use of runtime messages instead of plain objects. usage: pbjs [options] file1.proto file2.json ... (or) other | pbjs [options] - ``` diff --git a/cli/package.json b/cli/package.json index 9e26dfeeb..6b17b0088 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1 +1 @@ -{} \ No newline at end of file +{"version": "6.7.0"} \ No newline at end of file diff --git a/examples/streaming-rpc.js b/examples/streaming-rpc.js index 4559e3c0a..f06c08ea7 100644 --- a/examples/streaming-rpc.js +++ b/examples/streaming-rpc.js @@ -1,4 +1,4 @@ -// this example demonstrates how to implement streaming rpc for services. +// this example demonstrates how to consume a streaming rpc service. /*eslint-disable strict, no-console*/ var protobuf = require(".."); @@ -53,20 +53,28 @@ var greeter = Greeter.create(/* rpcImpl */ (function() { // API documentation: S ended = true; return; } - setTimeout(function() { - try { - // begin exemplary server side code - var hello = Hello.decodeDelimited(requestData); - var responseData = World.encodeDelimited({ message: "Hello " + hello.name }).finish(); - // end exemplary server side code - return callback(null, responseData); - } catch (err) { - return callback(err); - } - }, Math.random() * 500); + // in a real-world scenario, the client would now send requestData to a server using some + // sort of transport layer (i.e. http), wait for responseData and call the callback. + performRequestOverTransportChannel(requestData, function(responseData) { + callback(null, responseData); + }); }; })(), /* requestDelimited? */ true, /* responseDelimited? */ true); +// examplary server-side code for the sake of this example +function performRequestOverTransportChannel(requestData, callback) { + setTimeout(/* simulated delay */function() { + // 1. server decodes the request + var request = Hello.decodeDelimited(requestData); + // 2. server handles the request and creates a response + var response = { message: "Hello " + request.name }; + setTimeout(/* simulated delay */function() { + // 3. server encodes and sends the response + callback(World.encodeDelimited(response).finish()); + }, Math.random() * 250); + }, Math.random() * 250); +} + // Listen for events: greeter.on("data", function(response, method) { @@ -100,6 +108,7 @@ setTimeout(function() { greeter.end(); // ^ Signals rpcImpl that the service has been ended client-side by calling it with a null buffer. // Likewise, rpcImpl can also end the stream by calling its callback with an explicit null buffer. - - greeter.sayHello({ name: "three" }); // does nothing + greeter.sayHello({ name: "three" }, function(err) { + console.error("this should fail: " + err.message); + }); }, 501);