{"id":18974996,"url":"https://github.com/bufferapp/buffer-rpc","last_synced_at":"2025-04-19T16:44:32.737Z","repository":{"id":33153120,"uuid":"147545845","full_name":"bufferapp/buffer-rpc","owner":"bufferapp","description":"Buffer RPC request handler","archived":false,"fork":false,"pushed_at":"2024-09-23T14:14:08.000Z","size":874,"stargazers_count":1,"open_issues_count":14,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-29T10:23:50.238Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bufferapp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-05T16:11:49.000Z","updated_at":"2024-09-23T14:14:07.000Z","dependencies_parsed_at":"2023-01-14T23:40:38.917Z","dependency_job_id":null,"html_url":"https://github.com/bufferapp/buffer-rpc","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufferapp%2Fbuffer-rpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufferapp%2Fbuffer-rpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufferapp%2Fbuffer-rpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bufferapp%2Fbuffer-rpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bufferapp","download_url":"https://codeload.github.com/bufferapp/buffer-rpc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249106790,"owners_count":21213778,"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":[],"created_at":"2024-11-08T15:16:54.596Z","updated_at":"2025-04-16T09:34:26.214Z","avatar_url":"https://github.com/bufferapp.png","language":"JavaScript","readme":"# deprecated\nAs of the 23rd of September 2024, `buffer-rpc` will be unmaintained and deprecated. \n\n# buffer-rpc\n\n[![Build Status](https://travis-ci.org/bufferapp/buffer-rpc.svg?branch=master)](https://travis-ci.org/bufferapp/buffer-rpc)\n\nBuffer RPC request handler\n\n## Quickstart\n\nCreate a RPC method to add 2 numbers:\n\n```js\n// index.js\nconst express = require('express')\nconst { rpc, method } = require('@bufferapp/buffer-rpc')\nconst app = express()\napp.use(bodyParser.json()) // this is required\napp.post('/rpc/:method?', rpc(method('add', (a, b) =\u003e a + b)))\nconst port = 3000\napp.listen(port, () =\u003e console.log(`App Is Listening On Port ${port}`))\n```\n\nStart the server\n\n```sh\nnode index.js\n```\n\nOr you can use curl to call the `add` method:\n\n```sh\ncurl -H \"Content-Type: application/json\" -X POST -d '{\"args\": \"[2, 3]\"}' localhost:3000/add | python -m json.tool\n\n# {\n#    \"result\": 5\n# }\n```\n\n_Note: it is recommended that you use the RPC client:_\n\nhttps://github.com/bufferapp/micro-rpc-client\n\nTo see a list of all available methods use the `methods` call:\n\n```sh\ncurl -H \"Content-Type: application/json\" -X POST -d '{\"name\": \"methods\"}' localhost:3000 | python -m json.tool\n\n# {\n#   result: [\n#     {\n#       \"docs\": \"add two numbers\"\n#       \"name\": \"add\"\n#     },\n#     {\n#       \"docs\": \"list all available methods\",\n#       \"name\": \"methods\"\n#     }\n#   ]\n# }\n```\n\n## Usage\n\nHere's a few examples of how to hook up the handler methods:\n\n```js\nconst express = require('express')\nconst { rpc, method } = require('@bufferapp/buffer-rpc')\nconst app = express()\napp.use(bodyParser.json()) // this is required\n\napp.post(\n  '/rpc/:method?',\n  rpc(\n    method('add', (a, b) =\u003e a + b),\n    method(\n      'addAsync',\n      (a, b) =\u003e\n        new Promise(resolve =\u003e {\n          resolve(a + b)\n        }),\n    ),\n    method('addItems', ({ a, b }) =\u003e a + b),\n    method(\n      'addItemsAsync',\n      ({ a, b }) =\u003e\n        new Promise(resolve =\u003e {\n          resolve(a + b)\n        }),\n    ),\n    method('throwError', () =\u003e {\n      throw createError({ message: \"I'm sorry I can't do that\" })\n    }),\n\n    method(\n      'throwErrorAsync',\n      () =\u003e\n        new Promise((resolve, reject) =\u003e {\n          reject(\n            createError({\n              message: 'Something is broke internally',\n              statusCode: 500,\n            }),\n          )\n        }),\n    ),\n    method(\n      'documentation',\n      `\n  # documentation\n\n  Document what a method does.\n  `,\n      () =\u003e 'documentation',\n    ),\n  ),\n)\n\nconst port = 3000\napp.listen(port, () =\u003e console.log(`App Is Listening On Port ${port}`))\n```\n\n## Dependency Injection\n\nTo simplify the code in your RPC methods, you may want to pass some common utilities down via simple dependancy injection. To do this, you call the `rpc()` method with slightly different syntax.\n\nInstead of this (seen in the other README examples):\n\n```js\nrpc(methodOne, methodTwo, methodThree, ...);\n```\n\nPass the methods as an `Array` and pass `utils` as a second parameter:\n\n```js\nrpc([methodOne, methodTwo, methodThree], utils);\n```\n\nWhere `utils` is an `Object` that will be exposed to your RPC methods as the last parameter. For example, you might use it like this (example is simplified):\n\n```js\n// rpcHandler.js\nconst { rpc } = require('@bufferapp/buffer-rpc');\n\nconst PublishAPI = require('./publishAPI');\nconst myMethod = require('./myMethod');\n\nmodule.exports = rpc([myMethod], { PublishAPI });\n\n// myMethod.js\nconst { method } = require('@bufferapp/buffer-rpc');\n\nmodule.exports = method(\n  'myMethod',\n  'myMethodDocs',\n  (args, req, res, { PublishAPI }) =\u003e PublishAPI.fetch('/1/user.json')\n);\n```\n\n## Error Handling\n\n### Handled Flag\n\nTo help understand what the handled flag is for lets talk about a simplified distributed system. \n\n```\nclient -\u003e server\n```\n\nThe server is the RPC endpoints and the client is the source of the request, perhaps a browser or another service.. When handled = true this means there is nothing more for the client to do, when handled = false this means there _might_ be more work to resolve an issue. So handled = false is a maybe. An example of a definite handled = true is when you make a request to an RPC endpoint that does not exist. There's no partial state to resolve. An example of handled = false would be when you have to make multiple writes to a database, the first one passes and the second one fails. You've got a partially handled failure case. The client would be notified with a handled = false and then resolve the issue by either deleting the first record or writing the second -- depends on what the application does!\n\nWhile this doesn't happen very often, it is more likely when we choose to use a NoSQL database since we don't have joins. That being said most of the time, you'll return an error with handled = true... especially if you're keeping RPC endpoints simple. Avoid distributed systems problems when you can!\n\n**createError** handled = true (customizable)\n\n**errorMiddleware** handled = false\n\n**method not found** handled = true\n\n### Error Codes\n\nThese are the default error codes for error type responses\n\n**1000** - createError default (customizable)  \n**4040** - method not found (404)  \n**5000** - unhandled exception (500)\n\n## API\n\n### rpc\n\nTakes a bunch of methods as arguments. Passes requests to right RPC endpoint\n\n```js\nrpc(...methods)\n```\n\n**...methods** - _method_ - rpc method (see below)\n\n### method\n\nadd a remote method\n\n```js\nmethod(name, [docs], fn)\n```\n\n**name** - _string_ - the name of the method  \n**docs** - _string_ - documentation about a method  \n**fn** - _function_ - the function to call and apply parameters the method is requested\n\n### createError\n\ncreate an error to be thrown, optionally set the status code\n\n```js\ncreateError({\n  message,\n  code = 1000,\n  statusCode = 400,\n  handled = true,\n})\n```\n\n**message** - _string_ - error message to return  \n**code** - _integer_ - custom error code to add to response body HTTP status code (default to 1000)  \n**statusCode** - _integer_ - HTTP status code (default to 400)\n**handled** - _boolean_ - add if error was handled on backend to the response body (default to true)\n\n### errorMiddleware\n\n[express/connect error handling middleware](https://expressjs.com/en/guide/error-handling.html) that receives and unhandled error and returns a JSON response\n\n```js\napp.post('/rpc', rpc(method('awake', () =\u003e 'OK')), errorHandler)\n\n/*\nstatusCode = 500\nbody = {\n  handled: false,\n  code: 5000,\n  error: 'some error message' // set from error.message\n}\n*/\n```\n\n## Request and Response Objects\n\nRequest and response objects are always passed along as the last two arguments in case they're needed.\n\n```js\nmethod('addWithSession', (a, b, req, res) =\u003e {\n  if (!req.session) {\n    throw createError({ message: 'a session is needed to add numbers', statusCode: 401})\n  }\n  return a + b\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbufferapp%2Fbuffer-rpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbufferapp%2Fbuffer-rpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbufferapp%2Fbuffer-rpc/lists"}