{"id":13740884,"url":"https://github.com/bojand/grpc-caller","last_synced_at":"2025-04-04T13:11:05.635Z","repository":{"id":14663059,"uuid":"76818367","full_name":"bojand/grpc-caller","owner":"bojand","description":"An improved Node.js gRPC client","archived":false,"fork":false,"pushed_at":"2023-08-18T22:50:37.000Z","size":643,"stargazers_count":183,"open_issues_count":22,"forks_count":34,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-12-16T17:05:22.184Z","etag":null,"topics":["grpc","hacktoberfest"],"latest_commit_sha":null,"homepage":"https://bojand.github.io/grpc-caller","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bojand.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}},"created_at":"2016-12-19T01:41:31.000Z","updated_at":"2024-11-02T19:29:19.000Z","dependencies_parsed_at":"2023-10-20T18:30:49.063Z","dependency_job_id":null,"html_url":"https://github.com/bojand/grpc-caller","commit_stats":{"total_commits":93,"total_committers":6,"mean_commits":15.5,"dds":"0.12903225806451613","last_synced_commit":"69cd1ec56225846ae1436147997a38dc38b8572a"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojand%2Fgrpc-caller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojand%2Fgrpc-caller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojand%2Fgrpc-caller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bojand%2Fgrpc-caller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bojand","download_url":"https://codeload.github.com/bojand/grpc-caller/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182342,"owners_count":20897379,"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":["grpc","hacktoberfest"],"created_at":"2024-08-03T04:00:53.258Z","updated_at":"2025-04-04T13:11:05.618Z","avatar_url":"https://github.com/bojand.png","language":"JavaScript","funding_links":[],"categories":["Language-Specific"],"sub_categories":["Node.js"],"readme":"# grpc-caller\n\nAn improved [gRPC](http://www.grpc.io) client.\n\n[![npm version](https://img.shields.io/npm/v/grpc-caller.svg?style=flat-square)](https://www.npmjs.com/package/grpc-caller)\n[![build status](https://img.shields.io/travis/bojand/grpc-caller/master.svg?style=flat-square)](https://travis-ci.org/bojand/grpc-caller)\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](https://standardjs.com)\n[![License](https://img.shields.io/github/license/bojand/grpc-caller.svg?style=flat-square)](https://raw.githubusercontent.com/bojand/grpc-caller/master/LICENSE)\n\n#### Features\n\n* Promisifies request / response (Unary) calls if no callback is supplied\n* Promisifies request stream / response calls if no callback is supplied\n* Automatically converts plain javascript object to metadata in calls.\n* Adds optional retry functionality to request / response (Unary) calls.\n* Exposes expanded `Request` API for collecting metadata and status.\n\n## Installation\n\n```\n$ npm install grpc-caller\n```\n\n## Overview\n\n#### Improved unary calls\n\nWorks as standard gRPC client:\n\n```js\nconst caller = require('grpc-caller')\nconst PROTO_PATH = path.resolve(__dirname, './protos/helloworld.proto')\nconst client = caller('0.0.0.0:50051', PROTO_PATH, 'Greeter')\nclient.sayHello({ name: 'Bob' }, (err, res) =\u003e {\n  console.log(res)\n})\n```\n\nFor unary calls, also promisified if callback is not provided:\n\n```js\nclient.sayHello({ name: 'Bob' })\n  .then(res =\u003e console.log(res))\n```\n\nWhich means means you can use is with `async / await`\n\n```js\nconst res = await client.sayHello({ name: 'Bob' })\nconsole.log(res)\n```\n\nFor Unary calls we expose `retry` option identical to [async.retry](http://caolan.github.io/async/docs.html#retry).\n\n```\nconst res = await client.sayHello({ name: 'Bob' }, {}, { retry: 3 })\nconsole.log(res)\n```\n\n#### Improved request stream / response calls\n\nLets say we have a remote call `writeStuff` that accepts a stream of messages\nand returns some result based on processing of the stream input.\n\nWorks as standard gRPC client:\n\n```js\nconst call = client.writeStuff((err, res) =\u003e {\n  if (err) console.error(err)\n  console.log(res)\n})\n\n// ... write stuff to call\n```\n\nIf no callback is provided we promisify the call such that it returns an **object\nwith two properties** `call` and `res` such that:\n\n* `call` - the standard stream to write to as returned normally by grpc\n* `res` - a promise that's resolved / rejected when the call is finished, in place of the callback.\n\nUsing destructuring we can do something like:\n\n```js\nconst { call, res } = client.writeStuff()\nres\n  .then(res =\u003e console.log(res))\n  .catch(err =\u003e console.error(err))\n\n// ... write stuff to call\n```\n\nThis means we can abstract the whole operation into a nicer promise returning\nasync function to use with `async / await`\n\n```js\nasync function writeStuff() {\n  const { call, res } = client.writeStuff()\n  // ... write stuff to call\n  return res\n}\n\nconst res = await writeStuff()\nconsole.log(res)\n```\n\n#### Automatic `Metadata` creation\n\nAll standard gRPC client calls accept [`Metadata`](http://www.grpc.io/grpc/node/module-src_metadata-Metadata.html)\nas first or second parameter (depending on the call type). However one has to\nmanually create the Metadata object. This module uses\n[grpc-create-metadata](https://www.github.com/bojand/grpc-create-metadata)\nto automatically create Metadata if plain Javascript object is passed in.\n\n```js\n// the 2nd parameter will automatically be converted to gRPC Metadata and\n// included in the request\nconst res = await client.sayHello({ name: 'Bob' }, { requestid: 'my-request-id-123' })\nconsole.log(res)\n```\n\nWe can still pass an actual `Metadata` object and it will be used as is:\n\n```js\nconst meta = new grpc.Metadata()\nmeta.add('requestid', 'my-request-id-123')\nconst res = await client.sayHello({ name: 'Bob' }, meta)\nconsole.log(res)\n```\n\n## Request API\n\nIn addition to simple API above, the library provides a more detailed `\"Request\"` API that can \nbe used to control the call details. The API can only be used for Unary and \nrequest streaming calls.\n\n#### Unary calls\n\n```js\nconst req = new client\n  .Request('sayHello', { name: 'Bob' }) // call method name and argument\n  .withMetadata({ requestId: 'bar-123' }) // call request metadata\n  .withResponseMetadata(true) // we want to collect response metadata\n  .withResponseStatus(true) // we want to collect the response status\n  .withRetry(5) // retry options\n\nconst res = await req.exec()  \n// res is an instance of our `Response`\n// we can also call exec() using a callback\n\nconsole.log(res.response) // the actual response data { message: 'Hello Bob!' }\nconsole.log(res.metadata) // the response metadata\nconsole.log(res.status)   // the response status\nconsole.log(res.call)     // the internal gRPC call\n```\n\n#### Request streaming calls\n\nIn case of request streaming calls if `exec()` is called with a callback the gRPC `call` stream is returned.\nIf no callback is provided an object is returned with `call` property being the call stream and `res`\nproperty being a Promise fulfilled when the call is completed. There is no `retry` option for \nrequest streaming calls.\n\n```js\n\nconst req = new client.Request('writeStuff') // the call method name\n    .withMetadata({ requestId: 'bar-123' })  // the call request metadata\n    .withResponseMetadata(true) // we want to collect response metadata\n    .withResponseStatus(true)   // we want to collect the response status\n\nconst { call, res: resPromise } = req.exec()\n\n// ... write data to call\n\nconst res = await resPromise // res is our `Response`\n\nconsole.log(res.response) // the actual response data\nconsole.log(res.metadata) // the response metadata\nconsole.log(res.status)   // the response status\nconsole.log(res.call)     // the internal gRPC call\n```\n\n## API Reference\n\n\u003ca name=\"Request\"\u003e\u003c/a\u003e\n\n### Request\nA Request class that encapsulates the request of a call.\n\n**Kind**: global class  \n\n* [Request](#Request)\n    * [new Request(methodName, param)](#new_Request_new)\n    * [.withGrpcOptions(opts)](#Request+withGrpcOptions) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.withMetadata(opts)](#Request+withMetadata) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.withRetry(retry)](#Request+withRetry) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.withResponseMetadata(value)](#Request+withResponseMetadata) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.withResponseStatus(value)](#Request+withResponseStatus) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.exec(fn)](#Request+exec) ⇒ \u003ccode\u003ePromise\u003c/code\u003e \\| \u003ccode\u003eObject\u003c/code\u003e\n\n\u003ca name=\"new_Request_new\"\u003e\u003c/a\u003e\n\n#### new Request(methodName, param)\nCreates a Request instance.\n\n\n| Param | Type | Description |\n| --- | --- | --- |\n| methodName | \u003ccode\u003eString\u003c/code\u003e | the method name. |\n| param | \u003ccode\u003e\\*\u003c/code\u003e | the call argument in case of `UNARY` calls. |\n\n\u003ca name=\"Request+withGrpcOptions\"\u003e\u003c/a\u003e\n\n#### request.withGrpcOptions(opts) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate a request with call options.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - the request instance.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | \u003ccode\u003eObject\u003c/code\u003e | The gRPC call options. |\n\n\u003ca name=\"Request+withMetadata\"\u003e\u003c/a\u003e\n\n#### request.withMetadata(opts) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate a request with call metadata.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - the request instance.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | \u003ccode\u003eObject\u003c/code\u003e | The gRPC call metadata.                      Can either be a plain object or an instance of `grpc.Metadata`. |\n\n\u003ca name=\"Request+withRetry\"\u003e\u003c/a\u003e\n\n#### request.withRetry(retry) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate a request with retry options.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - the request instance.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| retry | \u003ccode\u003eNumber\u003c/code\u003e \\| \u003ccode\u003eObject\u003c/code\u003e | The retry options. Identical to `async.retry`. |\n\n\u003ca name=\"Request+withResponseMetadata\"\u003e\u003c/a\u003e\n\n#### request.withResponseMetadata(value) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate a request indicating whether we want to collect the response metadata.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - the request instance.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| value | \u003ccode\u003eBoolean\u003c/code\u003e | `true` to collect the response metadata. Default `false`. |\n\n\u003ca name=\"Request+withResponseStatus\"\u003e\u003c/a\u003e\n\n#### request.withResponseStatus(value) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate a request indicating whether we want to collect the response status metadata.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003eObject\u003c/code\u003e - the request instance.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| value | \u003ccode\u003eBoolean\u003c/code\u003e | `true` to collect the response status metadata. Default `false`. |\n\n\u003ca name=\"Request+exec\"\u003e\u003c/a\u003e\n\n#### request.exec(fn) ⇒ \u003ccode\u003ePromise\u003c/code\u003e \\| \u003ccode\u003eObject\u003c/code\u003e\nExecute the request.\n\n**Kind**: instance method of [\u003ccode\u003eRequest\u003c/code\u003e](#Request)  \n**Returns**: \u003ccode\u003ePromise\u003c/code\u003e \\| \u003ccode\u003eObject\u003c/code\u003e - If no callback is provided in case of `UNARY` call a Promise is returned.\n                         If no callback is provided in case of `REQUEST_STREAMING` call an object is\n                         returned with `call` property being the call stream and `res`\n                         property being a Promise fulfilled when the call is completed.  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| fn | \u003ccode\u003efunction\u003c/code\u003e | Optional callback |\n\n\u003ca name=\"Response\"\u003e\u003c/a\u003e\n\n### Response\nA Response class that encapsulates the response of a call using the `Request` API.\n\n**Kind**: global class  \n\n* [Response](#Response)\n    * [.call](#Response+call) : \u003ccode\u003eObject\u003c/code\u003e\n    * [.response](#Response+response) : \u003ccode\u003eObject\u003c/code\u003e\n    * [.metadata](#Response+metadata) : \u003ccode\u003eObject\u003c/code\u003e\n    * [.status](#Response+status) : \u003ccode\u003eObject\u003c/code\u003e\n\n\u003ca name=\"Response+call\"\u003e\u003c/a\u003e\n\n#### response.call : \u003ccode\u003eObject\u003c/code\u003e\nThe response's gRPC call.\n\n**Kind**: instance property of [\u003ccode\u003eResponse\u003c/code\u003e](#Response)  \n\u003ca name=\"Response+response\"\u003e\u003c/a\u003e\n\n#### response.response : \u003ccode\u003eObject\u003c/code\u003e\nThe actual response data from the call.\n\n**Kind**: instance property of [\u003ccode\u003eResponse\u003c/code\u003e](#Response)  \n\u003ca name=\"Response+metadata\"\u003e\u003c/a\u003e\n\n#### response.metadata : \u003ccode\u003eObject\u003c/code\u003e\nThe response metadata.\n\n**Kind**: instance property of [\u003ccode\u003eResponse\u003c/code\u003e](#Response)  \n\u003ca name=\"Response+status\"\u003e\u003c/a\u003e\n\n#### response.status : \u003ccode\u003eObject\u003c/code\u003e\nThe response status metadata.\n\n**Kind**: instance property of [\u003ccode\u003eResponse\u003c/code\u003e](#Response)  \n\u003ca name=\"caller\"\u003e\u003c/a\u003e\n\n### caller(host, proto, name, credentials, options, defaults) ⇒ \u003ccode\u003eObject\u003c/code\u003e\nCreate client isntance.\n\n**Kind**: global function  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| host | \u003ccode\u003eString\u003c/code\u003e | The host to connect to |\n| proto | \u003ccode\u003eString\u003c/code\u003e \\| \u003ccode\u003eObject\u003c/code\u003e | Path to the protocol buffer definition file or                              Object specifying \u003ccode\u003efile\u003c/code\u003e to load and \u003ccode\u003eload\u003c/code\u003e options for proto loader. |\n| name | \u003ccode\u003eString\u003c/code\u003e | In case of proto path the name of the service as defined in the proto definition. |\n| credentials | \u003ccode\u003eObject\u003c/code\u003e | The credentials to use to connect. Defaults to `grpc.credentials.createInsecure()` |\n| options | \u003ccode\u003eObject\u003c/code\u003e | Options to be passed to the gRPC client constructor |\n| options.retry | \u003ccode\u003eObject\u003c/code\u003e | In addition to gRPC client constructor options, we accept a `retry` option.                                 The retry option is identical to `async.retry` and is passed as is to it.                                 This is used only for `UNARY` calls to add automatic retry capability. |\n| defaults | \u003ccode\u003eObject\u003c/code\u003e | Metadata and Options that will be passed to every Request |\n\n**Example** *(Create client dynamically)*  \n```js\nconst PROTO_PATH = path.resolve(__dirname, './protos/helloworld.proto')\nconst client = caller('localhost:50051', PROTO_PATH, 'Greeter')\n```\n**Example** *(With options)*  \n```js\nconst file = path.join(__dirname, 'helloworld.proto')\nconst load = {\n  // ... proto-loader load options\n}\nconst client = caller('localhost:50051', { file, load }, 'Greeter')\n```\n**Example** *(Create a static client)*  \n```js\nconst services = require('./static/helloworld_grpc_pb')\nconst client = caller('localhost:50051', services.GreeterClient)\n```\n**Example** *(Pass Options, Default Metadata and Interceptor options)*  \n```js\nconst metadata = { node_id: process.env.CLUSTER_NODE_ID };\nconst credentials = grpc.credentials.createInsecure()\nconst options = {\n  interceptors = [ bestInterceptorEver ]\n}\nconst client = caller('localhost:50051', PROTO_PATH, 'Greeter', credentials, options, {\n  metadata: { foo: 'bar' }\n})\n\n// Now every call with that client will result\n// in invoking the interceptor and sending the default metadata\n```\n\n* [caller(host, proto, name, credentials, options, defaults)](#caller) ⇒ \u003ccode\u003eObject\u003c/code\u003e\n    * [.metadata](#caller.metadata)\n    * [.wrap](#caller.wrap)\n\n\u003ca name=\"caller.metadata\"\u003e\u003c/a\u003e\n\n#### caller.metadata\nUtility helper function to create \u003ccode\u003eMetadata\u003c/code\u003e object from plain Javascript object.\nSee \u003ccode\u003egrpc-create-metadata\u003c/code\u003e module.\n\n**Kind**: static property of [\u003ccode\u003ecaller\u003c/code\u003e](#caller)  \n\u003ca name=\"caller.wrap\"\u003e\u003c/a\u003e\n\n#### caller.wrap\nUtility function that can be used to wrap an already constructed client instance.\n\n**Kind**: static property of [\u003ccode\u003ecaller\u003c/code\u003e](#caller)  \n## License\n\n  Apache-2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbojand%2Fgrpc-caller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbojand%2Fgrpc-caller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbojand%2Fgrpc-caller/lists"}